wangfukang 1 week ago
parent
commit
c69f26f44d
  1. 19
      src/api/fishMarket.js
  2. 5
      src/api/index.js
  3. 22
      src/views/app/bill/current/current.vue
  4. 13
      src/views/app/bill/historical/historical.vue
  5. 157
      src/views/app/business/bus/addEdit.vue
  6. 18
      src/views/app/business/courier/courier.vue
  7. 87
      src/views/app/business/courier/logisticsAddress.vue
  8. 814
      src/views/app/business/expressCompany/expressCompany.vue
  9. 31
      src/views/app/business/logistics/logistics.vue
  10. 70
      src/views/app/business/logistics/logisticsAddress.vue
  11. 44
      src/views/app/business/logiticsCompany/addEdit.vue
  12. 5
      src/views/app/business/logiticsCompany/logiticsCompany.vue
  13. 42
      src/views/app/business/luckey/luckey.vue
  14. 3
      src/views/app/business/recharge/logisticsAddress.vue
  15. 18
      src/views/app/business/recharge/recharge.vue
  16. 32
      src/views/app/shop/addEdit.vue
  17. 160
      src/views/app/shop/dictManage.vue
  18. 87
      src/views/app/shop/logisticsAddress.vue
  19. 26
      src/views/app/shop/shop.vue

19
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);

5
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)

22
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
}
});
},

13
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;

157
src/views/app/business/bus/addEdit.vue

@ -36,14 +36,14 @@
<Row v-if="!isEdit" :gutter="32">
<Col span="24">
<FormItem label="使用门槛" prop="type">
<RadioGroup v-model="form.type" :disabled="isEdit">
<RadioGroup v-model="form.type" :disabled="isEdit" @on-change="handleTypeChange">
<Radio label="2">无门槛</Radio>
<Radio label="1"><Input v-model='form.minAmount' style="width: 70px;" :disabled="isEdit"></Input >使</Radio>
<Radio label="1"><Input v-model='form.minAmount' style="width: 70px;" :disabled="isEdit" @on-change="validateThreshold"></Input >使</Radio>
</RadioGroup>
</FormItem>
</Col>
</Row>
<Row v-if="!isEdit" :gutter="32">
<!-- <Row v-if="!isEdit" :gutter="32">
<Col span="24">
<FormItem label="规则类型">
<RadioGroup v-model="form.ruleType" :disabled="isEdit">
@ -52,7 +52,7 @@
</RadioGroup>
</FormItem>
</Col>
</Row>
</Row> -->
<Row v-if="!isEdit" :gutter="32">
<Col span="24">
<FormItem label="优惠金额" prop="discountAmount">
@ -71,10 +71,10 @@
<Row v-if="!isEdit" :gutter="32">
<Col span="24">
<FormItem label="有效期" prop="validType">
<RadioGroup v-model="form.validType" vertical :disabled="isEdit">
<RadioGroup v-model="form.validType" vertical :disabled="isEdit" @on-change="handleValidTypeChange">
<Radio label="1">固定日期</Radio>
<DatePicker @on-change="changeDate" v-if="form.validType == '1'" type="datetimerange" format="yyyy-MM-dd HH:mm:ss" split-panels placeholder="选择起止时间" style="width: 320px" :options="datePickerOptions" :disabled="isEdit"></DatePicker>
<Radio label="2">领券后<Input v-model='form.validDays' style="width: 70px;" :disabled="isEdit"></Input ></Radio>
<Radio label="2">领券后<Input v-if="form.validType == '2'" v-model='form.validDays' style="width: 70px;" :disabled="isEdit" @on-change="validateValidity"></Input >天有效</Radio>
</RadioGroup>
</FormItem>
@ -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;
},
},

18
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: "确认恢复",

87
src/views/app/business/courier/logisticsAddress.vue

@ -9,6 +9,12 @@
size="small" show-total show-elevator show-sizer></Page>
</Row>
</Card>
<Modal title="查看回复" v-model="replyVisible" :mask-closable="false" :width="900">
<Table border :columns="replyColumns" :data="replyList" :size="tableSize"></Table>
<div slot="footer">
<Button type="text" @click="replyVisible = false">关闭</Button>
</div>
</Modal>
</div>
</template>
@ -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

814
src/views/app/business/expressCompany/expressCompany.vue

@ -3,479 +3,351 @@
@import "./expressCompany.less";
</style>
<template>
<div class="search">
<Card>
<Row v-show="openSearch" @keydown.enter.native="handleSearch">
<Form ref="searchForm" :model="searchForm" inline :label-width="100">
<FormItem label="名称" prop="companyName">
<Input type="text" v-model="searchForm.name" clearable placeholder="请输入快递公司名称"
style="width: 200px" />
</FormItem>
<FormItem style="margin-left: -35px" class="br">
<Button @click="handleSearch" type="primary" icon="ios-search">搜索</Button>
<Button @click="handleReset">重置</Button>
<a class="drop-down" @click="dropDown">
{{ dropDownContent }}
<Icon :type="dropDownIcon"></Icon>
</a>
</FormItem>
</Form>
</Row>
<Row align="middle" justify="space-between" class="operation">
<div>
<Button @click="add" type="primary" icon="md-add">添加</Button>
<Button @click="delAll" icon="md-trash">批量删除</Button>
<Dropdown @on-click="handleDropdown">
<Button>
更多操作
<Icon type="md-arrow-dropdown" />
</Button>
<DropdownMenu slot="list">
<DropdownItem name="refresh">刷新</DropdownItem>
<DropdownItem name="exportData">导出所选数据</DropdownItem>
<DropdownItem name="exportAll">导出全部数据</DropdownItem>
</DropdownMenu>
</Dropdown>
</div>
<div class="icons">
<Tooltip content="刷新" placement="top" transfer>
<Icon type="md-refresh" size="18" class="item" @click="getDataList" />
</Tooltip>
<Tooltip :content="openSearch ? '关闭搜索' : '开启搜索'" placement="top" transfer>
<Icon type="ios-search" size="18" class="item tip" @click="openSearch = !openSearch" />
</Tooltip>
<Tooltip :content="openTip ? '关闭提示' : '开启提示'" placement="top" transfer>
<Icon type="md-bulb" size="18" class="item tip" @click="openTip = !openTip" />
</Tooltip>
<Tooltip content="表格密度" placement="top" transfer>
<Dropdown @on-click="changeTableSize" trigger="click">
<Icon type="md-list" size="18" class="item" />
<DropdownMenu slot="list">
<DropdownItem :selected="tableSize == 'default'" name="default">默认</DropdownItem>
<DropdownItem :selected="tableSize == 'large'" name="large">宽松</DropdownItem>
<DropdownItem :selected="tableSize == 'small'" name="small">紧密</DropdownItem>
</DropdownMenu>
</Dropdown>
</Tooltip>
</div>
</Row>
<Alert show-icon v-show="openTip">
已选择
<span class="select-count">{{ selectList.length }}</span>
<a class="select-clear" @click="clearSelectAll">清空</a>
</Alert>
<Table :loading="loading" border :columns="columns" :data="data" :size="tableSize" sortable="custom"
@on-sort-change="changeSort" @on-selection-change="showSelect" ref="table"></Table>
<Row type="flex" justify="end" class="page">
<Page :current="searchForm.pageNumber" :total="total" :page-size="searchForm.pageSize"
@on-change="changePage" @on-page-size-change="changePageSize" :page-size-opts="[10, 20, 50]"
size="small" show-total show-elevator show-sizer></Page>
</Row>
</Card>
<div class="search">
<Card>
<Tabs v-model="activeTab" @on-click="handleTabChange">
<TabPane label="商品管理" name="goods">
<Row @keydown.enter.native="loadGoods">
<Form :model="goodsQuery" inline :label-width="80">
<FormItem label="关键词">
<Input v-model="goodsQuery.keyword" clearable placeholder="标题/发布人" style="width: 180px" />
</FormItem>
<FormItem label="学校">
<Input v-model="goodsQuery.regionId" clearable placeholder="校区ID" style="width: 160px" />
</FormItem>
<FormItem label="审核">
<Select v-model="goodsQuery.auditStatus" clearable style="width: 120px">
<Option :value="0">待审核</Option>
<Option :value="1">通过</Option>
<Option :value="2">拒绝</Option>
</Select>
</FormItem>
<FormItem label="上下架">
<Select v-model="goodsQuery.status" clearable style="width: 120px">
<Option :value="1">正常</Option>
<Option :value="2">下架</Option>
<Option :value="3">删除</Option>
</Select>
</FormItem>
<FormItem>
<Button type="primary" icon="ios-search" @click="loadGoods">搜索</Button>
<Button @click="resetGoods">重置</Button>
</FormItem>
</Form>
</Row>
<Table border :loading="loading" :columns="goodsColumns" :data="goodsList"></Table>
<Row type="flex" justify="end" class="page">
<Page :current="goodsQuery.pageNum" :total="goodsTotal" :page-size="goodsQuery.pageSize"
@on-change="p => changePage('goods', p)" @on-page-size-change="s => changePageSize('goods', s)"
:page-size-opts="[10,20,50]" size="small" show-total show-elevator show-sizer />
</Row>
</TabPane>
<!-- 自定义导出数据 -->
<Modal v-model="exportModalVisible" :title="exportTitle" :loading="loadingExport" @on-ok="exportCustomData">
<Form ref="exportForm" :label-width="100">
<FormItem label="导出文件名">
<Input v-model="filename" />
</FormItem>
<FormItem label="自定义导出列">
<CheckboxGroup v-model="chooseColumns">
<Checkbox v-for="(item, i) in exportColumns" :label="item.title" :key="i" :value="item.checked"
:disabled="item.disabled"></Checkbox>
</CheckboxGroup>
</FormItem>
</Form>
</Modal>
<Modal :title="充值记录明细" v-model="rechargeVisiable" :mask-closable="false" :scrollabele="true" :width="1000">
<recharge-one v-if="rechargeVisiable" ref="rechargelog"></recharge-one>
<div slot="footer" v-show=rechargeVisiable>
<Button type="text" @click="rechargeVisiable = false">关闭</Button>
</div>
</Modal>
</div>
<TabPane label="分类管理" name="category">
<Row class="operation">
<Button type="primary" icon="md-add" @click="openCategory()">新增分类</Button>
<Button icon="md-refresh" @click="loadCategories">刷新</Button>
</Row>
<Table border :loading="loading" :columns="categoryColumns" :data="categoryList"></Table>
</TabPane>
<TabPane label="用户管理" name="user">
<Row @keydown.enter.native="loadUserLimits">
<Form :model="userQuery" inline :label-width="80">
<FormItem label="用户ID">
<Input v-model="userQuery.userId" clearable placeholder="用户ID" style="width: 220px" />
</FormItem>
<FormItem>
<Button type="primary" icon="ios-search" @click="loadUserLimits">搜索</Button>
<Button type="warning" @click="openUserLimit()">新增风控</Button>
</FormItem>
</Form>
</Row>
<Table border :loading="loading" :columns="userColumns" :data="userLimitList"></Table>
<Row type="flex" justify="end" class="page">
<Page :current="userQuery.pageNum" :total="userTotal" :page-size="userQuery.pageSize"
@on-change="p => changePage('user', p)" @on-page-size-change="s => changePageSize('user', s)"
:page-size-opts="[10,20,50]" size="small" show-total show-elevator show-sizer />
</Row>
</TabPane>
<TabPane label="举报管理" name="complaint">
<Row @keydown.enter.native="loadComplaints">
<Form :model="complaintQuery" inline :label-width="80">
<FormItem label="状态">
<Select v-model="complaintQuery.status" clearable style="width: 130px">
<Option :value="0">待处理</Option>
<Option :value="1">通过</Option>
<Option :value="2">驳回</Option>
</Select>
</FormItem>
<FormItem label="类型">
<Select v-model="complaintQuery.type" clearable style="width: 130px">
<Option value="goods">商品</Option>
<Option value="comment">评论</Option>
<Option value="chat">聊天</Option>
</Select>
</FormItem>
<FormItem>
<Button type="primary" icon="ios-search" @click="loadComplaints">搜索</Button>
</FormItem>
</Form>
</Row>
<Table border :loading="loading" :columns="complaintColumns" :data="complaintList"></Table>
<Row type="flex" justify="end" class="page">
<Page :current="complaintQuery.pageNum" :total="complaintTotal" :page-size="complaintQuery.pageSize"
@on-change="p => changePage('complaint', p)" @on-page-size-change="s => changePageSize('complaint', s)"
:page-size-opts="[10,20,50]" size="small" show-total show-elevator show-sizer />
</Row>
</TabPane>
</Tabs>
</Card>
<Modal v-model="categoryModal" title="分类信息" @on-ok="saveCategory">
<Form :model="categoryForm" :label-width="90">
<FormItem label="名称"><Input v-model="categoryForm.name" /></FormItem>
<FormItem label="排序"><InputNumber v-model="categoryForm.sortOrder" :min="0" /></FormItem>
<FormItem label="图标"><Input v-model="categoryForm.icon" /></FormItem>
<FormItem label="颜色"><Input v-model="categoryForm.color" /></FormItem>
<FormItem label="状态">
<i-switch v-model="categoryForm.statusBool" size="large">
<span slot="open">启用</span>
<span slot="close">禁用</span>
</i-switch>
</FormItem>
</Form>
</Modal>
<Modal v-model="userLimitModal" title="用户风控" @on-ok="saveUserLimit">
<Form :model="userLimitForm" :label-width="100">
<FormItem label="用户ID"><Input v-model="userLimitForm.userId" /></FormItem>
<FormItem label="二手禁言"><i-switch v-model="userLimitForm.mutedBool" /></FormItem>
<FormItem label="禁止发布"><i-switch v-model="userLimitForm.publishBannedBool" /></FormItem>
<FormItem label="永久封禁"><i-switch v-model="userLimitForm.permanentBannedBool" /></FormItem>
<FormItem label="封禁原因"><Input v-model="userLimitForm.reason" type="textarea" /></FormItem>
</Form>
</Modal>
</div>
</template>
<script>
import {
getAllLogiticsCompanyData,
deleteLogiticsCompany,
onLineCompany,
offLineCompany
} from "@/api/app";
import {
shortcuts
} from "@/libs/shortcuts";
//
import {
exportColumn
} from "./exportColumn";
import excel from "@/libs/excel";
//
import rechargeOne from "@/views/app/business/recharge/rechargeOne.vue";
export default {
name: "logiticsCompany",
components: {
rechargeOne
},
data() {
return {
tableSize: "default",
message: "",
selectIndex: "",
currentRow: {},
height: 510,
showCompany: false,
showType: "0",
openSearch: true,
openTip: true,
loading: true,
reading: false,
loadingExport: true,
exportModalVisible: false,
importModalVisible: false,
deployModalVisible: false,
uploadfile: {
name: "",
},
drop: false,
selectList: [],
searchForm: {
name:'',
schoolId:'1',
orderByField:'',
remark:''
},
selectDate: null,
options: {
shortcuts: shortcuts,
},
form: {},
columns: [{
type: "selection",
width: 60,
align: "center",
fixed: "left",
},
{
type: "index",
width: 60,
align: "center",
fixed: "left",
},
{
title: "名称",
key: "name",
minWidth: 250
},
{
title: "排序",
key: "orderByField",
minWidth: 160
},
{
title: "学校id",
key: "schoolId",
minWidth: 150,
sortable: true,
},
{
title: "备注",
key: "remark",
minWidth: 250,
},
{
title: "操作",
key: "action",
width: 200,
align: "center",
fixed: "right",
render: (h, params) => {
let onOrOffLine = "";
return h("div", [
onOrOffLine,
h(
"a", {
on: {
click: () => {
this.edit(params.row);
},
},
},
"编辑"
),
h("Divider", {
props: {
type: "vertical",
},
}),
h(
"a", {
on: {
click: () => {
this.remove(params.row);
},
},
},
"删除"
)
]);
},
},
],
exportColumns: exportColumn,
chooseColumns: [],
filename: "公司数据",
exportTitle: "确认导出",
exportType: "",
data: [],
exportData: [],
total: 0,
rechargeVisiable: false,
};
},
methods: {
init() {
this.getDataList();
//
let array = [];
this.exportColumns.forEach((e) => {
//
if (
!this.getStore("roles").includes("ROLE_ADMIN") &&
e.key == "mobile"
) {
e.title = "[无权导出] " + e.title;
e.disabled = true;
} else {
e.disabled = false;
}
array.push(e.title);
});
this.chooseColumns = array;
},
changePage(v) {
this.getDataList();
this.clearSelectAll();
},
changeTableSize(v) {
this.tableSize = v;
},
changePageSize(v) {
this.getDataList();
},
getDataList() {
//
this.loading = true;
},
handleSearch() {
this.getDataList();
},
handleReset() {
this.$refs.searchForm.resetFields();
this.selectDate = null;
//
this.getDataList();
},
changeSort(e) {
this.getDataList();
},
handleDropdown(name) {
if (name == "refresh") {
this.getDataList();
} else if (name == "exportData") {
if (this.selectList.length <= 0) {
this.$Message.warning("您还未选择要导出的数据");
return;
}
this.exportType = "part";
this.exportModalVisible = true;
this.exportTitle = "确认导出 " + this.selectList.length + " 条数据";
} else if (name == "exportAll") {
this.exportType = "all";
this.exportModalVisible = true;
this.exportTitle = "确认导出全部 " + this.total + " 条数据";
getAllLogiticsCompanyData().then((res) => {
if (res.success) {
this.exportData = res.result;
}
});
}
},
exportCustomData() {
if (this.filename == "") {
this.filename = "公司数据";
}
//
let array = [];
this.exportColumns.forEach((e) => {
this.chooseColumns.forEach((c) => {
if (e.title == c && !e.disabled) {
array.push(e);
}
});
});
this.exportColumns = array;
this.exportModalVisible = false;
let title = [];
let key = [];
this.exportColumns.forEach((e) => {
title.push(e.title);
key.push(e.key);
});
const params = {
title: title,
key: key,
data: this.exportData,
autoWidth: true,
filename: this.filename,
};
excel.export_array_to_excel(params);
},
showDetail(v) {
// null""
for (let attr in v) {
if (v[attr] == null) {
v[attr] = "";
}
}
let str = JSON.stringify(v);
let data = JSON.parse(str);
this.form = data;
this.showType = "0";
this.showCompany = true;
},
add() {
this.showType = "2";
this.showCompany = true;
},
edit(v) {
// null""
for (let attr in v) {
if (v[attr] == null) {
v[attr] = "";
}
}
let str = JSON.stringify(v);
let data = JSON.parse(str);
this.form = data;
this.showType = "1";
this.showCompany = true;
},
remove(v) {
this.$Modal.confirm({
title: "确认删除",
content: "您确认要删除楼栋配置 " + v.name + " ?",
loading: true,
onOk: () => {
deleteLogiticsCompany({
id: v.id,
delFlag:0
}).then((res) => {
this.$Modal.remove();
if (res.success) {
this.clearSelectAll();
this.$Message.success("删除成功");
this.getDataList();
}
});
},
});
},
dropDown() {
this.drop = !this.drop;
},
showSelect(e) {
this.exportData = e;
this.selectList = e;
if (e.length === 1) {
const row = e[0];
this.selectIndex = row.id;
this.currentRow = row;
} else {
this.currentRow = {};
this.selectIndex = "";
}
},
clearSelectAll() {
this.$refs.table.selectAll(false);
},
delAll() {
if (this.selectList.length <= 0) {
this.$Message.warning("您还未选择要删除的数据");
return;
}
this.$Modal.confirm({
title: "确认删除",
content: "您确认要删除所选的 " + this.selectList.length + " 条数据?",
loading: true,
onOk: () => {
let ids = "";
this.selectList.forEach(function(e) {
ids += e.id + ",";
});
ids = ids.substring(0, ids.length - 1);
deletelogiticsCompany({
ids: ids
}).then((res) => {
this.$Modal.remove();
if (res.success) {
this.$Message.success("删除成功");
this.clearSelectAll();
this.getDataList();
}
});
},
});
},
findRechargeLog(v) {
this.rechargeVisiable = true;
this.$nextTick(() => {
this.$refs.rechargelog.initRecharge(v);
});
},
offLine(v) {
this.$Modal.confirm({
title: "确认下线",
content: "您确认要使 " + v.companyName + " 下线吗?",
loading: true,
onOk: () => {
offLineCompany({
id: v.id
}).then((res) => {
this.$Modal.remove();
if (res.success) {
this.$Message.success("操作成功");
this.getDataList();
}
});
},
});
},
onLine(v) {
this.$Modal.confirm({
title: "确认上线",
content: "您确认要使 " + v.companyName + " 上线吗?",
loading: true,
onOk: () => {
onLineCompany({
id: v.id
}).then((res) => {
this.$Modal.remove();
if (res.success) {
this.$Message.success("操作成功");
this.getDataList();
}
});
},
});
}
},
mounted() {
//
this.height = Number(document.documentElement.clientHeight - 230);
this.init();
},
};
import {
fishGoodsPage,
fishGoodsStatus,
fishCategoryList,
fishCategorySave,
fishCategoryDelete,
fishComplaintPage,
fishComplaintHandle,
fishUserLimitPage,
fishUserLimitSave,
} from "@/api/fishMarket";
export default {
name: "fishMarketAdmin",
data() {
return {
activeTab: "goods",
loading: false,
goodsList: [],
goodsTotal: 0,
categoryList: [],
userLimitList: [],
userTotal: 0,
complaintList: [],
complaintTotal: 0,
categoryModal: false,
userLimitModal: false,
categoryForm: {},
userLimitForm: {},
goodsQuery: { pageNum: 1, pageSize: 10 },
userQuery: { pageNum: 1, pageSize: 10 },
complaintQuery: { pageNum: 1, pageSize: 10, status: 0 },
goodsColumns: [
{ title: "标题", key: "title", minWidth: 180 },
{ title: "学校", key: "regionName", width: 130 },
{ title: "发布人", key: "userName", width: 120 },
{ title: "分类", key: "categoryName", width: 100 },
{ title: "价格", key: "price", width: 90 },
{ title: "审核", key: "auditStatus", width: 90, render: (h, p) => h("Tag", { props: { color: this.auditColor(p.row.auditStatus) } }, this.auditText(p.row.auditStatus)) },
{ title: "状态", key: "status", width: 90, render: (h, p) => h("Tag", { props: { color: p.row.status == 1 ? "green" : "red" } }, p.row.status == 1 ? "正常" : "下架") },
{ title: "举报", key: "complaintCount", width: 80 },
{ title: "浏览", key: "browseCount", width: 80 },
{ title: "发布时间", key: "createTime", minWidth: 150 },
{ title: "操作", width: 250, fixed: "right", render: (h, p) => h("div", [
h("Button", { props: { type: "success", size: "small" }, style: { marginRight: "6px" }, on: { click: () => this.handleGoods(p.row, 1, "审核通过") } }, "通过"),
h("Button", { props: { type: "warning", size: "small" }, style: { marginRight: "6px" }, on: { click: () => this.handleGoods(p.row, 2, "强制下架") } }, "下架"),
h("Button", { props: { type: "primary", size: "small" }, style: { marginRight: "6px" }, on: { click: () => this.handleGoods(p.row, 1, "恢复上架") } }, "恢复"),
h("Button", { props: { type: "error", size: "small" }, on: { click: () => this.handleGoods(p.row, 3, "删除") } }, "删除")
]) }
],
categoryColumns: [
{ title: "名称", key: "name" },
{ title: "排序", key: "sortOrder", width: 100 },
{ title: "图标", key: "icon", minWidth: 180 },
{ title: "颜色", key: "color", width: 100 },
{ title: "状态", key: "status", width: 90, render: (h, p) => h("Tag", { props: { color: p.row.status == 1 ? "green" : "default" } }, p.row.status == 1 ? "启用" : "禁用") },
{ title: "操作", width: 160, render: (h, p) => h("div", [
h("Button", { props: { type: "primary", size: "small" }, style: { marginRight: "8px" }, on: { click: () => this.openCategory(p.row) } }, "编辑"),
h("Button", { props: { type: "error", size: "small" }, on: { click: () => this.deleteCategory(p.row) } }, "删除")
]) }
],
userColumns: [
{ title: "用户ID", key: "userId", minWidth: 180 },
{ title: "禁言", key: "muted", width: 90, render: (h, p) => h("Tag", { props: { color: p.row.muted == 1 ? "red" : "green" } }, p.row.muted == 1 ? "是" : "否") },
{ title: "禁止发布", key: "publishBanned", width: 110 },
{ title: "永久封禁", key: "permanentBanned", width: 110 },
{ title: "原因", key: "banReason", minWidth: 200 },
{ title: "更新时间", key: "updateTime", minWidth: 150 },
{ title: "操作", width: 100, render: (h, p) => h("Button", { props: { type: "primary", size: "small" }, on: { click: () => this.openUserLimit(p.row) } }, "编辑") }
],
complaintColumns: [
{ title: "类型", key: "complaintType", width: 100 },
{ title: "商品ID", key: "goodsId", minWidth: 170 },
{ title: "举报人", key: "reporterName", width: 120 },
{ title: "卖家ID", key: "sellerId", minWidth: 170 },
{ title: "原因", key: "reason", minWidth: 220 },
{ title: "状态", key: "status", width: 90, render: (h, p) => h("Tag", { props: { color: p.row.status == 0 ? "orange" : (p.row.status == 1 ? "green" : "default") } }, this.complaintStatusText(p.row.status)) },
{ title: "时间", key: "createTime", minWidth: 150 },
{ title: "操作", width: 230, fixed: "right", render: (h, p) => h("div", [
h("Button", { props: { type: "success", size: "small" }, style: { marginRight: "6px" }, on: { click: () => this.handleComplaint(p.row, 1) } }, "通过"),
h("Button", { props: { size: "small" }, style: { marginRight: "6px" }, on: { click: () => this.handleComplaint(p.row, 2) } }, "驳回"),
h("Button", { props: { type: "error", size: "small" }, on: { click: () => this.handleComplaint(p.row, 1, true) } }, "下架封号")
]) }
]
};
},
mounted() {
this.loadGoods();
},
methods: {
handleTabChange() {
if (this.activeTab == "goods") this.loadGoods();
if (this.activeTab == "category") this.loadCategories();
if (this.activeTab == "user") this.loadUserLimits();
if (this.activeTab == "complaint") this.loadComplaints();
},
loadGoods() {
this.loading = true;
fishGoodsPage(this.goodsQuery).then(res => {
this.goodsList = this.records(res);
this.goodsTotal = this.total(res);
}).finally(() => this.loading = false);
},
resetGoods() {
this.goodsQuery = { pageNum: 1, pageSize: 10 };
this.loadGoods();
},
loadCategories() {
this.loading = true;
fishCategoryList({}).then(res => {
this.categoryList = res.result || res || [];
}).finally(() => this.loading = false);
},
loadUserLimits() {
this.loading = true;
fishUserLimitPage(this.userQuery).then(res => {
this.userLimitList = this.records(res);
this.userTotal = this.total(res);
}).finally(() => this.loading = false);
},
loadComplaints() {
this.loading = true;
fishComplaintPage(this.complaintQuery).then(res => {
this.complaintList = this.records(res);
this.complaintTotal = this.total(res);
}).finally(() => this.loading = false);
},
changePage(type, page) {
this[`${type}Query`].pageNum = page;
this.handleTabChange();
},
changePageSize(type, size) {
this[`${type}Query`].pageSize = size;
this[`${type}Query`].pageNum = 1;
this.handleTabChange();
},
records(res) {
const data = res.result || res || {};
return data.records || data.content || [];
},
total(res) {
const data = res.result || res || {};
return Number(data.total || data.totalElements) || 0;
},
auditText(status) {
return status == 1 ? "通过" : (status == 2 ? "拒绝" : "待审");
},
auditColor(status) {
return status == 1 ? "green" : (status == 2 ? "red" : "orange");
},
complaintStatusText(status) {
return status == 1 ? "通过" : (status == 2 ? "驳回" : "待处理");
},
handleGoods(row, status, title) {
this.$Modal.confirm({
title,
render: (h) => h("Input", { props: { autofocus: true, placeholder: "请输入原因" }, on: { input: val => this.actionReason = val } }),
onOk: () => {
fishGoodsStatus({ goodsId: row.id, status, auditStatus: status == 1 ? 1 : row.auditStatus, reason: this.actionReason || title }).then(() => {
this.$Message.success("处理成功");
this.loadGoods();
});
}
});
},
openCategory(row = {}) {
this.categoryForm = { ...row, statusBool: row.status !== 0 };
this.categoryModal = true;
},
saveCategory() {
const data = { ...this.categoryForm, status: this.categoryForm.statusBool ? 1 : 0 };
fishCategorySave(data).then(() => {
this.$Message.success("保存成功");
this.loadCategories();
});
},
deleteCategory(row) {
this.$Modal.confirm({
title: "删除分类",
content: "确认删除该分类吗?",
onOk: () => fishCategoryDelete(row.id).then(() => this.loadCategories())
});
},
openUserLimit(row = {}) {
this.userLimitForm = {
...row,
reason: row.banReason || "",
mutedBool: row.muted == 1,
publishBannedBool: row.publishBanned == 1,
permanentBannedBool: row.permanentBanned == 1
};
this.userLimitModal = true;
},
saveUserLimit() {
const data = {
...this.userLimitForm,
muted: this.userLimitForm.mutedBool ? 1 : 0,
publishBanned: this.userLimitForm.publishBannedBool ? 1 : 0,
permanentBanned: this.userLimitForm.permanentBannedBool ? 1 : 0
};
fishUserLimitSave(data).then(() => {
this.$Message.success("保存成功");
this.loadUserLimits();
});
},
handleComplaint(row, status, blockUser) {
fishComplaintHandle({
complaintId: row.id,
status,
blockUser: !!blockUser,
reason: blockUser ? "举报成立,执行风控" : "",
handleResult: status == 1 ? "举报通过" : "举报驳回"
}).then(() => {
this.$Message.success("处理成功");
this.loadComplaints();
});
}
}
};
</script>

31
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 "外卖";

70
src/views/app/business/logistics/logisticsAddress.vue

@ -1,6 +1,6 @@
<template>
<div class="search">
<div class='waiceng' style="margin-top: -5px;">
<div class='waiceng' style="margin-top: 12px;">
<div class="nei1">
<div style="flex:1;padding-left:10px;border-right:1px solid #eee;">订单号{{orderData.numberCode}}</div>
<div style="flex:1;padding-left:10px;">配送单生成时间{{orderData.deliveryInfo.createTime | formatDateTime}}
@ -129,9 +129,26 @@
<div style="flex:1;padding-left:10px;border-right:1px solid #eee;">订单总计时</div>
<div style="width: 33%;padding-left:10px;">{{getMinutesDiff(orderData.createTime,orderData.deliveryInfo.finishTime != null?orderData.deliveryInfo.finishTime:1)}}分钟</div>
</div>
<div class="nei1">
<div class="nei1" v-if="getTimeoutMinutes(orderData.deliveryInfo) >= 0">
<div style="flex:1;padding-left:10px;border-right:1px solid #eee;">超时</div>
<div style="width: 33%;padding-left:10px;">{{getMinutesDiff(orderData.deliveryInfo.mustFinishTime,orderData.deliveryInfo.finishTime != null?orderData.deliveryInfo.finishTime:1)}}分钟</div>
<div style="width: 33%;padding-left:10px;">{{getTimeoutMinutes(orderData.deliveryInfo)}}分钟</div>
</div>
</div>
<div class="title" v-if="reassignRecords.length">转单记录</div>
<div class='waiceng' style="text-align: center;" v-if="reassignRecords.length">
<div class="nei1">
<div style="flex:1;padding-left:10px;border-right:1px solid #eee;">转单前配送员</div>
<div style="flex:1;padding-left:10px;border-right:1px solid #eee;">转单后配送员</div>
<div style="flex:1;padding-left:10px;">转单时间</div>
</div>
<div class="nei1" v-for="item in reassignRecords" :key="item.id">
<div style="flex:1;padding-left:10px;border-right:1px solid #eee;">
{{formatWorkerInfo(item.oldWorkerName, item.oldWorkerPhone, item.oldWorkerId)}}
</div>
<div style="flex:1;padding-left:10px;border-right:1px solid #eee;">
{{formatWorkerInfo(item.newWorkerName, item.newWorkerPhone, item.newWorkerId)}}
</div>
<div style="flex:1;padding-left:10px;">{{item.reassignTime | formatDateTime}}</div>
</div>
</div>
</div>
@ -140,12 +157,14 @@
<script>
import {
getOrderDetail,
getDeliveryReassignRecords,
} from "@/api/index";
export default {
name: "logisticsAddress",
data() {
return {
orderData: {},
reassignRecords: [],
};
},
@ -183,14 +202,37 @@
return diffMinutes;
},
getTimeoutMinutes(deliveryInfo) {
if (!deliveryInfo || !deliveryInfo.mustFinishTime) return 0;
const mustFinishTime = new Date(deliveryInfo.mustFinishTime);
const endTime = deliveryInfo.finishTime ? new Date(deliveryInfo.finishTime) : new Date();
if (isNaN(mustFinishTime.getTime()) || isNaN(endTime.getTime())) return 0;
return Math.ceil((endTime - mustFinishTime) / (1000 * 60));
},
formatWorkerInfo(name, phone, workerId) {
if (!name && !phone && !workerId) return "无(抢单大厅指派)";
if (name && phone) return `${name}${phone}`;
return name || phone || workerId;
},
orderDetail(id) {
getOrderDetail(id).then((res) => {
this.loading = false;
if (res.success) {
this.orderData = res.result
const deliveryId = this.orderData.deliveryInfo && this.orderData.deliveryInfo.id;
this.getReassignRecords(deliveryId);
}
});
},
getReassignRecords(deliveryId) {
this.reassignRecords = [];
if (!deliveryId) return;
getDeliveryReassignRecords({ deliveryId }).then((res) => {
if (res.success) {
this.reassignRecords = res.result || [];
}
});
}
}
};
@ -199,14 +241,21 @@
//@import "@/styles/table-common.less";
.nei1 {
display: flex;
padding-top: 10rpx;
border: 1px solid #eee;
height: 30px;
line-height: 30px;
min-height: 30px;
line-height: 20px;
}
.nei1 > div {
padding-top: 5px;
padding-bottom: 5px;
box-sizing: border-box;
word-break: break-all;
}
.goods-table-row {
display: flex;
align-items: stretch;
min-height: 30px;
border: 1px solid #eee;
line-height: 20px;
@ -214,8 +263,11 @@
.goods-table-cell {
flex: 1;
min-width: 0;
padding: 5px 10px;
border-right: 1px solid #eee;
box-sizing: border-box;
white-space: normal;
word-break: break-all;
}
@ -229,13 +281,19 @@
.goods-summary-label {
flex: 1;
min-width: 0;
padding: 5px 10px;
border-right: 1px solid #eee;
box-sizing: border-box;
word-break: break-all;
}
.goods-summary-price {
width: 25%;
min-width: 0;
padding: 5px 10px;
box-sizing: border-box;
word-break: break-all;
}
.title {

44
src/views/app/business/logiticsCompany/addEdit.vue

@ -4,10 +4,10 @@
<div :style="{ maxHeight: maxHeight }" class="drawer-content">
<Form ref="form" :model="form" :rules="formValidate" label-position="top">
<FormItem label="分类名称" prop="categoryName">
<Input v-model="form.categoryName" placeholder="请输入分类名称" />
<Input v-model="form.categoryName" :maxlength="6" placeholder="请输入分类名称" />
</FormItem>
<FormItem label="排名">
<InputNumber v-model="form.sort" :min="0" style="width: 100%" />
<FormItem label="排名" prop="sort">
<InputNumber v-model="form.sort" :min="0" :max="100000" :precision="0" style="width: 100%" />
</FormItem>
<FormItem label="状态">
<RadioGroup v-model="form.status">
@ -15,9 +15,9 @@
<Radio :label="0">禁用</Radio>
</RadioGroup>
</FormItem>
<FormItem label="备注">
<!-- <FormItem label="备注">
<Input v-model="form.remark" type="textarea" :rows="4" placeholder="请输入备注" />
</FormItem>
</FormItem> -->
</Form>
</div>
<div class="drawer-footer br" v-show="type != '0'">
@ -48,6 +48,29 @@ export default {
},
},
data() {
const validateCategoryName = (rule, value, callback) => {
const name = String(value || "").trim();
if (!name) {
callback(new Error("请输入分类名称"));
return;
}
if (name.length > 6) {
callback(new Error("分类名称最多6个字"));
return;
}
callback();
};
const validateSort = (rule, value, callback) => {
if (value === "" || value === null || value === undefined) {
callback(new Error("请输入排名"));
return;
}
if (!Number.isInteger(Number(value)) || Number(value) < 0 || Number(value) > 100000) {
callback(new Error("排名必须是0-100000的整数"));
return;
}
callback();
};
return {
visible: this.value,
title: "",
@ -57,9 +80,14 @@ export default {
formValidate: {
categoryName: [
{
required: true,
message: "请输入分类名称",
trigger: "blur",
validator: validateCategoryName,
trigger: "change",
},
],
sort: [
{
validator: validateSort,
trigger: "change",
},
],
},

5
src/views/app/business/logiticsCompany/logiticsCompany.vue

@ -85,11 +85,6 @@ export default {
minWidth: 100,
render: (h, params) => h("span", params.row.status == 1 ? "启用" : "禁用"),
},
{
title: "备注",
key: "remark",
minWidth: 180,
},
{
title: "操作",
key: "action",

42
src/views/app/business/luckey/luckey.vue

@ -219,7 +219,7 @@
<!-- 奖项管理 -->
<Modal v-model="rewardModal" title="奖项配置" width="720" :mask-closable="false">
<Button type="primary" icon="md-add" @click="addRewardRow" style="margin-bottom:12px">新增奖项</Button>
<Button v-if="!currentPoolDrawn" type="primary" icon="md-add" @click="addRewardRow" style="margin-bottom:12px">新增奖项</Button>
<Table border :columns="rewardColumns" :data="rewardList"></Table>
<div slot="footer">
<Button @click="rewardModal=false">关闭</Button>
@ -436,6 +436,7 @@
rewardModal: false,
rewardList: [],
currentPoolId: '',
currentPoolStatus: '',
rewardEditModal: false,
rewardForm: {},
taskModal: false,
@ -456,6 +457,9 @@
const map = { tree: '券树周期', warehouse: '仓库等级', tower: '防御塔等级', search: '搜查规则', stamina: '体力道具', landmark: '校园地标', college: '学院配置' }
return (this.operateForm.id ? '编辑' : '新增') + (map[this.operateType] || '经营配置')
},
currentPoolDrawn() {
return Number(this.currentPoolStatus) === 1
},
operateFields() {
const fields = {
tree: [
@ -518,7 +522,6 @@
],
college: [
{ key: 'collegeName', label: '学院名称' },
{ key: 'shortName', label: '简称' },
{ key: 'sort', label: '排序', type: 'number' },
{ key: 'enabled', label: '是否启用', type: 'switch' }
]
@ -535,41 +538,43 @@
{ title: '参与', key: 'joinCount', width: 70 },
{ title: '中奖', key: 'winnerCount', width: 70 },
{
title: '状态', width: 90, render: (h, p) => h('Tag', {
title: '状态', width: 100, render: (h, p) => h('Tag', {
props: { color: p.row.status === 1 ? 'green' : 'blue' }
}, p.row.status === 1 ? '已开奖' : '进行中')
},
{
title: '操作', width: 280, align: 'center', render: (h, params) => {
return h('div', [
h('Button', { props: { type: 'text', size: 'small' }, on: { click: () => this.openPool(params.row) } }, '编辑'),
const actions = [
h('Button', { props: { type: 'text', size: 'small' }, on: { click: () => this.openReward(params.row) } }, '奖项'),
/* h('Button', {
props: { type: 'text', size: 'small', disabled: params.row.status === 1 },
on: { click: () => this.doManualDraw(params.row) }
}, '手动开奖'), */
h('Button', { props: { type: 'text', size: 'small' }, style: { color: '#ed4014' }, on: { click: () => this.delPool(params.row) } }, '删除')
])
]
if (!this.isPoolDrawn(params.row)) {
actions.unshift(h('Button', { props: { type: 'text', size: 'small' }, on: { click: () => this.openPool(params.row) } }, '编辑'))
actions.push(h('Button', { props: { type: 'text', size: 'small' }, style: { color: '#ed4014' }, on: { click: () => this.delPool(params.row) } }, '删除'))
}
return h('div', actions)
}
}
]
},
rewardColumns() {
return [
const columns = [
{ title: '层级', key: 'level', width: 70 },
{ title: '名称', key: 'levelName', minWidth: 100 },
{ title: '类型', width: 80, render: (h, p) => h('span', p.row.rewardType === 1 ? '优惠券' : '现金') },
{ title: '金额', key: 'amount', width: 90 },
{ title: '名额', key: 'quota', width: 70 },
{
{ title: '名额', key: 'quota', width: 70 }
]
if (!this.currentPoolDrawn) {
columns.push({
title: '操作', width: 130, align: 'center', render: (h, params) => {
return h('div', [
h('Button', { props: { type: 'text', size: 'small' }, on: { click: () => this.editReward(params.row) } }, '编辑'),
h('Button', { props: { type: 'text', size: 'small' }, style: { color: '#ed4014' }, on: { click: () => this.delReward(params.row) } }, '删除')
])
}
}
]
})
}
return columns
},
taskColumns() {
return [
@ -734,7 +739,6 @@
collegeColumns() {
return [
{ title: '学院名称', key: 'collegeName', minWidth: 150 },
{ title: '简称', key: 'shortName', minWidth: 100 },
{ title: '排序', key: 'sort', minWidth: 80 },
{ title: '启用', minWidth: 70, render: (h, p) => this.enabledTag(h, p.row.enabled) },
this.operateActionColumn('college')
@ -821,6 +825,9 @@
enabledTag(h, enabled) {
return h('Tag', { props: { color: enabled === 1 ? 'green' : 'default' } }, enabled === 1 ? '是' : '否')
},
isPoolDrawn(row) {
return Number(row && row.status) === 1
},
operateActionColumn(type) {
return {
title: '操作', width: 150, align: 'center', render: (h, params) => h('div', [
@ -970,6 +977,7 @@
// ---- ----
openReward(row) {
this.currentPoolId = row.id
this.currentPoolStatus = row.status
this.rewardModal = true
this.loadReward()
},

3
src/views/app/business/recharge/logisticsAddress.vue

@ -14,8 +14,6 @@
<div>团长订单ID<span class="blue-color">{{groupData.headOrderId || '-'}}</span></div>
<div>拼团价格<span class="money">{{formatAmount(groupData.groupPrice)}}</span></div>
<div>配送员ID<span class="blue-color">{{groupData.workerId || '-'}}</span></div>
<div>配送员佣金<span class="money">{{formatAmount(groupData.workerCommission)}}</span></div>
<div>总配送费<span class="money">{{formatAmount(groupData.totalDeliveryFee)}}</span></div>
<div>创建时间{{formatDateTime(groupData.createTime)}}</div>
<div>过期时间{{formatDateTime(groupData.expireTime)}}</div>
<div>成团时间{{formatDateTime(groupData.successTime)}}</div>
@ -35,6 +33,7 @@
<div>支付订单编号{{item.id ? 'ORDER_' + item.id : '-'}}</div>
<div>订单类型{{getOrderType(item.orderType)}}</div>
<div>配送方式<span class="blue-color">{{item.deliveryType == 1 ? '外卖配送' : '到店自取'}}</span></div>
<div v-if="item.deliveryType == 1">配送费:<span class="blue-color">{{item.deliveryFee}}</span></div>
<div>创建时间{{formatDateTime(item.createTime)}}</div>
<div>支付时间{{formatDateTime(item.payTime)}}</div>
<div>备注{{item.remark || '-'}}</div>

18
src/views/app/business/recharge/recharge.vue

@ -189,24 +189,6 @@
]);
},
},
{
title: "配送员佣金",
key: "workerCommission",
width: 110,
align: "center",
render: (h, params) => {
return h("span", this.formatAmount(params.row.workerCommission));
}
},
{
title: "总配送费",
key: "totalDeliveryFee",
width: 110,
align: "center",
render: (h, params) => {
return h("span", this.formatAmount(params.row.totalDeliveryFee));
}
},
{
title: "创建时间",
key: "createTime",

32
src/views/app/shop/addEdit.vue

@ -49,6 +49,21 @@
</FormItem>
</Col>
</Row>
<Row :gutter="32">
<Col span="12">
<FormItem label="明厨亮灶视频地址" prop="openKitchenVideoUrl">
<Input v-model="form.openKitchenVideoUrl" autocomplete="off" :maxlength="500" />
</FormItem>
</Col>
<Col span="12">
<FormItem label="堂食商家" prop="supportDineIn">
<RadioGroup v-model="form.supportDineIn">
<Radio :label="1">可堂食</Radio>
<Radio :label="0">无堂食</Radio>
</RadioGroup>
</FormItem>
</Col>
</Row>
<Row :gutter="32">
<Col span="24">
<FormItem label="店铺详细地址" prop="shopAddress">
@ -58,8 +73,8 @@
</Row>
<Row :gutter="32">
<Col span="12">
<FormItem label="联系人" prop="nickname">
<Input v-model="form.nickname" autocomplete="off" :maxlength="16" />
<FormItem label="联系人" prop="shopLename">
<Input v-model="form.shopLename" autocomplete="off" :maxlength="16" />
</FormItem>
</Col>
<Col span="12">
@ -290,6 +305,8 @@
address: [],
merchantType: 1,
isStudent: 0,
openKitchenVideoUrl: "",
supportDineIn: 0,
qita: [],
supportShopDelivery: 0,
orderBkge: 0,
@ -307,7 +324,7 @@
trigger: "blur"
},
],
nickname: [{
shopLename: [{
required: true,
message: "请输入用户名",
trigger: "blur"
@ -540,8 +557,13 @@
if (this.form.isStudent == null || this.form.isStudent === "") {
this.$set(this.form, "isStudent", 0);
}
if (this.form.supportDineIn == null || this.form.supportDineIn === "") {
this.$set(this.form, "supportDineIn", 0);
}
this.form.merchantType = Number(this.form.merchantType);
this.form.isStudent = Number(this.form.isStudent);
this.form.supportDineIn = Number(this.form.supportDineIn);
this.form.openKitchenVideoUrl = this.form.openKitchenVideoUrl || "";
if (!this.form.contactPhone && this.form.mobile) {
this.form.contactPhone = this.form.mobile;
}
@ -690,6 +712,8 @@
this.form = Object.assign({}, registerData, {
merchantType: registerData.merchantType == null ? 1 : Number(registerData.merchantType),
isStudent: registerData.isStudent == null ? 0 : Number(registerData.isStudent),
openKitchenVideoUrl: registerData.openKitchenVideoUrl || "",
supportDineIn: registerData.supportDineIn == null ? 0 : Number(registerData.supportDineIn),
contactPhone: registerData.contactPhone || registerData.mobile || "",
mobile: registerData.mobile || registerData.contactPhone || "",
zhengzhao: registerData.zhengzhao || "",
@ -723,6 +747,8 @@
address: [],*/
merchantType: 1,
isStudent: 0,
openKitchenVideoUrl: "",
supportDineIn: 0,
qita: [],
supportShopDelivery: 0,
orderBkge: 0,

160
src/views/app/shop/dictManage.vue

@ -150,20 +150,20 @@
<editDictType ref="editTypePage" :data="dictForm" v-model="showEditDict" @on-submit="editDictSuccess" />
<Modal :title="modalTitle" v-model="modalVisible" :mask-closable="false" :width="screenWidth *0.9">
<Form ref="form" :model="form" :label-width="80" :rules="formValidate">
<Form ref="form" :model="addGoodsForm" :label-width="80" :rules="formValidate">
<Col span="6">
<FormItem label="商品图标" class="form-noheight">
<upload-pic-input v-model="addGoodsForm.productPicture"></upload-pic-input>
</FormItem>
</Col>
<Col span="6">
<FormItem label="名称" prop="title">
<Input v-model="addGoodsForm.productName" />
<FormItem label="名称" prop="productName">
<Input v-model="addGoodsForm.productName" :maxlength="20" show-word-limit placeholder="最多20字" />
</FormItem>
</Col>
<Col span="6">
<FormItem label="排名" class="form-noheight">
<Input v-model="addGoodsForm.orderFiled" type="number" placeholder="排名" />
<FormItem label="排名" prop="orderFiled">
<Input v-model="addGoodsForm.orderFiled" type="number" :min="0" :max="100000" placeholder="0-100000整数" />
</FormItem>
</Col>
<Col span="6">
@ -176,8 +176,8 @@
<div>
<div v-for="(item,index) in addGoodsForm.attributeListPrice" style="display: flex;margin-top:5px;">
<Input v-model="item.specName" v-if="item.specName != ''&& addGoodsForm.attributeListPrice.length != 1" style="padding-right: 10px;" disabled />
<Input v-model="item.specPrice" style="padding-right: 10px;" @click="changePrice(index)" placeholder="商品价格" />
<Input v-model="item.specNum" style="padding-right: 10px;" @click="changecount(index)" placeholder="商品库存"/>
<Input v-model="item.specPrice" type="number" :min="0.1" :max="9999" style="padding-right: 10px;" @click="changePrice(index)" @on-blur="validateSpecPrice(index)" placeholder="价格0.1-9999,最多2位小数" />
<Input v-model="item.specNum" style="padding-right: 10px;" @click="changeCount(index)" placeholder="商品库存"/>
<button @click="deldantiaoguige(index)" v-if="addGoodsForm.attributeListPrice.length>1" style="width: 120px;height: 30px;line-height: 30px;color: red;border:none;background: #fff;">删除</button>
</div>
<div @click="checkSpec('guige')" style="margin-top:5px;width: 80px;height: 30px;text-align: center;line-height: 30px;background: #008ba0;color:#fff;">
@ -190,8 +190,8 @@
<FormItem label="拼团信息" class="form-noheight">
<div>
<div v-for="(item,index) in addGoodsForm.productGroupBuyPrices" style="display: flex;margin-top:5px;">
<Input v-model="item.groupCount" style="padding-right: 10px;" placeholder="成团人数" />
<Input v-model="item.groupPrice" style="padding-right: 10px;" placeholder="成团价格"/>
<Input v-model="item.groupCount" type="number" :min="2" :max="10" style="padding-right: 10px;" @on-blur="validateGroupCount(index)" placeholder="人数2-10整数" />
<Input v-model="item.groupPrice" type="number" :min="0.1" :max="9999" style="padding-right: 10px;" @on-blur="validateGroupPrice(index)" placeholder="价格0.1-9999,最多2位小数"/>
<button @click="delGroup(index)" v-if="addGoodsForm.productGroupBuyPrices.length>1" style="width: 120px;height: 30px;line-height: 30px;color: red;border:none;background: #fff;">删除</button>
</div>
<div @click="addGroup()" style="margin-top:5px;width: 80px;height: 30px;text-align: center;line-height: 30px;background: #008ba0;color:#fff;">
@ -201,8 +201,8 @@
</FormItem>
</Col>
<Col span="6">
<FormItem label="餐盒费" class="form-noheight">
<Input v-model="addGoodsForm.lunchBox" />
<FormItem label="餐盒费" prop="lunchBox">
<Input v-model="addGoodsForm.lunchBox" type="number" :min="0" :max="10" placeholder="0-10,最多2位小数" />
</FormItem>
</Col>
<Col span="6">
@ -223,8 +223,8 @@
</FormItem>
</Col>
<Col span="6">
<FormItem label="起售数量" class="form-noheight">
<Input v-model="addGoodsForm.startPayNum" type="number" placeholder="每笔订单起购数量" />
<FormItem label="起售数量" prop="startPayNum">
<Input v-model="addGoodsForm.startPayNum" type="number" :min="1" :max="10" placeholder="1-10整数" />
</FormItem>
</Col>
<Col span="8">
@ -323,6 +323,28 @@
editor
},
data() {
const validateIntegerRange = (min, max, fieldName, allowEmpty) => {
return (rule, value, callback) => {
if ((value === "" || value === null || value === undefined) && allowEmpty) {
callback();
return;
}
if (!this.isIntegerInRange(value, min, max)) {
callback(new Error(`${fieldName}需为${min}-${max}的整数`));
return;
}
callback();
};
};
const validateDecimalRange = (min, max, fieldName) => {
return (rule, value, callback) => {
if (!this.isDecimalInRange(value, min, max)) {
callback(new Error(`${fieldName}需为${min}-${max},最多2位小数`));
return;
}
callback();
};
};
return {
Visiable: false,
specValueArr:[],
@ -381,7 +403,7 @@
productName:'', //
orderFiled:'', //
lunchBox:0, //
startPayNum:'', //
startPayNum:1, //
attributeListPrice:[{ //
specPrice:"",
specNum:9999
@ -399,7 +421,23 @@
//
productName: [{
required: true,
message: "请输入",
message: "请输入名称",
trigger: "blur"
}, {
max: 20,
message: "名称最多20字",
trigger: "blur"
}],
orderFiled: [{
validator: validateIntegerRange(0, 100000, "排名", true),
trigger: "blur"
}],
lunchBox: [{
validator: validateDecimalRange(0, 10, "餐盒费"),
trigger: "blur"
}],
startPayNum: [{
validator: validateIntegerRange(1, 10, "起售数量", false),
trigger: "blur"
}]
},
@ -613,6 +651,80 @@
};
},
methods: {
isIntegerInRange(value, min, max) {
if (value === "" || value === null || value === undefined) return false;
const text = String(value);
if (!/^\d+$/.test(text)) return false;
const num = Number(text);
return num >= min && num <= max;
},
isDecimalInRange(value, min, max) {
if (value === "" || value === null || value === undefined) return false;
const text = String(value);
if (!/^\d+(\.\d{1,2})?$/.test(text)) return false;
const num = Number(text);
return num >= min && num <= max;
},
validateGoodsForm() {
const productName = (this.addGoodsForm.productName || "").trim();
if (!productName) {
this.$Message.warning("请输入名称");
return false;
}
if (productName.length > 20) {
this.$Message.warning("名称最多20字");
return false;
}
if (this.addGoodsForm.orderFiled !== "" && this.addGoodsForm.orderFiled !== null && this.addGoodsForm.orderFiled !== undefined && !this.isIntegerInRange(this.addGoodsForm.orderFiled, 0, 100000)) {
this.$Message.warning("排名需为0-100000的整数");
return false;
}
if (!this.isDecimalInRange(this.addGoodsForm.lunchBox, 0, 10)) {
this.$Message.warning("餐盒费需为0-10,最多2位小数");
return false;
}
if (!this.isIntegerInRange(this.addGoodsForm.startPayNum, 1, 10)) {
this.$Message.warning("起售数量需为1-10的整数");
return false;
}
for (let i = 0; i < this.addGoodsForm.attributeListPrice.length; i++) {
if (!this.isDecimalInRange(this.addGoodsForm.attributeListPrice[i].specPrice, 0.1, 9999)) {
this.$Message.warning(`${i + 1}个商品规格价格需为0.1-9999,最多2位小数`);
return false;
}
}
for (let i = 0; i < this.addGoodsForm.productGroupBuyPrices.length; i++) {
const item = this.addGoodsForm.productGroupBuyPrices[i];
if (!this.isIntegerInRange(item.groupCount, 2, 10)) {
this.$Message.warning(`${i + 1}个拼团人数需为2-10的整数`);
return false;
}
if (!this.isDecimalInRange(item.groupPrice, 0.1, 9999)) {
this.$Message.warning(`${i + 1}个拼团价格需为0.1-9999,最多2位小数`);
return false;
}
}
this.addGoodsForm.productName = productName;
return true;
},
validateSpecPrice(index) {
const item = this.addGoodsForm.attributeListPrice[index];
if (item && item.specPrice !== "" && !this.isDecimalInRange(item.specPrice, 0.1, 9999)) {
this.$Message.warning(`${index + 1}个商品规格价格需为0.1-9999,最多2位小数`);
}
},
validateGroupCount(index) {
const item = this.addGoodsForm.productGroupBuyPrices[index];
if (item && item.groupCount !== "" && !this.isIntegerInRange(item.groupCount, 2, 10)) {
this.$Message.warning(`${index + 1}个拼团人数需为2-10的整数`);
}
},
validateGroupPrice(index) {
const item = this.addGoodsForm.productGroupBuyPrices[index];
if (item && item.groupPrice !== "" && !this.isDecimalInRange(item.groupPrice, 0.1, 9999)) {
this.$Message.warning(`${index + 1}个拼团价格需为0.1-9999,最多2位小数`);
}
},
onCanbuyChange(categoryName, value){
// Mapcanbuy
let entry = this.addGoodsForm.attributeList1.get(categoryName)
@ -751,7 +863,7 @@
addGroup(){
let data = {
groupCount:'',
groupPrice:0
groupPrice:''
}
this.addGoodsForm.productGroupBuyPrices.push(data)
},
@ -1108,13 +1220,14 @@
productPicture:'', //
productName:'', //
lunchBox:0, //
startPayNum:'', //
startPayNum:1, //
orderFiled:'',//
attributeListPrice:[{ //
specPrice:"",
specNum:9999
}],
sellTime:0, //
isMoreBuy:0, //
sellBeginTime:'', //---
sellEndTime:'', //---
attributeList:'',
@ -1145,9 +1258,18 @@
let str = JSON.stringify(v);
let data = JSON.parse(str);
this.addGoodsForm = data;
if(this.addGoodsForm.productGroupBuyPrices == ''){
if(this.addGoodsForm.productGroupBuyPrices == '' || this.addGoodsForm.productGroupBuyPrices === undefined || this.addGoodsForm.productGroupBuyPrices === null){
this.addGoodsForm.productGroupBuyPrices = []
}
if(this.addGoodsForm.lunchBox === '' || this.addGoodsForm.lunchBox === undefined || this.addGoodsForm.lunchBox === null){
this.addGoodsForm.lunchBox = 0
}
if(this.addGoodsForm.startPayNum === '' || this.addGoodsForm.startPayNum === undefined || this.addGoodsForm.startPayNum === null){
this.addGoodsForm.startPayNum = 1
}
if(this.addGoodsForm.isMoreBuy === '' || this.addGoodsForm.isMoreBuy === undefined || this.addGoodsForm.isMoreBuy === null){
this.addGoodsForm.isMoreBuy = 0
}
this.addGoodsForm.attributeList1 = JSON.parse(this.addGoodsForm.attributeList)
this.addGoodsForm.attributeList1 = new Map(Object.entries(this.addGoodsForm.attributeList1));
// canbuy1
@ -1174,7 +1296,7 @@
handelSubmit() {
this.$refs.form.validate((valid) => {
if (valid) {
if (!this.validateGoodsForm()) return;
this.submitLoading = true;
if (this.modalType == 0) {

87
src/views/app/shop/logisticsAddress.vue

@ -9,6 +9,12 @@
size="small" show-total show-elevator show-sizer></Page>
</Row>
</Card>
<Modal title="查看回复" v-model="replyVisible" :mask-closable="false" :width="900">
<Table border :columns="replyColumns" :data="replyList" :size="tableSize"></Table>
<div slot="footer">
<Button type="text" @click="replyVisible = false">关闭</Button>
</div>
</Modal>
</div>
</template>
@ -38,6 +44,37 @@
},
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",
@ -103,6 +140,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: {
@ -152,6 +204,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

26
src/views/app/shop/shop.vue

@ -8,6 +8,14 @@
word-break: break-all;
line-height: 20px;
}
.shop-address-ellipsis {
display: block;
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
</style>
<template>
<div class="search">
@ -251,23 +259,19 @@
transfer: true,
placement: "top",
maxWidth: 520,
},
style: {
display: "block",
width: "100%",
}
}, [
h("span", {
style: {
display: "inline-block",
width: "100%",
overflow: "hidden",
textOverflow: "ellipsis",
whiteSpace: "nowrap",
verticalAlign: "middle",
},
}, address)
,
class: "shop-address-ellipsis",
}, address || "-"),
h("div", {
slot: "content",
class: "shop-address-tooltip"
}, address)
}, address || "-")
]);
},
},

Loading…
Cancel
Save