基础管理-移动端

This commit is contained in:
zzyuan 2025-03-31 16:37:46 +08:00
parent 7babf5804a
commit f62b8df356
7 changed files with 1454 additions and 28 deletions

142
src/api/base/mobile.js Normal file
View File

@ -0,0 +1,142 @@
import request from '@/utils/request'
// 系统区域权限树
export function systemAreaTreeApi(data) {
return request({
url: '/smart-canteen/api/v2/alloc/area/system-auth/tree',
method: 'post',
headers: {
"merchant-id":"378915229716713472",
},
data: data
})
}
// 通过区域Id查询食堂
export function getCanteenByAreaApi(data) {
return request({
url: '/smart-canteen/api/v2/alloc/canteen/list-all-auth-canteen',
method: 'post',
headers: {
"merchant-id":"378915229716713472",
},
data: data
})
}
// 通过食堂Id查询档口
export function getStallByCanteenApi(data) {
return request({
url: '/smart-canteen/api/v2/alloc/canteen/list-multiple-auth-stall',
method: 'post',
headers: {
"merchant-id":"378915229716713472",
},
data: data
})
}
// 来源下拉数据
export function getSourceTypeListApi(data) {
return request({
url: '/smart-canteen/api/v2/order/enums/source/type-list',
method: 'post',
headers: {
"merchant-id":"378915229716713472",
},
data: data
})
}
// 投诉建议列表
export function getPlaintByPageApi(data) {
return request({
url: '/smart-canteen/api/v1/complaint/getPlaintByPage',
method: 'post',
headers: {
"merchant-id":"378915229716713472",
},
data: data
})
}
// 回复-投诉建议
export function replyComplaintApi(data) {
return request({
url: '/smart-canteen/api/v1/complaint/replyComplaint',
method: 'post',
headers: {
"merchant-id":"378915229716713472",
},
data: data
})
}
// 订单评价列表
export function getOrderEvaluatePageApi(data) {
return request({
url: '/smart-canteen/api/v1/applet/menuevaluaorder/page/evaluate/order',
method: 'post',
headers: {
"merchant-id":"378915229716713472",
},
data: data
})
}
// 订单评价-回复
export function orderEvaluateReplyApi(data) {
return request({
url: '/smart-canteen/api/v1/applet/menuevaluaorder/add/evalua/reply',
method: 'post',
headers: {
"merchant-id":"378915229716713472",
},
data: data
})
}
// 食堂评价列表
export function getCanteenEvaluatePageApi(data) {
return request({
url: '/smart-canteen/api/v1/canteen/evaluate/page',
method: 'post',
headers: {
"merchant-id":"378915229716713472",
},
data: data
})
}
// 食堂评价-详情
export function getCanteenEvaluateDetailApi(data) {
return request({
url: '/smart-canteen/api/v1/canteen/evaluate/get-evaluate-detail',
method: 'post',
headers: {
"merchant-id":"378915229716713472",
},
data: data
})
}
// 评价统计列表
export function getEvaluateCountPageApi(data) {
return request({
url: '/smart-canteen/api/v1/canteen/evaluate/page-evaluate-count',
method: 'post',
headers: {
"merchant-id":"378915229716713472",
},
data: data
})
}

View File

@ -162,7 +162,7 @@
/>
<!-- 添加或修改参数配置对话框 -->
<el-dialog :title="title+'-档口'" :visible.sync="open" width="1000px" append-to-body>
<el-dialog :title="title+'-档口'" :visible.sync="open" width="1200px" append-to-body>
<el-tabs v-model="activeName" @tab-click="handleTabClick">
<!-- 基础设置 -->
<el-tab-pane label="基础设置" name="baseSetting" style="height: 600px;overflow-y: auto;">
@ -365,9 +365,141 @@
<!-- <el-tab-pane label="配送设置" name="deliverySetting" style="height: 600px;overflow-y: auto;">
</el-tab-pane> -->
<!-- 预订/点餐/报餐设置 -->
<!-- <el-tab-pane label="预订/点餐/报餐设置" name="orderSetting" style="height: 600px;overflow-y: auto;">
</el-tab-pane> -->
<el-tab-pane label="预订设置" name="orderSetting" style="height: 600px;overflow-y: auto;">
<el-form ref="orderDTO" :model="orderDTO" label-width="80px">
<el-row>
<el-col :span="12">
<el-form-item label="启用本档口独立规则" prop="ifEnableOrder" label-width="160px">
<el-switch
v-model="orderDTO.ifEnableOrder"
active-text="开启"
inactive-text="关闭"
:active-value="1"
:inactive-value="2">
</el-switch>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="允许预定餐预定当天" prop="ifAllowReserveToday" label-width="160px">
<el-switch
v-model="orderDTO.ifAllowReserveToday"
active-text="开启"
inactive-text="关闭"
active-value="1"
inactive-value="2">
</el-switch>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-table :data="mealtimeList" height="400" >
<el-table-column label="餐次类型" align="center" prop="mealtimeName" width="100"/>
<el-table-column label="餐次时段" align="center" width="220">
<template slot-scope="scope">
<el-time-picker
is-range
v-model="scope.row.orderTimeList" style="width: 190px;"
range-separator="至" format="HH:mm:ss" value-format="HH:mm:ss"
start-placeholder="开始时间"
end-placeholder="结束时间"
placeholder="选择时间范围" @change="changeOrderTimeList(scope.row)">
</el-time-picker>
<!-- <span>{{scope.row.startTime}}</span>-<span>{{scope.row.endTime}}</span> -->
</template>
</el-table-column>
<el-table-column label="预定餐" align="center">
<el-table-column label="预定时段" align="center" width="220">
<template slot-scope="scope">
<el-time-picker
is-range :clearable="true"
v-model="scope.row.reserveTimeList" style="width: 190px;"
range-separator="至" format="HH:mm:ss" value-format="HH:mm:ss"
start-placeholder="开始时间"
end-placeholder="结束时间"
placeholder="选择时间范围" @change="changeReserveTimeList(scope.row)">
</el-time-picker>
</template>
</el-table-column>
<el-table-column label="退单截止时间" align="center" width="150">
<template slot-scope="scope">
<el-time-picker
v-model="scope.row.reserveRefundDeadline" style="width: 120px;"
placeholder="选择时间">
</el-time-picker>
</template>
</el-table-column>
<el-table-column label="自动打印时间" align="center" width="150">
<template slot-scope="scope">
<el-time-picker
v-model="scope.row.reservePrintTime" style="width: 120px;"
placeholder="选择时间">
</el-time-picker>
</template>
</el-table-column>
</el-table-column>
<el-table-column label="当餐点餐" align="center">
<el-table-column label="点餐时段" align="center" width="220">
<template slot-scope="scope">
<el-time-picker
is-range :clearable="true"
v-model="scope.row.currTimeList" style="width: 190px;"
range-separator="至" format="HH:mm:ss" value-format="HH:mm:ss"
start-placeholder="开始时间"
end-placeholder="结束时间"
placeholder="选择时间范围" @change="changeCurrTimeList(scope.row)">
</el-time-picker>
</template>
</el-table-column>
<el-table-column label="退单截止时间" align="center" width="150">
<template slot-scope="scope">
<el-time-picker
v-model="scope.row.currRefundDeadline" style="width: 120px;"
placeholder="选择时间">
</el-time-picker>
</template>
</el-table-column>
</el-table-column>
<el-table-column label="状态" align="center" prop="ifUse" width="150">
<template slot-scope="scope">
<el-switch
v-model="scope.row.ifUse"
active-text="开启"
inactive-text="关闭"
:active-value="1"
:inactive-value="2">
</el-switch>
</template>
</el-table-column>
</el-table>
</el-row>
<div style="font-weight: bold;margin: 10px 0;">预订第二天及以后相关设置</div>
<el-row style="margin-bottom: 10px;">
<el-col :span="12">
<span>预订餐最多允许订</span><el-input style="width: 100px;margin: auto 5px;" v-model="orderDTO.reserveLimitDay" @input="(v)=>(orderDTO.reserveLimitDay=v.replace(/[^\d]/g,''))"></el-input><span></span>
<el-checkbox v-model="orderDTO.ifReserveSkipHoliday" style="margin: auto 5px;" :true-label="1" :false-label="2">跳过节假日</el-checkbox>
</el-col>
<el-col :span="12">
<span>今天预订第二天餐次截止</span>
<el-time-picker
v-model="orderDTO.reserveEndTime" style="width: 120px;margin: auto 5px;" clearable
placeholder="选择时间">
</el-time-picker>
</el-col>
</el-row>
<el-row style="margin-bottom: 10px;">
<el-col :span="12">
<span>每天</span>
<el-time-picker
v-model="orderDTO.reserveRefundEndTime" style="width: 120px;margin: auto 5px;" clearable
placeholder="选择时间">
</el-time-picker>
<span>系统自动确认次日订单一经确认用户不可退</span>
</el-col>
</el-row>
</el-form>
</el-tab-pane>
</el-tabs>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
@ -541,10 +673,23 @@ export default {
dialogVisible:false,//
dialogImageUrl:"",//
deliveryModel:{},//
orderDTO:{},//
deliveryModel:{},//
mealtimeList:[],//
orderDTO: {//
"bookEndTime": "",
"bookRefundEndTime": "",
"cancelBookFeeRatio": "",
"dayBeforeCancelBookChargeTime": "",
"ifAllowReserveToday": "1",
"ifBookSkipHoliday": "",
"ifEnableOrder": 2,
"ifReserveSkipHoliday": "1",
"nearDinnerCancelBookChargeHour": "2",
"reportMealLimitDay": 0,
"reserveEndTime": "",
"reserveLimitDay": 0,
"reserveRefundEndTime": ""
},
};
},
created() {
@ -637,6 +782,7 @@ export default {
this.stallId=""
this.reset();
this.getMealtimeList()
this.activeName="baseSetting"
this.open = true;
this.title = "新增";
},
@ -650,13 +796,29 @@ export default {
this.fileList=[]
this.checkUrlList=[]
this.baseForm = {};
this.orderDTO = {//
"bookEndTime": "",
"bookRefundEndTime": "",
"cancelBookFeeRatio": "",
"dayBeforeCancelBookChargeTime": "",
"ifAllowReserveToday": "1",
"ifBookSkipHoliday": "",
"ifEnableOrder": 2,
"ifReserveSkipHoliday": "1",
"nearDinnerCancelBookChargeHour": "2",
"reportMealLimitDay": 0,
"reserveEndTime": "",
"reserveLimitDay": 0,
"reserveRefundEndTime": ""
}
this.rangeTime=["08:00:00", "18:00:00"]
this.resetForm("baseForm");
},
/** 修改按钮操作 */
handleUpdate(row) {
console.log(row)
this.reset();
this.reset();
this.activeName="baseSetting"
getStallInfoModifyApi({"stallId":row.stallId}).then(response => {
console.log(response)
this.stallId = response.stallId;
@ -680,6 +842,11 @@ export default {
this.deliveryModel = response.deliveryModel;
this.orderDTO = response.orderDTO;
this.mealtimeList = response.mealtimeList;
this.mealtimeList.forEach(item=>{
this.$set(item,"orderTimeList",[item.startTime,item.endTime])
this.$set(item,"reserveTimeList",[item.reserveStartTime||'',item.reserveEndTime||''])
this.$set(item,"currTimeList",[item.currStartTime||'',item.currEndTime||''])
})
this.open = true;
this.title = "修改";
});
@ -764,21 +931,7 @@ export default {
"ifEnableDelivery": "2",
"minDeliveryFeeOnOff": 1
},
"orderDTO": {//
"bookEndTime": "",
"bookRefundEndTime": "",
"cancelBookFeeRatio": "",
"dayBeforeCancelBookChargeTime": "",
"ifAllowReserveToday": "1",
"ifBookSkipHoliday": "",
"ifEnableOrder": 2,
"ifReserveSkipHoliday": "1",
"nearDinnerCancelBookChargeHour": "2",
"reportMealLimitDay": 0,
"reserveEndTime": "",
"reserveLimitDay": 0,
"reserveRefundEndTime": ""
},
"orderDTO":this.orderDTO,
"mealtimeList":this.mealtimeList
}
if (this.stallId != "") {
@ -967,13 +1120,33 @@ export default {
//
getMealtimeList() {
getMealtimeListApi({}).then((response) => {
this.mealtimeList = response
console.log(response)
this.mealtimeList = response;
this.mealtimeList.forEach(item=>{
this.$set(item,"orderTimeList",[item.startTime,item.endTime])
this.$set(item,"reserveTimeList",['',''])
this.$set(item,"currTimeList",['',''])
})
});
},
changeOrderTimeList(row){
console.log(row)
row.startTime = row.orderTimeList[0]
row.endTime = row.orderTimeList[1]
},
changeReserveTimeList(row){ //item.reserveStartTime,item.reserveEndTime
console.log(row)
if(row.reserveTimeList){
row.reserveStartTime = row.reserveTimeList[0]
row.reserveEndTime = row.reserveTimeList[1]
}
},
changeCurrTimeList(row){ //item.currStartTime,item.currEndTime
console.log(row)
if(row.currTimeList){
row.currStartTime = row.currTimeList[0]
row.currEndTime = row.currTimeList[1]
}
}

View File

@ -0,0 +1,354 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="日期">
<el-date-picker
v-model="dateRange"
type="daterange"
align="right"
unlink-panels
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期" clearable
format="yyyy-MM-dd" style="width: 220px"
:picker-options="pickerOptions" >
</el-date-picker>
</el-form-item>
<el-form-item label="投诉建议">
<el-input v-model="queryParams.informContent" placeholder="请输入投诉建议" maxlength="20" clearable style="width: 220px"/>
</el-form-item>
<el-form-item label="所属区域" prop="areaIdList">
<el-cascader v-model="queryParams.areaIdList"
:options="treeAreaOptions" :filterable="true" style="width: 220px" :show-all-levels="false"
:props="{
multiple: true,
emitPath: false,// falseid
checkStrictly: true,//
value:'id',label:'treeName'
}" clearable collapse-tags @change="handleAreaChange">
</el-cascader>
</el-form-item>
<el-form-item label="所属食堂" prop="canteenIds">
<el-select v-model="queryParams.canteenIds" multiple collapse-tags clearable placeholder="请选择所属食堂" style="width: 220px">
<el-option v-for="item in canteenOptions"
:key="item.canteenId"
:label="item.canteenName"
:value="item.canteenId"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="来源" prop="sourceTypes">
<el-select v-model="queryParams.sourceTypes" multiple collapse-tags clearable placeholder="请选择来源" style="width: 220px">
<el-option v-for="item in sourceTypesOptions"
:key="item.key"
:label="item.value"
:value="item.key"
></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="tableListData" height="800">
<el-table-column label="投诉人" align="center" prop="custName" :show-overflow-tooltip="true"/>
<el-table-column label="用户手机号" align="center" prop="mobile" :show-overflow-tooltip="true"/>
<el-table-column label="投诉日期" align="center" prop="complaintDate" :show-overflow-tooltip="true"/>
<el-table-column label="所属区域" align="center" prop="areaName" :show-overflow-tooltip="true"/>
<el-table-column label="所属食堂" align="center" prop="canteenName" :show-overflow-tooltip="true"/>
<el-table-column label="来源" align="center" prop="sourceName" :show-overflow-tooltip="true"/>
<el-table-column label="投诉建议内容" align="center" prop="content" :show-overflow-tooltip="true"/>
<el-table-column label="图片" align="center" prop="complaintPicture" :show-overflow-tooltip="true" width="100">
<template slot-scope="scope">
<img :src="scope.row.complaintPicture" alt="" v-if="scope.row.complaintPicture" style="width: 80px;height: 40px;" @click="openImg(scope.row)">
<span v-else></span>
</template>
</el-table-column>
<el-table-column label="回复内容" align="center" prop="replyContent" :show-overflow-tooltip="true"/>
<el-table-column label="操作" align="center" width="180" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
@click="handleView(scope.row)"
>详情</el-button>
<el-button
size="mini"
type="text"
@click="handleUpdate(scope.row)"
>回复</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<!-- 添加或修改参数配置对话框 -->
<el-dialog title="回复 - 投诉建议" :visible.sync="open" width="700px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
<el-form-item label="投诉人" prop="custName">
<el-input v-model="form.custName" disabled style="width: 100%"/>
</el-form-item>
<el-form-item label="用户手机号" prop="mobile">
<el-input v-model="form.mobile" disabled style="width: 100%"/>
</el-form-item>
<el-form-item label="来源" prop="sourceName">
<el-input v-model="form.sourceName" disabled style="width: 100%"/>
</el-form-item>
<el-form-item label="投诉建议内容" prop="content">
<el-input
type="textarea"
:rows="3" style="width: 100%;margin: 0 auto;"
placeholder="投诉建议内容" disabled
v-model="form.content">
</el-input>
</el-form-item>
<el-form-item label="回复" prop="replyContent">
<el-input
type="textarea"
:rows="3" style="width: 100%;margin: 0 auto;"
placeholder="请输入回复内容" maxlength="150"
v-model="form.replyContent">
</el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</el-dialog>
<el-dialog title="投诉建议内容" :visible.sync="contentVisible" width="600px" append-to-body>
<el-input
type="textarea"
:rows="5" style="width: 100%;margin: 0 auto;"
placeholder="投诉建议内容" readonly="true" maxlength="150"
v-model="dialogContent">
</el-input>
<div slot="footer" class="dialog-footer">
<el-button @click="contentVisible=false"> </el-button>
</div>
</el-dialog>
<el-dialog :visible.sync="dialogVisible">
<img width="100%" :src="dialogImageUrl" alt="">
</el-dialog>
</div>
</template>
<script>
import { getPlaintByPageApi,systemAreaTreeApi,getCanteenByAreaApi,getSourceTypeListApi,replyComplaintApi } from "@/api/base/mobile";
export default {
name: "",
dicts: [],
data() {
return {
//
loading: true,
//
ids: [],
//
single: true,
//
multiple: true,
//
showSearch: true,
//
total: 0,
//
tableListData: [],
//
open: false,
//
queryParams: {
pageNum: 1,
pageSize: 10,
informContent:null,
areaIdList:[],
canteenIds:[],
sourceTypes:[]
},
dateRange:[],
pickerOptions: {
shortcuts: [{
text: '最近一周',
onClick(picker) {
const start = new Date();
const end = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 6);
picker.$emit('pick', [start, end]);
}
},{
text: '最近一个月',
onClick(picker) {
const start = new Date();
const end = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
picker.$emit('pick', [start, end]);
}
},{
text: '最近三个月',
onClick(picker) {
const start = new Date();
const end = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 91);
picker.$emit('pick', [start, end]);
}
}]
},
treeAreaOptions:[],//
canteenOptions:[],//-
sourceTypesOptions:[],//-
dialogVisible:false,//
dialogImageUrl:"",//
contentVisible:false,//
dialogContent:"",//
//
form: {},
//
rules: {
replyContent: [
{ required: true, message: "回复内容不能为空", trigger: "blur" }
]
}
};
},
created() {
this.getAreaTreeData();
this.getSourceTypeList();
this.getList();
},
methods: {
//
getAreaTreeData() {
systemAreaTreeApi({}).then((response) => {
this.treeAreaOptions = response;
});
},
handleAreaChange(e){
let param= {
areaIdList:this.queryParams.areaIdList
}
getCanteenByAreaApi(param).then((response) => {
this.canteenOptions=response||[]
this.queryParams.canteenIds=[]
});
},
getSourceTypeList(){
let param= {}
getSourceTypeListApi(param).then((response) => {
this.sourceTypesOptions=response||[]
});
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.dateRange=[]
this.queryParams = {
pageNum: 1,
pageSize: 10,
informContent:null,
areaIdList:[],
canteenIds:[],
sourceTypes:[]
}
this.resetForm("queryForm");
this.handleQuery();
},
/** 查询列表 */
getList() {
this.loading = true;
let param = {
"object":{
informContent:this.queryParams.informContent,
areaIdList:this.queryParams.areaIdList,
canteenIds:this.queryParams.canteenIds,
sourceTypes:this.queryParams.sourceTypes,
startTime:null,
endTime:null,
},
"page":{
"current": this.queryParams.pageNum,
"size": this.queryParams.pageSize,
}
}
console.log(param)
if(this.dateRange.length>0){
param.object.startTime = this.formatDate(this.dateRange[0])
param.object.endTime = this.formatDate(this.dateRange[1])
}
getPlaintByPageApi(param).then(response => {
this.tableListData = response.data.records;
this.total = Number(response.data.total);
this.loading = false;
});
},
/** 回复按钮操作 */
handleUpdate(row) {
this.reset();
this.form = Object.assign({}, row)
this.open = true;
},
//
cancel() {
this.open = false;
this.reset();
},
//
reset() {
this.form = {};
this.resetForm("form");
},
/** 提交按钮 */
submitForm: function() {
this.$refs["form"].validate(valid => {
if (valid) {
let param = {
complaintId:this.form.complaintId,
replyContent:this.form.replyContent
}
replyComplaintApi(param).then(response => {
this.$modal.msgSuccess("回复成功");
this.open = false;
this.getList();
});
}
});
},
/** 详情按钮操作 */
handleView(row) {
this.dialogContent = row.content||'';
this.contentVisible = true;
},
openImg(row) {
this.dialogImageUrl = row.complaintPicture;
this.dialogVisible = true;
},
//
formatDate(date) {
// YYYY-MM-DD
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0'); // 0
const day = String(date.getDate()).padStart(2, '0');
return `${year}-${month}-${day}`;
}
}
};
</script>

View File

@ -0,0 +1,757 @@
<template>
<div class="app-container">
<el-tabs v-model="activeName" @tab-click="handleTabClick">
<el-tab-pane label="订单评价" name="1">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="日期时间">
<el-date-picker
v-model="dateTimeRange"
type="datetimerange"
align="right"
unlink-panels
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
format="yyyy-MM-dd HH:mm:ss" style="width: 340px"
:default-time="['00:00:00', '23:59:59']"
:picker-options="pickerOptions" >
</el-date-picker>
</el-form-item>
<el-form-item label="所属区域" prop="areaIdList">
<el-cascader v-model="queryParams.areaIdList"
:options="treeAreaOptions" :filterable="true" style="width: 220px" :show-all-levels="false"
:props="{
multiple: true,
emitPath: false,// falseid
checkStrictly: true,//
value:'id',label:'treeName'
}" clearable collapse-tags @change="handleAreaChange">
</el-cascader>
</el-form-item>
<el-form-item label="所属食堂" prop="canteenIdList">
<el-select v-model="queryParams.canteenIdList" multiple collapse-tags clearable placeholder="请选择所属食堂" style="width: 220px" @change="handleCanteenChange">
<el-option v-for="item in canteenOptions"
:key="item.canteenId"
:label="item.canteenName"
:value="item.canteenId"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="所属档口" prop="stallIdList">
<el-select v-model="queryParams.stallIdList" multiple collapse-tags clearable placeholder="请选择所属档口" style="width: 220px" >
<el-option v-for="item in stallOptions"
:key="item.stallId"
:label="item.stallName"
:value="item.stallId"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="订单ID">
<el-input v-model="queryParams.ordId" placeholder="请输入订单Id" maxlength="20" clearable style="width: 220px"/>
</el-form-item>
<el-form-item label="订单类型" prop="orderEvaluaType">
<el-select v-model="queryParams.orderEvaluaType" collapse-tags clearable placeholder="请选择订单类型" style="width: 220px">
<el-option label="食堂订单" value="1"></el-option>
<el-option label="商超订单" value="2"></el-option>
</el-select>
</el-form-item>
<el-form-item label="餐次" prop="mealtimeType">
<el-select v-model="queryParams.mealtimeType" style="width: 220px" clearable>
<el-option label="早餐" value="1"></el-option>
<el-option label="午餐" value="2"></el-option>
<el-option label="下午茶" value="3"></el-option>
<el-option label="晚餐" value="4"></el-option>
<el-option label="夜宵" value="5"></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="tableListData" height="550">
<el-table-column label="订单ID" align="center" prop="ordId" :show-overflow-tooltip="true" width="180"/>
<el-table-column label="用户姓名" align="center" prop="custName" :show-overflow-tooltip="true" width="100"/>
<el-table-column label="所属区域" align="center" prop="areaName" :show-overflow-tooltip="true" width="120"/>
<el-table-column label="所属食堂" align="center" prop="canteenName" :show-overflow-tooltip="true" width="120"/>
<el-table-column label="所属档口" align="center" prop="stallName" :show-overflow-tooltip="true" width="120"/>
<el-table-column label="餐次" align="center" prop="mealtimeName" :show-overflow-tooltip="true" width="80"/>
<el-table-column label="菜品评分" align="center" prop="starLevel" :show-overflow-tooltip="true" width="80"/>
<el-table-column label="评价内容" align="center" prop="description" :show-overflow-tooltip="true" width="200"/>
<el-table-column label="评价照片" align="center" prop="pictureList" :show-overflow-tooltip="true" width="180">
<template slot-scope="scope">
<div v-if="scope.row.pictureList&&scope.row.pictureList.length>0">
<img v-for="(item,index) in scope.row.pictureList" :key="index" :src="item" alt="" style="width: 80px;height: 40px;" @click="openImg(item)">
</div>
<span v-else></span>
</template>
</el-table-column>
<el-table-column label="评价时间" align="center" prop="crtime" :show-overflow-tooltip="true" width="160"/>
<el-table-column label="回复内容" align="center" prop="reply" :show-overflow-tooltip="true" width="120"/>
<el-table-column label="是否显示" align="center" prop="showFlag" :show-overflow-tooltip="true" width="80">
<template slot-scope="scope">
<span v-if="scope.row.showFlag==1"></span>
<span v-else></span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="180" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
@click="handleView1(scope.row)"
>详情</el-button>
<el-button
size="mini"
type="text"
@click="handleReply(scope.row)"
>回复</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
</el-tab-pane>
<el-tab-pane label="食堂评价" name="2">
<el-form :model="queryParams2" ref="queryForm2" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="评价日期">
<el-date-picker
v-model="dateRange"
type="daterange"
align="right"
unlink-panels
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
format="yyyy-MM-dd" style="width: 220px"
:picker-options="pickerOptions2" >
</el-date-picker>
</el-form-item>
<el-form-item label="所属区域" prop="areaIdList">
<el-cascader v-model="queryParams2.areaIdList"
:options="treeAreaOptions" :filterable="true" style="width: 220px" :show-all-levels="false"
:props="{
multiple: true,
emitPath: false,// falseid
checkStrictly: true,//
value:'id',label:'treeName'
}" clearable collapse-tags @change="handleAreaChange2">
</el-cascader>
</el-form-item>
<el-form-item label="所属食堂" prop="canteenIdList">
<el-select v-model="queryParams2.canteenIdList" multiple collapse-tags clearable placeholder="请选择所属食堂" style="width: 220px" @change="handleCanteenChange2">
<el-option v-for="item in canteenOptions2"
:key="item.canteenId"
:label="item.canteenName"
:value="item.canteenId"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="所属档口" prop="stallIdList">
<el-select v-model="queryParams2.stallIdList" multiple collapse-tags clearable placeholder="请选择所属档口" style="width: 220px" >
<el-option v-for="item in stallOptions2"
:key="item.stallId"
:label="item.stallName"
:value="item.stallId"
></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery2">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery2">重置</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="tableListData2" height="550">
<el-table-column label="所属区域" align="center" prop="areaName" :show-overflow-tooltip="true"/>
<el-table-column label="所属食堂" align="center" prop="canteenName" :show-overflow-tooltip="true"/>
<el-table-column label="所属档口" align="center" prop="stname" :show-overflow-tooltip="true"/>
<el-table-column label="意见和建议" align="center" prop="proposal" :show-overflow-tooltip="true"/>
<el-table-column label="用户姓名" align="center" prop="custName" :show-overflow-tooltip="true"/>
<el-table-column label="评价日期" align="center" prop="evaluateDate" :show-overflow-tooltip="true"/>
<el-table-column label="操作" align="center" width="180" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
@click="handleView2(scope.row)"
>详情</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total2>0"
:total="total2"
:page.sync="queryParams2.pageNum"
:limit.sync="queryParams2.pageSize"
@pagination="getList2"
/>
</el-tab-pane>
<el-tab-pane label="评价统计" name="3">
<el-form :model="queryParams3" ref="queryForm3" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="统计日期">
<el-date-picker
v-model="dateRange3"
type="daterange"
align="right"
unlink-panels
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
format="yyyy-MM-dd" style="width: 220px"
:picker-options="pickerOptions2" >
</el-date-picker>
</el-form-item>
<el-form-item label="所属区域" prop="areaIdList">
<el-cascader v-model="queryParams3.areaIdList"
:options="treeAreaOptions" :filterable="true" style="width: 220px" :show-all-levels="false"
:props="{
multiple: true,
emitPath: false,// falseid
checkStrictly: true,//
value:'id',label:'treeName'
}" clearable collapse-tags @change="handleAreaChange3">
</el-cascader>
</el-form-item>
<el-form-item label="所属食堂" prop="canteenIdList">
<el-select v-model="queryParams3.canteenIdList" multiple collapse-tags clearable placeholder="请选择所属食堂" style="width: 220px" @change="handleCanteenChange3">
<el-option v-for="item in canteenOptions2"
:key="item.canteenId"
:label="item.canteenName"
:value="item.canteenId"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="所属档口" prop="stallIdList">
<el-select v-model="queryParams3.stallIdList" multiple collapse-tags clearable placeholder="请选择所属档口" style="width: 220px" >
<el-option v-for="item in stallOptions2"
:key="item.stallId"
:label="item.stallName"
:value="item.stallId"
></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery3">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery3">重置</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="tableListData3" height="550">
<el-table-column label="所属区域" align="center" prop="areaName" :show-overflow-tooltip="true"/>
<el-table-column label="所属食堂" align="center" prop="canteenName" :show-overflow-tooltip="true"/>
<el-table-column label="所属档口" align="center" prop="stallName" :show-overflow-tooltip="true"/>
<el-table-column v-for="(item,index) in titleList3" :key="index" :label="item.functionName" align="center" :prop="item.functionId+''" :show-overflow-tooltip="true">
</el-table-column>
</el-table>
<pagination
v-show="total3>0"
:total="total3"
:page.sync="queryParams3.pageNum"
:limit.sync="queryParams3.pageSize"
@pagination="getList3"
/>
</el-tab-pane>
</el-tabs>
<!-- 添加或修改参数配置对话框 -->
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-form-item label="订单ID" prop="ordId">
<el-input v-model="form.ordId" disabled style="width: 100%"/>
</el-form-item>
<el-form-item label="用户姓名" prop="custName">
<el-input v-model="form.custName" disabled style="width: 100%"/>
</el-form-item>
<el-form-item label="用户手机号" prop="mobile">
<el-input v-model="form.mobile" disabled style="width: 100%"/>
</el-form-item>
<el-form-item label="评价内容" prop="description">
<el-input
type="textarea"
:rows="3" style="width: 100%;margin: 0 auto;"
placeholder="评价内容" disabled
v-model="form.description">
</el-input>
</el-form-item>
<el-form-item label="回复内容" prop="reply">
<el-input
type="textarea"
:rows="3" style="width: 100%;margin: 0 auto;"
placeholder="请输入回复内容" maxlength="150"
v-model="form.reply">
</el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</el-dialog>
<el-dialog title="评价详情" :visible.sync="contentVisible" width="600px" append-to-body>
<el-input
type="textarea"
:rows="5" style="width: 100%;margin: 0 auto;" disabled
placeholder="评价详情内容" readonly="true" maxlength="150"
v-model="dialogContent">
</el-input>
<div slot="footer" class="dialog-footer">
<el-button @click="contentVisible=false"> </el-button>
</div>
</el-dialog>
<el-dialog title="评价详情" :visible.sync="contentVisible2" width="1200px" append-to-body>
<el-table :data="dialogContent2">
<el-table-column v-for="(item,index) in titleList2" :key="index" :label="item.functionName" align="center" :prop="item.functionId+''" :show-overflow-tooltip="true"></el-table-column>
</el-table>
<div slot="footer" class="dialog-footer">
<el-button @click="contentVisible2=false"> </el-button>
</div>
</el-dialog>
<el-dialog :visible.sync="dialogVisible">
<img width="100%" :src="dialogImageUrl" alt="">
</el-dialog>
</div>
</template>
<script>
import { getOrderEvaluatePageApi,systemAreaTreeApi,getCanteenByAreaApi,getStallByCanteenApi,getCanteenEvaluatePageApi,getEvaluateCountPageApi,getCanteenEvaluateDetailApi,orderEvaluateReplyApi } from "@/api/base/mobile";
export default {
name: "",
dicts: [],
data() {
return {
//
loading: true,
//
ids: [],
//
single: true,
//
multiple: true,
//
showSearch: true,
//
title: "",
//
open: false,
activeName:'1',
//
//
queryParams: {
pageNum: 1,
pageSize: 10,
areaIdList:[],
canteenIdList:[],
stallIdList:[],
ordId:null,
mealtimeType:null,
orderEvaluaType:null
},
dateTimeRange:this.defaultDateRange(),
pickerOptions: {
shortcuts: [{
text: '最近一周',
onClick(picker) {
const end = new Date(new Date().toLocaleDateString());
end.setTime(end.getTime() + 24 * 60 * 60 * 1000 - 1);
const start = new Date((new Date().toLocaleDateString()));
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
picker.$emit('pick', [start, end]);
}
}, {
text: '最近一个月',
onClick(picker) {
const end = new Date(new Date().toLocaleDateString());
end.setTime(end.getTime() + 24 * 60 * 60 * 1000 - 1);
const start = new Date((new Date().toLocaleDateString()));
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
picker.$emit('pick', [start, end]);
}
}, {
text: '最近三个月',
onClick(picker) {
const end = new Date(new Date().toLocaleDateString());
end.setTime(end.getTime() + 24 * 60 * 60 * 1000 - 1);
const start = new Date((new Date().toLocaleDateString()));
start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
picker.$emit('pick', [start, end]);
}
}]
},
treeAreaOptions:[],//
canteenOptions:[],//-
stallOptions:[],//-
total: 0,//
tableListData: [], //
//
queryParams2:{
pageNum: 1,
pageSize: 10,
areaIdList:[],
canteenIdList:[],
stallIdList:[],
},
dateRange:[new Date(),new Date()],
pickerOptions2: {
shortcuts: [{
text: '最近一周',
onClick(picker) {
const start = new Date();
const end = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 6);
picker.$emit('pick', [start, end]);
}
},{
text: '最近一个月',
onClick(picker) {
const start = new Date();
const end = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
picker.$emit('pick', [start, end]);
}
},{
text: '最近三个月',
onClick(picker) {
const start = new Date();
const end = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 91);
picker.$emit('pick', [start, end]);
}
}]
},
canteenOptions2:[],//-
stallOptions2:[],//-
total2: 0, //
tableListData2: [],//
//
queryParams3:{
pageNum: 1,
pageSize: 10,
areaIdList:[],
canteenIdList:[],
stallIdList:[],
},
dateRange3:[new Date(),new Date()],
canteenOptions3:[],//-
stallOptions3:[],//-
total3: 0,//
tableListData3: [],//
titleList3: [],//
dialogVisible:false,//
dialogImageUrl:"",//
contentVisible:false,
dialogContent:"",
contentVisible2:false,
dialogContent2:[],
titleList2:[],
//
form: {},
//
rules: {
reply: [
{ required: true, message: "回复内容不能为空", trigger: "blur" }
]
}
};
},
created() {
this.getAreaTreeData();
if(this.activeName=='1'){
this.getList();
}else if(this.activeName=='2'){
this.getList2();
}else if(this.activeName=='2'){
this.getList3();
}
},
methods: {
//
getAreaTreeData() {
systemAreaTreeApi({}).then((response) => {
this.treeAreaOptions = response;
});
},
handleAreaChange(e){
let param= {
areaIdList:this.queryParams.areaIdList
}
getCanteenByAreaApi(param).then((response) => {
this.canteenOptions=response||[]
this.queryParams.canteenIdList=[]
this.queryParams.stallIdList=[]
});
},
handleCanteenChange(e){
let param= {
canteenIdList:this.queryParams.canteenIdList
}
getStallByCanteenApi(param).then((response) => {
this.stallOptions=response||[]
this.queryParams.stallIdList=[]
});
},
handleAreaChange2(e){
let param= {
areaIdList:this.queryParams2.areaIdList
}
getCanteenByAreaApi(param).then((response) => {
this.canteenOptions2=response||[]
this.queryParams2.canteenIdList=[]
this.queryParams2.stallIdList=[]
});
},
handleCanteenChange2(e){
let param= {
canteenIdList:this.queryParams2.canteenIdList
}
getStallByCanteenApi(param).then((response) => {
this.stallOptions2=response||[]
this.queryParams2.stallIdList=[]
});
},
handleAreaChange3(e){
let param= {
areaIdList:this.queryParams3.areaIdList
}
getCanteenByAreaApi(param).then((response) => {
this.canteenOptions3=response||[]
this.queryParams3.canteenIdList=[]
this.queryParams3.stallIdList=[]
});
},
handleCanteenChange3(e){
let param= {
canteenIdList:this.queryParams3.canteenIdList
}
getStallByCanteenApi(param).then((response) => {
this.stallOptions3=response||[]
this.queryParams3.stallIdList=[]
});
},
handleTabClick(tab, event) {
console.log(tab.name,tab.label)
if(this.activeName=='1'){
this.getList();
}else if(this.activeName=='2'){
this.getList2();
}else if(this.activeName=='2'){
this.getList3();
}
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.dateTimeRange = this.defaultDateRange()
this.queryParams = {
pageNum: 1,
pageSize: 10,
areaIdList:[],
canteenIdList:[],
stallIdList:[],
ordId:null,
mealtimeType:null,
orderEvaluaType:null
}
this.resetForm("queryForm");
this.handleQuery();
},
/** 搜索按钮操作 */
handleQuery2() {
this.queryParams2.pageNum = 1;
this.getList2();
},
/** 重置按钮操作 */
resetQuery2() {
this.dateRange = [new Date(),new Date()]
this.queryParams2 = {
pageNum: 1,
pageSize: 10,
areaIdList:[],
canteenIdList:[],
stallIdList:[],
}
this.resetForm("queryForm2");
this.handleQuery2();
},
/** 搜索按钮操作 */
handleQuery3() {
this.queryParams3.pageNum = 1;
this.getList3();
},
/** 重置按钮操作 */
resetQuery3() {
this.dateRange3 = [new Date(),new Date()]
this.queryParams3 = {
pageNum: 1,
pageSize: 10,
areaIdList:[],
canteenIdList:[],
stallIdList:[],
}
this.resetForm("queryForm3");
this.handleQuery3();
},
/** 查询列表 */
getList() {
this.loading = true;
let param = {
areaIdList:this.queryParams.areaIdList,
canteenIdList:this.queryParams.canteenIdList,
stallIdList:this.queryParams.stallIdList,
ordId:this.queryParams.ordId,
mealtimeType:this.queryParams.mealtimeType,
orderEvaluaType:this.queryParams.orderEvaluaType,
startTime:this.formatDateTime(this.dateTimeRange[0]),
endTime:this.formatDateTime(this.dateTimeRange[1]),
current: this.queryParams.pageNum,
size: this.queryParams.pageSize,
}
getOrderEvaluatePageApi(param).then(response => {
this.tableListData = response.records;
this.total = Number(response.total);
this.loading = false;
});
},
/** 详情按钮操作 */
handleView1(row) {
this.dialogContent = row.description||'';
this.contentVisible = true;
},
handleReply(row) {
this.reset();
this.form = Object.assign({}, row)
this.open = true;
this.title = "回复";
},
getList2() {
this.loading = true;
let param = {
areaIdList:this.queryParams2.areaIdList,
canteenIdList:this.queryParams2.canteenIdList,
stallIdList:this.queryParams2.stallIdList,
startDate:this.formatDate(this.dateRange[0]),
endDate:this.formatDate(this.dateRange[1]),
current: this.queryParams2.pageNum,
size: this.queryParams2.pageSize,
}
getCanteenEvaluatePageApi(param).then(response => {
this.tableListData2 = response.records;
this.total2 = Number(response.total);
this.loading = false;
});
},
/** 详情按钮操作 */
handleView2(row) {
getCanteenEvaluateDetailApi({"content":row.evaluateId}).then(response => {
this.dialogContent2 = response.dataList
this.titleList2 = response.titleList
this.contentVisible2 = true;
});
},
getList3() {
this.loading = true;
let param = {
areaIdList:this.queryParams3.areaIdList,
canteenIdList:this.queryParams3.canteenIdList,
stallIdList:this.queryParams3.stallIdList,
startDate:this.formatDate(this.dateRange3[0]),
endDate:this.formatDate(this.dateRange3[1]),
current: this.queryParams3.pageNum,
size: this.queryParams3.pageSize,
}
getEvaluateCountPageApi(param).then(response => {
this.tableListData3 = response.countDetailPage.records;
this.total3 = Number(response.countDetailPage.total);
this.titleList3 = response.titleList
this.loading = false;
});
},
//
cancel() {
this.open = false;
this.reset();
},
//
reset() {
this.form = {};
this.resetForm("form");
},
/** 提交按钮 */
submitForm: function() {
this.$refs["form"].validate(valid => {
if (valid) {
let param = {
evaluaId:this.form.evaluaId,
reply:this.form.reply,
}
orderEvaluateReplyApi(param).then(response => {
this.$modal.msgSuccess("回复成功");
this.open = false;
this.getList();
});
}
});
},
openImg(item) {
this.dialogImageUrl = item;
this.dialogVisible = true;
},
defaultDateRange() {
const end = new Date(new Date().toLocaleDateString());
end.setTime(end.getTime() + 24 * 60 * 60 * 1000 - 1);
const start = new Date((new Date().toLocaleDateString()));
start.setTime(start.getTime());
this.start = parseInt(start.getTime() / 1000)
this.end = parseInt(end.getTime() / 1000)
return [start, end]
},
//
formatDateTime(date) {
// YYYY-MM-DD
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0'); // 0
const day = String(date.getDate()).padStart(2, '0');
const hours = date.getHours() < 10 ? '0' + date.getHours() : date.getHours()
const minutes = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes()
const seconds = date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds()
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
},
//
formatDate(date) {
// YYYY-MM-DD
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0'); // 0
const day = String(date.getDate()).padStart(2, '0');
return `${year}-${month}-${day}`;
}
}
};
</script>