import { Provide } from "@midwayjs/core"; import { InjectRepository } from "@midwayjs/sequelize"; import { Repository } from "sequelize-typescript"; import { Op } from "sequelize"; import { Context } from "@midwayjs/koa"; import Worker from "../entity/worker.entity"; // 电工状态:1在岗 0离职 const STATUS_ON_DUTY = 1; // 推荐位数量 const RECOMMEND_LIMIT = 5; // 经验分基准场次(达到即满分) const EXP_BASE_COUNT = 50; @Provide() export class WorkerService { @InjectRepository(Worker) workerModel!: Repository; // 列表:姓名/手机号/资质模糊检索 + 状态过滤 + 分页 async list(query: any, ctx: Context): Promise { const page = Number(query.page) || 1; const pageSize = Number(query.pageSize || query.limit) || 10; const where: any = {}; if (query.keyword) { where[Op.or] = [ { workerName: { [Op.like]: `%${query.keyword}%` } }, { phone: { [Op.like]: `%${query.keyword}%` } }, { certInfo: { [Op.like]: `%${query.keyword}%` } } ]; } if (query.status !== undefined && query.status !== "") where.status = Number(query.status); const { count, rows } = await this.workerModel.findAndCountAll({ where, limit: pageSize, offset: (page - 1) * pageSize, order: [["rating", "DESC"]], distinct: true }); return { code: 200, message: "获取共享电工列表成功", data: { list: rows.map((r) => r.toJSON()), total: count, page, pageSize } }; } // 下拉选项:仅在岗电工 async options(ctx: Context): Promise { const rows = await this.workerModel.findAll({ where: { status: STATUS_ON_DUTY }, attributes: ["id", "workerName", "workerTitle", "rating", "certInfo", "certVerified", "completedCount"], order: [["rating", "DESC"]] }); return { code: 200, message: "获取共享电工选项成功", data: rows.map((r) => r.toJSON()) }; } // 智能推荐:评分 50% + 资质 30% + 经验 20% 加权,取前 5 名 async recommend(query: any, ctx: Context): Promise { const rows = await this.workerModel.findAll({ where: { status: STATUS_ON_DUTY } }); if (rows.length === 0) return { code: 200, message: "获取推荐电工成功", data: [] }; const certKeyword: string = query.certKeyword || ""; const list = rows.map((row) => { const certInfo: string = row.certInfo || ""; const rating = Number(row.rating) || 0; const completedCount = Number(row.completedCount) || 0; const scoreRating = rating / 5; let scoreCert = row.certVerified ? (certInfo ? 1 : 0.7) : 0.4; // 关键词命中持证资质时资质分置满 if (certKeyword && certInfo.includes(certKeyword)) scoreCert = 1; const scoreExp = Math.min(completedCount / EXP_BASE_COUNT, 1); const score = 0.5 * scoreRating + 0.3 * scoreCert + 0.2 * scoreExp; return { id: row.id, workerName: row.workerName, workerTitle: row.workerTitle, rating, certInfo, certVerified: row.certVerified, completedCount, matchRate: Number((score * 100).toFixed(1)), rank: 0, isTop: false }; }); list.sort((a, b) => b.matchRate - a.matchRate || b.rating - a.rating || b.completedCount - a.completedCount); const data = list.slice(0, RECOMMEND_LIMIT).map((item, index) => { const rank = index + 1; return { ...item, rank, isTop: rank === 1 }; }); return { code: 200, message: "获取推荐电工成功", data }; } }