From 0e2c0ac1906ca97c70f6023ed5660306b374e5f1 Mon Sep 17 00:00:00 2001 From: b2894lxlx <517289602@qq.com> Date: Tue, 27 Oct 2026 03:28:33 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E7=AD=BE=E7=BA=A6=E5=AE=9D=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E8=B5=A0=E9=80=81=E6=AC=A1=E6=95=B0=EF=BC=8C=E5=B9=B3?= =?UTF-8?q?=E5=8F=B0=E7=94=A8=E6=88=B7=E5=88=97=E8=A1=A8=E5=B1=95=E7=A4=BA?= =?UTF-8?q?=E7=AD=BE=E7=BA=A6=E6=AC=A1=E6=95=B0=E7=BB=9F=E8=AE=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Cursor --- pages/signOnlyUser/list.vue | 56 ++++ pages_plugs/system/user/list.vue | 5 + .../service/admin/system/user/sys/getList.js | 283 ++++++++++++++---- .../admin/system/user/sys/giftQybNum.js | 46 +++ 4 files changed, 334 insertions(+), 56 deletions(-) create mode 100644 uniCloud-tcb/cloudfunctions/router/service/admin/system/user/sys/giftQybNum.js diff --git a/pages/signOnlyUser/list.vue b/pages/signOnlyUser/list.vue index ea26305..600725c 100644 --- a/pages/signOnlyUser/list.vue +++ b/pages/signOnlyUser/list.vue @@ -113,6 +113,23 @@ 关闭 + + + + 用户:{{ giftDialog.user.nickname || '未设置' }}({{ giftDialog.user.mobile || '未绑定' }}) + + 请输入赠送次数 + + + @@ -143,6 +160,12 @@ export default { return { showInviteList: false, inviteList: [], + giftDialog: { + show: false, + loading: false, + giftNum: 1, + user: null + }, // 页面是否请求中或加载中 loading: false, // init请求返回的数据 @@ -163,6 +186,14 @@ export default { } }); } + }, + { + title: "赠送", + onClick: function (item) { + that.giftDialog.user = item; + that.giftDialog.giftNum = 1; + that.giftDialog.show = true; + } } ], // 表格数据请求地址 @@ -177,6 +208,7 @@ export default { {key: "qybUsedNum", title: "已消费次数", type: "text", width: 120, defaultValue: 0}, {key: "qybNum", title: "剩余签约次数", type: "text", width: 120, defaultValue: 0}, {key: "qybGiftNum", title: "优惠政策赠送次数", type: "text", width: 150, defaultValue: 0}, + {key: "qybTotalGiftNum", title: "累计赠送次数", type: "text", width: 120, defaultValue: 0}, { key: "userLevel", title: "用户等级", @@ -604,6 +636,30 @@ export default { dcloudAppidData } }; + }, + // 提交赠送签约次数 + submitGiftQybNum() { + const user = that.giftDialog.user; + const giftNum = Number(that.giftDialog.giftNum); + if (!user || !user._id) return vk.toast('请选择用户'); + if (!Number.isInteger(giftNum) || giftNum <= 0) return vk.toast('赠送次数必须为正整数'); + that.giftDialog.loading = true; + vk.callFunction({ + url: 'admin/system/user/sys/giftQybNum', + title: '赠送中...', + data: { + user_id: user._id, + giftNum + }, + success: () => { + that.giftDialog.show = false; + that.$notify({ message: '赠送成功', type: 'success' }); + that.refresh(); + }, + complete: () => { + that.giftDialog.loading = false; + } + }); } }, // 监听属性 diff --git a/pages_plugs/system/user/list.vue b/pages_plugs/system/user/list.vue index 89d0f73..bb4287d 100644 --- a/pages_plugs/system/user/list.vue +++ b/pages_plugs/system/user/list.vue @@ -173,6 +173,11 @@ export default { // {key: "username", title: "用户名", type: "text", width: 180, defaultValue: '未设置'}, {key: "nickname", title: "昵称", type: "text", width: 180, defaultValue: '未设置'}, {key: "mobile", title: "手机号", type: "text", width: 120, defaultValue: "未绑定"}, + {key: "qybBuyNum", title: "累计购买", type: "text", width: 100, defaultValue: 0}, + {key: "qybUsedNum", title: "已消费", type: "text", width: 100, defaultValue: 0}, + {key: "qybNum", title: "剩余签约", type: "text", width: 100, defaultValue: 0}, + {key: "qybGiftNum", title: "赠送", type: "text", width: 100, defaultValue: 0}, + {key: "qybTotalGiftNum", title: "总共赠送次数", type: "text", width: 120, defaultValue: 0}, { key: "userLevel", title: "用户等级", diff --git a/uniCloud-tcb/cloudfunctions/router/service/admin/system/user/sys/getList.js b/uniCloud-tcb/cloudfunctions/router/service/admin/system/user/sys/getList.js index fd98542..b50d08f 100644 --- a/uniCloud-tcb/cloudfunctions/router/service/admin/system/user/sys/getList.js +++ b/uniCloud-tcb/cloudfunctions/router/service/admin/system/user/sys/getList.js @@ -1,59 +1,230 @@ module.exports = { - /** - * 查询用户列表(可登录后台的) - * @url admin/system/user/sys/getList 前端调用的url参数地址 - * data 请求参数 说明 - * @param {Number} pageIndex 当前页码 - * @param {Number} pageSize 每页显示数量 - * @param {Array} sortRule 排序规则 - * @param {object} formData 查询条件数据源 - * @param {Array} columns 查询条件规则 - * res 返回参数说明 - * @param {Number} code 错误码,0表示成功 - * @param {String} msg 详细信息 - */ - main: async (event) => { - let { data = {}, userInfo, util, filterResponse, originalParam } = event; - let { customUtil, uniID, config, pubFun, vk, db, _ } = util; - let { uid } = data; - let res = { code: 0, msg: '' }; - // 业务逻辑开始----------------------------------------------------------- - let { dcloud_appid, appids } = data.formData || {}; - let whereJson = {}; - if (dcloud_appid) { - if (dcloud_appid === "___empty-array___") { - whereJson["dcloud_appid"] = []; - } else if (dcloud_appid === "___error___") { - whereJson["dcloud_appid"] = _.and(_.exists(true), _.nin(appids)); - } else if (dcloud_appid === "___non-existent___") { - whereJson["dcloud_appid"] = _.exists(false); - } else { - whereJson["dcloud_appid"] = _.or(_.eq(dcloud_appid), _.exists(false)); - } - } - let dbName = "uni-id-users"; - res = await vk.baseDao.getTableData({ - dbName, - data, - whereJson, - sortArr: [{ "name": "register_date", "type": "desc" }], - // 副表列表 - foreignDB: [{ - dbName: "opendb-app-list", - localKey: "dcloud_appid", - foreignKey: "appid", - localKeyType: "array", - as: "appList", - limit: 500 - }], - }); - for (let i = 0; i < res.rows.length; i++) { - if (res.rows[i].isNotaryBusiness === undefined || res.rows[i].isNotaryBusiness === null) { - res.rows[i].isNotaryBusiness = res.rows[i].notaryUnionPayProfile && res.rows[i].notaryUnionPayProfile.status === 1 ? 1 : 0; - } - } - // 业务逻辑结束----------------------------------------------------------- - return res; - } + /** + * 查询用户列表(可登录后台的) + * @url admin/system/user/sys/getList 前端调用的url参数地址 + * data 请求参数 说明 + * @param {Number} pageIndex 当前页码 + * @param {Number} pageSize 每页显示数量 + * @param {Array} sortRule 排序规则 + * @param {object} formData 查询条件数据源 + * @param {Array} columns 查询条件规则 + * res 返回参数说明 + * @param {Number} code 错误码,0表示成功 + * @param {String} msg 详细信息 + */ + main: async (event) => { + let {data = {}, userInfo, util, filterResponse, originalParam} = event; + let {customUtil, uniID, config, pubFun, vk, db, _} = util; + let {uid} = data; + let res = {code: 0, msg: ''}; + // 业务逻辑开始----------------------------------------------------------- + let {dcloud_appid, appids, type} = data.formData || {}; + let whereJson = {}; + if (dcloud_appid) { + if (dcloud_appid === "___empty-array___") { + whereJson["dcloud_appid"] = []; + } else if (dcloud_appid === "___error___") { + whereJson["dcloud_appid"] = _.and(_.exists(true), _.nin(appids)); + } else if (dcloud_appid === "___non-existent___") { + whereJson["dcloud_appid"] = _.exists(false); + } else { + whereJson["dcloud_appid"] = _.or(_.eq(dcloud_appid), _.exists(false)); + } + } + if (type) { + whereJson["accountType"] = type; + } + if (data.type) { + whereJson["accountType"] = data.type; + } + if (data.isCompanyQuote) { + whereJson["isCompanyQuote"] = 1; + } + if (data.isProductQuote) { + whereJson["isProductQuote"] = 1; + } + if (data.isCostQuote) { + whereJson["isCostQuote"] = 1; + } + + if (data.formData) { + if (data.formData.address && data.formData.address.province) { + whereJson["company.addressRegion.province.code"] = data.formData.address.province.code + } + if (data.formData.type) whereJson["accountType"] = data.formData.type; + if (data.formData.isSignOnly) whereJson["isSignOnly"] = true; + if (data.formData.onlyNotaryUnionPayProfile) { + whereJson["notaryUnionPayProfile.status"] = _.in([0, 1, 2]); + } + if (data.formData.hasOwnProperty('profileStatus') && data.formData.profileStatus !== '' && data.formData.profileStatus !== null && data.formData.profileStatus !== undefined) { + if (parseInt(data.formData.profileStatus) === -1) { + whereJson["notaryUnionPayProfile.status"] = _.exists(false); + } else { + whereJson["notaryUnionPayProfile.status"] = parseInt(data.formData.profileStatus); + } + } + } + console.log('whereJson', whereJson) + let dbName = "uni-id-users"; + res = await vk.baseDao.getTableData({ + dbName, + data, + whereJson, + sortArr: [{"name": "register_date", "type": "desc"}], + // 副表列表 + foreignDB: [ + { + dbName: "opendb-app-list", + localKey: "dcloud_appid", + foreignKey: "appid", + localKeyType: "array", + as: "appList", + limit: 500 + }, + { + dbName: "uni-id-users", + localKey: "inviter_uid", + foreignKey: "_id", + localKeyType: "array", + as: "parent", + limit: 1 + } + ], + }); + const toNum = (value, defaultValue = 0) => { + const num = Number(value); + return Number.isNaN(num) ? defaultValue : num; + }; + if (res.rows && res.rows.length > 0) { + const userIds = res.rows.map(item => item._id).filter(Boolean); + const qybStatMap = {}; + userIds.forEach(userId => { + qybStatMap[userId] = { + qybBuyNum: 0, + qybUsedNum: 0, + qybPackageGiftNum: 0, + qybTotalGetNum: 0 + }; + }); + + if (userIds.length > 0) { + const payRes = await vk.baseDao.select({ + dbName: "jjx-sign-pay_list", + pageSize: 5000, + whereJson: { + userId: _.in(userIds) + } + }); + (payRes.rows || []).forEach(item => { + if (item.userId && qybStatMap[item.userId]) qybStatMap[item.userId].qybUsedNum += 1; + }); + + const orderRes = await vk.baseDao.select({ + dbName: "jjx-order", + pageSize: 5000, + whereJson: { + uid: _.in(userIds), + type: 13, + orderStatus: 4 + } + }); + const orderUserMap = {}; + const orderIds = []; + (orderRes.rows || []).forEach(item => { + if (item._id && item.uid && qybStatMap[item.uid]) { + orderUserMap[item._id] = item.uid; + orderIds.push(item._id); + } + }); + + if (orderIds.length > 0) { + const goodsRes = await vk.baseDao.select({ + dbName: "jjx-order-goods", + pageSize: 5000, + whereJson: { + orderId: _.in(orderIds) + } + }); + const goodsRows = goodsRes.rows || []; + const qybIds = [...new Set(goodsRows.map(item => item.goodsId).filter(Boolean))]; + const qybMap = {}; + if (qybIds.length > 0) { + const qybRes = await vk.baseDao.select({ + dbName: "jjx-qyb", + pageSize: 5000, + whereJson: { + _id: _.in(qybIds) + } + }); + (qybRes.rows || []).forEach(item => { + qybMap[item._id] = item; + }); + } + + goodsRows.forEach(item => { + const userId = orderUserMap[item.orderId]; + if (userId && qybStatMap[userId]) { + const buyNum = Math.max(toNum(item.num, 1), 1); + const qyb = qybMap[item.goodsId]; + const getNum = qyb ? toNum(qyb.getNum, 1) : 1; + qybStatMap[userId].qybBuyNum += buyNum; + qybStatMap[userId].qybTotalGetNum += getNum * buyNum; + } + }); + } + + Object.keys(qybStatMap).forEach(userId => { + qybStatMap[userId].qybPackageGiftNum = Math.max(qybStatMap[userId].qybTotalGetNum - qybStatMap[userId].qybBuyNum, 0); + }); + res.rows.forEach(item => { + const qybStat = qybStatMap[item._id] || {}; + const adminGiftNum = toNum(item.qybTotalGiftNum, 0); + // 用户表上的 qybGiftNum 为后台赠送累加值;套餐优惠政策赠送从订单统计 + const storedGiftNum = toNum(item.qybGiftNum, 0); + item.qybBuyNum = qybStat.qybBuyNum || 0; + item.qybUsedNum = qybStat.qybUsedNum || 0; + item.qybNum = toNum(item.qybNum, 0); + item.qybGiftNum = (qybStat.qybPackageGiftNum || 0) + storedGiftNum; + item.qybTotalGiftNum = adminGiftNum || storedGiftNum; + }); + } + } + for (let i = 0; i < res.rows.length; i++) { + if (res.rows[i].isNotaryBusiness === undefined || res.rows[i].isNotaryBusiness === null) { + res.rows[i].isNotaryBusiness = res.rows[i].notaryUnionPayProfile && res.rows[i].notaryUnionPayProfile.status === 1 ? 1 : 0 + } + res.rows[i].profileStatus = res.rows[i].notaryUnionPayProfile ? res.rows[i].notaryUnionPayProfile.status : -1 + if (res.rows[i].accountType === 1) { + if (res.rows[i].person && res.rows[i].person.mainSpotCategoryIds && res.rows[i].person.mainSpotCategoryIds.length > 0) { + const goodsRes = await vk.baseDao.select({ + dbName: "jjx-spot-category", + whereJson: { + _id: _.in(res.rows[i].person.mainSpotCategoryIds) + } + }); + console.log('goodsRes', goodsRes) + if (goodsRes.rows && goodsRes.rows.length > 0) { + res.rows[i].person.mainSpotCategoryNames = goodsRes.rows.map(item => item.name).join(","); + } + } + } + if (res.rows[i].accountType === 2) { + if (res.rows[i].company && res.rows[i].company.mainSpotCategoryIds && res.rows[i].company.mainSpotCategoryIds.length > 0) { + const goodsRes = await vk.baseDao.select({ + dbName: "jjx-spot-category", + whereJson: { + _id: _.in(res.rows[i].company.mainSpotCategoryIds) + } + }); + console.log('goodsRes', goodsRes) + if (goodsRes.rows && goodsRes.rows.length > 0) { + res.rows[i].company.mainSpotCategoryNames = goodsRes.rows.map(item => item.name).join(","); + } + } + } + } + // 业务逻辑结束----------------------------------------------------------- + return res; + } } diff --git a/uniCloud-tcb/cloudfunctions/router/service/admin/system/user/sys/giftQybNum.js b/uniCloud-tcb/cloudfunctions/router/service/admin/system/user/sys/giftQybNum.js new file mode 100644 index 0000000..607c1e1 --- /dev/null +++ b/uniCloud-tcb/cloudfunctions/router/service/admin/system/user/sys/giftQybNum.js @@ -0,0 +1,46 @@ +'use strict'; +module.exports = { + /** + * 后台赠送签约宝次数 + * @url admin/system/user/sys/giftQybNum + * @param {String} user_id 用户ID + * @param {Number} giftNum 赠送次数 + */ + main: async (event) => { + let { data = {}, util } = event; + let { vk, _ } = util; + let res = { code: 0, msg: '' }; + + const { user_id, giftNum } = data; + const num = Number(giftNum); + + if (!user_id) { + return { code: -1, msg: '用户ID不能为空' }; + } + if (!Number.isInteger(num) || num <= 0) { + return { code: -1, msg: '赠送次数必须为正整数' }; + } + + const user = await vk.baseDao.findById({ + dbName: 'uni-id-users', + id: user_id + }); + if (!user) { + return { code: -1, msg: '用户不存在' }; + } + + // 剩余签约次数、优惠政策赠送次数、累计赠送次数同步累加 + await vk.baseDao.updateById({ + dbName: 'uni-id-users', + id: user_id, + dataJson: { + qybNum: _.inc(num), + qybGiftNum: _.inc(num), + qybTotalGiftNum: _.inc(num) + } + }); + + res.msg = '赠送成功'; + return res; + } +};