import { Provide } from '@midwayjs/core'; import { InjectEntityModel } from '@midwayjs/typeorm'; import { Order } from '../entity/order.entity'; import { Repository } from 'typeorm'; import { CustomerTag } from '../entity/customer_tag.entity'; import { Customer } from '../entity/customer.entity'; @Provide() export class CustomerService { @InjectEntityModel(Order) orderModel: Repository; @InjectEntityModel(CustomerTag) customerTagModel: Repository; @InjectEntityModel(Customer) customerModel: Repository; async getCustomerList(param: Record) { const { current = 1, pageSize = 10, email, tags, sorterKey, sorterValue, state, first_purchase_date, customerId, rate, } = param; const whereConds: string[] = []; const havingConds: string[] = []; // 邮箱搜索 if (email) { whereConds.push(`o.customer_email LIKE '%${email}%'`); } // 省份搜索 if (state) { whereConds.push( `JSON_UNQUOTE(JSON_EXTRACT(o.billing, '$.state')) = '${state}'` ); } // customerId 过滤 if (customerId) { whereConds.push(`c.id = ${Number(customerId)}`); } // rate 过滤 if (rate) { whereConds.push(`c.rate = ${Number(rate)}`); } // tags 过滤 if (tags) { const tagList = tags .split(',') .map(tag => `'${tag.trim()}'`) .join(','); havingConds.push(` EXISTS ( SELECT 1 FROM customer_tag ct WHERE ct.email = o.customer_email AND ct.tag IN (${tagList}) ) `); } // 首次购买时间过滤 if (first_purchase_date) { havingConds.push( `DATE_FORMAT(MIN(o.date_paid), '%Y-%m') = '${first_purchase_date}'` ); } // 公用过滤 const baseQuery = ` ${whereConds.length ? `WHERE ${whereConds.join(' AND ')}` : ''} GROUP BY o.customer_email ${havingConds.length ? `HAVING ${havingConds.join(' AND ')}` : ''} `; // 主查询 const sql = ` SELECT o.customer_email AS email, MIN(o.date_created) AS date_created, MIN(o.date_paid) AS first_purchase_date, MAX(o.date_paid) AS last_purchase_date, COUNT(DISTINCT o.id) AS orders, SUM(o.total) AS total, ANY_VALUE(o.shipping) AS shipping, ANY_VALUE(o.billing) AS billing, ( SELECT JSON_ARRAYAGG(tag) FROM customer_tag ct WHERE ct.email = o.customer_email ) AS tags, c.id AS customerId, c.rate AS rate, yoone_stats.yoone_orders, yoone_stats.yoone_total FROM \`order\` o LEFT JOIN customer c ON o.customer_email = c.email LEFT JOIN ( SELECT oo.customer_email, COUNT(DISTINCT oi.orderId) AS yoone_orders, SUM(oi.total) AS yoone_total FROM order_item oi JOIN \`order\` oo ON oi.orderId = oo.id WHERE oi.name LIKE '%yoone%' GROUP BY oo.customer_email ) yoone_stats ON yoone_stats.customer_email = o.customer_email ${baseQuery} ${sorterKey ? `ORDER BY ${sorterKey} ${sorterValue === 'descend' ? 'DESC' : 'ASC'}` : 'ORDER BY orders ASC, yoone_total DESC'} LIMIT ${pageSize} OFFSET ${(current - 1) * pageSize} `; // 统计总数 const countSql = ` SELECT COUNT(*) AS total FROM ( SELECT o.customer_email FROM \`order\` o LEFT JOIN customer c ON o.customer_email = c.email ${baseQuery} ) AS sub `; const [items, countResult] = await Promise.all([ this.orderModel.query(sql), this.orderModel.query(countSql), ]); const total = countResult[0]?.total || 0; return { items, total, current, pageSize, }; } async addTag(email: string, tag: string) { const isExist = await this.customerTagModel.findOneBy({ email, tag }); if (isExist) throw new Error(`${tag}已存在`); return await this.customerTagModel.save({ email, tag }); } async delTag(email: string, tag: string) { const isExist = await this.customerTagModel.findOneBy({ email, tag }); if (!isExist) throw new Error(`${tag}不存在`); return await this.customerTagModel.delete({ email, tag }); } async getTags() { const tags = await this.customerTagModel .createQueryBuilder('tag') .select('DISTINCT tag.tag', 'tag') .getRawMany(); return tags.map(t => t.tag); } async setRate(params: { id: number; rate: number }) { return await this.customerModel.update(params.id, { rate: params.rate }); } }