Browse Source

add tid1807 logic

tid1867
刘嘉炜 5 months ago
parent
commit
7923fea0db
  1. 16
      src/pages.json
  2. 10
      src/pages/menu/forth.vue
  3. 33
      src/store/actions.js
  4. 4
      src/subpackage/message/components/edit/fixed_button.vue
  5. 78
      src/subpackage/message/components/edit/info_edit.vue
  6. 104
      src/subpackage/message/components/edit/upload_img.vue
  7. 2
      src/subpackage/message/components/fixed_button.vue
  8. 21
      src/subpackage/message/components/message_item.vue
  9. 11
      src/subpackage/message/js/api.js
  10. 9
      src/subpackage/message/js/server.js
  11. 73
      src/subpackage/message/pages/complaint/edit.vue
  12. 62
      src/subpackage/message/pages/complaint/list.vue
  13. 99
      src/subpackage/message/pages/work_order/edit.vue

16
src/pages.json

@ -1,6 +1,10 @@
{
"pages": [ //pageshttps://uniapp.dcloud.io/collocation/pages
{
"path": "pages/index/index",
"style": { }
},
{
"path": "pages/menu/forth",
"style": {
"navigationBarTitleText": "个人中心",
@ -11,11 +15,7 @@
}
}
},
{
"path": "pages/index/index",
"style": {
}
},
{
"path": "pages/login/login",
"style": {
@ -932,6 +932,12 @@
"style" : {
"navigationBarTitleText": "投诉详情"
}
},
{
"path": "pages/work_order/edit",
"style" : {
"navigationBarTitleText": "提交工单"
}
}
]
},

10
src/pages/menu/forth.vue

@ -13,7 +13,12 @@
</line-tab>
<line-tab :icon-num='1'>帮助中心</line-tab>
<line-tab :icon-num='2'>教练助手</line-tab>
<line-tab :icon-num='3'>收银系统</line-tab>
<line-tab :icon-num='3'>
<template slot="default">收银系统</template>
<template slot="right">
<view class="fm-copy">(复制网址)</view>
</template>
</line-tab>
<line-tab :icon-num='4'>总后台(<text class="fm-txt">admin.ouxuanzhineng.cn <text class="ft-copy">复制</text></text>)</line-tab>
<line-tab :icon-num='5'>投诉建议</line-tab>
<line-tab :icon-num='6'>解绑退出</line-tab>
@ -63,4 +68,7 @@ export default {
height: 30upx;
}
}
.fm-copy{
@include flcw(32upx, 44upx, $mColor);
}
</style>

33
src/store/actions.js

@ -1,6 +1,8 @@
// 异步方法
import { servers } from '../js/server';
import { API } from '../js/api';
import { showLoad, hideLoad, showModal } from '../utils/util';
export default {
getBrandInfo({commit, state}){
if(state?.brandInfo?.brand?.id)return Promise.resolve(state.brandInfo);
@ -24,5 +26,34 @@ export default {
.catch(err=>{
console.warn('actions getOrderRefundList err -->', err);
})
}
},
// 获取门店列表
getStadiumLs({ commit, state }, brand_id){
showLoad();
return servers.post({
url: API.stadiumList,
data: { page_size: 9999, page: 1, brand_id },
isDefaultGet: false,
})
.then(res => {
hideLoad();
let _data = res?.data || {};
if(_data.code === 0){
let _ls = _data?.data?.list || [];
return _ls;
}else{
return Promise.reject(_data);
}
})
.catch(err => {
hideLoad();
showModal({
title: '提示',
content: err.message || '加载店铺失败!'
})
console.warn('store actions getStadiumLs err --->', err);
// return Promise.reject(err);
})
},
}

4
src/subpackage/message/components/edit/fixed_button.vue

@ -1,7 +1,7 @@
<template>
<view class="fixed-button">
<button class="fb-btn">取消</button>
<button class="fb-btn">提交</button>
<button class="fb-btn" @click="$emit('click:cancel')">取消</button>
<button class="fb-btn" @click="$emit('click:submit')">提交</button>
</view>
</template>

78
src/subpackage/message/components/edit/info_edit.vue

@ -1,11 +1,11 @@
<template>
<view class="info-edit">
<!-- 门店picker -->
<view class="ie-stadium">
<view class="ie-stadium" v-if="isStadium">
<view class="ie-title"><text class="it-star">*</text>门店</view>
<picker mode="selector">
<picker mode="selector" :range="stadiumList" range-key="name" @change="stadiumChange">
<view class="is-box">
<input type="text" class="ib-ipt" disabled/>
<input type="text" class="ib-ipt" placeholder="请选择门店" :value="fromData.curStadium.name || ''" disabled/>
<image class="ib-icon" mode="aspectFit" src="/subpackage/message/static/images/unfold.png"></image>
</view>
</picker>
@ -13,14 +13,14 @@
<!-- 标题 -->
<view class="ie-section">
<view class="ie-title"><text class="it-star">*</text>标题</view>
<input type="text" class="ie-ipt" placeholder="请输入" />
<input type="text" class="ie-ipt" placeholder="请输入" v-model="fromData.titleStr" />
</view>
<!-- 类型 -->
<view class="ie-types">
<view class="ie-types" v-if="isStadium">
<view class="ie-title"><text class="it-star">*</text>类型</view>
<view class="it-ls">
<view class="il-item" v-for="(e, i) in ['硬件', '软件']" :key="i">
<view class="ii-icon" :class="{ active: i === 0 }"></view>
<view class="il-item" v-for="(e, i) in ['硬件', '软件']" :key="i" @click="fromData.typeStr = e">
<view class="ii-icon" :class="{ 'active': e === fromData.typeStr }"></view>
<view class="ii-txt">{{ e || '' }}</view>
</view>
</view>
@ -28,14 +28,73 @@
<!-- 反馈内容 -->
<view class="ie-section">
<view class="ie-title"><text class="it-star">*</text>反馈内容</view>
<textarea class="ie-tarea" placeholder="请输入"></textarea>
<textarea class="ie-tarea" placeholder="请输入" v-model="fromData.feedbackStr"></textarea>
</view>
</view>
</template>
<script>
import { showNone } from "@/utils/util"
export default {
props: {
isStadium: {
type: Boolean,
default: false
},
isType: {
type: Boolean,
default: false
}
},
data(){
return {
stadiumList: [],
fromData: {
curStadium: {},
titleStr: '',
typeStr: '硬件',
feedbackStr: '',
},
}
},
methods: {
async initStadiumLs({ brand_id, stadium_id }){
let _stadiums = await this.$store?.dispatch?.('getStadiumLs', brand_id);
if(_stadiums.length > 0)this.stadiumList = _stadiums ?? [];
if(stadium_id){
let _curStadium = _stadiums.find(item => item.id === stadium_id);
if(_curStadium?.id)this.fromData.curStadium = _curStadium;
}
},
stadiumChange(e){
let { value } = e.detail;
if(value === -1)return;
this.fromData.curStadium = this.stadiumList[value];
},
async getData(){
let { fromData, isStadium, isType } = this;
let { curStadium, titleStr, typeStr, feedbackStr } = fromData;
if(titleStr === ''){
showNone('请输入标题');
return Promise.reject('请输入标题');
}
if(feedbackStr === ''){
showNone('请输入反馈内容');
return Promise.reject('请输入反馈内容');
}
if(isStadium&&!curStadium?.id){
showNone('请选择门店');
return Promise.reject('请选择门店');
}
let _data = {
title: titleStr,
content: feedbackStr,
}
if(isType)_data['type'] = typeStr;
if(isStadium)_data['stadium_id'] = curStadium.id;
return _data;
}
}
}
</script>
@ -65,6 +124,7 @@ export default {
}
.ie-tarea{
height: 306upx;
width: auto;
}
.ie-stadium{
@include ctf;

104
src/subpackage/message/components/edit/upload_img.vue

@ -1,12 +1,12 @@
<template>
<view class="upload-img">
<view class="ui-title">上传照片<text class="ut-txt">(最多上传3只支持.jpgpng 格式)</text></view>
<view class="ui-title">上传照片<text class="ut-txt">(最多上传{{ max }}只支持.jpgpng 格式)</text></view>
<view class="ui-ls">
<view class="ul-item" v-for="i in 4" :key="i">
<image class="ui-pic"></image>
<image class="ui-close" mode="aspectFit" src="/subpackage/message/static/images/close.png"></image>
<view class="ul-item" v-for="(e, i) in imgTemLs" :key="i">
<image class="ui-pic" @click="previewImg(e)" mode="aspectFit" :src="e"></image>
<image class="ui-close" @click="delImg(i)" mode="aspectFit" src="/subpackage/message/static/images/close.png"></image>
</view>
<view class="ul-item ul-add">
<view class="ul-item ul-add" @click="chooseImg" v-if="max > imgTemLs.length">
<view class="ua-icon"></view>
<view class="ua-txt">上传照片</view>
</view>
@ -15,8 +15,101 @@
</template>
<script>
import { showModal, jsonPar, showLoad, hideLoad, promisify } from "@/utils/util";
import server from "../../js/server";
import { MESSAGE_API } from "../../js/api";
export default {
props: {
max: {
type: Number,
default: 3
}
},
data(){
return {
imgTemLs: [],
}
},
methods: {
chooseImg(){
uni.chooseImage({
count: 3,
sourceType: ['album', 'camera'],
success: (res) => {
let { imgTemLs } = this;
if(imgTemLs.length >= 3)return showModal({ content: '最多上传3张图片!' });
this.imgTemLs = imgTemLs.concat(res.tempFilePaths);
}
});
},
delImg(idx){
this.imgTemLs.splice(idx, 1);
},
previewImg(url){
uni.previewImage({ urls: this.imgTemLs, current: url });
},
async getUrls(){
try{
let _urls = [];
let { imgTemLs } = this;
showLoad('图片上传中...');
for(let i = 0; i < imgTemLs?.length; i++){
let _url = await this.uploadImg(imgTemLs[i]);
if(_url !== '')_urls.push(_url);
}
if(_urls?.length < imgTemLs?.length){
let _showModal = promisify(showModal);
hideLoad();
if(_urls?.length === 0){
return _showModal({ content: '图片上传失败,请稍后重试' })
.then(_=>Promise.reject('全部图片上传失败'));
}
let _diffVal = imgTemLs?.length - _urls?.length;
return _showModal({
content: `${_diffVal}张图片上传失败`,
showCancel: true,
cancelText: '重试',
confirmText: '继续提交',
})
.then(res=>{
if(res.confirm)return { temps: imgTemLs, urls: _urls };
return Promise.reject(res);
})
}
hideLoad();
return {
temps: imgTemLs,
urls: _urls,
};
}catch(err){
hideLoad();
console.warn('message components edit upload_img getUrls err --->', err)
}
},
async uploadImg(url){
try{
let _imgInfo = await server.uploadFile({
url: MESSAGE_API.zs_message_imgs,
filePath: url,
});
if(_imgInfo.statusCode != 200)throw(_imgInfo);
let _imgRes = jsonPar(_imgInfo.data);
if(_imgRes.code != 0)throw(_imgRes);
return _imgRes?.data?.url ?? '';
}catch(err){
// showModal({
// titile: '',
// content: err?.errMsg ?? err?.message ?? ''
// });
console.warn('message components edit upload_img uploadImg err --->', err)
// return Promise.reject(err);
return '';
}
},
}
}
</script>
@ -50,7 +143,6 @@ export default {
width: 100%;
height: 100%;
border-radius: 10upx;
background: skyblue;
}
.ui-close{
position: absolute;

2
src/subpackage/message/components/fixed_button.vue

@ -1,6 +1,6 @@
<template>
<view class="fixed-button">
<button class="fb-btn" hover-class="hover-active">新建投诉</button>
<button class="fb-btn" hover-class="hover-active" @click="$emit('click')">新建投诉</button>
</view>
</template>

21
src/subpackage/message/components/message_item.vue

@ -4,10 +4,10 @@
<view class="mi-content">
<view class="mc-info">
<view class="mi-top">
<view class="mt-title">标题</view>
<view class="mt-tag">返回的状态</view>
<view class="mt-title">{{ title || '-' }}</view>
<view class="mt-tag" v-if="status">{{ status || '-' }}</view>
</view>
<view class="mi-content">巴拉巴拉巴拉....</view>
<view class="mi-content">{{ content || '-' }}</view>
</view>
<image class="mc-arrow"></image>
</view>
@ -16,7 +16,20 @@
<script>
export default {
props: {
title: {
type: String,
default: ''
},
status: {
type: String,
default: ''
},
content: {
type: String,
default: ''
}
},
}
</script>

11
src/subpackage/message/js/api.js

@ -0,0 +1,11 @@
import { ORIGIN } from '@/js/api';
export const MESSAGE_API = {
zs_message_imgs:`${ORIGIN}/upload/file/zs_message_imgs`, // 投诉/工单图片
complaintSubmit:`${ORIGIN}/admin/assistant/complaint/submit`, // 投诉提交
complaintList:`${ORIGIN}/admin/assistant/complaint/list`, // 投诉列表
workorderSubmit:`${ORIGIN}/admin/assistant/workorder/submit`, // 工单提交
}
export default { ORIGIN, MESSAGE_API };

9
src/subpackage/message/js/server.js

@ -0,0 +1,9 @@
import { Server } from '@/js/server';
class _server extends Server {
constructor(props){
super(props)
}
}
export default new _server();

73
src/subpackage/message/pages/complaint/edit.vue

@ -1,9 +1,12 @@
<template>
<view class="complaint-edit">
<info-edit></info-edit>
<info-edit ref="infoEdit"></info-edit>
<view style="height: 24rpx;"></view>
<upload-img></upload-img>
<fixed-button></fixed-button>
<upload-img ref="uploadImg"></upload-img>
<fixed-button
@click:cancel="cancelBtn"
@click:submit="submitBtn"
></fixed-button>
</view>
</template>
@ -11,12 +14,68 @@
import infoEdit from "../../components/edit/info_edit.vue";
import uploadImg from "../../components/edit/upload_img.vue";
import fixedButton from "../../components/edit/fixed_button.vue";
import { routeTo, debounce, showLoad, hideLoad, showModal, showNone } from "@/utils/util.js";
import { MESSAGE_API } from "../../js/api.js";
import server from "../../js/server.js";
export default {
components: {
infoEdit,
uploadImg,
fixedButton,
components: { infoEdit, uploadImg, fixedButton },
data() {
return {
brand_id: '',
}
},
onLoad(options) {
let _bid = options?.brand_id ?? '';
this.brand_id = _bid;
},
methods: {
cancelBtn: routeTo,
submitBtn: debounce(async function(){
try{
let { brand_id } = this;
let _infoData = await this.$refs?.infoEdit?.getData?.();
let { urls, temps } = await this.$refs?.uploadImg?.getUrls?.();
this.complaintSubmit({
brand_id,
title: _infoData?.title ?? '',
content: _infoData?.content ?? '',
showimgs: urls ?? [],
})
}catch(err){
hideLoad();
console.warn('subpackage message pages complaint edit submitBtn err --->', err);
}
}, 300, true),
//
complaintSubmit({ brand_id, title = '', content = '', showimgs = [] }){
showLoad();
return server.post({
url: MESSAGE_API.complaintSubmit,
data: { brand_id: +brand_id, title, content, showimgs },
isDefaultGet: false,
})
.then(res => {
hideLoad();
let _data = res?.data || {};
if(_data.code === 0){
showNone(_data?.message ?? '操作成功!');
setTimeout(routeTo, 1000);
}else{
return Promise.reject(_data);
}
})
.catch(err => {
hideLoad();
showModal({
title: '提示',
content: err.message || '操作失败!'
})
console.warn('subpackage message pages complaint edit complaintSubmit err --->', err);
// return Promise.reject(err);
})
},
}
}
</script>

62
src/subpackage/message/pages/complaint/list.vue

@ -1,20 +1,78 @@
<template>
<view class="complaint-list">
<view class="cl-ls">
<message-item></message-item>
<block v-for="(e, i) in listData" :key="i">
<message-item
:title="e.title"
:status="e.status"
:content="e.content"
></message-item>
<view style="height: 24rpx;"></view>
</block>
</view>
<fixed-button></fixed-button>
<fixed-button @click="clickBtn"></fixed-button>
</view>
</template>
<script>
import fixedButton from "../../components/fixed_button.vue";
import messageItem from "../../components/message_item.vue";
import { routeTo, debounce, showLoad, hideLoad, showModal, showNone } from "@/utils/util.js";
import { MESSAGE_API } from "../../js/api.js";
import server from "../../js/server.js";
export default {
components: {
fixedButton,
messageItem,
},
data(){
return {
brand_id: '',
listData: [],
}
},
onLoad(options){
let _bid = options?.brand_id ?? '';
this.brand_id = _bid;
this.complaintList({ brand_id: _bid });
},
methods: {
clickBtn(){
let { brand_id } = this;
routeTo(`/subpackage/message/pages/complaint/edit?brand_id=${brand_id ?? ''}`, 'nT');
},
complaintList({ brand_id, page = 1, page_size = 20}){
showLoad();
return server.post({
url: MESSAGE_API.complaintList,
data: { brand_id: +brand_id, page, page_size },
isDefaultGet: false,
})
.then(res => {
hideLoad();
let _data = res?.data || {};
if(_data.code === 0){
let _ls = _data?.data ?? [];
if(page === 1)return this.listData = _ls;
if(!_ls.length)return showNone('没有更多!');
this.page = page;
this.listData = [ ...this.listData, ..._ls ];
return _ls;
}else{
return Promise.reject(_data);
}
})
.catch(err => {
hideLoad();
showModal({
title: '提示',
content: err.message || '加载失败!'
})
console.warn('subpackage message pages complaint list complaintList err --->', err);
// return Promise.reject(err);
})
},
}
}
</script>

99
src/subpackage/message/pages/work_order/edit.vue

@ -0,0 +1,99 @@
<template>
<view class="work-order-edit">
<info-edit
ref="infoEdit"
is-stadium
is-type
></info-edit>
<view style="height: 24rpx;"></view>
<upload-img ref="uploadImg"></upload-img>
<fixed-button
@click:cancel="cancelBtn"
@click:submit="submitBtn"
></fixed-button>
</view>
</template>
<script>
import infoEdit from "../../components/edit/info_edit.vue";
import uploadImg from "../../components/edit/upload_img.vue";
import fixedButton from "../../components/edit/fixed_button.vue";
import { routeTo, debounce, showLoad, hideLoad, showModal, showNone } from "@/utils/util.js";
import { MESSAGE_API } from "../../js/api.js";
import server from "../../js/server.js";
export default {
components: { infoEdit, uploadImg, fixedButton },
data() {
return {
brand_id: '',
}
},
onLoad(options) {
let _bid = options?.brand_id ?? '';
this.brand_id = _bid;
this.$nextTick(_=>{
this.$refs?.infoEdit?.initStadiumLs?.({
brand_id: _bid,
stadium_id: +(options?.stadium_id ?? '')
});
})
},
methods: {
cancelBtn: routeTo,
submitBtn: debounce(async function(){
try{
let { brand_id } = this;
let _infoData = await this.$refs?.infoEdit?.getData?.();
let { urls, temps } = await this.$refs?.uploadImg?.getUrls?.();
this.workorderSubmit({
brand_id,
stadium_id: _infoData?.stadium_id ?? '',
type: _infoData?.type ?? '',
title: _infoData?.title ?? '',
content: _infoData?.content ?? '',
showimgs: urls ?? [],
})
}catch(err){
hideLoad();
console.warn('subpackage message pages work order edit submitBtn err --->', err);
}
}, 300, true),
//
workorderSubmit({ brand_id, stadium_id, type, title = '', content = '', showimgs = [] }){
showLoad();
return server.post({
url: MESSAGE_API.workorderSubmit,
data: { brand_id: +brand_id, stadium_id, type, title, content, showimgs },
isDefaultGet: false,
})
.then(res => {
hideLoad();
let _data = res?.data || {};
if(_data.code === 0){
showNone(_data?.message ?? '操作成功!');
setTimeout(routeTo, 1000);
}else{
return Promise.reject(_data);
}
})
.catch(err => {
hideLoad();
showModal({
title: '提示',
content: err.message || '操作失败!'
})
console.warn('subpackage message pages work order edit workorderSubmit err --->', err);
// return Promise.reject(err);
})
},
}
}
</script>
<style lang="scss">
.work-order-edit{
padding: 24upx;
@include isPd(120upx);
}
</style>
Loading…
Cancel
Save