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