| @ -0,0 +1,315 @@ | |||||
| <template> | |||||
| <view class="page__view"> | |||||
| <image class="bg" src="@/static/image/center-bg.png" mode="widthFix"></image> | |||||
| <view class="main"> | |||||
| <view class="content"> | |||||
| <view class="flex user"> | |||||
| <!-- 用户信息 --> | |||||
| <template v-if="isLogin"> | |||||
| <view class="user-avatar"> | |||||
| <image class="user-avatar-img" :src="userInfo.avatar" mode="scaleToFill"></image> | |||||
| </view> | |||||
| <view class="user-info"> | |||||
| <view class="user-info-name">{{ userInfo.name }}</view> | |||||
| <view class="user-info-desc">{{ userInfo.phone }}</view> | |||||
| </view> | |||||
| </template> | |||||
| <template v-else> | |||||
| <view class="user-avatar is-default"> | |||||
| <image class="user-avatar-img" src="@/pages_order/static/center/avatar-default.png" mode="scaleToFill"></image> | |||||
| </view> | |||||
| <view class="user-info"> | |||||
| <view class="user-info-tips">暂未登录 请先登录</view> | |||||
| </view> | |||||
| </template> | |||||
| </view> | |||||
| <!-- 订单信息 --> | |||||
| <template v-if="isLogin"> | |||||
| <order-card :statistics="statistics"></order-card> | |||||
| </template> | |||||
| <!-- 用户菜单 --> | |||||
| <template v-if="isLogin"> | |||||
| <view class="card"> | |||||
| <view v-for="item in list1" :key="item.id"> | |||||
| <template v-if="item.key === 'service'"> | |||||
| <button plain class="flex btn-service" open-type="contact"> | |||||
| <view class="flex row"> | |||||
| <view class="flex label"> | |||||
| <image class="icon" :src="item.icon" mode="scaleToFill"></image> | |||||
| <view>{{ item.label }}</view> | |||||
| </view> | |||||
| <uv-icon name="arrow-right" color="#C6C6C6" size="24rpx"></uv-icon> | |||||
| </view> | |||||
| </button> | |||||
| </template> | |||||
| <view v-else class="flex row" @click="onClick(item)"> | |||||
| <view class="flex label"> | |||||
| <image class="icon" :src="item.icon" mode="scaleToFill"></image> | |||||
| <view>{{ item.label }}</view> | |||||
| </view> | |||||
| <uv-icon name="arrow-right" color="#C6C6C6" size="24rpx"></uv-icon> | |||||
| </view> | |||||
| </view> | |||||
| </view> | |||||
| <view class="card"> | |||||
| <view v-for="item in list2" :key="item.id"> | |||||
| <view class="flex row" @click="onClick(item)"> | |||||
| <view class="flex label"> | |||||
| <image class="icon" :src="item.icon" mode="scaleToFill"></image> | |||||
| <view>{{ item.label }}</view> | |||||
| </view> | |||||
| <uv-icon name="arrow-right" color="#C6C6C6" size="24rpx"></uv-icon> | |||||
| </view> | |||||
| </view> | |||||
| </view> | |||||
| </template> | |||||
| <!-- 用户登陆 --> | |||||
| <template v-else> | |||||
| <view class="login"> | |||||
| <button class="btn" @click="$utils.toLogin">立即登录</button> | |||||
| <view class="tips">暂未登录 请先登录</view> | |||||
| </view> | |||||
| </template> | |||||
| </view> | |||||
| <tabber select="center" /> | |||||
| </view> | |||||
| </view> | |||||
| </template> | |||||
| <script> | |||||
| import { mapState } from 'vuex' | |||||
| import tabber from '@/components/base/tabbar.vue' | |||||
| import orderCard from '@/pages_order/center/orderCard.vue' | |||||
| export default { | |||||
| components: { | |||||
| orderCard, | |||||
| tabber, | |||||
| }, | |||||
| data() { | |||||
| return { | |||||
| statistics: {}, | |||||
| list1: [ | |||||
| { id: '001', label: '检测预约', icon: '/pages_order/static/center/icon-detectBook.png', path: '/pages_order/checkup/checkupRecords' }, | |||||
| { id: '002', label: '联系客服', icon: '/pages_order/static/center/icon-service.png', key: 'service' }, | |||||
| // todo: check key | |||||
| { id: '003', label: '服用说明', icon: '/pages_order/static/center/icon-instruc.png', path: `/pages_order/common?key=instruc&title=服用说明` }, | |||||
| // todo: check key | |||||
| { id: '004', label: '用户须知', icon: '/pages_order/static/center/icon-userAgreement.png', path: `/pages_order/common?key=userAgreement&title=用户须知` }, | |||||
| ], | |||||
| list2: [ | |||||
| { id: '005', label: '我的评价', icon: '/pages_order/static/center/icon-comment.png', key: 'comment' }, | |||||
| // todo: check key | |||||
| { id: '006', label: '关于我们', icon: '/pages_order/static/center/icon-aboutUs.png', path: `/pages_order/common?key=aboutUs&title=关于我们` }, | |||||
| { id: '007', label: '修改信息', icon: '/pages_order/static/center/icon-modifyInfo.png', path: `/pages_order/auth/wxUserInfo?mode=edit` }, | |||||
| { id: '008', label: '退出登录', icon: '/pages_order/static/center/icon-logout.png', key: 'logout' }, | |||||
| ], | |||||
| } | |||||
| }, | |||||
| computed: { | |||||
| ...mapState(['userInfo', 'configList']), | |||||
| isLogin() { | |||||
| return this.userInfo && this.userInfo.id | |||||
| } | |||||
| }, | |||||
| onShow() { | |||||
| if(uni.getStorageSync('token')){ | |||||
| this.$store.commit('getUserInfo') | |||||
| this.fetchOrderStatistics() | |||||
| } | |||||
| }, | |||||
| methods: { | |||||
| onClick(target) { | |||||
| const { key, path } = target | |||||
| switch(key) { | |||||
| case 'comment': | |||||
| this.$utils.navigateTo('/pages_order/comment/commentRecords') | |||||
| break | |||||
| case 'logout': | |||||
| this.$store.commit('logout') | |||||
| break | |||||
| default: | |||||
| path && this.$utils.navigateTo(path) | |||||
| break | |||||
| } | |||||
| }, | |||||
| async fetchOrderStatistics() { | |||||
| return | |||||
| try { | |||||
| this.statistics = await this.$fetch('getOrderStatistics', { id: '' }) | |||||
| } catch (err) { | |||||
| } | |||||
| }, | |||||
| }, | |||||
| } | |||||
| </script> | |||||
| <style scoped lang="scss"> | |||||
| .page__view { | |||||
| width: 100vw; | |||||
| min-height: 100vh; | |||||
| background-color: $uni-bg-color; | |||||
| position: relative; | |||||
| /deep/ .nav-bar__view { | |||||
| position: fixed; | |||||
| top: 0; | |||||
| left: 0; | |||||
| } | |||||
| .nav-icon { | |||||
| width: 200rpx; | |||||
| height: auto; | |||||
| vertical-align: top; | |||||
| } | |||||
| } | |||||
| .bg { | |||||
| width: 100vw; | |||||
| height: auto; | |||||
| } | |||||
| .main { | |||||
| position: absolute; | |||||
| top: 176rpx; | |||||
| left: 0; | |||||
| width: 100%; | |||||
| } | |||||
| .content { | |||||
| width: 100%; | |||||
| padding: 16rpx 32rpx 80rpx 32rpx; | |||||
| box-sizing: border-box; | |||||
| } | |||||
| .user { | |||||
| column-gap: 24rpx; | |||||
| &-avatar { | |||||
| flex: none; | |||||
| width: 100rpx; | |||||
| height: 100rpx; | |||||
| border: 4rpx solid #FFFFFF; | |||||
| border-radius: 50%; | |||||
| overflow: hidden; | |||||
| &.is-default { | |||||
| width: 108rpx; | |||||
| height: 108rpx; | |||||
| border: none; | |||||
| } | |||||
| &-img { | |||||
| width: 100%; | |||||
| height: 100%; | |||||
| } | |||||
| } | |||||
| &-info { | |||||
| flex: 1; | |||||
| &-name { | |||||
| font-family: PingFang SC; | |||||
| font-weight: 600; | |||||
| font-size: 36rpx; | |||||
| line-height: 1.2; | |||||
| color: #FFFFFF; | |||||
| } | |||||
| &-desc { | |||||
| margin-top: 8rpx; | |||||
| font-family: PingFang SC; | |||||
| font-weight: 400; | |||||
| font-size: 24rpx; | |||||
| line-height: 1.5; | |||||
| color: #F4F4F4; | |||||
| } | |||||
| &-tips { | |||||
| font-family: PingFang SC; | |||||
| font-weight: 400; | |||||
| font-size: 36rpx; | |||||
| line-height: 1.2; | |||||
| color: #FFFFFF; | |||||
| } | |||||
| } | |||||
| } | |||||
| .card { | |||||
| margin-top: 32rpx; | |||||
| width: 100%; | |||||
| background: #FAFAFF; | |||||
| border: 2rpx solid #FFFFFF; | |||||
| border-radius: 32rpx; | |||||
| box-sizing: border-box; | |||||
| .row { | |||||
| justify-content: space-between; | |||||
| width: 100%; | |||||
| padding: 40rpx; | |||||
| box-sizing: border-box; | |||||
| .label { | |||||
| font-family: PingFang SC; | |||||
| font-weight: 400; | |||||
| font-size: 28rpx; | |||||
| line-height: 1; | |||||
| color: #252545; | |||||
| .icon { | |||||
| margin-right: 16rpx; | |||||
| width: 40rpx; | |||||
| height: 40rpx; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| .btn-service { | |||||
| border: none; | |||||
| padding: 0; | |||||
| } | |||||
| .login { | |||||
| margin-top: 307rpx; | |||||
| padding: 0 128rpx; | |||||
| .btn { | |||||
| padding: 16rpx 0; | |||||
| font-family: PingFang SC; | |||||
| font-weight: 500; | |||||
| font-size: 36rpx; | |||||
| line-height: 1.4; | |||||
| color: #FFFFFF; | |||||
| background-image: linear-gradient(to right, #21FEEC, #019AF9); | |||||
| border-radius: 41rpx; | |||||
| } | |||||
| .tips { | |||||
| margin-top: 16rpx; | |||||
| text-align: center; | |||||
| font-family: PingFang SC; | |||||
| font-weight: 400; | |||||
| font-size: 26rpx; | |||||
| line-height: 1.4; | |||||
| color: #A3A3A3; | |||||
| } | |||||
| } | |||||
| </style> | |||||
| @ -0,0 +1,115 @@ | |||||
| <template> | |||||
| <view> | |||||
| <uv-popup ref="popup" :round="24"> | |||||
| <view class="popup__view"> | |||||
| <view class="header"> | |||||
| 用户隐私保护提示 | |||||
| </view> | |||||
| <view class="content"> | |||||
| 在你使用 鸿宇研学生服务之前,请仔细阅读 | |||||
| <text class="highlight" @click="$refs.modal.open('user_ys', '用户服务协议')">《用户服务协议》</text> | |||||
| 和 | |||||
| <text class="highlight" @click="$refs.modal.open('user_bh', '隐私政策')">《隐私政策》</text> | |||||
| 如你同意该指引,请点击“同意“开始使用本小程序。 | |||||
| </view> | |||||
| <view class="footer"> | |||||
| <button class="btn" @click="onConfirm(false)">拒绝</button> | |||||
| <button class="btn btn-confirm" @click="onConfirm(true)">同意</button> | |||||
| </view> | |||||
| </view> | |||||
| </uv-popup> | |||||
| <agreementModal ref="modal" @confirm="onConfirmSingle"></agreementModal> | |||||
| </view> | |||||
| </template> | |||||
| <script> | |||||
| import agreementModal from '@/pages_order/components/agreementModal.vue' | |||||
| export default { | |||||
| name: 'agreementModal', | |||||
| components: { | |||||
| agreementModal, | |||||
| }, | |||||
| data() { | |||||
| return { | |||||
| confirmSet: new Set(), | |||||
| } | |||||
| }, | |||||
| methods: { | |||||
| open() { | |||||
| this.$refs.popup.open('bottom'); | |||||
| }, | |||||
| onConfirm(confirm) { | |||||
| this.$emit('confirm', confirm) | |||||
| this.$refs.popup.close(); | |||||
| }, | |||||
| onConfirmSingle(confirm, key) { | |||||
| if (!this.confirmSet.has(key) && confirm) { | |||||
| this.confirmSet.add(key) | |||||
| } else if (this.confirmSet.has(key) && !confirm) { | |||||
| this.confirmSet.delete(key) | |||||
| } | |||||
| if (this.confirmSet.size === 2) { | |||||
| this.onConfirm(true) | |||||
| } | |||||
| } | |||||
| }, | |||||
| } | |||||
| </script> | |||||
| <style lang="scss" scoped> | |||||
| .popup__view { | |||||
| display: flex; | |||||
| flex-direction: column; | |||||
| padding: 44rpx 46rpx 128rpx 46rpx; | |||||
| } | |||||
| .header { | |||||
| font-size: 32rpx; | |||||
| font-family: PingFang SC; | |||||
| font-weight: 600; | |||||
| line-height: 1.5; | |||||
| color: #000000; | |||||
| } | |||||
| .content { | |||||
| margin-top: 30rpx; | |||||
| font-size: 32rpx; | |||||
| font-family: PingFang SC; | |||||
| font-weight: 400; | |||||
| line-height: 1.5; | |||||
| text-align: left; | |||||
| color: #000000; | |||||
| .highlight { | |||||
| color: #4C6EAE; | |||||
| } | |||||
| } | |||||
| .footer { | |||||
| margin-top: 122rpx; | |||||
| text-align: center; | |||||
| .btn { | |||||
| display: inline-flex; | |||||
| align-items: center; | |||||
| justify-content: center; | |||||
| border-radius: 8rpx; | |||||
| width: 232rpx; | |||||
| padding: 18rpx 84rpx; | |||||
| font-size: 32rpx; | |||||
| font-family: PingFang SC; | |||||
| font-weight: 500; | |||||
| background: #F5F5F5; | |||||
| color: #07C160; | |||||
| &-confirm { | |||||
| background: #07C160; | |||||
| color: #FFFFFF; | |||||
| } | |||||
| } | |||||
| .btn + .btn { | |||||
| margin-left: 30rpx; | |||||
| } | |||||
| } | |||||
| </style> | |||||
| @ -1,155 +1,157 @@ | |||||
| <template> | <template> | ||||
| <view class="login"> | |||||
| <view class="logo"> | |||||
| <!-- <image src="/static/image/login/logo.png" mode=""></image> --> | |||||
| </view> | |||||
| <view class="title"> | |||||
| 欢迎使用酒店桌布租赁平台 | |||||
| </view> | |||||
| <view class="btn mt" | |||||
| @click="wxLogin"> | |||||
| <view class="icon"> | |||||
| <image src="../static/auth/wx.png" mode=""></image> | |||||
| </view> | |||||
| <view class=""> | |||||
| 微信授权登录 | |||||
| </view> | |||||
| </view> | |||||
| <!-- <view class="btn b2"> | |||||
| 使用短信验证登录 | |||||
| </view> --> | |||||
| <view class="btn b2" | |||||
| @click="qux"> | |||||
| 取消登录 | |||||
| </view> | |||||
| <view class="config"> | |||||
| <uv-checkbox-group | |||||
| v-model="checkboxValue" | |||||
| shape="circle"> | |||||
| <view class="content"> | |||||
| <view | |||||
| style="display: flex;"> | |||||
| <uv-checkbox | |||||
| size="40rpx" | |||||
| icon-size="30rpx" | |||||
| activeColor="#FD5100" | |||||
| :name="1" | |||||
| ></uv-checkbox> | |||||
| 阅读并同意我们的<text @click="$refs.popup.open('getPrivacyPolicy')">“服务协议与隐私条款”</text> | |||||
| </view> | |||||
| <view class=""> | |||||
| 以及<text @click="$refs.popup.open('getUserAgreement')">个人信息保护指引</text> | |||||
| </view> | |||||
| <view class="page_view"> | |||||
| <view class="flex flex-column content"> | |||||
| <!-- todo: check key --> | |||||
| <image class="logo" src="@/static/image/temp-29.png" mode="widthFix"></image> | |||||
| <!-- todo: check key --> | |||||
| <view class="name">鸿宇研学生</view> | |||||
| <button class="btn btn-login flex" @click="wxLogin" >登 录</button> | |||||
| <button class="btn btn-cancel flex" @click="onCancel">取消登录</button> | |||||
| <view class="agreement"> | |||||
| <uv-checkbox-group | |||||
| v-model="checkboxValue" | |||||
| shape="circle" | |||||
| > | |||||
| <uv-checkbox | |||||
| size="36rpx" | |||||
| icon-size="36rpx" | |||||
| activeColor="#00A9FF" | |||||
| :name="1" | |||||
| ></uv-checkbox> | |||||
| </uv-checkbox-group> | |||||
| <view class="desc"> | |||||
| 我已阅读并同意 | |||||
| <!-- todo: 替换配置项key --> | |||||
| <text class="highlight" @click="$refs.modal.open('user_ys', '服务协议')">《服务协议》</text> | |||||
| 和 | |||||
| <!-- todo: 替换配置项key --> | |||||
| <text class="highlight" @click="$refs.modal.open('user_bh', '隐私政策')">《隐私政策》</text> | |||||
| </view> | </view> | ||||
| </uv-checkbox-group> | |||||
| </view> | |||||
| </view> | </view> | ||||
| <configPopup ref="popup"></configPopup> | |||||
| <agreementConfirmPopup ref="popup" @confirm="onConfirmAgreement"></agreementConfirmPopup> | |||||
| <agreementModal ref="modal" @confirm="onConfirmAgreement"></agreementModal> | |||||
| </view> | </view> | ||||
| </template> | </template> | ||||
| <script> | <script> | ||||
| export default { | |||||
| name : 'Login', | |||||
| data() { | |||||
| return { | |||||
| checkboxValue : [] | |||||
| import agreementConfirmPopup from './agreementConfirmPopup.vue' | |||||
| import agreementModal from '@/pages_order/components/agreementModal.vue' | |||||
| export default { | |||||
| name : 'Login', | |||||
| components: { | |||||
| agreementConfirmPopup, | |||||
| agreementModal, | |||||
| }, | |||||
| data() { | |||||
| return { | |||||
| checkboxValue : [] | |||||
| } | |||||
| }, | |||||
| methods: { | |||||
| wxLogin(){ | |||||
| if(!this.checkboxValue.length){ | |||||
| this.openAgreementConfirmPopup() | |||||
| return | |||||
| } | } | ||||
| this.$store.commit('login') | |||||
| }, | |||||
| openAgreementConfirmPopup() { | |||||
| this.$refs.popup.open() | |||||
| }, | |||||
| onConfirmAgreement(confirm) { | |||||
| if (confirm) { | |||||
| this.checkboxValue = [1] | |||||
| } else { | |||||
| this.checkboxValue = [] | |||||
| } | |||||
| }, | |||||
| onCancel() { | |||||
| uni.reLaunch({ | |||||
| url: '/pages/index/index' | |||||
| }) | |||||
| }, | }, | ||||
| methods: { | |||||
| wxLogin(){ | |||||
| if(!this.checkboxValue.length){ | |||||
| return uni.showToast({ | |||||
| title: '请先同意隐私协议', | |||||
| icon:'none' | |||||
| }) | |||||
| } | |||||
| this.$store.commit('login') | |||||
| }, | |||||
| qux(){ | |||||
| uni.reLaunch({ | |||||
| url: '/pages/index/index' | |||||
| }) | |||||
| }, | |||||
| } | |||||
| } | } | ||||
| } | |||||
| </script> | </script> | ||||
| <style scoped lang="scss"> | <style scoped lang="scss"> | ||||
| .login{ | |||||
| display: flex; | |||||
| justify-content: center; | |||||
| align-items: center; | |||||
| height: 80vh; | |||||
| flex-direction: column; | |||||
| position: relative; | |||||
| .logo{ | |||||
| height: 140rpx; | |||||
| width: 140rpx; | |||||
| background-color: #ddd; | |||||
| border-radius: 30rpx; | |||||
| image{ | |||||
| height: 140rpx; | |||||
| width: 140rpx; | |||||
| border-radius: 30rpx; | |||||
| } | |||||
| margin-bottom: 20rpx; | |||||
| } | |||||
| .title{ | |||||
| position: relative; | |||||
| font-weight: 900; | |||||
| font-size: 45rpx; | |||||
| &::after{ | |||||
| content: ''; | |||||
| position: absolute; | |||||
| left: 0; | |||||
| top: 100%; | |||||
| display: block; | |||||
| height: 8rpx; | |||||
| width: 210rpx; | |||||
| background: linear-gradient(to right,$uni-color, #fff); | |||||
| } | |||||
| } | |||||
| .btn{ | |||||
| width: 80%; | |||||
| height: 100rpx; | |||||
| background-color: $uni-color; | |||||
| color: #fff; | |||||
| display: flex; | |||||
| justify-content: center; | |||||
| align-items: center; | |||||
| margin: 20rpx 0; | |||||
| border-radius: 20rpx; | |||||
| .icon{ | |||||
| margin-right: 10rpx; | |||||
| image{ | |||||
| width: 40rpx; | |||||
| height: 35rpx; | |||||
| } | |||||
| } | |||||
| .page_view { | |||||
| width: 100vw; | |||||
| height: 100vh; | |||||
| padding: 320rpx 116rpx 0 116rpx; | |||||
| box-sizing: border-box; | |||||
| background: #E5F2F9; | |||||
| } | |||||
| .content { | |||||
| width: 100%; | |||||
| } | |||||
| .logo { | |||||
| width: 248rpx; | |||||
| height: auto; | |||||
| } | |||||
| .name { | |||||
| margin-top: 20rpx; | |||||
| font-family: Alimama ShuHeiTi; | |||||
| font-size: 56rpx; | |||||
| font-weight: 700; | |||||
| color: #000000; | |||||
| } | |||||
| .btn { | |||||
| width: 100%; | |||||
| border-radius: 44rpx; | |||||
| padding: 21rpx 0; | |||||
| font-size: 30rpx; | |||||
| line-height: 1.4; | |||||
| font-family: PingFang SC; | |||||
| border: 2rpx solid $uni-color; | |||||
| &-login { | |||||
| margin-top: 222rpx; | |||||
| font-weight: 600; | |||||
| color: #FFFFFF; | |||||
| background: $uni-color; | |||||
| } | } | ||||
| .b2{ | |||||
| background-color: rgba($uni-color, 0.2); | |||||
| &-cancel { | |||||
| margin-top: 24rpx; | |||||
| font-weight: 400; | |||||
| color: $uni-color; | color: $uni-color; | ||||
| background: transparent; | |||||
| } | } | ||||
| .mt{ | |||||
| margin-top: 200rpx; | |||||
| } | |||||
| .config{ | |||||
| position: absolute; | |||||
| bottom: 0; | |||||
| } | |||||
| .agreement { | |||||
| margin-top: 24rpx; | |||||
| display: flex; | |||||
| .desc { | |||||
| font-family: PingFang SC; | |||||
| font-size: 24rpx; | font-size: 24rpx; | ||||
| text-align: center; | |||||
| line-height: 40rpx; | |||||
| text{ | |||||
| color: $uni-color; | |||||
| } | |||||
| font-weight: 400; | |||||
| line-height: 1.4; | |||||
| color: #8B8B8B; | |||||
| } | |||||
| .highlight { | |||||
| color: $uni-color; | |||||
| } | } | ||||
| } | } | ||||
| </style> | </style> | ||||
| @ -1,133 +1,361 @@ | |||||
| <template> | <template> | ||||
| <view class="login"> | |||||
| <view class="title"> | |||||
| 酒店桌布租赁平台 | |||||
| </view> | |||||
| <view class="title"> | |||||
| 申请获取你的头像、昵称 | |||||
| </view> | |||||
| <view class="page__view"> | |||||
| <button class="chooseAvatar" open-type="chooseAvatar" @chooseavatar="onChooseAvatar"> | |||||
| <view class="line"> | |||||
| <view class=""> | |||||
| 头像 | |||||
| </view> | |||||
| <view class=""> | |||||
| <image :src="userInfo.headImage" v-if="userInfo.headImage" style="width: 60rpx;height: 60rpx;" | |||||
| mode=""></image> | |||||
| <image src="../static/auth/headImage.png" v-else style="width: 50rpx;height: 50rpx;" mode=""></image> | |||||
| </view> | |||||
| </view> | |||||
| </button> | |||||
| <view class="line"> | |||||
| <view class=""> | |||||
| 昵称 | |||||
| <navbar title="修改信息" leftClick @leftClick="$utils.navigateBack" color="#191919" bgColor="#FFFFFF" /> | |||||
| <view class="flex flex-column content"> | |||||
| <!-- todo: check key --> | |||||
| <image class="logo" src="@/static/image/temp-29.png" mode="widthFix"></image> | |||||
| <!-- todo: check key --> | |||||
| <view class="name">鸿宇研学生</view> | |||||
| <view class="title"> | |||||
| 申请获取你的头像、昵称 | |||||
| </view> | </view> | ||||
| <view class=""> | |||||
| <input type="nickname" placeholder="请输入昵称" style="text-align: right;" id="nickName" | |||||
| v-model="userInfo.nickName" /> | |||||
| <view class="form"> | |||||
| <uv-form | |||||
| ref="form" | |||||
| :model="form" | |||||
| :rules="rules" | |||||
| errorType="toast" | |||||
| > | |||||
| <view class="form-item"> | |||||
| <uv-form-item prop="phone" :customStyle="formItemStyle"> | |||||
| <view class="row"> | |||||
| <view class="form-item-label">头像</view> | |||||
| <view class="form-item-content input"> | |||||
| <button class="btn btn-avatar" :plain="true" :hairline="false" open-type="chooseAvatar" @chooseavatar="onChooseAvatar"> | |||||
| <view v-if="form.avatar" class="avatar"> | |||||
| <image class="img" :src="form.avatar" mode="aspectFill"></image> | |||||
| <view class="flex mask"> | |||||
| <image class="icon" src="@/pages_order/static/center/icon-change.png" mode="widthFix" /> | |||||
| </view> | |||||
| </view> | |||||
| <view v-else class="flex avatar is-empty"> | |||||
| <image class="icon" src="@/pages_order/static/auth/avatar.png" mode="widthFix" /> | |||||
| </view> | |||||
| </button> | |||||
| </view> | |||||
| </view> | |||||
| </uv-form-item> | |||||
| </view> | |||||
| <view class="form-item"> | |||||
| <uv-form-item prop="name" :customStyle="formItemStyle"> | |||||
| <view class="row"> | |||||
| <view class="form-item-label">昵称</view> | |||||
| <view class="form-item-content input"> | |||||
| <input | |||||
| type="nickname" | |||||
| placeholder="请输入" | |||||
| placeholderStyle="color: #C6C6C6; font-size: 32rpx; font-weight: 400;" | |||||
| v-model="form.name" | |||||
| style="text-align: right;" | |||||
| /> | |||||
| </view> | |||||
| </view> | |||||
| </uv-form-item> | |||||
| </view> | |||||
| <view class="form-item"> | |||||
| <uv-form-item prop="phone" :customStyle="formItemStyle"> | |||||
| <view class="row"> | |||||
| <view class="form-item-label">电话</view> | |||||
| <view class="form-item-content input"> | |||||
| <formInput v-if="form.phone" v-model="form.phone"></formInput> | |||||
| <view v-else> | |||||
| <button | |||||
| class="btn btn-phone" | |||||
| open-type="getPhoneNumber" | |||||
| @getphonenumber="getPhone" | |||||
| > | |||||
| <view class="text placeholder">获取电话号码</view> | |||||
| </button> | |||||
| </view> | |||||
| </view> | |||||
| </view> | |||||
| </uv-form-item> | |||||
| </view> | |||||
| </uv-form> | |||||
| </view> | </view> | ||||
| <button class="btn btn-save" @click="onSubmit">保存</button> | |||||
| </view> | </view> | ||||
| <view class="btn" @click="submit"> | |||||
| 确认 | |||||
| </view> | |||||
| </view> | </view> | ||||
| </template> | </template> | ||||
| <script> | <script> | ||||
| import { mapState } from 'vuex' | |||||
| import formInput from '@/pages_order/components/formInput.vue' | |||||
| export default { | export default { | ||||
| components: { | |||||
| formInput, | |||||
| }, | |||||
| props: { | |||||
| mode: { | |||||
| type: String, | |||||
| default: null, | |||||
| } | |||||
| }, | |||||
| data() { | data() { | ||||
| return { | return { | ||||
| userInfo: { | |||||
| headImage: '', | |||||
| nickName: '', | |||||
| } | |||||
| }; | |||||
| form: { | |||||
| name: null, | |||||
| phone: null, | |||||
| avatar: null, | |||||
| }, | |||||
| rules: { | |||||
| 'name': { | |||||
| type: 'string', | |||||
| required: true, | |||||
| message: '请输入昵称', | |||||
| }, | |||||
| 'phone': { | |||||
| type: 'string', | |||||
| required: true, | |||||
| message: '请输入手机号', | |||||
| }, | |||||
| 'avatar': { | |||||
| type: 'array', | |||||
| required: true, | |||||
| message: '请选择头像', | |||||
| }, | |||||
| }, | |||||
| formItemStyle: { padding: 0 }, | |||||
| } | |||||
| }, | |||||
| computed: { | |||||
| ...mapState(['userInfo']), | |||||
| }, | |||||
| onLoad(arg) { | |||||
| this.mode = arg.mode | |||||
| this.form.name = this.userInfo.name || '' | |||||
| this.form.phone = this.userInfo.phone || '' | |||||
| this.form.avatar = this.userInfo.avatar || '' | |||||
| }, | }, | ||||
| onShow() {}, | |||||
| computed: {}, | |||||
| methods: { | methods: { | ||||
| onChooseAvatar(res) { | onChooseAvatar(res) { | ||||
| let self = this | |||||
| self.$Oss.ossUpload(res.target.avatarUrl) | |||||
| .then(url => { | |||||
| self.userInfo.headImage = url | |||||
| }) | |||||
| this.$Oss.ossUpload(res.target.avatarUrl) | |||||
| .then(url => { | |||||
| this.form.avatar = url | |||||
| }) | |||||
| }, | }, | ||||
| submit() { | |||||
| let self = this | |||||
| uni.createSelectorQuery().in(this) | |||||
| .select("#nickName") | |||||
| .fields({ | |||||
| properties: ["value"], | |||||
| }) | |||||
| .exec((res) => { | |||||
| const nickName = res?.[0]?.value | |||||
| self.userInfo.nickName = nickName | |||||
| getPhone(e){ | |||||
| this.$api('bindPhone', { | |||||
| code : e.detail.code | |||||
| }, res => { | |||||
| if(res.code == 200){ | |||||
| if (self.$utils.verificationAll(self.userInfo, { | |||||
| headImage: '请选择头像', | |||||
| nickName: '请填写昵称', | |||||
| })) { | |||||
| return | |||||
| if(res.success){ | |||||
| this.form.phone = res.result | |||||
| }else{ | |||||
| uni.showModal({ | |||||
| title: res.message | |||||
| }) | |||||
| } | } | ||||
| } | |||||
| }) | |||||
| }, | |||||
| async onSubmit() { | |||||
| try { | |||||
| await this.$refs.form.validate() | |||||
| const { | |||||
| name, | |||||
| phone, | |||||
| avatar, | |||||
| } = this.form | |||||
| const params = { | |||||
| name, | |||||
| phone, | |||||
| avatar, | |||||
| } | |||||
| // todo: check 415 Unsupported Media Type | |||||
| const res = await this.$fetch('updateInfo', params, false) | |||||
| if (res.code == 200) { | |||||
| self.$api('updateInfo', self.userInfo, res => { | |||||
| if (res.code == 200) { | |||||
| uni.switchTab({ | |||||
| url:'/pages/index/index' | |||||
| }) | |||||
| uni.showToast({ | |||||
| icon: 'success', | |||||
| title: '保存成功', | |||||
| }); | |||||
| this.$store.commit('getUserInfo') | |||||
| setTimeout(() => { | |||||
| if (this.mode === 'edit') { | |||||
| this.$utils.navigateBack() | |||||
| return | |||||
| } | } | ||||
| }) | |||||
| }) | |||||
| }, | |||||
| } | |||||
| uni.reLaunch({ | |||||
| url:'/pages/index/index' | |||||
| }) | |||||
| }, 800) | |||||
| } | |||||
| } catch (err) { | |||||
| console.log('onSubmit err', err) | |||||
| } | |||||
| }, | |||||
| }, | |||||
| } | } | ||||
| </script> | </script> | ||||
| <style lang="scss" scoped> | <style lang="scss" scoped> | ||||
| .login { | |||||
| .page__view { | |||||
| width: 100vw; | |||||
| min-height: 100vh; | |||||
| padding: 0 40rpx; | |||||
| box-sizing: border-box; | |||||
| background: #FFFFFF; | |||||
| } | |||||
| .content { | |||||
| margin-top: 52rpx; | |||||
| } | |||||
| .logo { | |||||
| width: 248rpx; | |||||
| height: auto; | |||||
| } | |||||
| .name { | |||||
| margin-top: 20rpx; | |||||
| font-family: Alimama ShuHeiTi; | |||||
| font-size: 56rpx; | |||||
| font-weight: 700; | |||||
| color: #000000; | |||||
| } | |||||
| .title { | |||||
| color: #333333; | |||||
| font-size: 32rpx; | |||||
| font-weight: 500; | |||||
| margin-top: 20rpx; | |||||
| } | |||||
| .row { | |||||
| display: flex; | display: flex; | ||||
| flex-direction: column; | |||||
| justify-content: center; | |||||
| justify-content: space-between; | |||||
| align-items: center; | align-items: center; | ||||
| height: 80vh; | |||||
| font-family: PingFang SC; | |||||
| font-weight: 400; | |||||
| line-height: 1.4; | |||||
| column-gap: 24rpx; | |||||
| } | |||||
| .title { | |||||
| line-height: 45rpx; | |||||
| font-weight: 900; | |||||
| } | |||||
| .form { | |||||
| margin-top: 122rpx; | |||||
| width: 100%; | |||||
| &-item { | |||||
| border-bottom: 2rpx solid #EEEEEE; | |||||
| & + & { | |||||
| margin-top: 20rpx; | |||||
| } | |||||
| &-label { | |||||
| min-height: 96rpx; | |||||
| font-family: PingFang SC; | |||||
| font-size: 36rpx; | |||||
| font-weight: 500; | |||||
| line-height: 96rpx; | |||||
| color: #181818; | |||||
| } | |||||
| .line { | |||||
| display: flex; | |||||
| justify-content: space-between; | |||||
| align-items: center; | |||||
| width: 80%; | |||||
| border-bottom: 1px solid #00000023; | |||||
| padding: 30rpx 0; | |||||
| margin: 0 auto; | |||||
| &-content { | |||||
| margin-top: 14rpx; | |||||
| padding: 6rpx 0; | |||||
| .text { | |||||
| padding: 2rpx 0; | |||||
| font-family: PingFang SC; | |||||
| font-weight: 400; | |||||
| font-size: 32rpx; | |||||
| line-height: 1.4; | |||||
| &.placeholder { | |||||
| color: #C6C6C6; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | } | ||||
| } | |||||
| .btn-phone { | |||||
| text-align: left; | |||||
| font-family: PingFang SC; | |||||
| font-weight: 400; | |||||
| font-size: 32rpx; | |||||
| line-height: 1.4; | |||||
| color: #393939; | |||||
| } | |||||
| .chooseAvatar { | |||||
| .btn-avatar { | |||||
| display: inline-block; | |||||
| width: auto; | |||||
| border: none; | |||||
| } | |||||
| .avatar { | |||||
| position: relative; | |||||
| width: 96rpx; | |||||
| height: 96rpx; | |||||
| border-radius: 24rpx; | |||||
| overflow: hidden; | |||||
| .img { | |||||
| width: 100%; | |||||
| height: 100%; | |||||
| } | |||||
| .mask { | |||||
| position: absolute; | |||||
| top: 0; | |||||
| left: 0; | |||||
| width: 100%; | width: 100%; | ||||
| padding: 0; | |||||
| margin: 0; | |||||
| margin-top: 10vh; | |||||
| border: none; | |||||
| height: 100%; | |||||
| background: #00000080; | |||||
| border-radius: 24rpx; | |||||
| .icon { | |||||
| width: 64rpx; | |||||
| height: 64rpx; | |||||
| } | |||||
| } | } | ||||
| .btn { | |||||
| // background: $uni-linear-gradient-btn-color; | |||||
| background: $uni-color; | |||||
| color: #fff; | |||||
| width: 80%; | |||||
| padding: 20rpx 0; | |||||
| text-align: center; | |||||
| border-radius: 15rpx; | |||||
| margin-top: 10vh; | |||||
| &.is-empty { | |||||
| background: #F3F2F7; | |||||
| .icon { | |||||
| width: 61rpx; | |||||
| height: auto; | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| .btn-save { | |||||
| margin-top: 100rpx; | |||||
| width: 100%; | |||||
| padding: 16rpx 0; | |||||
| box-sizing: border-box; | |||||
| font-family: PingFang SC; | |||||
| font-weight: 500; | |||||
| font-size: 36rpx; | |||||
| line-height: 1; | |||||
| color: #FFFFFF; | |||||
| background-image: linear-gradient(to right, #21FEEC, #019AF9); | |||||
| border-radius: 41rpx; | |||||
| } | |||||
| </style> | </style> | ||||
| @ -0,0 +1,91 @@ | |||||
| <template> | |||||
| <view class="flex card cols"> | |||||
| <view class="flex flex-column col" v-for="item in list" :key="item.id" @click="jumpToOrderList(item.index)"> | |||||
| <view class="icon"> | |||||
| <image class="icon-img" :src="item.icon" mode="scaleToFill"></image> | |||||
| <view class="flex sup" v-if="item.value">{{ item.value }}</view> | |||||
| </view> | |||||
| <view class="label">{{ item.label }}</view> | |||||
| </view> | |||||
| </view> | |||||
| </template> | |||||
| <script> | |||||
| export default { | |||||
| props: { | |||||
| statistics: { | |||||
| type: Object, | |||||
| default() { | |||||
| return {} | |||||
| } | |||||
| } | |||||
| }, | |||||
| data() { | |||||
| return { | |||||
| } | |||||
| }, | |||||
| computed: { | |||||
| list() { | |||||
| return [ | |||||
| { id: '001', label: '待支付', value: this.statistics[0] || 0, index: 1, icon: '/pages_order/static/center/order-1.png' }, | |||||
| { id: '002', label: '待发货', value: this.statistics[1] || 0, index: 2, icon: '/pages_order/static/center/order-2.png' }, | |||||
| { id: '003', label: '待收货', value: this.statistics[2] || 0, index: 3, icon: '/pages_order/static/center/order-3.png' }, | |||||
| // todo: check | |||||
| { id: '004', label: '售后', value: this.statistics['afterSales'] || 0, index: 0, icon: '/pages_order/static/center/order-4.png' }, | |||||
| { id: '005', label: '全部', index: 0, icon: '/pages_order/static/center/order-5.png' }, | |||||
| ] | |||||
| } | |||||
| }, | |||||
| methods: { | |||||
| jumpToOrderList(index) { | |||||
| this.$utils.navigateTo(`/pages_order/order/orderList/index?index=${index}`) | |||||
| } | |||||
| }, | |||||
| } | |||||
| </script> | |||||
| <style scoped lang="scss"> | |||||
| @import './styles/card.scss'; | |||||
| .card { | |||||
| padding: 32rpx; | |||||
| column-gap: 16rpx; | |||||
| } | |||||
| .icon { | |||||
| position: relative; | |||||
| width: 48rpx; | |||||
| height: 48rpx; | |||||
| &-img { | |||||
| width: 100%; | |||||
| height: 100%; | |||||
| } | |||||
| .sup { | |||||
| position: absolute; | |||||
| top: 0; | |||||
| right: 0; | |||||
| transform: translate(50%, -50%); | |||||
| min-width: 32rpx; | |||||
| height: 32rpx; | |||||
| font-family: PingFang SC; | |||||
| font-weight: 500; | |||||
| font-size: 24rpx; | |||||
| line-height: 1.3; | |||||
| color: #FFFFFF; | |||||
| background: #F53F3F; | |||||
| border-radius: 32rpx; | |||||
| } | |||||
| } | |||||
| .label { | |||||
| margin-top: 12rpx; | |||||
| font-family: PingFang SC; | |||||
| font-weight: 400; | |||||
| font-size: 28rpx; | |||||
| line-height: 1; | |||||
| color: #252545; | |||||
| } | |||||
| </style> | |||||
| @ -0,0 +1,56 @@ | |||||
| <template> | |||||
| <uv-popup | |||||
| ref="popup" | |||||
| :overlayOpacity="0.8" | |||||
| mode="bottom" | |||||
| round="20rpx" | |||||
| :zIndex="1000000" | |||||
| > | |||||
| <view class="flex qr-popup"> | |||||
| <text class="tips">即刻关注</text> | |||||
| <image class="qr" :src="src" :show-menu-by-longpress="true"></image> | |||||
| </view> | |||||
| </uv-popup> | |||||
| </template> | |||||
| <script> | |||||
| export default { | |||||
| props: { | |||||
| src: { | |||||
| type: String, | |||||
| default: null | |||||
| } | |||||
| }, | |||||
| data() { | |||||
| return { | |||||
| } | |||||
| }, | |||||
| methods: { | |||||
| open() { | |||||
| this.$refs.popup.open(); | |||||
| }, | |||||
| close() { | |||||
| this.$refs.popup.close(); | |||||
| }, | |||||
| }, | |||||
| } | |||||
| </script> | |||||
| <style scoped lang="scss"> | |||||
| .qr-popup { | |||||
| flex-direction: column; | |||||
| padding-bottom: 104rpx; | |||||
| .tips { | |||||
| margin-top: 75rpx; | |||||
| color: #1B1B1B; | |||||
| font-size: 32rpx; | |||||
| } | |||||
| .qr { | |||||
| margin-top: 40rpx; | |||||
| width: 350rpx; | |||||
| height: 350rpx; | |||||
| } | |||||
| } | |||||
| </style> | |||||
| @ -0,0 +1,15 @@ | |||||
| .card { | |||||
| margin-top: 32rpx; | |||||
| width: 100%; | |||||
| background: #FAFAFF; | |||||
| border: 2rpx solid #FFFFFF; | |||||
| border-radius: 32rpx; | |||||
| box-sizing: border-box; | |||||
| } | |||||
| .cols { | |||||
| .col { | |||||
| flex: 1; | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,99 @@ | |||||
| <template> | |||||
| <view> | |||||
| <uv-modal ref="modal" :showConfirmButton="false"> | |||||
| <view class="modal__view"> | |||||
| <view class="header"> | |||||
| {{ title }} | |||||
| </view> | |||||
| <view class="content"> | |||||
| <uv-parse :content="content"></uv-parse> | |||||
| </view> | |||||
| <view class="footer"> | |||||
| <button class="btn" @click="onConfirm(false)">拒绝</button> | |||||
| <button class="btn btn-confirm" @click="onConfirm(true)">同意</button> | |||||
| </view> | |||||
| </view> | |||||
| </uv-modal> | |||||
| <configPopup ref="popup"></configPopup> | |||||
| </view> | |||||
| </template> | |||||
| <script> | |||||
| import { mapState } from 'vuex' | |||||
| export default { | |||||
| data() { | |||||
| return { | |||||
| key: '', | |||||
| title : '', | |||||
| content : '', | |||||
| } | |||||
| }, | |||||
| computed : { | |||||
| ...mapState(['configList']) | |||||
| }, | |||||
| methods: { | |||||
| open(key, title) { | |||||
| this.key = key | |||||
| this.title = title | |||||
| this.content = this.configList[key] | |||||
| this.$refs.modal.open() | |||||
| }, | |||||
| onConfirm(confirm) { | |||||
| this.$emit('confirm', confirm, this.key) | |||||
| this.$refs.modal.close() | |||||
| }, | |||||
| }, | |||||
| } | |||||
| </script> | |||||
| <style lang="scss" scoped> | |||||
| .modal__view { | |||||
| width: 100%; | |||||
| display: flex; | |||||
| flex-direction: column; | |||||
| padding-top: 40rpx; | |||||
| } | |||||
| .header { | |||||
| text-align: center; | |||||
| font-size: 34rpx; | |||||
| font-family: PingFang SC; | |||||
| font-weight: 600; | |||||
| line-height: 1.4; | |||||
| color: #181818; | |||||
| } | |||||
| .content { | |||||
| padding: 8rpx 32rpx 40rpx 32rpx; | |||||
| font-size: 28rpx; | |||||
| font-family: PingFang SC; | |||||
| font-weight: 400; | |||||
| line-height: 1.7; | |||||
| text-align: left; | |||||
| color: #636465; | |||||
| } | |||||
| .footer { | |||||
| display: flex; | |||||
| border-top: 1rpx solid #EEEEEE; | |||||
| .btn { | |||||
| flex: 1; | |||||
| display: inline-flex; | |||||
| align-items: center; | |||||
| justify-content: center; | |||||
| padding: 22rpx 32rpx; | |||||
| font-size: 32rpx; | |||||
| font-family: PingFang SC; | |||||
| font-weight: 400; | |||||
| line-height: 1.4; | |||||
| color: #393939; | |||||
| &-confirm { | |||||
| color: $uni-color; | |||||
| border-left: 1rpx solid #EEEEEE; | |||||
| } | |||||
| } | |||||
| } | |||||
| </style> | |||||
| @ -0,0 +1,46 @@ | |||||
| <template> | |||||
| <uv-input | |||||
| :type="type" | |||||
| :inputAlign="inputAlign" | |||||
| :value="value" | |||||
| @input="$emit('input', $event)" | |||||
| :placeholder="placeholder" | |||||
| placeholderStyle="color: #C6C6C6; font-size: 32rpx; font-weight: 400;" | |||||
| :customStyle="{ | |||||
| backgroundColor: 'transparent', | |||||
| padding: '0', | |||||
| boxSizing: 'border-box', | |||||
| fontSize: '32rpx', | |||||
| border: 'none', | |||||
| transform: 'translateX(-4px)' | |||||
| }" | |||||
| fontSize="32rpx" | |||||
| ></uv-input> | |||||
| </template> | |||||
| <script> | |||||
| export default { | |||||
| props: { | |||||
| value: { | |||||
| default: null | |||||
| }, | |||||
| placeholder: { | |||||
| type: String, | |||||
| default: '请输入' | |||||
| }, | |||||
| type: { | |||||
| type: String, | |||||
| default: 'text' | |||||
| }, | |||||
| inputAlign: { | |||||
| type: String, | |||||
| default: 'left' | |||||
| }, | |||||
| }, | |||||
| data() { | |||||
| return { | |||||
| } | |||||
| }, | |||||
| } | |||||
| </script> | |||||