-
3src/App.vue
-
5src/js/api.js
-
12src/js/server.js
-
3src/main.js
-
4src/manifest.json
-
133src/pages.json
-
377src/pages/index/index.vue
-
6src/pages/login/login.vue
-
243src/pages/menu/forth.vue
-
32src/pages/menu/second.vue
-
117src/pages/menu/third.vue
-
4src/pages/merchant_login/merchant_login.vue
-
3src/pages/web_view/web_view.vue
-
BINsrc/static/images/icon/arrow_b2.png
-
BINsrc/static/images/icon/index/green_bg_circle.png
-
BINsrc/static/images/icon/index/tab_12.png
-
BINsrc/static/images/icon/index/tab_13.png
-
BINsrc/static/images/icon/index/tab_8.png
-
BINsrc/static/images/icon/scan_code_btn.png
-
BINsrc/static/images/icon/selected_ring.png
-
BINsrc/static/images/icon/write_off_fail.png
-
BINsrc/static/images/tab/ta_1.png
-
BINsrc/static/images/tab/ta_2.png
-
BINsrc/static/images/tab/ta_3.png
-
BINsrc/static/images/tab/ta_4.png
-
BINsrc/static/images/tab/tab_1.png
-
BINsrc/static/images/tab/tab_2.png
-
BINsrc/static/images/tab/tab_3.png
-
BINsrc/static/images/tab/tab_4.png
-
BINsrc/static/images/third_pages/banner.png
-
BINsrc/static/images/third_pages/bg.png
-
BINsrc/static/images/third_pages/tab_a.png
-
BINsrc/static/images/third_pages/tab_b.png
-
74src/store/actions.js
-
24src/store/index.js
-
13src/store/mutations.js
-
188src/subpackage/authorization/components/login.vue
-
25src/subpackage/authorization/components/user_info/iconfont.css
-
133src/subpackage/authorization/components/user_info/impower.vue
-
357src/subpackage/authorization/components/user_info/tuniaoui-wx-user-info.vue
-
9src/subpackage/authorization/js/api.js
-
10src/subpackage/authorization/js/server.js
-
16src/subpackage/authorization/pages/index.vue
-
0src/subpackage/authorization/static/images/author_modal.png
-
41src/subpackage/menu/components/bottom_logo.vue
-
87src/subpackage/menu/components/mine/header.vue
-
63src/subpackage/menu/components/mine/line_tab.vue
-
16src/subpackage/menu/pages/index.vue
-
BINsrc/subpackage/menu/static/images/arrow_b2.png
-
BINsrc/subpackage/menu/static/images/bot_logo.png
-
BINsrc/subpackage/menu/static/images/mine_tab/0.png
-
BINsrc/subpackage/menu/static/images/mine_tab/1.png
-
BINsrc/subpackage/menu/static/images/mine_tab/2.png
-
BINsrc/subpackage/menu/static/images/mine_tab/3.png
-
BINsrc/subpackage/menu/static/images/mine_tab/4.png
-
BINsrc/subpackage/menu/static/images/mine_tab/5.png
-
BINsrc/subpackage/menu/static/images/mine_tab/6.png
-
59src/subpackage/message/components/detail/answer_item.vue
-
51src/subpackage/message/components/detail/image_flow.vue
-
60src/subpackage/message/components/detail/info.vue
-
37src/subpackage/message/components/edit/fixed_button.vue
-
195src/subpackage/message/components/edit/info_edit.vue
-
189src/subpackage/message/components/edit/upload_img.vue
-
33src/subpackage/message/components/fixed_button.vue
-
85src/subpackage/message/components/message_item.vue
-
16src/subpackage/message/js/api.js
-
9src/subpackage/message/js/server.js
-
171src/subpackage/message/pages/complaint/detail.vue
-
87src/subpackage/message/pages/complaint/edit.vue
-
105src/subpackage/message/pages/complaint/list.vue
-
171src/subpackage/message/pages/work_order/detail.vue
-
99src/subpackage/message/pages/work_order/edit.vue
-
105src/subpackage/message/pages/work_order/list.vue
-
BINsrc/subpackage/message/static/images/arrow_b2.png
-
BINsrc/subpackage/message/static/images/close.png
-
BINsrc/subpackage/message/static/images/message.png
-
BINsrc/subpackage/message/static/images/unfold.png
-
14src/subpackage/verification/pages/record.vue
-
4src/subpackage/wallet/pages/index/index.vue
-
12src/uni.scss
-
8src/utils/util.js
@ -0,0 +1,243 @@ |
|||
<template> |
|||
<view class="forth-menu"> |
|||
<!-- 后端: account-> 如果有手机号就显示手机号 没有的话显示username, 都没有的话就空好了 --> |
|||
<mine-header |
|||
:is-login="loginState" |
|||
:nickname="userInfo.nickname" |
|||
:name="userInfo.actual_name" |
|||
:account="userInfo.mobile || userInfo.username || ''" |
|||
:photo="userInfo.avatar_url" |
|||
@on:munted="menuPackageLoaded = true" |
|||
@click:login="loginBtn" |
|||
@click:update="updateUser" |
|||
></mine-header> |
|||
<block v-if="menuPackageLoaded"> |
|||
<line-tab :icon-num='0'> |
|||
<template slot="default">账号管理</template> |
|||
<template slot="right"> |
|||
<view class="ft-account"> |
|||
<view class="fc-name" v-if="loginState">{{ accountName || '-' }}</view> |
|||
<image class="fc-icon" mode="aspectFit" src="/static/images/icon/arrow_b2.png"></image> |
|||
</view> |
|||
</template> |
|||
</line-tab> |
|||
<line-tab :icon-num='1' @click="toWebView(deadData.helpCenterLink)">帮助中心</line-tab> |
|||
<block v-if="loginState"> |
|||
<line-tab :icon-num='2' @click="toMiniProgram(deadData.assistantCoachAppid)">教练助手</line-tab> |
|||
<line-tab :icon-num='3'> |
|||
<template slot="default">收银系统</template> |
|||
<template slot="right"> |
|||
<view class="fm-copy" @click="copyLink(deadData.cashierSystemLink)">(复制网址)</view> |
|||
</template> |
|||
</line-tab> |
|||
<line-tab :icon-num='4' @click="toWebView(deadData.backstageLink)"> |
|||
<view class="fm-admin"> |
|||
<view class="fa-txt">总后台<text class="ft-txt">({{ deadData.backstageLink }})</text></view><view class="fa-copy" @click.stop="copyLink(deadData.backstageLink)">复制</view> |
|||
</view> |
|||
</line-tab> |
|||
</block> |
|||
<line-tab :icon-num='5' @click="toComplaint">投诉建议</line-tab> |
|||
<line-tab :icon-num='6' v-if="loginState" @click="unBindBtn">解绑退出</line-tab> |
|||
</block> |
|||
<bottom-logo></bottom-logo> |
|||
|
|||
<authorization-login ref="authorizationLogin"></authorization-login> |
|||
<authorization-user ref="authorizationUser"></authorization-user> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import mineHeader from "@/subpackage/menu/components/mine/header.vue"; |
|||
import lineTab from "@/subpackage/menu/components/mine/line_tab.vue"; |
|||
import bottomLogo from "@/subpackage/menu/components/bottom_logo.vue"; |
|||
import authorizationLogin from "@/subpackage/authorization/components/login.vue"; |
|||
import authorizationUser from "@/subpackage/authorization/components/user_info/impower.vue"; |
|||
import { routeTo, debounce, showLoad, hideLoad, showModal, showNone, jsonStr } from "@/utils/util.js"; |
|||
import { mapGetters, mapState } from 'vuex'; |
|||
import { servers } from '../../js/server'; |
|||
import { API } from '../../js/api'; |
|||
export default { |
|||
components:{ |
|||
mineHeader, |
|||
lineTab, |
|||
bottomLogo, |
|||
authorizationLogin, |
|||
authorizationUser, |
|||
}, |
|||
data(){ |
|||
return { |
|||
// 异步组件加载完成状态 |
|||
menuPackageLoaded: false, |
|||
userInfo: {}, |
|||
deadData: { |
|||
helpCenterLink: 'https://help.ouxuanzhineng.cn/', // 帮助中心 |
|||
cashierSystemLink: 'https://kb.ouxuanzhineng.cn/', // 收银系统 |
|||
backstageLink: 'https://admin.ouxuanzhineng.cn/', // 总后台 |
|||
assistantCoachAppid: 'wxd71043ec955dfecf', // 教练助手:AppID |
|||
}, |
|||
} |
|||
}, |
|||
computed: { |
|||
...mapGetters([ 'loginState' ]), |
|||
...mapState([ 'brandInfo' ]), |
|||
extension(){ |
|||
return this.userInfo?.extension || {} |
|||
}, |
|||
/** |
|||
* @param {string} permission_type 1:ADMIN-STADIUM 2:ADMIN-BRAND |
|||
* */ |
|||
permissionType(){ |
|||
return this.userInfo?.extension?.permission_type || ''; |
|||
}, |
|||
accountName(){ |
|||
let { permissionType, extension } = this; |
|||
if(permissionType === 'ADMIN-STADIUM')return extension?.stadium_name ?? ''; |
|||
if(permissionType === 'ADMIN-BRAND')return extension?.brand_name ?? ''; |
|||
return ''; |
|||
} |
|||
}, |
|||
onLoad(options){ |
|||
if(this.loginState)this.getUserInfo(); |
|||
}, |
|||
methods: { |
|||
// 解绑 |
|||
unBindBtn: debounce(function(){ |
|||
let { userInfo } = this; |
|||
if(!userInfo?.id)return showModal({ content: '用户信息有误' }) |
|||
showModal({ |
|||
content: '您确定要解绑退出吗?', |
|||
showCancel: true, |
|||
success: mRes=>{ |
|||
if(mRes.confirm)this.unBindReq(userInfo.id); |
|||
} |
|||
}) |
|||
|
|||
}, 300, true), |
|||
// 解绑请求 |
|||
unBindReq(user_id){ |
|||
showLoad(); |
|||
return servers.post({ |
|||
url: API.mine.unbindAssistant, |
|||
data: { user_id }, |
|||
isDefaultGet: false, |
|||
}) |
|||
.then(res => { |
|||
hideLoad(); |
|||
let _data = res?.data || {}; |
|||
if(_data.code === 0){ |
|||
showNone('操作成功!'); |
|||
setTimeout(() => { |
|||
this.$store.commit('setLoginState', { loginState: false }); |
|||
routeTo(`/pages/login/login`,'rL'); |
|||
}, 1000); |
|||
console.log('pages menu unBindReq res --->', _data); |
|||
}else{ |
|||
return Promise.reject(_data); |
|||
} |
|||
}) |
|||
.catch(err => { |
|||
hideLoad(); |
|||
showModal({ content: err?.message || '操作失败!' }); |
|||
console.warn('pages menu unBindReq err --->', err); |
|||
// return Promise.reject(err); |
|||
}) |
|||
}, |
|||
// 更新用户信息 |
|||
updateUser(){ |
|||
this.$refs?.authorizationUser?.show?.({ success: this.getUserInfo }); |
|||
}, |
|||
// 跳转小程序 |
|||
toMiniProgram(appid){ |
|||
uni.navigateToMiniProgram({ appId: appid }); |
|||
}, |
|||
// 跳转网页 |
|||
toWebView(url){ |
|||
routeTo(`/pages/web_view/web_view?src=${jsonStr(url)}`, 'nT'); |
|||
}, |
|||
// 复制链接 |
|||
copyLink(url){ |
|||
uni.setClipboardData({ data: url }); |
|||
}, |
|||
// 投诉建议 |
|||
toComplaint(){ |
|||
let { loginState, showAuthor, brandInfo } = this; |
|||
if(!loginState)return showAuthor(); |
|||
routeTo(`/subpackage/message/pages/complaint/list?brand_id=${brandInfo?.brand?.id}`, 'nT'); |
|||
}, |
|||
// 登录 |
|||
loginBtn(){ |
|||
this.showAuthor(); |
|||
}, |
|||
showAuthor(){ |
|||
this.$refs?.authorizationLogin?.alert?.({ success: this.getUserInfo }); |
|||
}, |
|||
getUserInfo(){ |
|||
showLoad(); |
|||
return servers.post({ |
|||
url: API.mine.userCurrent, |
|||
data: {}, |
|||
isDefaultGet: false, |
|||
}) |
|||
.then(res => { |
|||
hideLoad(); |
|||
let _data = res?.data || {}; |
|||
if(_data.code === 0){ |
|||
this.userInfo = _data?.data || {}; |
|||
console.log('pages menu getUserInfo res --->', _data); |
|||
}else{ |
|||
return Promise.reject(_data); |
|||
} |
|||
}) |
|||
.catch(err => { |
|||
hideLoad(); |
|||
showModal({ content: err?.message || '加载用户失败!' }); |
|||
console.warn('pages menu getUserInfo err --->', err); |
|||
// return Promise.reject(err); |
|||
}) |
|||
}, |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
.forth-menu{ |
|||
|
|||
} |
|||
.fm-txt{ |
|||
font-size: 28upx; |
|||
.ft-copy{ |
|||
color: $mColor; |
|||
} |
|||
} |
|||
.ft-account{ |
|||
@include ctf(flex-end); |
|||
.fc-name{ |
|||
@include flcw(32upx, 48upx, #9A9A9D); |
|||
@include tHide; |
|||
} |
|||
.fc-icon{ |
|||
flex-shrink: 0; |
|||
margin-left: 22upx; |
|||
width: 30upx; |
|||
height: 30upx; |
|||
} |
|||
} |
|||
.fm-copy{ |
|||
@include flcw(32upx, 44upx, $mColor); |
|||
} |
|||
.fm-admin{ |
|||
@include ctf; |
|||
.fa-txt{ |
|||
@include flcw(32upx, 44upx, #9A9A9D); |
|||
@include tHide; |
|||
.ft-txt{ |
|||
font-size: 28upx; |
|||
} |
|||
} |
|||
.fa-copy{ |
|||
padding: 0upx 10upx; |
|||
flex-shrink: 0; |
|||
@include flcw(28upx, 44upx, $mColor); |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,32 @@ |
|||
<template> |
|||
<view class="second-pages"> |
|||
<view class="sp-post"> |
|||
<view class="sp-box"> |
|||
<view class="tl-tit">板块更新中</view> |
|||
</view> |
|||
</view> |
|||
<bottom-logo is-fixed></bottom-logo> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import bottomLogo from "@/subpackage/menu/components/bottom_logo.vue"; |
|||
export default { |
|||
components:{ bottomLogo }, |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
.sp-post{ |
|||
padding: 24upx; |
|||
.sp-box{ |
|||
padding: 22upx 28upx; |
|||
height: 400upx; |
|||
background-image: linear-gradient(270deg, #d7d7da 0%, $mColor 100%); |
|||
.tl-tit{ |
|||
@include flcw(43upx, 60upx, #fff, 500); |
|||
@include tHide; |
|||
} |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,117 @@ |
|||
<template> |
|||
<view class="third-page"> |
|||
<view class="tp-container"> |
|||
<image class="tc-post" mode="aspectFit" src="/static/images/third_pages/banner.png"></image> |
|||
<view class="tc-bot"> |
|||
<view class="tb-left" @click="clickTap"> |
|||
<image class="tl-bg" mode="aspectFill" src="/static/images/third_pages/bg.png"></image> |
|||
<view class="tl-tit">采购商城</view> |
|||
<view class="tl-txt">采购专业装备</view> |
|||
</view> |
|||
<view class="tb-right"> |
|||
<view class="tr-item active" @click="clickTap"> |
|||
<view class="ti-title">客服外包</view> |
|||
<view class="ti-text">客服外包</view> |
|||
<image class="tr-icon" src="/static/images/third_pages/tab_a.png"></image> |
|||
</view> |
|||
<view class="tr-item" @click="clickTap"> |
|||
<view class="ti-title">敬请期待</view> |
|||
<view class="ti-text">敬请期待</view> |
|||
<image class="tr-icon" src="/static/images/third_pages/tab_b.png"></image> |
|||
</view> |
|||
<view class="tr-item" @click="clickTap"> |
|||
<view class="ti-title">敬请期待</view> |
|||
<view class="ti-text">敬请期待</view> |
|||
<image class="tr-icon" src="/static/images/third_pages/tab_b.png"></image> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
<bottom-logo is-fixed></bottom-logo> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import bottomLogo from "@/subpackage/menu/components/bottom_logo.vue"; |
|||
import { showNone } from "@/utils/util"; |
|||
export default { |
|||
components:{ bottomLogo }, |
|||
methods: { |
|||
clickTap(){ |
|||
showNone('板块更新中'); |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
.third-page{ |
|||
.tp-container{ |
|||
padding: 28upx 24upx 0upx; |
|||
.tc-post{ |
|||
display: block; |
|||
height: 400upx; |
|||
width: 100%; |
|||
} |
|||
.tc-bot{ |
|||
margin-top: 24upx; |
|||
display: flex; |
|||
align-items: stretch; |
|||
.tb-left{ |
|||
position: relative; |
|||
flex-shrink: 0; |
|||
margin-right: 22upx; |
|||
padding: 22upx 28upx; |
|||
width: 340upx; |
|||
height: 420upx; |
|||
.tl-bg{ |
|||
position: absolute; |
|||
left: 0; |
|||
top: 0; |
|||
width: 100%; |
|||
height: 100%; |
|||
z-index: -1; |
|||
} |
|||
.tl-tit{ |
|||
@include flcw(43upx, 60upx, #fff, 500); |
|||
@include tHide; |
|||
} |
|||
.tl-txt{ |
|||
@include flcw(30upx, 42upx, #fff, 500); |
|||
@include tHide; |
|||
} |
|||
} |
|||
.tb-right{ |
|||
flex-grow: 1; |
|||
display: flex; |
|||
flex-direction: column; |
|||
justify-content: space-between; |
|||
.tr-item{ |
|||
position: relative; |
|||
height: 124upx; |
|||
background-image: linear-gradient(270deg, #FFFFFF 0%, #C8C8CA 100%); |
|||
padding: 16upx; |
|||
&.active{ |
|||
background-image: linear-gradient(270deg, #F2D286 0%, #E0A46F 100%); |
|||
} |
|||
.ti-title{ |
|||
@include flcw(32upx, 44upx, #fff, 500); |
|||
@include tHide; |
|||
} |
|||
.ti-text{ |
|||
@include flcw(22upx, 32upx, #fff, 500); |
|||
@include tHide; |
|||
} |
|||
.tr-icon{ |
|||
position: absolute; |
|||
right: 6upx; |
|||
bottom: 0upx; |
|||
width: 136upx; |
|||
height: 104upx; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</style> |
Before Width: 40 | Height: 40 | Size: 251 B After Width: 15 | Height: 15 | Size: 226 B |
Before Width: 296 | Height: 296 | Size: 51 KiB After Width: 296 | Height: 296 | Size: 7.7 KiB |
Before Width: 52 | Height: 52 | Size: 2.4 KiB After Width: 52 | Height: 52 | Size: 901 B |
After Width: 52 | Height: 52 | Size: 1.2 KiB |
Before Width: 52 | Height: 52 | Size: 2.4 KiB After Width: 52 | Height: 52 | Size: 775 B |
Before Width: 172 | Height: 172 | Size: 932 B |
Before Width: 32 | Height: 32 | Size: 419 B |
Before Width: 420 | Height: 420 | Size: 9.6 KiB |
After Width: 56 | Height: 56 | Size: 558 B |
After Width: 56 | Height: 56 | Size: 795 B |
After Width: 56 | Height: 56 | Size: 726 B |
After Width: 56 | Height: 56 | Size: 553 B |
After Width: 56 | Height: 56 | Size: 653 B |
After Width: 56 | Height: 56 | Size: 986 B |
After Width: 56 | Height: 56 | Size: 939 B |
After Width: 56 | Height: 56 | Size: 668 B |
After Width: 351 | Height: 200 | Size: 23 KiB |
After Width: 170 | Height: 210 | Size: 2.5 KiB |
After Width: 68 | Height: 57 | Size: 2.3 KiB |
After Width: 68 | Height: 57 | Size: 1.9 KiB |
@ -0,0 +1,188 @@ |
|||
<template> |
|||
<view class="authorization-login" v-show="isShow"> |
|||
<view class="ic-author-modal"> |
|||
<view class="iam-title">微信授权</view> |
|||
<view class="iam-tip">您的信息和数据将受到保护</view> |
|||
<image class="iam-pic" mode="aspectFit" src="../static/images/author_modal.png"></image> |
|||
<view class="iam-btns"> |
|||
<button plain hover-class="hover-active" @click="hide">取消</button> |
|||
|
|||
<button |
|||
v-if="isProfile" |
|||
plain |
|||
hover-class="hover-active" |
|||
@click="profileConfirm" |
|||
>授权并登录</button> |
|||
<button |
|||
v-else |
|||
plain |
|||
hover-class="hover-active" |
|||
open-type="getUserInfo" |
|||
lang="zh_CN" |
|||
@getuserinfo="confirmAuthor" |
|||
>授权并登录</button> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import { promisify, showModal, showNone, showLoad, hideLoad, routeTo } from "@/utils/util"; |
|||
import { AUTHOR_API } from "../js/api"; |
|||
import server from "../js/server"; |
|||
export default { |
|||
data(){ |
|||
return { |
|||
isShow: false, |
|||
initData: { |
|||
/** |
|||
* @param {Object} data |
|||
* @param {Function} data.success |
|||
* @param {Function} data.fail |
|||
* */ |
|||
}, |
|||
} |
|||
}, |
|||
methods: { |
|||
alert(data){ |
|||
this.isShow = true; |
|||
this.initData = data ?? {}; |
|||
}, |
|||
hide(){ |
|||
this.isShow = false; |
|||
}, |
|||
isProfile(){ |
|||
return !!uni.getUserProfile |
|||
}, |
|||
// 新获取用户信息 |
|||
profileConfirm(){ |
|||
uni.getUserProfile({ |
|||
lang: 'zh_CN', desc: '授权登陆', |
|||
success: res => { this.confirmAuthor({detail: {...res}}) }, |
|||
fail: err => { |
|||
showModal({ content: '获取用户信息失败!请重试' }); |
|||
console.warn('subpackage authorization components login getUserProfile Err ->', err) |
|||
} |
|||
}) |
|||
}, |
|||
async confirmAuthor(userRes){ |
|||
if(!userRes.detail.userInfo){ |
|||
this.hide(); |
|||
return showModal({ content: '获取用户信息失败!请稍后重试' }); |
|||
} |
|||
|
|||
let loginRes = await promisify(uni.login)(); |
|||
if(!loginRes.code){ |
|||
this.hide(); |
|||
return showModal({ content: '获取登陆凭证失败!请稍后重试' }); |
|||
} |
|||
this.serverLogin({ userRes, loginRes }) |
|||
}, |
|||
getLoginQuery({ |
|||
userInfo, |
|||
loginRes |
|||
}){ |
|||
return { |
|||
appid: uni.getAccountInfoSync?.()?.miniProgram?.appId ?? '', |
|||
code: loginRes?.code ?? '', |
|||
encryptedData: userInfo?.encryptedData ?? '', |
|||
// is_details: 1, |
|||
// 后端解密错误,直接传用户信息 |
|||
user_info: userInfo?.userInfo ?? {}, |
|||
user_raw_data: userInfo?.rawData ?? {}, |
|||
...(userInfo?.userInfo ?? {}), |
|||
} |
|||
}, |
|||
serverLogin({ userRes, loginRes }){ |
|||
showLoad(); |
|||
return server.post({ |
|||
url: AUTHOR_API.wechatMiniAppLoginAndSync, |
|||
data: this.getLoginQuery({ |
|||
userInfo: userRes.detail, |
|||
loginRes |
|||
}), |
|||
isDefaultGet: false, |
|||
}) |
|||
.then(res=>{ |
|||
hideLoad(); |
|||
let _data = res.data || {}; |
|||
if(_data.code == 0){ |
|||
if(_data.data == '')return routeTo(`/pages/login/login`,'rL'); |
|||
showNone(_data?.message || '登陆成功!'); |
|||
this.$store.commit('setLoginState', { loginState: true, token: _data.data }); |
|||
this.initData?.success?.(_data); |
|||
this.hide(); |
|||
return _data; |
|||
}else{ |
|||
return Promise.reject(_data); |
|||
} |
|||
}) |
|||
.catch(err=>{ |
|||
hideLoad(); |
|||
showModal({ content: err?.message || '后台登陆失败!' }); |
|||
console.warn('subpackage authorization components login serverLogin Err ->', err); |
|||
if(this.initData?.fail)return this.initData?.fail?.(err); |
|||
return Promise.reject(err); |
|||
}) |
|||
}, |
|||
cancelAuthor(){ |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
.authorization-login{ |
|||
position: fixed; |
|||
left: 0; |
|||
top: var(--window-top); |
|||
right: 0; |
|||
bottom: 0; |
|||
background-color: rgba(0, 0, 0, .5); |
|||
} |
|||
|
|||
.ic-author-modal{ |
|||
position: absolute; |
|||
left: 50%; |
|||
top: 50%; |
|||
transform: translate(-50%, -50%); |
|||
padding-top: 60upx; |
|||
width: 662upx; |
|||
height: 884upx; |
|||
border-radius: 10upx; |
|||
background-color: #fff; |
|||
.iam-title{ |
|||
margin-bottom: 22upx; |
|||
text-align: center; |
|||
@include flcw(44upx, 60upx, #1a1a1a, 500); |
|||
} |
|||
.iam-tip{ |
|||
margin-bottom: 52upx; |
|||
text-align: center; |
|||
@include flcw(28upx, 40upx, #9c9c9f); |
|||
} |
|||
.iam-pic{ |
|||
margin: 0 auto 62upx; |
|||
display: block; |
|||
width: 488upx; |
|||
height: 416upx; |
|||
} |
|||
.iam-btns{ |
|||
@include ctf(center); |
|||
>button{ |
|||
margin: 0 20upx; |
|||
width: 240upx; |
|||
height: 92upx; |
|||
text-align: center; |
|||
border-radius: 46upx; |
|||
border: 2upx solid $mColor; |
|||
@include flcw(32upx, 88upx, $mColor); |
|||
&+button{ |
|||
background-color: $mColor; |
|||
color: #fff; |
|||
} |
|||
} |
|||
} |
|||
|
|||
} |
|||
</style> |
@ -0,0 +1,25 @@ |
|||
@charset "UTF-8"; |
|||
|
|||
@font-face { |
|||
font-family: "tuniaoFont"; /* Project id 3784643 */ |
|||
src: |
|||
url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAAN8AAsAAAAAB4gAAAMvAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHFQGYACDBgqCQIIdATYCJAMMCwgABCAFhH8HPRuYBiMRpmvPIfurAzsYPj7DCVbrRAmElfXCs4V6xacO8aHO69VXu54tTy8h0hcJ7ufgieY+3+xscrn9B8wKQQFBywplLZCw9SwcOyZ5pKsoAQAbcICJTr7AjPPqr06NRkeIAemFpXv8cje1+/LkuLvD789WJZUANjOe9F76qptDOSMUui/Ua0WQKpZGXaqf5hHZdAD6x8tRJtRKtQd7j5UKkk6lWywYkGADCZBnGLugJd6CAI4GOjH956Ep4k7imdNkYTGFAkm2nJyPrBNwA7YhWwgQ/K4bLXITD8wl8xxuBN+XwyYJwOAp5jFjOwNbPNwd3l3WiyFAv3sCBLjcAB6gQM3GjLLSbJpDo1ANiqsiFiX7WAQzqTcMA06j/pb/eAbEx8yMAaAChg3sDjs6COwub8IAoAD4PEZkA7iAZClPKdicmJLc2OiZcQC3cV613sc3Ab9W7YItQtio9YgdKGjgr+ANlbg5gPvXFacv8IyvKTH4pcjV7VIcfnuIAUd3VCbxcCIKj++rvr/hpx/iwxd4/5mxDXeILbBp2+ByMIlGMuQEU3gjiVaMcXk8Dn2gWo5wuRwuIldLRqRwWogvmCRXE9/kSvrVQP4iFDVWRSbRakMk/AtcBYVpO6rpah1V9J/m/Wt+q8WfsOV+S5KFTGD5dwW9KFstZUs5smuYK3V495zwUG+r/Izf0PWtbWj/HUQsAL9u+cGK8NCiAgRnaRJ49fqljrxWc4PaKs4pQwBlMLUeAzgcEGLakvg5nCZ3zgTBkZzAEEUuFEeJyMrq4BGhGT6OPjiqGd4eIZkLKGKjgTKuAAgpPIAhjmdQUngnsrJdeKTxBz4pkgjHjJQeFqFMXv8PQqg0QP+F2cbAdoHqFmaM52jYlcbNoeTq4CtPkjzHAE1Zl0QvFEjGmp9fY6vKwBI9kOvIuQhJ4kJWy0k1dVXFVXcpbfTmIIRKA/RfmG0M7G1T3cKM8VwMXGlEnR1KY0uU+CTJnM1ODk1ZdxJdSOjYdGOp+TW2k6szsNg8qIvIuQipetFCVstpQCB1lcXHXUl5ZOpfdBvgMI9QMaJi8TZdzLS36K8/ueDZOWMAAA==') format('woff2'), |
|||
url('//at.alicdn.com/t/c/font_3784643_5jru9pe5fad.woff?t=1669045092678') format('woff'), |
|||
url('//at.alicdn.com/t/c/font_3784643_5jru9pe5fad.ttf?t=1669045092678') format('truetype'); |
|||
} |
|||
|
|||
[class*='tn-icon-'] { |
|||
font-family: 'tuniaoFont' !important; |
|||
font-style: normal; |
|||
-webkit-font-smoothing: antialiased; |
|||
text-align: center; |
|||
text-decoration: none; |
|||
} |
|||
|
|||
.tn-icon-close:before { |
|||
content: "\e74d"; |
|||
} |
|||
|
|||
.tn-icon-camera-fill:before { |
|||
content: "\e75d"; |
|||
} |
@ -0,0 +1,133 @@ |
|||
<template> |
|||
<wx-user-info-modal |
|||
v-model="showAuthorizationModal" |
|||
@updated="updatedUserInfoEvent" |
|||
:isModal="isModal" |
|||
:alway="alway" |
|||
></wx-user-info-modal> |
|||
</template> |
|||
|
|||
<script> |
|||
import WxUserInfoModal from './tuniaoui-wx-user-info.vue'; |
|||
import { AUTHOR_API } from '../../js/api'; |
|||
import servers from '../../js/server'; |
|||
import { showModal, jsonPar, showLoad, hideLoad } from '@/utils/util'; |
|||
export default { |
|||
components: { WxUserInfoModal }, |
|||
props: { |
|||
isModal: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
alway: { |
|||
type: Boolean, |
|||
default: false |
|||
} |
|||
}, |
|||
watch: { |
|||
showAuthorizationModal(nVal, oVal){ |
|||
let { initData } = this; |
|||
if(!nVal&&oVal)initData?.close?.(); |
|||
} |
|||
}, |
|||
data() { |
|||
return { |
|||
showAuthorizationModal: false, |
|||
initData: {}, |
|||
} |
|||
}, |
|||
methods: { |
|||
show(data){ |
|||
this.showAuthorizationModal = true; |
|||
this.initData = data; |
|||
}, |
|||
hide(){ |
|||
this.showAuthorizationModal = false; |
|||
}, |
|||
// 获取到的用户信息 |
|||
async updatedUserInfoEvent(info) { |
|||
let { initData, userEdit } = this; |
|||
try{ |
|||
let _imgUrl = await this.uploadImg(info.avatar); |
|||
let _editObj = { nickname: info.nickname, avatar_url: _imgUrl }; |
|||
await userEdit(_editObj); |
|||
this.hide(); |
|||
initData?.success?.(_editObj); |
|||
}catch(err){ |
|||
console.warn('authorize components user info impower updatedUserInfoEvent err --->', err) |
|||
initData?.fail?.(err); |
|||
} |
|||
}, |
|||
// 上传头像 |
|||
async uploadImg(url){ |
|||
try{ |
|||
showLoad(); |
|||
let _imgInfo = await servers.uploadFile({ |
|||
url: AUTHOR_API.zs_user_avatar, |
|||
filePath: url, |
|||
}); |
|||
if(_imgInfo.statusCode != 200)throw(_imgInfo); |
|||
let _imgRes = jsonPar(_imgInfo.data); |
|||
if(_imgRes.code != 0)throw(_imgRes); |
|||
hideLoad(); |
|||
return _imgRes.data.url || ''; |
|||
}catch(err){ |
|||
hideLoad(); |
|||
showModal({ content: err?.errMsg ?? err?.message ?? '上传图片失败!' }); |
|||
console.warn('authorize components user info impower uploadImg err --->', err) |
|||
return Promise.reject(err); |
|||
} |
|||
}, |
|||
// 用户信息上传 |
|||
userEdit({ nickname, avatar_url }){ |
|||
showLoad(); |
|||
return servers.post({ |
|||
url: AUTHOR_API.changeAvatar, |
|||
data: { nickname, avatar_url }, |
|||
isDefaultGet: false, |
|||
}) |
|||
.then(res => { |
|||
hideLoad(); |
|||
let _data = res?.data || {}; |
|||
if(_data.code === 0){ |
|||
console.log('userEdit res--->', _data); |
|||
return _data?.data; |
|||
}else{ |
|||
return Promise.reject(_data); |
|||
} |
|||
}) |
|||
.catch(err => { |
|||
hideLoad(); |
|||
showModal({ content: err.message || '操作失败!' }); |
|||
console.warn('authorize components user info impower userEdit err --->', err); |
|||
return Promise.reject(err); |
|||
}) |
|||
}, |
|||
// 刷新用户信息 |
|||
refreshUserInfo(){ |
|||
return servers.post({ |
|||
url: ATR_API.userCurrent, |
|||
data: {}, |
|||
isDefaultGet: false, |
|||
}) |
|||
.then(res => { |
|||
let _data = res?.data || {}; |
|||
if(_data.code === 0){ |
|||
uni.setStorageSync('userInfo', _data?.data); |
|||
this.$store.commit('refreshUserInfo', _data?.data); |
|||
return _data?.data; |
|||
}else{ |
|||
return Promise.reject(_data); |
|||
} |
|||
}) |
|||
.catch(err => { |
|||
console.warn('authorize components user info impower refreshUserInfo err --->', err); |
|||
// return Promise.reject(err); |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
</style> |
@ -0,0 +1,357 @@ |
|||
<template> |
|||
<view |
|||
v-if="openModal || alway" |
|||
class="wx-authorization-modal" |
|||
:class="{ 'modal-class': isModal }" |
|||
> |
|||
<view |
|||
class="wam__mask" |
|||
@touchmove.prevent="" |
|||
@tap.stop="closeModal" |
|||
></view> |
|||
|
|||
<!-- 内容区域 --> |
|||
<view class="wam__wrapper"> |
|||
<!-- 关闭按钮 --> |
|||
<view class="wam__close-btn" @tap.stop="closeModal"> |
|||
<text class="tn-icon-close"></text> |
|||
</view> |
|||
<!-- 标题 --> |
|||
<view class="wam__title">获取您的昵称、头像</view> |
|||
<!-- tips --> |
|||
<view class="wam__sub-title"> |
|||
获取用户头像、昵称,主要用于向用户提供具有辨识度的用户中心界面 |
|||
</view> |
|||
|
|||
<!-- 头像选择 --> |
|||
<view class="wam__avatar"> |
|||
<view class="button-shadow"> |
|||
<button |
|||
class="button" |
|||
open-type="chooseAvatar" |
|||
@chooseavatar="chooseAvatarEvent" |
|||
> |
|||
<view v-if="userInfo.avatar" class="avatar__image"> |
|||
<image class="image" :src="userInfo.avatar" mode="aspectFill"></image> |
|||
</view> |
|||
<view v-else class="avatar__empty"> |
|||
<!-- <image class="image" src="https://cdn.nlark.com/yuque/0/2022/jpeg/280373/1668928062708-assets/web-upload/764843cf-055a-4cb6-b5d3-dca528b33fd4.jpeg" mode="aspectFill"></image> --> |
|||
</view> |
|||
<view class="avatar--icon"> |
|||
<view class="tn-icon-camera-fill"></view> |
|||
</view> |
|||
</button> |
|||
</view> |
|||
</view> |
|||
|
|||
<!-- 昵称输入 --> |
|||
<view class="wam__nickname"> |
|||
<view class="nickname__data"> |
|||
<input class="input" type="nickname" v-model="userInfo.nickname" placeholder="请输入昵称" placeholder-style="color: #AAAAAA;"> |
|||
</view> |
|||
</view> |
|||
|
|||
|
|||
<!-- 保存按钮 --> |
|||
<view |
|||
class="wam__submit-btn" |
|||
:class="[{ |
|||
'disabled': !userInfo.avatar || !userInfo.nickname |
|||
}]" |
|||
hover-class="tn-btn-hover-class" |
|||
:hover-stay-time="150" |
|||
@tap.stop="submitUserInfo" |
|||
> |
|||
保 存 |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
|
|||
export default { |
|||
options: { |
|||
// 在微信小程序中将组件节点渲染为虚拟节点,更加接近Vue组件的表现(不会出现shadow节点下再去创建元素) |
|||
virtualHost: true |
|||
}, |
|||
props: { |
|||
value: { |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
isModal: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
alway: { |
|||
type: Boolean, |
|||
default: false |
|||
} |
|||
}, |
|||
data() { |
|||
return { |
|||
openModal: false, |
|||
userInfo: { |
|||
avatar: '', |
|||
nickname: '' |
|||
} |
|||
} |
|||
}, |
|||
watch: { |
|||
value: { |
|||
handler(val) { |
|||
this.openModal = val |
|||
}, |
|||
immediate: true |
|||
} |
|||
}, |
|||
methods: { |
|||
|
|||
|
|||
// 头像选择 |
|||
chooseAvatarEvent(e) { |
|||
this.userInfo.avatar = e.detail.avatarUrl |
|||
}, |
|||
|
|||
// 更新用户信息 |
|||
submitUserInfo() { |
|||
// 判断是否已经选择了用户头像和输入了用户昵称 |
|||
if (!this.userInfo.avatar || !this.userInfo.nickname) { |
|||
return uni.showToast({ |
|||
icon: 'none', |
|||
title: '请选择头像和输入用户信息' |
|||
}) |
|||
} |
|||
|
|||
// 更新完成事件 |
|||
this.$emit('updated', this.userInfo) |
|||
|
|||
}, |
|||
|
|||
// 关闭弹框 |
|||
closeModal() { |
|||
this.$emit('input', false) |
|||
}, |
|||
|
|||
|
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
|
|||
@import './iconfont.css'; |
|||
|
|||
.modal-class{ |
|||
position: fixed; |
|||
left: 0; |
|||
top: 0; |
|||
width: 100vw; |
|||
height: 100vh; |
|||
z-index: 99998; |
|||
.wam { |
|||
&__mask { |
|||
display: block !important; |
|||
position: absolute; |
|||
left: 0; |
|||
top: 0; |
|||
width: 100%; |
|||
height: 100%; |
|||
background-color: rgba(0, 0, 0, 0.5); |
|||
opacity: 0; |
|||
animation: showMask 0.25s ease 0.1s forwards; |
|||
} |
|||
&__close-btn { |
|||
display: block !important; |
|||
display: none; |
|||
position: absolute; |
|||
top: 30rpx; |
|||
right: 30rpx; |
|||
z-index: 99999; |
|||
} |
|||
&__wrapper{ |
|||
position: absolute; |
|||
left: 0; |
|||
bottom: 0; |
|||
width: 100%; |
|||
transform-origin: center bottom; |
|||
transform: scaleY(0); |
|||
animation: showWrapper 0.25s ease 0.1s forwards; |
|||
z-index: 99999; |
|||
} |
|||
} |
|||
|
|||
} |
|||
|
|||
.wx-authorization-modal { |
|||
// view { |
|||
// box-sizing: border-box; |
|||
// } |
|||
|
|||
.image { |
|||
width: 100%; |
|||
height: 100%; |
|||
border-radius: inherit; |
|||
} |
|||
|
|||
|
|||
|
|||
.wam { |
|||
/* mask */ |
|||
&__mask { |
|||
display: none; |
|||
} |
|||
|
|||
/* close-btn */ |
|||
&__close-btn { |
|||
display: none; |
|||
} |
|||
|
|||
/* wrapper */ |
|||
&__wrapper { |
|||
background-color: #FFFFFF; |
|||
border-radius: 20rpx 20rpx 0rpx 0rpx; |
|||
padding: 40rpx; |
|||
padding-top: 60rpx; |
|||
padding-bottom: 40rpx; |
|||
padding-bottom: calc(constant(safe-area-inset-bottom) + 40rpx); |
|||
padding-bottom: calc(env(safe-area-inset-bottom) + 40rpx); |
|||
|
|||
} |
|||
|
|||
/* title */ |
|||
&__title { |
|||
font-size: 34rpx; |
|||
} |
|||
/* sub-title */ |
|||
&__sub-title { |
|||
font-size: 26rpx; |
|||
color: #AAAAAA; |
|||
margin-top: 16rpx; |
|||
padding-bottom: 30rpx; |
|||
} |
|||
|
|||
/* 头像选择 */ |
|||
&__avatar { |
|||
width: 100%; |
|||
margin-top: 30rpx; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
|
|||
.button-shadow { |
|||
border: 8rpx solid rgba(255,255,255,0.05); |
|||
box-shadow: 0rpx 0rpx 80rpx 0rpx rgba(0, 0, 0, 0.15); |
|||
border-radius: 50%; |
|||
} |
|||
|
|||
.button { |
|||
position: relative; |
|||
width: 160rpx; |
|||
height: 160rpx; |
|||
border-radius: 50%; |
|||
overflow: visible; |
|||
background-image: repeating-linear-gradient(45deg, #E4E9EC, #F8F7F8); |
|||
color: #FFFFFF; |
|||
background-color: transparent; |
|||
padding: 0; |
|||
margin: 0; |
|||
font-size: inherit; |
|||
line-height: inherit; |
|||
border: none; |
|||
&::after { |
|||
border: none; |
|||
} |
|||
} |
|||
|
|||
.avatar { |
|||
&__empty, &__image { |
|||
width: 100%; |
|||
height: 100%; |
|||
border-radius: inherit; |
|||
} |
|||
|
|||
&--icon { |
|||
position: absolute; |
|||
right: -10rpx; |
|||
bottom: -6rpx; |
|||
width: 60rpx; |
|||
height: 60rpx; |
|||
// transform: translate(50%, 50%); |
|||
background-color: #1D2541; |
|||
color: #FFFFFF; |
|||
border-radius: 50%; |
|||
border: 6rpx solid #FFFFFF; |
|||
line-height: 1; |
|||
font-size: 36rpx; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
} |
|||
} |
|||
} |
|||
|
|||
/* 昵称 */ |
|||
&__nickname { |
|||
margin-top: 40rpx; |
|||
|
|||
.nickname { |
|||
|
|||
&__data { |
|||
margin-top: 16rpx; |
|||
width: 100%; |
|||
padding: 26rpx 20rpx; |
|||
border-radius: 10rpx; |
|||
background-color: #F8F7F8; |
|||
|
|||
.input { |
|||
color: #080808; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
/* 保存按钮 */ |
|||
&__submit-btn { |
|||
width: 100%; |
|||
background-color: $mColor; |
|||
color: #FFFFFF; |
|||
margin-top: 60rpx; |
|||
border-radius: 10rpx; |
|||
padding: 25rpx; |
|||
font-size: 32rpx; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
|
|||
&.disabled { |
|||
background-color: #E6E6E6; |
|||
} |
|||
} |
|||
|
|||
|
|||
} |
|||
} |
|||
|
|||
.tn-btn-hover-class { |
|||
box-shadow: inset 10rpx 2rpx 40rpx 0rpx rgba(0, 0, 0, 0.05); |
|||
} |
|||
|
|||
@keyframes showMask { |
|||
0% { |
|||
opacity: 0; |
|||
} |
|||
100% { |
|||
opacity: 1; |
|||
} |
|||
} |
|||
@keyframes showWrapper { |
|||
0% { |
|||
transform: scaleY(0); |
|||
} |
|||
100% { |
|||
transform: scaleY(1); |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,9 @@ |
|||
import { ORIGIN } from '@/js/api'; |
|||
|
|||
export const AUTHOR_API = { |
|||
wechatMiniAppLoginAndSync: `${ORIGIN}/assistant/WechatMiniAppGetToken`, // 小程序授权获取token,为空就登录
|
|||
zs_user_avatar:`${ORIGIN}/upload/file/zs_user_avatar`, // 头像图片上传
|
|||
changeAvatar: `${ORIGIN}/admin/assistant/changeAvatar`, // 修改用户头像、昵称
|
|||
} |
|||
|
|||
export default AUTHOR_API; |
@ -0,0 +1,10 @@ |
|||
import { Server } from '@/js/server'; |
|||
|
|||
class _Server extends Server { |
|||
constructor(props){ |
|||
super(props) |
|||
} |
|||
} |
|||
|
|||
|
|||
export default new _Server(); |
@ -0,0 +1,16 @@ |
|||
<template> |
|||
<!-- 需要定义一个页面以及在pagesjson里声明才能生成static文件夹 --> |
|||
<view> </view> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
|
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
page{ |
|||
background: #fff; |
|||
} |
|||
</style> |
Before Width: 488 | Height: 416 | Size: 14 KiB After Width: 488 | Height: 416 | Size: 14 KiB |
@ -0,0 +1,41 @@ |
|||
<template> |
|||
<view class="bottom-logo" :class="{ 'fixed-active': isFixed }" @click="toWebView"> |
|||
<image @click="toWebView" class="bl-img" mode="aspectFit" src="/subpackage/menu/static/images/bot_logo.png"></image> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import { routeTo, jsonStr } from '@/utils/util.js' |
|||
export default { |
|||
props: { |
|||
isFixed: { |
|||
type: Boolean, |
|||
default: false |
|||
} |
|||
}, |
|||
methods: { |
|||
toWebView(){ |
|||
routeTo(`/pages/web_view/web_view?src=${jsonStr('https://www.ouxuanzhineng.cn/')}`, 'nT'); |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
.bottom-logo{ |
|||
height: 200upx; |
|||
width: 100%; |
|||
@include ctf(center); |
|||
&.fixed-active{ |
|||
position: fixed; |
|||
left: 50%; |
|||
bottom: 0; |
|||
transform: translateX(-50%); |
|||
z-index: -1; |
|||
} |
|||
} |
|||
.bl-img{ |
|||
width: 312upx; |
|||
height: 100upx; |
|||
} |
|||
</style> |
@ -0,0 +1,87 @@ |
|||
<template> |
|||
<view class="mine-header"> |
|||
<view class="mh-user"> |
|||
<image class="mu-photo" mode="aspectFill" :src="photo"></image> |
|||
<view class="mu-info" v-if="isLogin"> |
|||
<view class="mi-line">昵称:{{ nickname || '-' }}</view> |
|||
<view class="mi-line">姓名:{{ name || '-' }}</view> |
|||
<view class="mi-line">账号:{{ account || '-' }}</view> |
|||
</view> |
|||
<button v-else class="mu-login" @click="$emit('click:login')">点击登录</button> |
|||
</view> |
|||
<view class="mh-update" v-if="isLogin" @click="$emit('click:update')">更新头像昵称</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
props: { |
|||
isLogin: { |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
nickname: { |
|||
type: String, |
|||
default: '' |
|||
}, |
|||
name: { |
|||
type: String, |
|||
default: '' |
|||
}, |
|||
account: { |
|||
type: String, |
|||
default: '' |
|||
}, |
|||
photo: { |
|||
type: String, |
|||
default: '' |
|||
} |
|||
}, |
|||
mounted(){ |
|||
console.log('mounted'); |
|||
this.$emit('on:munted'); |
|||
}, |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
.mine-header{ |
|||
padding-top: 70upx; |
|||
height: 270upx; |
|||
background: $mColor; |
|||
.mh-user{ |
|||
padding-left: 68upx; |
|||
padding-right: 30upx; |
|||
@include ctf; |
|||
.mu-photo{ |
|||
flex-shrink: 0; |
|||
margin-right: 28upx; |
|||
width: 120upx; |
|||
height: 120upx; |
|||
border-radius: 50%; |
|||
border: 4upx solid #FFFFFF; |
|||
} |
|||
.mu-info{ |
|||
.mi-line{ |
|||
@include flcw(32upx, 44upx, #FFFFFF); |
|||
@include tHide; |
|||
} |
|||
} |
|||
.mu-login{ |
|||
@include clearBtn; |
|||
width: 180upx; |
|||
height: 72upx; |
|||
text-align: center; |
|||
border-radius: 6upx; |
|||
background: #fff; |
|||
@include flcw(32upx, 72upx, $mColor, 500); |
|||
} |
|||
} |
|||
.mh-update{ |
|||
padding-left: 68upx; |
|||
margin-top: 8upx; |
|||
text-decoration: underline; |
|||
@include flcw(20upx, 28upx, #FFFFFF); |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,63 @@ |
|||
<template> |
|||
<view class="line-tab" @click="$emit('click')"> |
|||
<image class="lt-icon" mode="aspectFit" :src="'/subpackage/menu/static/images/mine_tab/' + iconNum + '.png'"></image> |
|||
<view class="lt-right"> |
|||
<view class="lr-left"> |
|||
<view class="lr-name"> |
|||
<slot name="default">账号管理</slot> |
|||
</view> |
|||
</view> |
|||
<view class="lr-right"> |
|||
<slot name="right"> |
|||
<image class="lr-arrow" mode="aspectFit" src="/subpackage/menu/static/images/arrow_b2.png"></image> |
|||
</slot> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
props: { |
|||
iconNum: { |
|||
type: Number, |
|||
default: 0 |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
.line-tab{ |
|||
padding-left: 22upx; |
|||
padding-right: 44upx; |
|||
height: 108upx; |
|||
background: #fff; |
|||
@include ctf; |
|||
.lt-icon{ |
|||
flex-shrink: 0; |
|||
margin-right: 22upx; |
|||
width: 48upx; |
|||
height: 48upx; |
|||
} |
|||
.lt-right{ |
|||
flex-grow: 1; |
|||
@include ctf(space-between); |
|||
.lr-left{ |
|||
.lr-name{ |
|||
@include flcw(32upx, 48upx, #9A9A9D); |
|||
@include tHide; |
|||
} |
|||
} |
|||
.lr-right{ |
|||
flex-shrink: 0; |
|||
max-width: 60%; |
|||
font-size: 0; |
|||
.lr-arrow{ |
|||
width: 30upx; |
|||
height: 30upx; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,16 @@ |
|||
<template> |
|||
<!-- 需要定义一个页面以及在pagesjson里声明才能生成static文件夹 --> |
|||
<view class="menu-index"> </view> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
|
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
page{ |
|||
background: #fff; |
|||
} |
|||
</style> |
After Width: 15 | Height: 15 | Size: 226 B |
After Width: 312 | Height: 100 | Size: 3.4 KiB |
After Width: 96 | Height: 96 | Size: 1.3 KiB |
After Width: 96 | Height: 96 | Size: 1.5 KiB |
After Width: 96 | Height: 96 | Size: 1.0 KiB |
After Width: 96 | Height: 96 | Size: 1.4 KiB |
After Width: 96 | Height: 96 | Size: 1.0 KiB |
After Width: 96 | Height: 96 | Size: 942 B |
After Width: 96 | Height: 96 | Size: 640 B |
@ -0,0 +1,59 @@ |
|||
<template> |
|||
<view class="answer-item" :class="{ 'active-bg': activeBg }"> |
|||
<view class="ai-user"> |
|||
<view class="au-name">{{ name || '-' }}</view> |
|||
<view class="au-time">[回复] {{ time || '-' }}</view> |
|||
</view> |
|||
<view class="ai-content">{{ content || '-' }}</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
props: { |
|||
name: { |
|||
type: String, |
|||
default: '' |
|||
}, |
|||
time: { |
|||
type: String, |
|||
default: '' |
|||
}, |
|||
content: { |
|||
type: String, |
|||
default: '' |
|||
}, |
|||
activeBg: { |
|||
type: Boolean, |
|||
default: false |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
.answer-item{ |
|||
padding: 30upx 22upx; |
|||
background: #fff; |
|||
border-radius: 10upx; |
|||
&.active-bg{ |
|||
background: #faeada; |
|||
} |
|||
} |
|||
.ai-user{ |
|||
@include ctf; |
|||
@include flcw(32upx, 44upx, #1A1A1A); |
|||
.au-name{ |
|||
@include tHide; |
|||
} |
|||
.au-time{ |
|||
flex-shrink: 0; |
|||
color: #9C9C9F; |
|||
} |
|||
} |
|||
.ai-content{ |
|||
padding-left: 26upx; |
|||
margin-top: 24upx; |
|||
@include flcw(28upx, 40upx, #9C9C9F); |
|||
} |
|||
</style> |
@ -0,0 +1,51 @@ |
|||
<template> |
|||
<view class="image-flow"> |
|||
<image |
|||
class="if-img" |
|||
v-for="(e, i) in imgs" |
|||
:key="i" |
|||
:src="e" |
|||
mode="aspectFill" |
|||
@click="previewImg(e)" |
|||
></image> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
props: { |
|||
imgs: { |
|||
type: Array, |
|||
default: ()=>[] |
|||
} |
|||
}, |
|||
methods: { |
|||
previewImg(url) { |
|||
let { imgs } = this; |
|||
uni.previewImage({ |
|||
urls: imgs, |
|||
current: url |
|||
}) |
|||
} |
|||
|
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
.image-flow{ |
|||
padding: 30upx 14upx; |
|||
background: #fff; |
|||
border-radius: 20upx; |
|||
font-size: 0; |
|||
.if-img{ |
|||
margin: 0 12upx; |
|||
width: 200upx; |
|||
height: 200upx; |
|||
border-radius: 10upx; |
|||
&:nth-of-type(n+4){ |
|||
margin-top: 28upx; |
|||
} |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,60 @@ |
|||
<template> |
|||
<view class="detail-info"> |
|||
<view class="di-line"> |
|||
<view class="dl-name">标题:</view> |
|||
<view class="dl-value">{{ title || '-' }}</view> |
|||
</view> |
|||
<view class="di-line"> |
|||
<view class="dl-name">类型:</view> |
|||
<view class="dl-value">{{ type || '-' }}</view> |
|||
</view> |
|||
<view class="di-line"> |
|||
<view class="dl-name">反馈内容:</view> |
|||
<view class="dl-value">{{ content || '-' }}</view> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
props: { |
|||
title: { |
|||
type: String, |
|||
default: '' |
|||
}, |
|||
type: { |
|||
type: String, |
|||
default: '' |
|||
}, |
|||
content: { |
|||
type: String, |
|||
default: '' |
|||
} |
|||
}, |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
.detail-info{ |
|||
padding: 30upx 24upx; |
|||
border-radius: 10upx; |
|||
background: #fff; |
|||
.di-line{ |
|||
display: flex; |
|||
align-items: flex-start; |
|||
justify-content: space-between; |
|||
&+.di-line{ |
|||
margin-top: 10upx; |
|||
} |
|||
.dl-name{ |
|||
flex-shrink: 0; |
|||
@include flcw(28upx, 40upx, #1a1a1a); |
|||
} |
|||
.dl-value{ |
|||
flex-grow: 1; |
|||
text-align: right; |
|||
@include flcw(28upx, 40upx, #1a1a1a); |
|||
} |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,37 @@ |
|||
<template> |
|||
<view class="fixed-button"> |
|||
<button class="fb-btn" @click="$emit('click:cancel')">取消</button> |
|||
<button class="fb-btn" @click="$emit('click:submit')">提交</button> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
|
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
.fixed-button{ |
|||
position: fixed; |
|||
left: 0; |
|||
bottom: 0; |
|||
padding: 10upx 20upx; |
|||
width: 100%; |
|||
@include isPd(10upx); |
|||
@include ctf(center); |
|||
.fb-btn{ |
|||
margin: 0 20upx; |
|||
width: 240upx; |
|||
text-align: center; |
|||
border: 2upx solid $mColor; |
|||
border-radius: 44upx; |
|||
background: #fff; |
|||
@include flcw(32upx, 88upx, $mColor); |
|||
&+.fb-btn{ |
|||
background: $mColor; |
|||
color: #fff; |
|||
} |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,195 @@ |
|||
<template> |
|||
<view class="info-edit"> |
|||
<!-- 门店picker --> |
|||
<view class="ie-stadium" v-if="isStadium"> |
|||
<view class="ie-title"><text class="it-star">*</text>门店</view> |
|||
<picker mode="selector" :range="stadiumList" range-key="name" @change="stadiumChange"> |
|||
<view class="is-box"> |
|||
<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> |
|||
</view> |
|||
<!-- 标题 --> |
|||
<view class="ie-section"> |
|||
<view class="ie-title"><text class="it-star">*</text>标题</view> |
|||
<input type="text" class="ie-ipt" placeholder="请输入" v-model="fromData.titleStr" /> |
|||
</view> |
|||
<!-- 类型 --> |
|||
<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" @click="fromData.typeStr = e"> |
|||
<view class="ii-icon" :class="{ 'active': e === fromData.typeStr }"></view> |
|||
<view class="ii-txt">{{ e || '' }}</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
<!-- 反馈内容 --> |
|||
<view class="ie-section"> |
|||
<view class="ie-title"><text class="it-star">*</text>反馈内容</view> |
|||
<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> |
|||
|
|||
<style lang="scss"> |
|||
.info-edit{ |
|||
padding: 30upx; |
|||
border-radius: 20upx; |
|||
background: #fff; |
|||
.ie-title{ |
|||
flex-shrink: 0; |
|||
@include flcw(32upx, 44upx, #1A1A1A, 500); |
|||
.it-star{ |
|||
color: #EA5061; |
|||
} |
|||
} |
|||
.ie-section{ |
|||
margin-top: 24upx; |
|||
|
|||
} |
|||
.ie-ipt, .ie-tarea{ |
|||
display: block; |
|||
margin-top: 24upx; |
|||
padding: 26upx 20upx; |
|||
border-radius: 16upx; |
|||
background: #F6F8F9; |
|||
@include flcw(28upx, 40upx, #1A1A1A); |
|||
} |
|||
.ie-tarea{ |
|||
height: 306upx; |
|||
width: auto; |
|||
} |
|||
.ie-stadium{ |
|||
@include ctf; |
|||
.ie-title{ |
|||
margin-right: 30upx; |
|||
} |
|||
.is-box{ |
|||
padding: 0 22upx; |
|||
width: 478upx; |
|||
height: 92upx; |
|||
border: 2upx solid #979797; |
|||
border-radius: 16upx; |
|||
@include ctf; |
|||
.ib-ipt{ |
|||
height: 100%; |
|||
flex-grow: 1; |
|||
@include flcw(28upx, 40upx, #1A1A1A); |
|||
} |
|||
.ib-icon{ |
|||
margin-left: 20upx; |
|||
flex-shrink: 0; |
|||
width: 28upx; |
|||
height: 28upx; |
|||
} |
|||
} |
|||
} |
|||
.ie-types{ |
|||
margin-top: 24upx; |
|||
@include ctf; |
|||
.ie-title{ |
|||
margin-right: 76upx; |
|||
} |
|||
.it-ls{ |
|||
@include ctf; |
|||
.il-item{ |
|||
width: 200upx; |
|||
@include ctf; |
|||
.ii-icon{ |
|||
position: relative; |
|||
width: 40upx; |
|||
height: 40upx; |
|||
border-radius: 50%; |
|||
border: 2upx solid #D8D8D8; |
|||
&.active{ |
|||
border-color: $mColor; |
|||
&::before{ |
|||
content: ''; |
|||
position: absolute; |
|||
top: 50%; |
|||
left: 50%; |
|||
transform: translate(-50%, -50%); |
|||
width: 28upx; |
|||
height: 28upx; |
|||
border-radius: 50%; |
|||
background: $mColor; |
|||
} |
|||
} |
|||
} |
|||
.ii-txt{ |
|||
margin-left: 12upx; |
|||
@include flcw(28upx, 40upx, #1A1A1A); |
|||
|
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,189 @@ |
|||
<template> |
|||
<view class="upload-img"> |
|||
<view class="ui-title">上传照片<text class="ut-txt">(最多上传{{ max }}张,只支持.jpg、png 格式)</text></view> |
|||
<view class="ui-ls"> |
|||
<view class="ul-item" v-for="(e, i) in imgTemLs" :key="i"> |
|||
<image class="ui-pic" @click="previewImg(e)" mode="aspectFill" :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" @click="chooseImg" v-if="max > imgTemLs.length"> |
|||
<view class="ua-icon"></view> |
|||
<view class="ua-txt">上传照片</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</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: 6 |
|||
} |
|||
}, |
|||
data(){ |
|||
return { |
|||
imgTemLs: [], |
|||
} |
|||
}, |
|||
methods: { |
|||
chooseImg(){ |
|||
let { max } = this; |
|||
uni.chooseImage({ |
|||
count: max, |
|||
sourceType: ['album', 'camera'], |
|||
success: (res) => { |
|||
let { imgTemLs, max } = this; |
|||
let _curImgNum = imgTemLs?.length ?? 0; |
|||
let _temImgNum = res?.tempFilePaths?.length ?? 0; |
|||
if((_curImgNum + _temImgNum) > max)return showModal({ content: `最多上传${max}张图片!` }); |
|||
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> |
|||
|
|||
<style lang="scss"> |
|||
.upload-img{ |
|||
padding: 30upx 18upx; |
|||
border-radius: 20upx; |
|||
background: #fff; |
|||
.ui-title{ |
|||
padding: 0 10upx; |
|||
@include flcw(32upx, 44upx, #333333); |
|||
.ut-txt{ |
|||
font-size: 24upx; |
|||
color: #9A9A9D; |
|||
} |
|||
} |
|||
.ui-ls{ |
|||
margin-top: 24upx; |
|||
font-size: 0; |
|||
.ul-item{ |
|||
position: relative; |
|||
margin: 0 10upx; |
|||
vertical-align: top; |
|||
display: inline-block; |
|||
width: 200upx; |
|||
height: 200upx; |
|||
&:nth-of-type(n+4){ |
|||
margin-top: 24upx; |
|||
} |
|||
.ui-pic{ |
|||
width: 100%; |
|||
height: 100%; |
|||
border-radius: 10upx; |
|||
} |
|||
.ui-close{ |
|||
position: absolute; |
|||
top: 6upx; |
|||
right: 6upx; |
|||
width: 40upx; |
|||
height: 40upx; |
|||
} |
|||
} |
|||
.ul-add{ |
|||
padding-top: 36upx; |
|||
border: 2upx solid #D8D8D8; |
|||
.ua-icon{ |
|||
position: relative; |
|||
margin: 0 auto; |
|||
width: 60upx; |
|||
height: 60upx; |
|||
&::before, &::after{ |
|||
content: ''; |
|||
position: absolute; |
|||
left: 50%; |
|||
top: 50%; |
|||
transform: translate(-50%, -50%); |
|||
display: block; |
|||
width: 100%; |
|||
height: 4upx; |
|||
background: #D8D8D8; |
|||
} |
|||
&::after{ |
|||
transform: translate(-50%, -50%) rotate(90deg); |
|||
} |
|||
} |
|||
.ua-txt{ |
|||
text-align: center; |
|||
margin-top: 28upx; |
|||
@include flcw(28upx, 40upx, #9A9A9D); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,33 @@ |
|||
<template> |
|||
<view class="fixed-button"> |
|||
<button class="fb-btn" hover-class="hover-active" @click="$emit('click')">新建</button> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
|
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
.fixed-button{ |
|||
position: fixed; |
|||
left: 0; |
|||
bottom: 0; |
|||
width: 100%; |
|||
padding: 10upx 24upx; |
|||
@include isPd(10upx); |
|||
.fb-btn{ |
|||
@include clearBtn; |
|||
text-align: center; |
|||
height: 112upx; |
|||
background: $mColor; |
|||
border-radius: 10upx; |
|||
@include flcw(32upx, 112upx, #fff, 500); |
|||
} |
|||
.hover-active{ |
|||
opacity: .9; |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,85 @@ |
|||
<template> |
|||
<view class="message-item" @click="$emit('click:item')"> |
|||
<image class="mi-icon" mode="aspectFit" src="/subpackage/message/static/images/message.png"></image> |
|||
<view class="mi-content"> |
|||
<view class="mc-info"> |
|||
<view class="mi-top"> |
|||
<view class="mt-title">{{ title || '-' }}</view> |
|||
<view class="mt-tag" v-if="status">{{ status || '-' }}</view> |
|||
</view> |
|||
<view class="mi-text">{{ content || '-' }}</view> |
|||
</view> |
|||
<image class="mc-arrow" mode="aspectFit" src="/subpackage/message/static/images/arrow_b2.png"></image> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
props: { |
|||
title: { |
|||
type: String, |
|||
default: '' |
|||
}, |
|||
status: { |
|||
type: String, |
|||
default: '' |
|||
}, |
|||
content: { |
|||
type: String, |
|||
default: '' |
|||
} |
|||
}, |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
.message-item{ |
|||
padding: 30upx 24upx; |
|||
border-radius: 10upx; |
|||
background: #fff; |
|||
@include ctf; |
|||
.mi-icon{ |
|||
flex-shrink: 0; |
|||
margin-right: 24upx; |
|||
width: 108upx; |
|||
height: 108upx; |
|||
} |
|||
.mi-content{ |
|||
flex-grow: 1; |
|||
@include ctf; |
|||
.mc-info{ |
|||
flex-grow: 1; |
|||
.mi-top{ |
|||
@include ctf; |
|||
.mt-title{ |
|||
@include flcw(32upx, 44upx, #1A1A1A); |
|||
@include tHide; |
|||
} |
|||
.mt-tag{ |
|||
flex-shrink: 0; |
|||
margin-left: 20upx; |
|||
padding: 4upx 12upx; |
|||
border: 2upx solid $mColor; |
|||
border-radius: 6upx; |
|||
text-align: center; |
|||
@include flcw(24upx, 34upx, $mColor); |
|||
} |
|||
} |
|||
.mi-text{ |
|||
margin-top: 18upx; |
|||
@include flcw(28upx, 40upx, #9C9C9F); |
|||
@include tHide(2); |
|||
} |
|||
} |
|||
.mc-arrow{ |
|||
align-self: flex-start; |
|||
flex-shrink: 0; |
|||
margin-left: 20upx; |
|||
margin-top: 8upx; |
|||
width: 28upx; |
|||
height: 28upx; |
|||
} |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,16 @@ |
|||
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`, // 投诉列表
|
|||
complaintInfo:`${ORIGIN}/admin/assistant/complaint/info`, // 投诉详情
|
|||
complaintReply:`${ORIGIN}/admin/assistant/complaint/reply`, // 投诉回复
|
|||
workorderSubmit:`${ORIGIN}/admin/assistant/workorder/submit`, // 工单提交
|
|||
workorderList:`${ORIGIN}/admin/assistant/workorder/list`, // 工单列表
|
|||
workorderInfo:`${ORIGIN}/admin/assistant/workorder/info`, // 工单详情
|
|||
workorderReply:`${ORIGIN}/admin/assistant/workorder/reply`, // 工单回复
|
|||
} |
|||
|
|||
|
|||
export default { ORIGIN, MESSAGE_API }; |
@ -0,0 +1,9 @@ |
|||
import { Server } from '@/js/server'; |
|||
|
|||
class _server extends Server { |
|||
constructor(props){ |
|||
super(props) |
|||
} |
|||
} |
|||
|
|||
export default new _server(); |
@ -0,0 +1,171 @@ |
|||
<template> |
|||
<view class="complaint-detail"> |
|||
<view class="top-status">当前状态:{{ orderInfo.status || '-' }}</view> |
|||
<view class="heigh-space" style="height: 24upx;"></view> |
|||
<detail-info |
|||
:title="orderInfo.title || '-'" |
|||
:type="orderInfo.type || '-'" |
|||
:content="orderInfo.content || '-'" |
|||
></detail-info> |
|||
<block v-if="imgArr.length"> |
|||
<view class="heigh-space" style="height: 24upx;"></view> |
|||
<image-flow :imgs="imgArr"></image-flow> |
|||
</block> |
|||
<view class="heigh-space" style="height: 24upx;"></view> |
|||
<button class="right-btn" @click="replyBtn">回复</button> |
|||
<block v-for="(e, i) in commentArr" :key="i"> |
|||
<view class="heigh-space" style="height: 24upx;"></view> |
|||
<answer-item |
|||
:name="e.user_name || ''" |
|||
:time="e.reply_time || ''" |
|||
:content="e.content || ''" |
|||
:active-bg="e.is_creator" |
|||
></answer-item> |
|||
</block> |
|||
|
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import detailInfo from "../../components/detail/info.vue"; |
|||
import imageFlow from "../../components/detail/image_flow.vue"; |
|||
import answerItem from "../../components/detail/answer_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: { |
|||
detailInfo, imageFlow, answerItem |
|||
}, |
|||
computed: { |
|||
imgArr(){ |
|||
let { orderInfo } = this; |
|||
let _showimgs = orderInfo?.showimgs ?? []; |
|||
return _showimgs; |
|||
}, |
|||
commentArr(){ |
|||
let { orderInfo } = this; |
|||
let _comment = orderInfo?.comment ?? []; |
|||
return _comment; |
|||
} |
|||
}, |
|||
data(){ |
|||
return { |
|||
orderInfo: {} |
|||
} |
|||
}, |
|||
onLoad(options){ |
|||
this.complaintInfo({ |
|||
brand_id: options?.brand_id ?? '', |
|||
id: options?.id ?? '' |
|||
}) |
|||
}, |
|||
methods: { |
|||
replyBtn(){ |
|||
let { orderInfo } = this; |
|||
showModal({ |
|||
title: '回复', |
|||
showCancel: true, |
|||
editable: true, |
|||
placeholderText: '请输入回复内容', |
|||
success: mRes=>{ |
|||
console.log('replyBtn mRes --->', mRes); |
|||
if(mRes?.confirm && mRes?.content)this.complaintReply({ |
|||
brand_id: orderInfo?.brand_id ?? '', |
|||
id: orderInfo?.id ?? '', |
|||
reply_text: mRes?.content ?? '' |
|||
}) |
|||
.then(res =>{ |
|||
if(res === 'success'){ |
|||
setTimeout(_=>{ |
|||
this.complaintInfo({ |
|||
brand_id: orderInfo?.brand_id ?? '', |
|||
id: orderInfo?.id ?? '' |
|||
}) |
|||
}, 1000); |
|||
} |
|||
}) |
|||
} |
|||
}) |
|||
}, |
|||
complaintInfo({ brand_id, id }){ |
|||
showLoad(); |
|||
return server.post({ |
|||
url: MESSAGE_API.complaintInfo, |
|||
data: { brand_id: +brand_id, id: +id }, |
|||
isDefaultGet: false, |
|||
}) |
|||
.then(res => { |
|||
hideLoad(); |
|||
let _data = res?.data || {}; |
|||
if(_data.code === 0){ |
|||
let _info = _data?.data ?? {}; |
|||
return this.orderInfo = _info; |
|||
}else{ |
|||
return Promise.reject(_data); |
|||
} |
|||
}) |
|||
.catch(err => { |
|||
hideLoad(); |
|||
showModal({ |
|||
title: '提示', |
|||
content: err.message || '加载失败!' |
|||
}) |
|||
console.warn('subpackage message pages complaint detail complaintInfo err --->', err); |
|||
// return Promise.reject(err); |
|||
}) |
|||
}, |
|||
complaintReply({ brand_id, id, reply_text }){ |
|||
showLoad(); |
|||
return server.post({ |
|||
url: MESSAGE_API.complaintReply, |
|||
data: { brand_id: +brand_id, id: +id, reply_text }, |
|||
isDefaultGet: false, |
|||
}) |
|||
.then(res => { |
|||
hideLoad(); |
|||
let _data = res?.data || {}; |
|||
if(_data.code === 0){ |
|||
showNone(_data?.message ?? '回复成功!'); |
|||
return 'success' |
|||
}else{ |
|||
return Promise.reject(_data); |
|||
} |
|||
}) |
|||
.catch(err => { |
|||
hideLoad(); |
|||
showModal({ |
|||
title: '提示', |
|||
content: err.message || '操作失败!' |
|||
}) |
|||
console.warn('subpackage message pages complaint detail complaintReply err --->', err); |
|||
// return Promise.reject(err); |
|||
}) |
|||
}, |
|||
}, |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
.complaint-detail{ |
|||
padding: 24upx; |
|||
@include isPd(24upx); |
|||
} |
|||
.top-status{ |
|||
padding: 0 24upx; |
|||
text-align: center; |
|||
border-radius: 10upx; |
|||
background: #fff; |
|||
@include tHide; |
|||
@include flcw(28upx, 84upx, #1A1A1A); |
|||
} |
|||
.right-btn{ |
|||
margin-left: auto; |
|||
margin-right: 0upx; |
|||
width: 192upx; |
|||
text-align: center; |
|||
border-radius: 10upx; |
|||
background: $mColor; |
|||
@include flcw(32upx, 88upx, #FFFFFF); |
|||
} |
|||
</style> |
@ -0,0 +1,87 @@ |
|||
<template> |
|||
<view class="complaint-edit"> |
|||
<info-edit ref="infoEdit"></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; |
|||
}, |
|||
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> |
|||
|
|||
<style lang="scss"> |
|||
.complaint-edit{ |
|||
padding: 24upx; |
|||
@include isPd(120upx); |
|||
} |
|||
</style> |
@ -0,0 +1,105 @@ |
|||
<template> |
|||
<view class="complaint-list"> |
|||
<view class="cl-ls"> |
|||
<block v-for="(e, i) in listData" :key="i"> |
|||
<message-item |
|||
:title="e.title" |
|||
:status="e.status" |
|||
:content="e.content" |
|||
@click:item="itemClick(e)" |
|||
></message-item> |
|||
<view style="height: 24rpx;"></view> |
|||
</block> |
|||
</view> |
|||
<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: [], |
|||
page: 1 |
|||
} |
|||
}, |
|||
onLoad(options){ |
|||
let _bid = options?.brand_id ?? ''; |
|||
this.brand_id = _bid; |
|||
this.complaintList({ brand_id: _bid }); |
|||
}, |
|||
async onPullDownRefresh(){ |
|||
let { brand_id } = this; |
|||
this.listData = []; |
|||
this.page = 1; |
|||
await this.complaintList({ brand_id }); |
|||
uni.stopPullDownRefresh(); |
|||
}, |
|||
onReachBottom(){ |
|||
let { page, brand_id } = this; |
|||
this.complaintList({ page: page + 1, brand_id }); |
|||
}, |
|||
methods: { |
|||
itemClick(e){ |
|||
let { brand_id } = this; |
|||
let _qryStr = `brand_id=${brand_id ?? ''}&id=${e?.id ?? ''}`; |
|||
routeTo(`/subpackage/message/pages/complaint/detail?${_qryStr}`, 'nT'); |
|||
}, |
|||
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> |
|||
|
|||
<style lang="scss"> |
|||
.complaint-list{ |
|||
@include isPd(132upx); |
|||
.cl-ls{ |
|||
padding: 28upx 24upx 0; |
|||
|
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,171 @@ |
|||
<template> |
|||
<view class="complaint-detail"> |
|||
<view class="top-status">当前状态:{{ orderInfo.status || '-' }}</view> |
|||
<view class="heigh-space" style="height: 24upx;"></view> |
|||
<detail-info |
|||
:title="orderInfo.title || '-'" |
|||
:type="orderInfo.type || '-'" |
|||
:content="orderInfo.content || '-'" |
|||
></detail-info> |
|||
<block v-if="imgArr.length"> |
|||
<view class="heigh-space" style="height: 24upx;"></view> |
|||
<image-flow :imgs="imgArr"></image-flow> |
|||
</block> |
|||
<view class="heigh-space" style="height: 24upx;"></view> |
|||
<button class="right-btn" @click="replyBtn">回复</button> |
|||
<block v-for="(e, i) in commentArr" :key="i"> |
|||
<view class="heigh-space" style="height: 24upx;"></view> |
|||
<answer-item |
|||
:name="e.user_name || ''" |
|||
:time="e.reply_time || ''" |
|||
:content="e.content || ''" |
|||
:active-bg="e.is_creator" |
|||
></answer-item> |
|||
</block> |
|||
|
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import detailInfo from "../../components/detail/info.vue"; |
|||
import imageFlow from "../../components/detail/image_flow.vue"; |
|||
import answerItem from "../../components/detail/answer_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: { |
|||
detailInfo, imageFlow, answerItem |
|||
}, |
|||
computed: { |
|||
imgArr(){ |
|||
let { orderInfo } = this; |
|||
let _showimgs = orderInfo?.showimgs ?? []; |
|||
return _showimgs; |
|||
}, |
|||
commentArr(){ |
|||
let { orderInfo } = this; |
|||
let _comment = orderInfo?.comment ?? []; |
|||
return _comment; |
|||
} |
|||
}, |
|||
data(){ |
|||
return { |
|||
orderInfo: {} |
|||
} |
|||
}, |
|||
onLoad(options){ |
|||
this.workorderInfo({ |
|||
brand_id: options?.brand_id ?? '', |
|||
id: options?.id ?? '' |
|||
}) |
|||
}, |
|||
methods: { |
|||
replyBtn(){ |
|||
let { orderInfo } = this; |
|||
showModal({ |
|||
title: '回复', |
|||
showCancel: true, |
|||
editable: true, |
|||
placeholderText: '请输入回复内容', |
|||
success: mRes=>{ |
|||
console.log('replyBtn mRes --->', mRes); |
|||
if(mRes?.confirm && mRes?.content)this.workorderReply({ |
|||
brand_id: orderInfo?.brand_id ?? '', |
|||
id: orderInfo?.id ?? '', |
|||
reply_text: mRes?.content ?? '' |
|||
}) |
|||
.then(res =>{ |
|||
if(res === 'success'){ |
|||
setTimeout(_=>{ |
|||
this.workorderInfo({ |
|||
brand_id: orderInfo?.brand_id ?? '', |
|||
id: orderInfo?.id ?? '' |
|||
}) |
|||
}, 1000); |
|||
} |
|||
}) |
|||
} |
|||
}) |
|||
}, |
|||
workorderInfo({ brand_id, id }){ |
|||
showLoad(); |
|||
return server.post({ |
|||
url: MESSAGE_API.workorderInfo, |
|||
data: { brand_id: +brand_id, id: +id }, |
|||
isDefaultGet: false, |
|||
}) |
|||
.then(res => { |
|||
hideLoad(); |
|||
let _data = res?.data || {}; |
|||
if(_data.code === 0){ |
|||
let _info = _data?.data ?? {}; |
|||
return this.orderInfo = _info; |
|||
}else{ |
|||
return Promise.reject(_data); |
|||
} |
|||
}) |
|||
.catch(err => { |
|||
hideLoad(); |
|||
showModal({ |
|||
title: '提示', |
|||
content: err.message || '加载失败!' |
|||
}) |
|||
console.warn('subpackage message pages work_order detail workorderInfo err --->', err); |
|||
// return Promise.reject(err); |
|||
}) |
|||
}, |
|||
workorderReply({ brand_id, id, reply_text }){ |
|||
showLoad(); |
|||
return server.post({ |
|||
url: MESSAGE_API.workorderReply, |
|||
data: { brand_id: +brand_id, id: +id, reply_text }, |
|||
isDefaultGet: false, |
|||
}) |
|||
.then(res => { |
|||
hideLoad(); |
|||
let _data = res?.data || {}; |
|||
if(_data.code === 0){ |
|||
showNone(_data?.message ?? '回复成功!'); |
|||
return 'success' |
|||
}else{ |
|||
return Promise.reject(_data); |
|||
} |
|||
}) |
|||
.catch(err => { |
|||
hideLoad(); |
|||
showModal({ |
|||
title: '提示', |
|||
content: err.message || '操作失败!' |
|||
}) |
|||
console.warn('subpackage message pages work_order detail workorderReply err --->', err); |
|||
// return Promise.reject(err); |
|||
}) |
|||
}, |
|||
}, |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
.complaint-detail{ |
|||
padding: 24upx; |
|||
@include isPd(24upx); |
|||
} |
|||
.top-status{ |
|||
padding: 0 24upx; |
|||
text-align: center; |
|||
border-radius: 10upx; |
|||
background: #fff; |
|||
@include tHide; |
|||
@include flcw(28upx, 84upx, #1A1A1A); |
|||
} |
|||
.right-btn{ |
|||
margin-left: auto; |
|||
margin-right: 0upx; |
|||
width: 192upx; |
|||
text-align: center; |
|||
border-radius: 10upx; |
|||
background: $mColor; |
|||
@include flcw(32upx, 88upx, #FFFFFF); |
|||
} |
|||
</style> |
@ -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> |
@ -0,0 +1,105 @@ |
|||
<template> |
|||
<view class="complaint-list"> |
|||
<view class="cl-ls"> |
|||
<block v-for="(e, i) in listData" :key="i"> |
|||
<message-item |
|||
:title="e.title" |
|||
:status="e.status" |
|||
:content="e.content" |
|||
@click:item="itemClick(e)" |
|||
></message-item> |
|||
<view style="height: 24rpx;"></view> |
|||
</block> |
|||
</view> |
|||
<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: [], |
|||
page: 1 |
|||
} |
|||
}, |
|||
onLoad(options){ |
|||
let _bid = options?.brand_id ?? ''; |
|||
this.brand_id = _bid; |
|||
this.workorderList({ brand_id: _bid }); |
|||
}, |
|||
async onPullDownRefresh(){ |
|||
let { brand_id } = this; |
|||
this.listData = []; |
|||
this.page = 1; |
|||
await this.workorderList({ brand_id }); |
|||
uni.stopPullDownRefresh(); |
|||
}, |
|||
onReachBottom(){ |
|||
let { page, brand_id } = this; |
|||
this.workorderList({ page: page + 1, brand_id }); |
|||
}, |
|||
methods: { |
|||
itemClick(e){ |
|||
let { brand_id } = this; |
|||
let _qryStr = `brand_id=${brand_id ?? ''}&id=${e?.id ?? ''}`; |
|||
routeTo(`/subpackage/message/pages/work_order/detail?${_qryStr}`, 'nT'); |
|||
}, |
|||
clickBtn(){ |
|||
let { brand_id } = this; |
|||
routeTo(`/subpackage/message/pages/work_order/edit?brand_id=${brand_id ?? ''}`, 'nT'); |
|||
}, |
|||
workorderList({ brand_id, page = 1, page_size = 20}){ |
|||
showLoad(); |
|||
return server.post({ |
|||
url: MESSAGE_API.workorderList, |
|||
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 work_order list workorderList err --->', err); |
|||
// return Promise.reject(err); |
|||
}) |
|||
}, |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
.complaint-list{ |
|||
@include isPd(132upx); |
|||
.cl-ls{ |
|||
padding: 28upx 24upx 0; |
|||
|
|||
} |
|||
} |
|||
</style> |
After Width: 15 | Height: 15 | Size: 226 B |
After Width: 40 | Height: 40 | Size: 401 B |
After Width: 54 | Height: 54 | Size: 959 B |
After Width: 28 | Height: 28 | Size: 288 B |