diff --git a/src/api/fishMarket.js b/src/api/fishMarket.js new file mode 100644 index 0000000..0fb03f3 --- /dev/null +++ b/src/api/fishMarket.js @@ -0,0 +1,19 @@ +import { getRequest, postBodyRequest } from '@/libs/axios'; + +const PREFIX = '/app/fishmarket/admin'; + +export const fishGoodsPage = (params) => postBodyRequest(`${PREFIX}/goods/page`, params); +export const fishGoodsStatus = (params) => postBodyRequest(`${PREFIX}/goods/status`, params); +export const fishWantPage = (params) => postBodyRequest(`${PREFIX}/wants/page`, params); + +export const fishCategoryList = (params) => getRequest(`${PREFIX}/categories`, params); +export const fishCategorySave = (params) => postBodyRequest(`${PREFIX}/categories`, params); +export const fishCategoryDelete = (id) => postBodyRequest(`${PREFIX}/categories/delete?id=${id}`, {}); + +export const fishComplaintPage = (params) => postBodyRequest(`${PREFIX}/complaints/page`, params); +export const fishComplaintHandle = (params) => postBodyRequest(`${PREFIX}/complaints/handle`, params); + +export const fishUserLimitPage = (params) => postBodyRequest(`${PREFIX}/users/limits/page`, params); +export const fishUserLimitSave = (params) => postBodyRequest(`${PREFIX}/users/limits`, params); + +export const fishAdminLogPage = (params) => postBodyRequest(`${PREFIX}/logs/page`, params); diff --git a/src/api/index.js b/src/api/index.js index 8a2ee59..6421d50 100644 --- a/src/api/index.js +++ b/src/api/index.js @@ -737,6 +737,11 @@ export const runshOrder = (params) => { return postRequest('/mall/delivery/reassignWorker', params) } +// 配送单转单记录 +export const getDeliveryReassignRecords = (params) => { + return getRequest('/mall/delivery/reassignRecords', params) +} + // 订单详情 export const getOrderDetail = (id,params) => { return getRequest(`/mall/order/detail/${id}`, params) diff --git a/src/views/app/bill/current/current.vue b/src/views/app/bill/current/current.vue index d2545f4..e8889f4 100644 --- a/src/views/app/bill/current/current.vue +++ b/src/views/app/bill/current/current.vue @@ -80,6 +80,7 @@ reading: false, drop: false, selectList: [], + settledShopIds: [], searchForm: { regionId:JSON.parse(this.getStore("user")).departmentId, settlementDate:'', @@ -209,6 +210,7 @@ }, changeDate(v){ this.searchForm.settlementDate = v + this.settledShopIds = [] }, handleSearch() { this.searchForm.pageNumber = 1; @@ -241,6 +243,7 @@ this.$Message.warning("请选择要结算的商家"); return } + const isCurrentPageEmpty = this.selectList.length >= this.data.length && this.searchForm.pageNumber > 1 let data = { shopIds:[], settlementDate:this.searchForm.settlementDate, @@ -253,10 +256,16 @@ settlementConfirm(data).then((res) => { if (res.success) { this.$Message.success("结算成功"); - const settledShopIds = data.shopIds; - this.data = this.data.filter(item => settledShopIds.indexOf(item.shopId) == -1); - this.total = Math.max(this.total - settledShopIds.length, 0); + this.settledShopIds = this.settledShopIds.concat(data.shopIds).filter((shopId, index, list) => list.indexOf(shopId) === index); this.clearSelectAll(); + this.selectList = []; + if (isCurrentPageEmpty) { + this.searchForm.pageNumber -= 1; + this.getDataList(); + } else { + this.data = this.data.filter(item => this.settledShopIds.indexOf(item.shopId) === -1); + this.total = Math.max(this.total - data.shopIds.length, 0); + } } }).finally(() => { this.settlementLoading = false @@ -271,8 +280,11 @@ getBillList(this.searchForm).then((res) => { this.loading = false; if (res.success) { - this.data = (res.result && res.result.records) || res.result || [] - this.total = (res.result && res.result.total) || this.data.length + const records = (res.result && res.result.records) || res.result || [] + const total = (res.result && res.result.total) || records.length + const hasSettledRecords = records.some(item => this.settledShopIds.indexOf(item.shopId) !== -1) + this.data = records.filter(item => this.settledShopIds.indexOf(item.shopId) === -1) + this.total = hasSettledRecords ? Math.max(total - this.settledShopIds.length, 0) : total } }); }, diff --git a/src/views/app/bill/historical/historical.vue b/src/views/app/bill/historical/historical.vue index ae9830e..fede621 100644 --- a/src/views/app/bill/historical/historical.vue +++ b/src/views/app/bill/historical/historical.vue @@ -258,8 +258,17 @@ if (res.success) { this.$Message.success("结算任务已提交"); this.selectList = []; - this.shopVisible = false; - this.getDataList(); + if (this.$refs.shopTable) { + this.$refs.shopTable.selectAll(false); + } + this.data = []; + this.total = 0; + this.shopData = []; + this.shopTotal = 0; + setTimeout(() => { + this.getShopSummary(); + this.getDataList(); + }, 2000); } }).finally(() => { this.settlementLoading = false; diff --git a/src/views/app/business/bus/addEdit.vue b/src/views/app/business/bus/addEdit.vue index 5d86c09..0ad939b 100644 --- a/src/views/app/business/bus/addEdit.vue +++ b/src/views/app/business/bus/addEdit.vue @@ -36,14 +36,14 @@ - + 无门槛 - 元可使用 + 元可使用 - + @@ -71,10 +71,10 @@ - + 固定日期 - 领券后天有效 + 领券后天有效 @@ -154,6 +154,11 @@ } callback(); }; + const validateTotalCount = (rule, value, callback) => { + if (validateIntegerRange(value, 1, 100000, "发券总数量必须是1-100000的整数", callback)) { + callback(); + } + }; const validateLimitPerUser = (rule, value, callback) => { if (validateIntegerRange(value, 1, 99, "每人限领数量必须是1-99的整数", callback)) { callback(); @@ -165,8 +170,10 @@ callback(new Error("请选择固定日期有效期")); return; } - const startTime = this.parseDateTime(this.form.validStartTime).getTime(); - const endTime = this.parseDateTime(this.form.validEndTime).getTime(); + const startDate = this.parseDateTime(this.form.validStartTime); + const endDate = this.parseDateTime(this.form.validEndTime); + const startTime = startDate ? startDate.getTime() : 0; + const endTime = endDate ? endDate.getTime() : 0; const now = Date.now(); if (!startTime || !endTime || startTime <= now || endTime <= now || endTime <= startTime) { callback(new Error("固定日期必须设置为当前时间之后,且结束时间晚于开始时间")); @@ -218,6 +225,9 @@ required: true, message: "请输入发券总数量", trigger: "change" + }, { + validator: validateTotalCount, + trigger: "change" }, ], applyScene: [{ required: true, @@ -278,7 +288,7 @@ minAmount:'', //使用门槛金额 discountAmount:'', //抵扣面额 totalCount:'', //发行总数 - limitPerUser:1, //每人最多限领张数 + limitPerUser:'', //每人最多限领张数 validType:'', //有效期类型:1-绝对时间段有效,2-领取后相对天数有效 validStartTime:'', //有效期开始时间 validEndTime:'', //有效期结束时间 @@ -298,6 +308,70 @@ this.form.validEndTime = v[1] this.$refs.form.validateField("validType"); }, + handleTypeChange(value) { + if (value !== "1") { + this.form.minAmount = ""; + } + this.validateThreshold(); + }, + handleValidTypeChange(value) { + if (value === "1") { + this.form.validDays = ""; + } else if (value === "2") { + this.form.validStartTime = ""; + this.form.validEndTime = ""; + } + this.validateValidity(); + }, + validateThreshold() { + this.$nextTick(() => { + this.$refs.form.validateField("type"); + }); + }, + validateValidity() { + this.$nextTick(() => { + this.$refs.form.validateField("validType"); + }); + }, + clearHiddenOptionValues() { + if (this.form.type !== "1") { + this.form.minAmount = ""; + } + if (this.form.validType === "1") { + this.form.validDays = ""; + } else if (this.form.validType === "2") { + this.form.validStartTime = ""; + this.form.validEndTime = ""; + } + }, + fillForm(data = {}) { + const nextForm = Object.assign(this.getDefaultForm(), data); + const toFormString = (value) => value === undefined || value === null ? "" : String(value); + nextForm.applyScene = toFormString(nextForm.applyScene) + nextForm.type = toFormString(nextForm.type) + nextForm.validType = toFormString(nextForm.validType) + nextForm.ruleType = toFormString(nextForm.ruleType) + nextForm.totalCount = toFormString(nextForm.totalCount) + Object.keys(this.form).forEach((key) => { + if (!Object.prototype.hasOwnProperty.call(nextForm, key)) { + this.$delete(this.form, key); + } + }); + Object.keys(nextForm).forEach((key) => { + this.$set(this.form, key, nextForm[key]); + }); + }, + clearValidateState() { + this.$nextTick(() => { + if (!this.$refs.form || !this.$refs.form.fields) { + return; + } + this.$refs.form.fields.forEach((field) => { + field.validateState = ""; + field.validateMessage = ""; + }); + }); + }, parseDateTime(value) { if (!value) { return null; @@ -352,33 +426,36 @@ return form; }, submit() { - this.$refs.form.validate((valid) => { - if (valid) { - const submitForm = this.getSubmitForm(); - if (this.type == "1") { - // 编辑 - this.submitLoading = true; - editCoupon(submitForm).then((res) => { - this.submitLoading = false; - if (res.success) { - this.$Message.success("操作成功"); - this.$emit("on-submit", true); - this.visible = false; - } - }); - } else { - // 添加1 - this.submitLoading = true; - addCoupon(submitForm).then((res) => { - this.submitLoading = false; - if (res.success) { - this.$Message.success("操作成功"); - this.$emit("on-submit", true); - this.visible = false; - } - }); + this.clearHiddenOptionValues(); + this.$nextTick(() => { + this.$refs.form.validate((valid) => { + if (valid) { + const submitForm = this.getSubmitForm(); + if (this.type == "1") { + // 编辑 + this.submitLoading = true; + editCoupon(submitForm).then((res) => { + this.submitLoading = false; + if (res.success) { + this.$Message.success("操作成功"); + this.$emit("on-submit", true); + this.visible = false; + } + }); + } else { + // 添加1 + this.submitLoading = true; + addCoupon(submitForm).then((res) => { + this.submitLoading = false; + if (res.success) { + this.$Message.success("操作成功"); + this.$emit("on-submit", true); + this.visible = false; + } + }); + } } - } + }); }); }, setCurrentValue(value) { @@ -401,18 +478,14 @@ if (this.$refs.form) { this.$refs.form.resetFields(); } - this.form = this.getDefaultForm(); + this.fillForm(); if (this.type == "0" || this.type == "1") { // 回显数据 let data = this.data; // 回显 - this.form = Object.assign(this.getDefaultForm(), data); - this.form.applyScene = JSON.stringify(this.form.applyScene) - this.form.type = JSON.stringify(this.form.type) - this.form.validType = JSON.stringify(this.form.validType) - this.form.ruleType = JSON.stringify(this.form.ruleType) - + this.fillForm(data); } + this.clearValidateState(); this.visible = value; }, }, diff --git a/src/views/app/business/courier/courier.vue b/src/views/app/business/courier/courier.vue index 39c9df9..f97c2df 100644 --- a/src/views/app/business/courier/courier.vue +++ b/src/views/app/business/courier/courier.vue @@ -197,9 +197,15 @@ minWidth: 125, }, { - title: "佣金余额(元)", + title: "佣金余额(元)", key: "depoBal", minWidth: 145, + render: (h, params) => { + return h("div", [ + h("div", "今日:" + this.formatAmount(params.row.depoBal)), + h("div", { style: { color: "#19be6b", marginTop: "4px" } }, "可提现:" + this.formatAmount(params.row.depoBalRel)), + ]); + }, }, { title: "联系方式", @@ -271,12 +277,6 @@ ]); } }, - { - title: "交易保障金", - key: "rebateAmount", - width: 200, - align: "center" - }, { title: "学生/身份证", key: "cardPicture", @@ -687,6 +687,10 @@ } return "-"; }, + formatAmount(v) { + const number = Number(v); + return isNaN(number) ? "0.00" : number.toFixed(2); + }, enable(v) { this.$Modal.confirm({ title: "确认恢复", diff --git a/src/views/app/business/courier/logisticsAddress.vue b/src/views/app/business/courier/logisticsAddress.vue index 9d9d876..f99db43 100644 --- a/src/views/app/business/courier/logisticsAddress.vue +++ b/src/views/app/business/courier/logisticsAddress.vue @@ -9,6 +9,12 @@ size="small" show-total show-elevator show-sizer> + +
+
+ +
+
@@ -37,6 +43,37 @@ shopId: "" }, selectList: [], // 多选数据 + replyVisible: false, + replyList: [], + replyColumns: [ + { + type: "index", + width: 60, + align: "center", + }, + { + title: "回复用户", + minWidth: 125, + render: (h, params) => { + return h("span", this.getReplyField(params.row, ["createByName", "replyUserName", "userName", "nickName", "createBy"]) || "-"); + }, + }, + { + title: "回复时间", + minWidth: 160, + render: (h, params) => { + const time = this.getReplyField(params.row, ["createTime", "replyTime", "updateTime"]); + return h("span", time ? this.formatDateTime(time) : "-"); + }, + }, + { + title: "回复内容", + minWidth: 260, + render: (h, params) => { + return h("span", this.formatReplyContent(params.row)); + }, + }, + ], columns: [ { type: "index", @@ -102,6 +139,21 @@ fixed: "right", render: (h, params) => { return h("div", [ + h( + "a", { + on: { + click: () => { + this.viewReply(params.row); + }, + }, + }, + "查看回复" + ), + h("Divider", { + props: { + type: "vertical", + }, + }), h( "a", { on: { @@ -151,6 +203,41 @@ }, }); }, + viewReply(v) { + this.replyList = this.normalizeReplyList(v.comments); + this.replyVisible = true; + }, + normalizeReplyList(comments) { + if (!comments) return []; + if (Array.isArray(comments)) return comments; + if (typeof comments === "string") { + if (!comments.trim()) return []; + try { + const parsed = JSON.parse(comments); + return this.normalizeReplyList(parsed); + } catch (e) { + return [{ + content: comments + }]; + } + } + if (comments.records && Array.isArray(comments.records)) return comments.records; + if (comments.list && Array.isArray(comments.list)) return comments.list; + return [comments]; + }, + getReplyField(row, keys) { + for (let i = 0; i < keys.length; i++) { + const value = row[keys[i]]; + if (value !== undefined && value !== null && value !== "") return value; + } + return ""; + }, + formatReplyContent(row) { + const content = this.getReplyField(row, ["remark", "content", "comment", "replyContent", "message"]); + if (!content) return "-"; + if (typeof content === "object") return JSON.stringify(content); + return content; + }, showPic(v) { if(v == ''){ this.$Message.warning("没有评价图");return diff --git a/src/views/app/business/expressCompany/expressCompany.vue b/src/views/app/business/expressCompany/expressCompany.vue index b782b4a..60d3c3c 100644 --- a/src/views/app/business/expressCompany/expressCompany.vue +++ b/src/views/app/business/expressCompany/expressCompany.vue @@ -3,479 +3,351 @@ @import "./expressCompany.less"; \ No newline at end of file diff --git a/src/views/app/business/logistics/logistics.vue b/src/views/app/business/logistics/logistics.vue index e985aef..c560fce 100644 --- a/src/views/app/business/logistics/logistics.vue +++ b/src/views/app/business/logistics/logistics.vue @@ -32,6 +32,17 @@ font-size: 13px; } + .worker-info-fee { + margin-top: 2px; + color: #515a6e; + font-size: 13px; + } + + .worker-info-fee-extra { + color: #999; + font-size: 12px; + } + .must-finish-time { display: inline-block; min-width: 168px; @@ -433,7 +444,7 @@ }, { title: "配送员", key: "workerName", - width: 150, + width: 170, align: "center", render: (h, params) => this.renderWorkerInfo(h, params.row, clickableWorker) },{ @@ -463,13 +474,6 @@ key: "receiverAddress", minWidth: 240, render: (h, params) => this.renderAddressBlock(h, params.row, "receiver") - }, { - title: "配送佣金", - key: "deliveryFee", - width: 150, - align: "center", - sortable: "custom", - render: (h, params) => this.renderFee(h, params.row) }, { title: "操作", key: "action", @@ -965,7 +969,8 @@ renderWorkerInfo(h, row, clickable = true) { const children = [ h("div", { class: "worker-info-name" }, row.workerName || "未分配"), - row.workerPhone ? h("div", { class: "worker-info-phone" }, row.workerPhone) : null + row.workerPhone ? h("div", { class: "worker-info-phone" }, row.workerPhone) : null, + this.renderWorkerFee(h, row) ]; if (!clickable || !row.workerId) return h("div", children); return h("div", { @@ -975,6 +980,14 @@ } }, children); }, + renderWorkerFee(h, row) { + const deliveryFee = this.toNumber(row.deliveryFee); + const marketplaceFee = this.toNumber(row.deliveryFeeMarketplace); + return h("div", [ + h("div", { class: "worker-info-fee" }, "佣金:¥" + (deliveryFee + marketplaceFee).toFixed(2)), + marketplaceFee > 0 ? h("div", { class: "worker-info-fee-extra" }, "含平台¥" + marketplaceFee.toFixed(2)) : null + ]); + }, getDeliveryTypeText(type, row) { if (row && row.workerId && this.tabName === "hall") return "指派单"; if (type == 1) return "外卖"; diff --git a/src/views/app/business/logistics/logisticsAddress.vue b/src/views/app/business/logistics/logisticsAddress.vue index beb2494..40f4b40 100644 --- a/src/views/app/business/logistics/logisticsAddress.vue +++ b/src/views/app/business/logistics/logisticsAddress.vue @@ -1,6 +1,6 @@