123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- 'use strict';
- const { CrudService } = require('naf-framework-mongoose-free/lib/service');
- const { BusinessError, ErrorCode } = require('naf-core').Error;
- const _ = require('lodash');
- const assert = require('assert');
- const { ObjectId } = require('mongoose').Types;
- //
- class GoodsService extends CrudService {
- constructor(ctx) {
- super(ctx, 'goods');
- this.goodsModel = this.ctx.model.Shop.Goods;
- this.goodsSpecModel = this.ctx.model.Shop.GoodsSpec;
- }
- /**
- *
- * @param {Object} query 查询条件
- * @param query.id 商品数据id
- */
- async goodsDetail({ id }) {
- const { populate } = this.ctx.service.shop.goods.getRefMods();
- let goods = await this.goodsModel.findById(id, { file: 1, tags: 1, name: 1, shot_brief: 1, brief: 1, send_time: 1, shop: 1, view_num: 1 }).populate(populate);
- if (!goods) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到商品数据');
- goods = JSON.parse(JSON.stringify(goods));
- let specs = await this.goodsSpecModel.find({ goods: id, status: '0' }, { sell_money: 1, flow_money: 1, freight: 1, name: 1, num: 1, can_group: 1, group_config: 1, file: 1 });
- specs = JSON.parse(JSON.stringify(specs));
- goods = _.omit(goods, [ 'meta', '__v' ]);
- const shop = _.pick(goods.shop, [ 'logo', 'name', 'person', 'phone', '_id' ]);
- delete goods.shop;
- // 2022-10-17反馈问题6:将规格图片和商品图片合并,规格图片在前
- for (const spec of specs) {
- if (_.isArray(spec.file)) {
- goods.file = [ ...spec.file, ..._.get(goods, 'file', []) ];
- }
- }
- // goods: 商品信息; specs:商品规格信息; shop:店铺信息
- const returnData = { goods, specs, shop };
- // 添加浏览次数
- await this.goodsModel.updateOne({ _id: id }, { view_num: (goods.view_num || 0) + 1 });
- return returnData;
- }
- async indexGoodsList(condition, { skip = 0, limit = 20 } = {}) {
- condition = this.dealFilter(condition);
- const pipline = [{ $match: { status: { $ne: '0' } } }]; // { $sort: { sort: 1 } },
- const { view_num, sell_num, sell_money, name, shop, tags } = condition;
- let sort = {};
- if (view_num) sort.view_num = parseInt(view_num);
- if (sell_num) sort.sell_num = parseInt(sell_num);
- if (sell_money) sort.sell_money = parseInt(sell_money);
- if (name) pipline.push({ $match: { name: new RegExp(name) } });
- if (shop) pipline.push({ $match: { shop } });
- if (tags) pipline.push({ $match: { tags: { $elemMatch: { $elemMatch: { $eq: tags } } } } });
- pipline.push({ $addFields: { goods_id: { $toString: '$_id' }, create_time: { $dateToString: { date: '$meta.createdAt', format: '%Y-%m-%d %H:%M:%S', timezone: '+08:00' } } } });
- // 表关联
- pipline.push({
- $lookup: {
- from: 'goodsSpec',
- localField: 'goods_id',
- foreignField: 'goods',
- as: 'specs',
- },
- });
- // 按照规格平铺数据
- pipline.push({ $unwind: '$specs' });
- // 格式化平铺后的数据
- // 2022-10-17反馈-问题6:将规格图片也拿出来
- // TODO: 整理规格图片与正常的商品图片
- pipline.push({
- $project: {
- name: 1,
- view_num: 1,
- sell_num: 1,
- file: 1,
- sort: 1,
- create_time: 1,
- sell_money: { $toDouble: '$specs.sell_money' },
- flow_money: { $toDouble: '$specs.flow_money' },
- createdAt: '$meta.createdAt',
- spec_file: '$specs.file',
- },
- });
- pipline.push({
- $group: {
- _id: '$_id',
- data: { $min: '$$CURRENT' },
- },
- });
- pipline.push({
- $project: {
- name: '$data.name',
- view_num: '$data.view_num',
- sell_num: '$data.sell_num',
- file: '$data.file',
- sell_money: '$data.sell_money',
- flow_money: '$data.flow_money',
- createdAt: '$data.createdAt',
- spec_file: '$data.spec_file',
- create_time: '$data.create_time',
- sort: '$data.sort',
- },
- });
- sort.sort = 1;
- sort = { ...sort, sort: 1, create_time: -1 };
- pipline.push({ $sort: sort });
- console.log(pipline);
- // 分页处理
- const qPipline = _.cloneDeep(pipline);
- if (parseInt(skip)) qPipline.push({ $skip: parseInt(skip) });
- if (parseInt(limit)) qPipline.push({ $limit: parseInt(limit) });
- let list = await this.goodsModel.aggregate(qPipline);
- // 处理合并图片
- list = list.map(i => {
- if (_.isArray(i.spec_file)) {
- i.file = [ ...i.spec_file, ...i.file ];
- delete i.spec_file;
- }
- return i;
- });
- const tPipline = _.cloneDeep(pipline);
- tPipline.push({ $count: 'total' });
- const total = await this.goodsModel.aggregate(tPipline);
- return { list, total: _.get(_.head(total), 'total', 0) };
- }
- async indexActTagsGoods() {
- // 将使用中且展示在首页的查出来排序
- const list = await this.ctx.model.System.ActTags.find({ status: '0', show_index: '0' }).sort({ sort: 1 });
- const result = [];
- for (const t of list) {
- const { label, value } = t;
- const list = await this.searchActTagsGoods(value);
- const arr = [];
- for (const g of list) {
- const obj = {
- url: _.get(g, 'file'),
- name: _.get(g, 'name'),
- id: _.get(g, '_id'),
- value,
- };
- if (arr.length === 0) {
- obj.title = label;
- }
- arr.push(obj);
- }
- result.push({ list: arr });
- }
- return result;
- }
- async searchActTagsGoods(act_tags, limit = 2) {
- const pipline = [{ $sort: { 'meta.createdAt': -1 } }, { $match: { status: { $ne: '0' }, act_tags } }];
- pipline.push({ $project: { name: 1, file: 1 } });
- if (parseInt(limit)) pipline.push({ $limit: parseInt(limit) });
- const list = await this.goodsModel.aggregate(pipline);
- return list;
- }
- }
- module.exports = GoodsService;
|