初始版本
This commit is contained in:
39
business_uniapp/src/pages/agreement/agreement.vue
Normal file
39
business_uniapp/src/pages/agreement/agreement.vue
Normal file
@@ -0,0 +1,39 @@
|
||||
<template>
|
||||
<view class="p-[24rpx]">
|
||||
<mp-html :content="agreementContent" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from "vue"
|
||||
import { onLoad } from "@dcloudio/uni-app";
|
||||
import { getPolicy } from "@/api/app"
|
||||
import { AgreementEnum } from "@/enums/agreementEnums"
|
||||
|
||||
let agreementType = ref('') // 协议类型
|
||||
const agreementContent = ref<string | null>('')
|
||||
|
||||
// 获取服务协议
|
||||
const getPolicyAgreement = async () => {
|
||||
const res = await getPolicy()
|
||||
console.log('res=>', res)
|
||||
if( agreementType == AgreementEnum.SERVICE) {
|
||||
agreementContent.value = res.service_agreement
|
||||
uni.setNavigationBarTitle({
|
||||
title: String(res.service_title)
|
||||
})
|
||||
}else {
|
||||
agreementContent.value = res.privacy_agreement
|
||||
uni.setNavigationBarTitle({
|
||||
title: String(res.privacy_title)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
onLoad((options:any) => {
|
||||
if (options.type) {
|
||||
agreementType = options.type
|
||||
getPolicyAgreement()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
30
business_uniapp/src/pages/as_us/as_us.vue
Normal file
30
business_uniapp/src/pages/as_us/as_us.vue
Normal file
@@ -0,0 +1,30 @@
|
||||
<template>
|
||||
<page-meta :page-style="$theme.pageStyle">
|
||||
<!-- #ifndef H5 -->
|
||||
<navigation-bar
|
||||
:front-color="$theme.navColor"
|
||||
:background-color="$theme.navBgColor"
|
||||
/>
|
||||
<!-- #endif -->
|
||||
</page-meta>
|
||||
<view class="as-us flex flex-1 flex-col items-center">
|
||||
<image :src="appStore.config.logo" mode="" class="img"></image>
|
||||
<view class="text-content mt-[20rpx]">当前版本{{ appStore.config.version }}</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useAppStore } from '@/stores/app'
|
||||
const appStore = useAppStore()
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.as-us {
|
||||
.img {
|
||||
width: 160rpx;
|
||||
height: 160rpx;
|
||||
border-radius: 20rpx;
|
||||
margin-top: 96rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
141
business_uniapp/src/pages/bind_mobile/bind_mobile.vue
Normal file
141
business_uniapp/src/pages/bind_mobile/bind_mobile.vue
Normal file
@@ -0,0 +1,141 @@
|
||||
<template>
|
||||
<page-meta :page-style="$theme.pageStyle">
|
||||
<!-- #ifndef H5 -->
|
||||
<navigation-bar
|
||||
:front-color="$theme.navColor"
|
||||
:background-color="$theme.navBgColor"
|
||||
/>
|
||||
<!-- #endif -->
|
||||
</page-meta>
|
||||
<view class="register min-h-full flex flex-col items-center px-[30rpx] pt-[60rpx] box-border">
|
||||
|
||||
<u-sticky h5-nav-height="0" bg-color="transparent">
|
||||
<u-navbar
|
||||
:is-back="true"
|
||||
:is-fixed="true"
|
||||
title="更换手机号"
|
||||
:border-bottom="false"
|
||||
:title-bold="false"
|
||||
:background="{ background: `rgba(256,256, 256, 0)` }"
|
||||
:title-color="'#000'"
|
||||
>
|
||||
</u-navbar>
|
||||
</u-sticky>
|
||||
|
||||
<view class="w-full mt-[380rpx]" v-if="bindType == bindMobileEnum.LOOK">
|
||||
<view class="text-content text-center mb-[8rpx] ">
|
||||
已绑定手机号
|
||||
</view>
|
||||
<view class="text-[48rpx] text-center font-black mb-[180rpx]">
|
||||
{{ mobile }}
|
||||
</view>
|
||||
<u-button type="primary" @click="bindType = bindMobileEnum.CHANGE" class="rounded-[24rpx] w-[380rpx]"> 更换手机号 </u-button>
|
||||
</view>
|
||||
|
||||
<view class="w-full" v-if="bindType == bindMobileEnum.CHANGE">
|
||||
<view class="bg-white mb-[30rpx] rounded-[24rpx] px-[48rpx] py-[15rpx] flex items-center">
|
||||
<u-image src="@/static/images/icon/icon_mobile.png" :height="28" :width="28" class="mr-[20rpx]"></u-image>
|
||||
<u-input
|
||||
class="flex-1"
|
||||
v-model="formData.mobile"
|
||||
:border="false"
|
||||
placeholder="请输入手机号码"
|
||||
placeholder-style="color: #999"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<view class="bg-white rounded-[24rpx] px-[48rpx] py-[15rpx] flex items-center items-center">
|
||||
<u-image src="@/static/images/icon/icon_code.png" :height="28" :width="28" class="mr-[20rpx]"></u-image>
|
||||
<u-input
|
||||
class="flex-1"
|
||||
v-model="formData.code"
|
||||
placeholder="请输入验证码"
|
||||
:border="false"
|
||||
placeholder-style="color: #999"
|
||||
/>
|
||||
<view
|
||||
class="text-muted leading-4 "
|
||||
@click="sendSms"
|
||||
>
|
||||
<u-verification-code
|
||||
ref="uCodeRef"
|
||||
:seconds="60"
|
||||
@change="codeChange"
|
||||
change-text="x秒"
|
||||
/>
|
||||
<text :class="formData.mobile ? 'text-primary' : 'text-muted'">
|
||||
{{ codeTips }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="mt-[112rpx]">
|
||||
<u-button type="primary" @click="handleConfirm" class="rounded-[24rpx]"> 确定 </u-button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
|
||||
<script setup lang="ts">
|
||||
import { userBindMobile } from '@/api/user'
|
||||
import { smsSend } from '@/api/app'
|
||||
import { SMSEnum } from '@/enums/appEnums'
|
||||
import { reactive, ref, shallowRef } from 'vue'
|
||||
import { useUserStore } from '@/stores/user'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
|
||||
enum bindMobileEnum {
|
||||
LOOK = 1, // 查看
|
||||
CHANGE = 2, // 更改
|
||||
}
|
||||
|
||||
const mobile = ref('')
|
||||
const bindType = ref(bindMobileEnum.LOOK)
|
||||
|
||||
const uCodeRef = shallowRef()
|
||||
const codeTips = ref('')
|
||||
|
||||
const userStore = useUserStore()
|
||||
const codeChange = (text: string) => {
|
||||
codeTips.value = text
|
||||
}
|
||||
|
||||
const formData = reactive({
|
||||
type: 'change',
|
||||
mobile: '',
|
||||
code: ''
|
||||
})
|
||||
const sendSms = async () => {
|
||||
if (!formData.mobile) return uni.$u.toast('请输入手机号码')
|
||||
if (uCodeRef.value?.canGetCode) {
|
||||
await smsSend({
|
||||
scene: SMSEnum.CHANGE_MOBILE,
|
||||
mobile: formData.mobile
|
||||
})
|
||||
uni.$u.toast('发送成功')
|
||||
uCodeRef.value?.start()
|
||||
}
|
||||
}
|
||||
const handleConfirm = async () => {
|
||||
if (!formData.mobile) return uni.$u.toast('请输入手机号码')
|
||||
if (!formData.code) return uni.$u.toast('请输入验证码')
|
||||
await userBindMobile(formData, { token: userStore.temToken })
|
||||
uni.$u.toast('更改成功')
|
||||
// userStore.login(userStore.temToken!)
|
||||
setTimeout(()=> {
|
||||
uni.navigateBack()
|
||||
}, 500)
|
||||
}
|
||||
|
||||
onLoad((options) => {
|
||||
// console.log(options.mobile)
|
||||
mobile.value = options.mobile
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
page {
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
101
business_uniapp/src/pages/change_password/change_password.vue
Normal file
101
business_uniapp/src/pages/change_password/change_password.vue
Normal file
@@ -0,0 +1,101 @@
|
||||
<template>
|
||||
|
||||
<page-meta :page-style="$theme.pageStyle">
|
||||
<!-- #ifndef H5 -->
|
||||
<navigation-bar
|
||||
:front-color="$theme.navColor"
|
||||
:background-color="$theme.navBgColor"
|
||||
/>
|
||||
<!-- #endif -->
|
||||
</page-meta>
|
||||
<view
|
||||
class="register min-h-full flex flex-col items-center px-[30rpx] pt-[60rpx] box-border"
|
||||
>
|
||||
<view class="w-full">
|
||||
<view v-if="type != 'set'" class="bg-white mb-[30rpx] rounded-[24rpx] px-[48rpx] py-[15rpx] flex">
|
||||
<u-icon class="mr-[20rpx]" name="lock" color="#999" size="28"></u-icon>
|
||||
<u-input
|
||||
class="flex-1"
|
||||
type="password"
|
||||
v-model="formData.old_password"
|
||||
:border="false"
|
||||
placeholder="请输入原密码"
|
||||
placeholder-style="color: #999"
|
||||
/>
|
||||
</view>
|
||||
<view class="bg-white mb-[30rpx] rounded-[24rpx] px-[48rpx] py-[15rpx] flex">
|
||||
<u-icon class="mr-[20rpx]" name="lock" color="#999" size="28"></u-icon>
|
||||
<u-input
|
||||
class="flex-1"
|
||||
type="password"
|
||||
v-model="formData.password"
|
||||
placeholder="请输入新密码"
|
||||
:border="false"
|
||||
placeholder-style="color: #999"
|
||||
/>
|
||||
</view>
|
||||
<view class="bg-white rounded-[24rpx] px-[48rpx] py-[15rpx] flex">
|
||||
<u-icon class="mr-[20rpx]" name="lock" color="#999" size="28"></u-icon>
|
||||
<u-input
|
||||
class="flex-1"
|
||||
type="password"
|
||||
v-model="formData.password_confirm"
|
||||
placeholder="请再次确认密码"
|
||||
:border="false"
|
||||
placeholder-style="color: #999"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<view class="mt-[112rpx]">
|
||||
<u-button type="primary" @click="handleConfirm" class="rounded-[24rpx]"> 确定 </u-button>
|
||||
</view>
|
||||
|
||||
<navigator url="/pages/forget_pwd/forget_pwd" class="mt-[40rpx] text-center text-primary" v-if="type != 'set'">
|
||||
忘记密码?
|
||||
</navigator>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { userChangePwd } from '@/api/user'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import { reactive, ref } from 'vue'
|
||||
import { validateInput } from '@/utils/util'
|
||||
|
||||
const type = ref('')
|
||||
const formData = reactive<any>({
|
||||
password: '',
|
||||
password_confirm: '',
|
||||
})
|
||||
|
||||
const handleConfirm = async () => {
|
||||
if (!formData.old_password && type.value != 'set') return uni.$u.toast('请输入原来的密码')
|
||||
if (!formData.password) return uni.$u.toast('请输入密码')
|
||||
if (!formData.password_confirm) return uni.$u.toast('请输入确认密码')
|
||||
if (formData.password != formData.password_confirm) return uni.$u.toast('两次输入的密码不一致')
|
||||
if (!validateInput(formData.password) || !validateInput(formData.password_confirm))
|
||||
return uni.$u.toast('密码应为6-20位数字+英文')
|
||||
await userChangePwd(formData)
|
||||
uni.$u.toast('操作成功')
|
||||
setTimeout(()=> {
|
||||
uni.navigateBack()
|
||||
}, 500)
|
||||
}
|
||||
|
||||
onLoad((options) => {
|
||||
type.value = options.type || ''
|
||||
if (type.value == 'set') {
|
||||
uni.setNavigationBarTitle({
|
||||
title: '设置登录密码',
|
||||
})
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
page {
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
70
business_uniapp/src/pages/collection/collection.vue
Normal file
70
business_uniapp/src/pages/collection/collection.vue
Normal file
@@ -0,0 +1,70 @@
|
||||
<template>
|
||||
<page-meta :page-style="$theme.pageStyle">
|
||||
<!-- #ifndef H5 -->
|
||||
<navigation-bar
|
||||
:front-color="$theme.navColor"
|
||||
:background-color="$theme.navBgColor"
|
||||
/>
|
||||
<!-- #endif -->
|
||||
</page-meta>
|
||||
<z-paging
|
||||
ref="paging"
|
||||
v-model="collectData"
|
||||
@query="queryList"
|
||||
:fixed="false"
|
||||
height="100%"
|
||||
use-page-scroll
|
||||
>
|
||||
<u-swipe-action
|
||||
:show="item.show"
|
||||
:index="index"
|
||||
v-for="(item, index) in collectData"
|
||||
:key="item.id"
|
||||
@click="handleCollect"
|
||||
:options="options"
|
||||
btn-width="120"
|
||||
>
|
||||
<news-card :item="item" :newsId="item.article_id"></news-card>
|
||||
</u-swipe-action>
|
||||
</z-paging>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, shallowRef } from 'vue'
|
||||
import { getCollect, cancelCollect } from '@/api/news'
|
||||
|
||||
const paging = shallowRef()
|
||||
const options = reactive([
|
||||
{
|
||||
text: '取消收藏',
|
||||
style: {
|
||||
color: '#FFFFFF',
|
||||
backgroundColor: '#FF2C3C'
|
||||
}
|
||||
}
|
||||
])
|
||||
const collectData: any = ref([])
|
||||
|
||||
const queryList = async (pageNo, pageSize) => {
|
||||
const { lists } = await getCollect()
|
||||
lists.forEach((item: any) => {
|
||||
item.show = false
|
||||
})
|
||||
collectData.value = lists
|
||||
paging.value.complete(lists)
|
||||
}
|
||||
|
||||
const handleCollect = async (index: number): Promise<void> => {
|
||||
try {
|
||||
const article_id: number = collectData.value[index].article_id
|
||||
await cancelCollect({ id: article_id })
|
||||
uni.$u.toast('已取消收藏')
|
||||
paging.value.reload()
|
||||
} catch (err) {
|
||||
//TODO handle the exception
|
||||
console.log('取消收藏报错=>', err)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
254
business_uniapp/src/pages/customer_service/customer_service.vue
Normal file
254
business_uniapp/src/pages/customer_service/customer_service.vue
Normal file
@@ -0,0 +1,254 @@
|
||||
<template>
|
||||
<view class="service pt-20">
|
||||
<view class="service-contain">
|
||||
<view class="header-image">
|
||||
<u-image
|
||||
:src="getImageUrl('/resource/image/shopapi/default/service.png')"
|
||||
width="100rpx"
|
||||
height="100rpx"
|
||||
shape="circle"
|
||||
style="margin-top: -50rpx"
|
||||
class="circle"
|
||||
></u-image>
|
||||
</view>
|
||||
|
||||
<!-- way==1 二维码客服 -->
|
||||
<template v-if="serviceData.way == 1">
|
||||
<view class="lg mt-[40rpx] flex justify-center" v-if="serviceData.remarks">
|
||||
{{ serviceData.remarks }}
|
||||
</view>
|
||||
|
||||
<view class="code flex justify-center">
|
||||
<u-image
|
||||
:src="serviceData.qr_code"
|
||||
width="320rpx"
|
||||
height="320rpx"
|
||||
border-radius="20"
|
||||
></u-image>
|
||||
</view>
|
||||
|
||||
<view
|
||||
class="mt-[20rpx] mb-[20rpx] xs muted flex justify-center"
|
||||
v-if="serviceData.phone"
|
||||
>
|
||||
客服电话:{{ serviceData.phone }}
|
||||
</view>
|
||||
<view
|
||||
class="xs mt-[20rpx] muted mb-[20rpx] flex justify-center"
|
||||
v-if="serviceData.business_time"
|
||||
>
|
||||
服务时间: {{ serviceData.business_time }}
|
||||
</view>
|
||||
</template>
|
||||
<!-- logo -->
|
||||
<template v-if="serviceData.way != 1">
|
||||
<view class="flex lg justify-center mt-[40rpx]">
|
||||
{{ appStore.config.shop_name }}
|
||||
</view>
|
||||
<view class="code flex justify-center">
|
||||
<u-image
|
||||
:src="appStore.config.shop_logo"
|
||||
width="320rpx"
|
||||
height="320rpx"
|
||||
border-radius="20"
|
||||
></u-image>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<!-- way==2 电话客服 -->
|
||||
|
||||
<template v-if="serviceData.way == 2">
|
||||
<view class="mt-[40rpx] flex justify-center" v-if="serviceData.phone">
|
||||
<view style="text-align: center">
|
||||
<view> 拨打客服热线 </view>
|
||||
<view style="text-decoration: underline" @click="handleCall">
|
||||
{{ serviceData.service_phone }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
<view class="pt-[20rpx]" v-if="serviceData.way == 4">
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<button
|
||||
open-type="contact"
|
||||
class="copy-btn icon-item text-white rounded-[20rpx] flex justify-center items-center"
|
||||
style="line-height: 88rpx"
|
||||
>
|
||||
<text style="line-height: 32rpx" class="text-[28rpx]">联系微信小程序客服</text>
|
||||
</button>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
<view class="pt-[20rpx]" v-else>
|
||||
<view
|
||||
class="rounded-[20rpx] copy-btn flex justify-center items-center text-white lg"
|
||||
v-if="serviceData.way == 1"
|
||||
@click="saveImageQr"
|
||||
>
|
||||
<text class="">保存二维码</text>
|
||||
</view>
|
||||
<view
|
||||
class="rounded-[20rpx] copy-btn flex justify-center items-center text-white lg"
|
||||
v-if="serviceData.way == 2"
|
||||
@click="handleCall"
|
||||
>
|
||||
<text class="">拨打电话</text>
|
||||
</view>
|
||||
<view
|
||||
class="rounded-[20rpx] copy-btn flex justify-center items-center text-white lg"
|
||||
v-if="serviceData.way == 3"
|
||||
@click="handleService"
|
||||
>
|
||||
<text class="">联系企业微信客服</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue'
|
||||
import { toast } from '@/utils/util'
|
||||
import { getKefuConfig } from '@/api/user'
|
||||
import { getClient } from '@/utils/client'
|
||||
import { serviceEnum } from '@/enums/appEnums'
|
||||
import { useAppStore } from '@/stores/app'
|
||||
|
||||
interface serviceDataObj {
|
||||
business_time: string
|
||||
enterprise_id: string
|
||||
kefu_link: string
|
||||
name: string
|
||||
phone: string
|
||||
qr_code: string
|
||||
remarks: string
|
||||
service_phone: string
|
||||
way: string | number
|
||||
}
|
||||
|
||||
const { getImageUrl } = useAppStore()
|
||||
const appStore = useAppStore()
|
||||
|
||||
const serviceData = ref<serviceDataObj>({
|
||||
business_time: '',
|
||||
enterprise_id: '',
|
||||
kefu_link: '',
|
||||
name: '',
|
||||
phone: '',
|
||||
qr_code: '',
|
||||
remarks: '',
|
||||
service_phone: '',
|
||||
way: ''
|
||||
})
|
||||
|
||||
// 获取客服信息
|
||||
const getContactService = async (): Promise<void> => {
|
||||
const res = await getKefuConfig()
|
||||
serviceData.value = res[serviceEnum[getClient()]]
|
||||
}
|
||||
|
||||
// 保存二维码
|
||||
const saveImageQr = async (): Promise<void> => {
|
||||
//#ifdef H5
|
||||
toast('长按图片保存')
|
||||
//#endif
|
||||
|
||||
//#ifndef H5
|
||||
try {
|
||||
const res = await uni.getImageInfo({ src: serviceData.value.qr_code })
|
||||
try {
|
||||
await uni.saveImageToPhotosAlbum({ filePath: res.path })
|
||||
toast('保存成功')
|
||||
} catch (e) {
|
||||
const modelRes = await uni.showModal({
|
||||
title: '图片保存失败',
|
||||
content: '请确认是否已开启授权'
|
||||
})
|
||||
if (modelRes.confirm) uni.openSetting()
|
||||
}
|
||||
} catch (err) {
|
||||
toast('请在小程序后台配置downloadFile')
|
||||
}
|
||||
//#endif
|
||||
}
|
||||
//拨打电话
|
||||
const handleCall = () => {
|
||||
if (!serviceData.value.service_phone) {
|
||||
toast('请在后台配置客服电话号码')
|
||||
return
|
||||
}
|
||||
uni.makePhoneCall({
|
||||
phoneNumber: serviceData.value.service_phone,
|
||||
success(res) {
|
||||
console.log(res)
|
||||
},
|
||||
fail(err) {
|
||||
console.log(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
const handleService = () => {
|
||||
// #ifdef MP-WEIXIN
|
||||
wx.openCustomerServiceChat({
|
||||
extInfo: { url: serviceData.value.kefu_link },
|
||||
corpId: serviceData.value.enterprise_id,
|
||||
success(res: any) {
|
||||
console.log(res)
|
||||
},
|
||||
fail(err: any) {
|
||||
console.log(err)
|
||||
toast('请在后台配置企业微信客服')
|
||||
}
|
||||
})
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
if (!serviceData.value.kefu_link) {
|
||||
toast('请在后台配置企业微信客服')
|
||||
return
|
||||
}
|
||||
window.open(serviceData.value.kefu_link, '_self')
|
||||
// #endif
|
||||
}
|
||||
|
||||
getContactService()
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.header-image {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
.circle {
|
||||
border-radius: 50%;
|
||||
border: 6rpx solid #ffffff;
|
||||
}
|
||||
}
|
||||
.service {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background-image: url(../../static/images/service_bg.jpg);
|
||||
background-size: 100% auto;
|
||||
&-contain {
|
||||
width: 620rpx;
|
||||
// height: 750rpx;
|
||||
margin: auto;
|
||||
margin-bottom: 40rpx;
|
||||
padding-bottom: 80rpx;
|
||||
border-radius: 10px;
|
||||
background-color: #ffffff;
|
||||
.code {
|
||||
border-radius: 20rpx;
|
||||
padding-top: 60rpx;
|
||||
}
|
||||
|
||||
.phone {
|
||||
padding: 0 20rpx;
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
.copy-btn {
|
||||
margin: 0 80rpx;
|
||||
height: 88rpx;
|
||||
// @include background_linear(90deg, 0, 100%);
|
||||
background: #000722;
|
||||
}
|
||||
</style>
|
||||
7
business_uniapp/src/pages/empty/empty.vue
Normal file
7
business_uniapp/src/pages/empty/empty.vue
Normal file
@@ -0,0 +1,7 @@
|
||||
<template>
|
||||
<div></div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts"></script>
|
||||
|
||||
<style></style>
|
||||
134
business_uniapp/src/pages/forget_pwd/forget_pwd.vue
Normal file
134
business_uniapp/src/pages/forget_pwd/forget_pwd.vue
Normal file
@@ -0,0 +1,134 @@
|
||||
<template>
|
||||
<page-meta :page-style="$theme.pageStyle">
|
||||
<!-- #ifndef H5 -->
|
||||
<navigation-bar
|
||||
:front-color="$theme.navColor"
|
||||
:background-color="$theme.navBgColor"
|
||||
/>
|
||||
<!-- #endif -->
|
||||
</page-meta>
|
||||
<view
|
||||
class="register min-h-full flex flex-col items-center px-[30rpx] pt-[60rpx] box-border"
|
||||
>
|
||||
<view class="w-full">
|
||||
<view class="bg-white mb-[30rpx] rounded-[24rpx] px-[48rpx] py-[15rpx] flex items-center">
|
||||
<u-image src="@/static/images/icon/icon_mobile.png" :height="28" :width="28" class="mr-[20rpx]"></u-image>
|
||||
<u-input
|
||||
class="flex-1"
|
||||
v-model="formData.mobile"
|
||||
:border="false"
|
||||
placeholder="请输入手机号码"
|
||||
placeholder-style="color: #999"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<view class="bg-white mb-[30rpx] rounded-[24rpx] px-[48rpx] py-[15rpx] flex items-center">
|
||||
<u-image src="@/static/images/icon/icon_password.png" :height="28" :width="28" class="mr-[20rpx]"></u-image>
|
||||
<u-input
|
||||
class="flex-1"
|
||||
type="password"
|
||||
v-model="formData.password"
|
||||
placeholder="请输入新密码"
|
||||
:border="false"
|
||||
placeholder-style="color: #999"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<view class="bg-white rounded-[24rpx] px-[48rpx] py-[15rpx] flex items-center items-center">
|
||||
<u-image src="@/static/images/icon/icon_code.png" :height="28" :width="28" class="mr-[20rpx]"></u-image>
|
||||
<u-input
|
||||
class="flex-1"
|
||||
v-model="formData.code"
|
||||
placeholder="请输入验证码"
|
||||
:border="false"
|
||||
placeholder-style="color: #999"
|
||||
/>
|
||||
<view
|
||||
class="text-muted leading-4 "
|
||||
@click="sendSms"
|
||||
>
|
||||
<u-verification-code
|
||||
ref="uCodeRef"
|
||||
:seconds="60"
|
||||
@change="codeChange"
|
||||
change-text="x秒"
|
||||
/>
|
||||
<text :class="formData.mobile ? 'text-primary' : 'text-muted'">
|
||||
{{ codeTips }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- <view class="bg-white mb-[30rpx] rounded-[24rpx] px-[48rpx] py-[15rpx] flex">
|
||||
<u-icon class="mr-[20rpx]" name="lock" color="#999" size="28"></u-icon>
|
||||
<u-input
|
||||
class="flex-1"
|
||||
type="password"
|
||||
v-model="formData.password_confirm"
|
||||
placeholder="再次输入新密码"
|
||||
:border="false"
|
||||
placeholder-style="color: #999"
|
||||
/>
|
||||
</view> -->
|
||||
|
||||
|
||||
<view class="mt-[112rpx]">
|
||||
<u-button type="primary" @click="handleConfirm" class="rounded-[24rpx]"> 确定 </u-button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { smsSend } from '@/api/app'
|
||||
import { forgotPassword } from '@/api/user'
|
||||
import { SMSEnum } from '@/enums/appEnums'
|
||||
import { reactive, ref, shallowRef } from 'vue'
|
||||
import { validateInput } from '@/utils/util'
|
||||
|
||||
const uCodeRef = shallowRef()
|
||||
const codeTips = ref('')
|
||||
const formData = reactive({
|
||||
mobile: '',
|
||||
code: '',
|
||||
password: '',
|
||||
// password_confirm: '',
|
||||
})
|
||||
|
||||
const codeChange = (text: string) => {
|
||||
codeTips.value = text
|
||||
}
|
||||
|
||||
const sendSms = async () => {
|
||||
if (!formData.mobile) return
|
||||
if (uCodeRef.value?.canGetCode) {
|
||||
await smsSend({
|
||||
scene: SMSEnum.FIND_PASSWORD,
|
||||
mobile: formData.mobile,
|
||||
})
|
||||
uni.$u.toast('发送成功')
|
||||
uCodeRef.value?.start()
|
||||
}
|
||||
}
|
||||
|
||||
const handleConfirm = async () => {
|
||||
if (!formData.mobile) return uni.$u.toast('请输入手机号码')
|
||||
if (!formData.password) return uni.$u.toast('请输入密码')
|
||||
// if (!formData.password_confirm) return uni.$u.toast('请输入确认密码')
|
||||
// if (formData.password != formData.password_confirm) return uni.$u.toast('两次输入的密码不一致')
|
||||
// if (!validateInput(formData.password) || !validateInput(formData.password_confirm))
|
||||
if (!validateInput(formData.password))
|
||||
return uni.$u.toast('密码应为6-20位数字+英文')
|
||||
await forgotPassword(formData)
|
||||
uni.$u.toast('操作成功')
|
||||
setTimeout(()=> {
|
||||
uni.navigateBack({delta: 2})
|
||||
}, 500)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
page {
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
98
business_uniapp/src/pages/income/components/card.vue
Normal file
98
business_uniapp/src/pages/income/components/card.vue
Normal file
@@ -0,0 +1,98 @@
|
||||
<template>
|
||||
<view class="bg-white px-[20rpx] pt-[30rpx] pb-[20rpx] rounded-t-lg">
|
||||
<view class="text-sm flex justify-between">
|
||||
<text class="text-info">订单编号:{{ sn }}</text>
|
||||
<text class="text-[#E86016]">{{ is_settle ? '已结算' : '未结算' }}</text>
|
||||
</view>
|
||||
<view v-for="item in order_goods" :key="item.order_id" class="mt-2 flex items-center">
|
||||
<view class="flex-none">
|
||||
<u-image
|
||||
:src="item.goods_image"
|
||||
width="130rpx"
|
||||
height="130rpx"
|
||||
border-radius="16rpx"
|
||||
></u-image>
|
||||
</view>
|
||||
|
||||
<view class="flex flex-col justify-between ml-2">
|
||||
<view class="line-clamp-1 font-bold text-lg">
|
||||
{{ item.goods_name }}
|
||||
</view>
|
||||
<view class="text-info text-sm">服务时间:{{ item.duration }}分钟</view>
|
||||
<price font-weight="700" :content="item.goods_price"></price>
|
||||
</view>
|
||||
<view class="ml-auto text-info">x{{ total_num }}</view>
|
||||
</view>
|
||||
<view class="mt-2 text-info text-xs">服务完成时间:{{ true_server_finish_time }}</view>
|
||||
</view>
|
||||
<!-- 未结算 -->
|
||||
<view
|
||||
class="bg-white px-[20rpx] pb-[30rpx] rounded-b-lg flex items-baseline justify-end"
|
||||
v-if="type == 0"
|
||||
>
|
||||
<view class="text-xs">总金额:</view>
|
||||
<price
|
||||
:content="order_amount"
|
||||
font-weight="700"
|
||||
main-size="40rpx"
|
||||
sub-size="24rpx"
|
||||
color="#333333"
|
||||
/>
|
||||
</view>
|
||||
<!-- 已结算 -->
|
||||
<view class="settle px-[20rpx] py-[30rpx] rounded-b-lg flex justify-between" v-else>
|
||||
<view class="ml-[20rpx]">
|
||||
<view class="text-xs mb-[4rpx]"> 总金额: </view>
|
||||
<price
|
||||
:content="settle_info.order_amount"
|
||||
font-weight="700"
|
||||
main-size="40rpx"
|
||||
sub-size="24rpx"
|
||||
color="#333333"
|
||||
/>
|
||||
</view>
|
||||
<view class="ml-[20rpx]">
|
||||
<view class="text-[#A2704A] text-xs mb-[4rpx]"> 结算佣金: </view>
|
||||
<price
|
||||
:content="settle_info.shop_settle"
|
||||
font-weight="700"
|
||||
main-size="40rpx"
|
||||
sub-size="24rpx"
|
||||
color="#703215"
|
||||
/>
|
||||
</view>
|
||||
<view class="ml-[20rpx]">
|
||||
<view class="text-[#A2704A] text-xs mb-[4rpx]"> 结算车费: </view>
|
||||
<price
|
||||
:content="settle_info.settle_car"
|
||||
font-weight="700"
|
||||
main-size="40rpx"
|
||||
sub-size="24rpx"
|
||||
color="#703215"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import price from '@/components/price/price.vue'
|
||||
|
||||
defineProps<{
|
||||
sn: string
|
||||
order_status_desc: string
|
||||
order_goods: any[]
|
||||
order_amount: string
|
||||
true_server_finish_time: string
|
||||
order_status: number
|
||||
settle_info: any
|
||||
type: number
|
||||
total_num: number
|
||||
is_settle: number
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.settle {
|
||||
background: linear-gradient(135.6deg, #fff2df 0%, #f4d7ac 100%);
|
||||
}
|
||||
</style>
|
||||
115
business_uniapp/src/pages/income/components/list.vue
Normal file
115
business_uniapp/src/pages/income/components/list.vue
Normal file
@@ -0,0 +1,115 @@
|
||||
<template>
|
||||
<view class="flex flex-col min-h-0 h-full">
|
||||
<option-com
|
||||
v-model:startDate="startDate"
|
||||
v-model:endDate="endDate"
|
||||
:orderAmount="orderAmount"
|
||||
:type="type"
|
||||
@change="paging?.reload()"
|
||||
/>
|
||||
<view class="h-full">
|
||||
<z-paging
|
||||
auto-show-back-to-top
|
||||
:auto="i == index"
|
||||
ref="paging"
|
||||
v-model="dataList"
|
||||
:data-key="i"
|
||||
@query="queryList"
|
||||
:fixed="false"
|
||||
height="100%"
|
||||
>
|
||||
<view
|
||||
v-for="(item, index) in dataList"
|
||||
:key="index"
|
||||
class="px-[30rpx] pb-3"
|
||||
@click="goToOrder(item.id)"
|
||||
>
|
||||
<card
|
||||
:sn="item.sn"
|
||||
:order_status_desc="item.order_status_desc"
|
||||
:order_goods="item.order_goods"
|
||||
:order_amount="item.order_amount"
|
||||
:true_server_finish_time="item.true_server_finish_time"
|
||||
:order_status="item.order_status"
|
||||
:settle_info="item.settle_info"
|
||||
:type="type"
|
||||
:total_num="item.total_num"
|
||||
:is_settle="item.is_settle"
|
||||
></card>
|
||||
</view>
|
||||
</z-paging>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, watch, nextTick, shallowRef } from 'vue'
|
||||
import cashOutIcon from '../../../static/images/cashOutIcon.png'
|
||||
import card from './card.vue'
|
||||
import optionCom from './option.vue'
|
||||
import { getInComeLists } from '@/api/order'
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
type: number
|
||||
i: number
|
||||
index: number
|
||||
}>(),
|
||||
{
|
||||
type: 0
|
||||
}
|
||||
)
|
||||
|
||||
const paging = shallowRef<any>(null)
|
||||
const dataList = ref<any>([])
|
||||
const isFirst = ref<boolean>(true)
|
||||
const startDate = ref('')
|
||||
const endDate = ref('')
|
||||
const orderAmount = ref(0)
|
||||
|
||||
watch(
|
||||
() => props.index,
|
||||
async () => {
|
||||
await nextTick()
|
||||
if (props.i == props.index && isFirst.value) {
|
||||
isFirst.value = false
|
||||
paging.value?.reload()
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
// watch(
|
||||
// () => [startDate.value, endDate.value],
|
||||
// () => {
|
||||
// paging.value?.reload()
|
||||
// }
|
||||
// )
|
||||
|
||||
// 去到订单详情页面
|
||||
const goToOrder = (id: number) => {
|
||||
uni.navigateTo({
|
||||
url: `/packages/pages/order_detail/order_detail?id=${id}`
|
||||
})
|
||||
}
|
||||
|
||||
const queryList = async (page_no: number, page_size: number) => {
|
||||
try {
|
||||
const { lists, extend } = await getInComeLists({
|
||||
type: props.type,
|
||||
start_time: startDate.value,
|
||||
end_time: endDate.value,
|
||||
page_no,
|
||||
page_size
|
||||
})
|
||||
orderAmount.value = extend.settle_amount
|
||||
paging.value.complete(lists)
|
||||
} catch (e) {
|
||||
console.log('报错=>', e)
|
||||
//TODO handle the exception
|
||||
paging.value.complete(false)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
76
business_uniapp/src/pages/income/components/option.vue
Normal file
76
business_uniapp/src/pages/income/components/option.vue
Normal file
@@ -0,0 +1,76 @@
|
||||
<template>
|
||||
<view class="px-[30rpx] py-[28rpx]">
|
||||
<view class="flex justify-between">
|
||||
<view class="flex items-center" @click="showDataPicker">
|
||||
<text>{{ startDate }} - {{ endDate }}</text>
|
||||
<u-icon class="ml-2" name="arrow-down-fill" size="18"></u-icon>
|
||||
</view>
|
||||
<view>
|
||||
<text>{{ type == 0 ? '未结算金额' : '总结算金额' }}</text>
|
||||
<text class="font-bold text-lg">{{ orderAmount }}</text>
|
||||
<text>元</text>
|
||||
</view>
|
||||
</view>
|
||||
<u-calendar
|
||||
v-model="show"
|
||||
mode="range"
|
||||
safe-area-inset-bottom
|
||||
@change="change"
|
||||
></u-calendar>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref } from 'vue'
|
||||
|
||||
const emits = defineEmits<{
|
||||
(e: 'update:startDate', value: string): void
|
||||
(e: 'update:endDate', value: string): void
|
||||
(e: 'change'): void
|
||||
}>()
|
||||
|
||||
const props = defineProps<{
|
||||
startDate: string
|
||||
endDate: string
|
||||
orderAmount: number
|
||||
type: number // 0: 未结算, 1: 已结算
|
||||
}>()
|
||||
|
||||
const show = ref(false)
|
||||
const startDate = ref('')
|
||||
const endDate = ref('')
|
||||
|
||||
// 初始化日期
|
||||
const today = new Date()
|
||||
const oneMonthAgo = new Date()
|
||||
oneMonthAgo.setMonth(today.getMonth() - 1)
|
||||
|
||||
// 格式化日期为 YYYY-MM-DD 格式
|
||||
const formatDate = (date: Date): string => {
|
||||
const year = date.getFullYear()
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0') // 月份从 0 开始,因此需要加 1
|
||||
const day = String(date.getDate()).padStart(2, '0') // 确保日期是两位数
|
||||
return `${year}-${month}-${day}`
|
||||
}
|
||||
|
||||
// 打开日期选择
|
||||
const showDataPicker = () => {
|
||||
show.value = true
|
||||
}
|
||||
|
||||
// 日期选择变化
|
||||
const change = (value: any) => {
|
||||
startDate.value = value.startDate
|
||||
endDate.value = value.endDate
|
||||
emits('update:startDate', value.startDate)
|
||||
emits('update:endDate', value.endDate)
|
||||
emits('change')
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
startDate.value = formatDate(oneMonthAgo)
|
||||
endDate.value = formatDate(today)
|
||||
emits('update:startDate', startDate.value)
|
||||
emits('update:endDate', endDate.value)
|
||||
})
|
||||
</script>
|
||||
64
business_uniapp/src/pages/income/income.vue
Normal file
64
business_uniapp/src/pages/income/income.vue
Normal file
@@ -0,0 +1,64 @@
|
||||
<template>
|
||||
<page-meta :page-style="$theme.pageStyle">
|
||||
<!-- #ifndef H5 -->
|
||||
<navigation-bar
|
||||
:front-color="$theme.navColor"
|
||||
:background-color="$theme.navBgColor"
|
||||
/>
|
||||
<!-- #endif -->
|
||||
</page-meta>
|
||||
<view>
|
||||
<tabs
|
||||
:isScroll="false"
|
||||
:current="current"
|
||||
@change="handleChange"
|
||||
height="80"
|
||||
bar-width="60"
|
||||
>
|
||||
<tab v-for="(item, i) in tabList" :key="i" :name="item.name">
|
||||
<!-- <optionCom></optionCom> -->
|
||||
<view class="orderList" v-if="userStore.isLogin">
|
||||
<list :type="item.type" :i="i" :index="current"></list>
|
||||
</view>
|
||||
|
||||
<view v-if="!userStore.isLogin">
|
||||
<no-login></no-login>
|
||||
</view>
|
||||
</tab>
|
||||
</tabs>
|
||||
<tabbar />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue'
|
||||
import list from './components/list.vue'
|
||||
import optionCom from './components/option.vue'
|
||||
import noLogin from '@/components/no-login/no-login.vue'
|
||||
import { useUserStore } from '@/stores/user'
|
||||
|
||||
const userStore = useUserStore()
|
||||
|
||||
const tabList = ref<any>([
|
||||
{
|
||||
name: '已结算',
|
||||
type: 1
|
||||
},
|
||||
{
|
||||
name: '未结算',
|
||||
type: 0
|
||||
}
|
||||
])
|
||||
const current = ref<number>(0)
|
||||
|
||||
const handleChange = (index: number) => {
|
||||
console.log(index)
|
||||
current.value = Number(index)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.orderList {
|
||||
height: calc(100vh - 100rpx - env(safe-area-inset-bottom));
|
||||
}
|
||||
</style>
|
||||
53
business_uniapp/src/pages/index/component/logoCom.vue
Normal file
53
business_uniapp/src/pages/index/component/logoCom.vue
Normal file
@@ -0,0 +1,53 @@
|
||||
<template>
|
||||
<view class="px-[40rpx] pb-[100rpx] py-[20rpx]">
|
||||
<!-- #ifndef H5 -->
|
||||
<u-sticky h5-nav-height="0" bg-color="transparent">
|
||||
<u-navbar
|
||||
:is-back="false"
|
||||
:is-fixed="true"
|
||||
:title="meta.title"
|
||||
:custom-title="meta.title_type == 2"
|
||||
:border-bottom="false"
|
||||
:title-bold="true"
|
||||
:background="{ background: `rgba(256,256, 256, ${percent})` }"
|
||||
:title-color="percent > 0.5 ? '#000' : meta.text_color == 1 ? '#fff' : '#000'"
|
||||
>
|
||||
<template #default>
|
||||
<view> </view>
|
||||
</template>
|
||||
<template #title>
|
||||
<image
|
||||
class="!h-[40rpx]"
|
||||
:src="appStore.getImageUrl(meta.title_img)"
|
||||
mode="heightFix"
|
||||
></image>
|
||||
</template>
|
||||
</u-navbar>
|
||||
</u-sticky>
|
||||
<!-- #endif -->
|
||||
|
||||
<view class="flex items-center justify-between">
|
||||
<view class="text-white font-bold text-[40rpx]">
|
||||
<view>Hello,</view>
|
||||
<view class="line-clamp-1">欢迎来到{{ appStore.config.shop_name || '-' }}</view>
|
||||
</view>
|
||||
<u-image
|
||||
width="100"
|
||||
height="100"
|
||||
:src="appStore.config.shop_logo"
|
||||
borderRadius="14"
|
||||
class="flex-none"
|
||||
></u-image>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useAppStore } from '@/stores/app'
|
||||
const appStore = useAppStore()
|
||||
|
||||
const props = defineProps<{
|
||||
meta: any
|
||||
percent: number
|
||||
}>()
|
||||
</script>
|
||||
171
business_uniapp/src/pages/index/component/main.vue
Normal file
171
business_uniapp/src/pages/index/component/main.vue
Normal file
@@ -0,0 +1,171 @@
|
||||
<template>
|
||||
<view class="bg-[#F6F7F8] rounded-t-lg px-[30rpx] py-[40rpx] mt-[-20rpx]">
|
||||
<view class="bg-white px-[20rpx] py-[28rpx] rounded-lg">
|
||||
<view class="font-bold text-xl">店铺数据</view>
|
||||
<view class="grid grid-cols-3 gap-[20rpx] mt-[28rpx]">
|
||||
<view class="p-[20rpx] bg-[#5565EF] rounded-[12rpx]">
|
||||
<u-image width="40" height="40" :src="visiter" borderRadius="14"></u-image>
|
||||
<view class="text-white text-xs mt-1">访客数</view>
|
||||
<view class="font-bold text-lg text-white">
|
||||
{{ data?.shop_data.shop_visit || 0 }}
|
||||
</view>
|
||||
<view class="mt-1 text-xs">
|
||||
<text class="text-white mr-1">较昨日</text>
|
||||
<text :class="handleColor(data?.shop_data.order_income_compare || '0%')">
|
||||
{{ data?.shop_data.visit_compare || '-' }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="p-[20rpx] bg-[#14C1DC] rounded-[12rpx]">
|
||||
<u-image width="40" height="40" :src="order" borderRadius="14"></u-image>
|
||||
<view class="text-white text-xs mt-1">订单数</view>
|
||||
<view class="font-bold text-lg text-white">{{ data?.shop_data.order_num || 0 }}</view>
|
||||
<view class="mt-1 text-xs">
|
||||
<text class="text-white mr-1">较昨日</text>
|
||||
<text :class="handleColor(data?.shop_data.order_income_compare || '0%')">
|
||||
{{ data?.shop_data.order_num_compare || '-' }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="p-[20rpx] bg-[#0B66EF] rounded-[12rpx]">
|
||||
<u-image width="40" height="40" :src="income" borderRadius="14"></u-image>
|
||||
<view class="text-white text-xs mt-1">收入金额(元)</view>
|
||||
<view class="font-bold text-lg text-white">
|
||||
{{ data?.shop_data.order_income || 0}}
|
||||
</view>
|
||||
<view class="mt-1 text-xs">
|
||||
<text class="text-white mr-1">较昨日</text>
|
||||
<text :class="handleColor(data?.shop_data.order_income_compare || '0%')">
|
||||
{{ data?.shop_data.order_income_compare || '-' }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="bg-white mt-2 px-[20rpx] py-[28rpx] rounded-lg">
|
||||
<view class="font-bold text-xl">待服务单</view>
|
||||
<view
|
||||
style="background: linear-gradient(92deg, #0b8cef 0%, #2479f9 100%)"
|
||||
class="grid grid-cols-3 px-[24rpx] py-[22rpx] rounded-lg mt-[28rpx]"
|
||||
>
|
||||
<view class="">
|
||||
<view class="text-white text-xs">今天待服务</view>
|
||||
<view class="font-bold text-2xl text-white mt-2">
|
||||
{{ data?.wait_order_data.today_order_num || 0 }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="">
|
||||
<view class="text-white text-xs">明天待服务</view>
|
||||
<view class="font-bold text-2xl text-white mt-2">
|
||||
{{ data?.wait_order_data.tomorrow_order_num || 0 }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="">
|
||||
<view class="text-white text-xs">后天待服务</view>
|
||||
<view class="font-bold text-2xl text-white mt-2">
|
||||
{{ data?.wait_order_data.dayafter_order_num || 0 }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<template v-if="userStore.isLogin">
|
||||
<view class="bg-white mt-2 px-[20rpx] py-[28rpx] rounded-lg">
|
||||
<view class="font-bold text-xl">订单数据</view>
|
||||
<view class="grid grid-cols-3 gap-[20rpx] mt-[28rpx]">
|
||||
<view class="bg-[#F5F8FD] px-[20rpx] py-[28rpx] rounded-md">
|
||||
<view class="text-[#666666] text-xs">待服务</view>
|
||||
<view class="font-bold text-3xl mt-3">{{ data?.order_data.wait_server_num || 0 }}</view>
|
||||
</view>
|
||||
<view class="bg-[#F5F8FD] px-[20rpx] py-[28rpx] rounded-md">
|
||||
<view class="text-[#666666] text-xs">待接单</view>
|
||||
<view class="font-bold text-3xl mt-3">{{ data?.order_data.wait_take_num || 0 }}</view>
|
||||
</view>
|
||||
<view class="bg-[#F5F8FD] px-[20rpx] py-[28rpx] rounded-md">
|
||||
<view class="text-[#666666] text-xs">已出发</view>
|
||||
<view class="font-bold text-3xl mt-3">{{ data?.order_data.depart_num || 0 }}</view>
|
||||
</view>
|
||||
<view class="bg-[#F5F8FD] px-[20rpx] py-[28rpx] rounded-md">
|
||||
<view class="text-[#666666] text-xs">已到达</view>
|
||||
<view class="font-bold text-3xl mt-3">{{ data?.order_data.arrive_num || 0 }}</view>
|
||||
</view>
|
||||
<view class="bg-[#F5F8FD] px-[20rpx] py-[28rpx] rounded-md">
|
||||
<view class="text-[#666666] text-xs">服务中</view>
|
||||
<view class="font-bold text-3xl mt-3">{{ data?.order_data.start_server_num || 0}}</view>
|
||||
</view>
|
||||
<view class="bg-[#F5F8FD] px-[20rpx] py-[28rpx] rounded-md">
|
||||
<view class="text-[#666666] text-xs">已完成</view>
|
||||
<view class="font-bold text-3xl mt-3">{{ data?.order_data.finish_server_num || 0}}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="bg-white mt-2 px-[20rpx] py-[28rpx] rounded-lg">
|
||||
<view class="font-bold text-xl">技师数据</view>
|
||||
<view class="grid grid-cols-3 gap-[28rpx] mt-[28rpx]">
|
||||
<view class="bg-[#F5F8FD] px-[20rpx] py-[28rpx] rounded-md">
|
||||
<view class="text-[#666666] text-xs">待审核</view>
|
||||
<view class="font-bold text-3xl mt-3">{{ data?.coach_data.wait_audtit_num || 0 }}</view>
|
||||
</view>
|
||||
<view class="bg-[#F5F8FD] px-[20rpx] py-[28rpx] rounded-md">
|
||||
<view class="text-[#666666] text-xs">上线技师</view>
|
||||
<view class="font-bold text-3xl mt-3">{{ data?.coach_data.online_coach_num || 0 }}</view>
|
||||
</view>
|
||||
<view class="bg-[#F5F8FD] px-[20rpx] py-[28rpx] rounded-md">
|
||||
<view class="text-[#666666] text-xs">下线技师</view>
|
||||
<view class="font-bold text-3xl mt-3">{{ data?.coach_data.downline_coach_num || 0 }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<template v-if="!userStore.isLogin">
|
||||
<view class="flex flex-col items-center mb-[100rpx]">
|
||||
<u-image :width="240" :height="240" :src="empty" />
|
||||
<view class="mt-2 sm text-muted">您当前未登录,登录后可查看信息</view>
|
||||
<u-button @click="toLogin" class="mt-4 w-[300rpx]" type="primary">去登录</u-button>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import visiter from '@/static/images/index/visiter.png'
|
||||
import order from '@/static/images/index/order.png'
|
||||
import income from '@/static/images/index/income.png'
|
||||
import empty from '@/static/images/empty.png'
|
||||
import { useUserStore } from '@/stores/user'
|
||||
|
||||
const userStore = useUserStore()
|
||||
|
||||
const toLogin = () => {
|
||||
uni.navigateTo({
|
||||
url: '/pages/login/login'
|
||||
})
|
||||
}
|
||||
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
}
|
||||
})
|
||||
|
||||
//
|
||||
const handleColor = (str: string) => {
|
||||
|
||||
// 去除字符串最后的%
|
||||
let strNuber = str.slice(0, -1)
|
||||
let num = Number(strNuber)
|
||||
|
||||
let classText = ''
|
||||
|
||||
if(num > 0)
|
||||
classText = 'text-error'
|
||||
else if (num == 0)
|
||||
classText = 'text-white'
|
||||
else
|
||||
classText = 'text-success'
|
||||
|
||||
return classText
|
||||
}
|
||||
|
||||
</script>
|
||||
158
business_uniapp/src/pages/index/component/mp-privacy-popup.vue
Normal file
158
business_uniapp/src/pages/index/component/mp-privacy-popup.vue
Normal file
@@ -0,0 +1,158 @@
|
||||
<template>
|
||||
<!-- modal:隐私授权弹窗-->
|
||||
<view v-if="show" class="modal-box" @tap.stop>
|
||||
<view class="dialog" @tap.stop>
|
||||
<view class="title">隐私政策提示</view>
|
||||
<view class="content">
|
||||
欢迎使用{{
|
||||
appStore.getWebsiteConfig.shop_name
|
||||
}}小程序,请您在使用前点击
|
||||
<text
|
||||
class="text-[#243245]"
|
||||
hover-class="hover"
|
||||
@click="openContract"
|
||||
>
|
||||
{{ name }}
|
||||
</text>
|
||||
并仔细阅读,如您同意全部内容,请点击同意开始使用我们的服务。
|
||||
</view>
|
||||
<view class="btn-box">
|
||||
<button
|
||||
class="btn disagree"
|
||||
hover-class="hover"
|
||||
@click="disagreePrivacy"
|
||||
>
|
||||
不同意
|
||||
</button>
|
||||
<button
|
||||
class="btn bg-primary text-white"
|
||||
hover-class="hover"
|
||||
id="agree-btn"
|
||||
open-type="agreePrivacyAuthorization"
|
||||
@agreeprivacyauthorization="agreePrivacy"
|
||||
>
|
||||
同意
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue'
|
||||
import { useAppStore } from '@/stores/app'
|
||||
const appStore = useAppStore()
|
||||
|
||||
const name = ref<string>('')
|
||||
const show = ref<boolean>(false)
|
||||
|
||||
interface PrivacyRes {
|
||||
errMsg: string
|
||||
privacyContractName: string
|
||||
needAuthorization: boolean
|
||||
}
|
||||
|
||||
if (wx.getPrivacySetting) {
|
||||
wx.getPrivacySetting({
|
||||
success(res: PrivacyRes) {
|
||||
console.log(res)
|
||||
name.value = res.privacyContractName
|
||||
show.value = res.needAuthorization
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const openContract = () => {
|
||||
wx.openPrivacyContract({
|
||||
success: () => {},
|
||||
fail: () => {}
|
||||
})
|
||||
}
|
||||
|
||||
const disagreeHandle = () => {
|
||||
// 用户点击拒绝后
|
||||
show.value = false
|
||||
}
|
||||
|
||||
const disagreePrivacy = () => {
|
||||
uni.$u.toast('同意隐私政策后可继续使用')
|
||||
// wx.exitMiniProgram()
|
||||
}
|
||||
|
||||
const agreePrivacy = () => {
|
||||
show.value = false
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.modal-box {
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
z-index: 99999;
|
||||
}
|
||||
|
||||
.modal-box .dialog {
|
||||
box-sizing: border-box;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
padding: 40rpx;
|
||||
padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
|
||||
background: #ffffff;
|
||||
border-radius: 20rpx 20rpx 0 0;
|
||||
}
|
||||
|
||||
.modal-box .title {
|
||||
text-align: center;
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
font-size: 34rpx;
|
||||
}
|
||||
|
||||
.modal-box .content {
|
||||
display: block;
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
margin-top: 20rpx;
|
||||
text-align: justify;
|
||||
line-height: 1.6;
|
||||
padding: 10rpx 20rpx;
|
||||
}
|
||||
|
||||
.modal-box .btn-box {
|
||||
margin-top: 50rpx;
|
||||
padding: 0 30rpx;
|
||||
padding-bottom: 30rpx;
|
||||
display: flex;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.modal-box .btn::after {
|
||||
border: none;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.modal-box .btn-box .btn {
|
||||
width: 50%;
|
||||
height: 76rpx;
|
||||
line-height: 76rpx;
|
||||
margin: 0 10rpx;
|
||||
padding: 0;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 60px;
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.modal-box .disagree {
|
||||
color: #0f0f0f;
|
||||
background: #f5f5f5;
|
||||
}
|
||||
</style>
|
||||
104
business_uniapp/src/pages/index/index.vue
Normal file
104
business_uniapp/src/pages/index/index.vue
Normal file
@@ -0,0 +1,104 @@
|
||||
<template>
|
||||
<page-meta :page-style="$theme.pageStyle">
|
||||
<!-- #ifndef H5 -->
|
||||
<navigation-bar :front-color="$theme.navColor" :background-color="$theme.navBgColor"/>
|
||||
<!-- #endif -->
|
||||
</page-meta>
|
||||
<view class="index" :style="pageStyle">
|
||||
<!-- 组件 -->
|
||||
<Logo
|
||||
:meta="decoratePage.meta"
|
||||
:percent="percent"
|
||||
></Logo>
|
||||
<Main :data="shopData"></Main>
|
||||
|
||||
<!-- 返回顶部按钮 -->
|
||||
<u-back-top
|
||||
:scroll-top="scrollTop"
|
||||
:top="100"
|
||||
:customStyle="{
|
||||
backgroundColor: '#FFF',
|
||||
color: '#000',
|
||||
boxShadow: '0px 3px 6px rgba(0, 0, 0, 0.1)'
|
||||
}"
|
||||
>
|
||||
</u-back-top>
|
||||
|
||||
<!-- #ifdef MP -->
|
||||
<!-- 微信小程序隐私弹窗 -->
|
||||
<MpPrivacyPopup></MpPrivacyPopup>
|
||||
<!-- #endif -->
|
||||
|
||||
<tabbar/>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {getDecoratePage} from '@/api/decorate'
|
||||
import {getIndexData} from '@/api/shop'
|
||||
import {onShow, onPageScroll} from '@dcloudio/uni-app'
|
||||
import {computed, reactive, ref} from 'vue'
|
||||
import {useAppStore} from '@/stores/app'
|
||||
import Logo from './component/logoCom.vue'
|
||||
import Main from './component/main.vue'
|
||||
|
||||
// #ifdef MP
|
||||
import MpPrivacyPopup from './component/mp-privacy-popup.vue'
|
||||
// #endif
|
||||
|
||||
const appStore = useAppStore()
|
||||
const {getImageUrl} = useAppStore()
|
||||
|
||||
const decoratePage = reactive<{
|
||||
data: any[]
|
||||
meta: any
|
||||
}>({
|
||||
data: [],
|
||||
meta: {}
|
||||
})
|
||||
const scrollTop = ref<number>(0)
|
||||
const percent = ref<number>(0)
|
||||
|
||||
// 根页面样式
|
||||
const pageStyle = computed(() => {
|
||||
const {bg_type, bg_color, bg_image} = decoratePage?.meta ?? {}
|
||||
return bg_type == 1 ?
|
||||
{'background-color': bg_color} :
|
||||
{'background-image': `url(${getImageUrl(bg_image)})`}
|
||||
})
|
||||
|
||||
const shopData = ref<any>()
|
||||
|
||||
// 初始化页面数据
|
||||
const initData = async () => {
|
||||
//获取装修数据
|
||||
const res = await getDecoratePage({
|
||||
type: 1
|
||||
})
|
||||
decoratePage.data = JSON.parse(res?.data)
|
||||
decoratePage.meta = JSON.parse(res?.meta)[0].content
|
||||
|
||||
uni.setNavigationBarTitle({
|
||||
title: decoratePage.meta.title
|
||||
})
|
||||
|
||||
//获取首页数据
|
||||
shopData.value = await getIndexData()
|
||||
}
|
||||
|
||||
onPageScroll((event: any) => {
|
||||
scrollTop.value = event.scrollTop
|
||||
const top = uni.upx2px(100)
|
||||
percent.value = event.scrollTop / top > 1 ? 1 : event.scrollTop / top
|
||||
})
|
||||
onShow( () => { initData() })
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.index {
|
||||
padding-bottom: 100rpx;
|
||||
background-size: 100% auto;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
</style>
|
||||
|
||||
168
business_uniapp/src/pages/login/component/bind-mobile.vue
Normal file
168
business_uniapp/src/pages/login/component/bind-mobile.vue
Normal file
@@ -0,0 +1,168 @@
|
||||
<template>
|
||||
<view>
|
||||
<u-popup
|
||||
v-model="showPopup"
|
||||
mode="bottom"
|
||||
border-radius="14"
|
||||
:mask-close-able="false"
|
||||
safe-area-inset-bottom
|
||||
closeable
|
||||
@close="emit('close')"
|
||||
>
|
||||
<view class="my-[30rpx] px-[30rpx] flex flex-col justify-center">
|
||||
<view class="flex-1">
|
||||
<view class="text-[36rpx]"> 绑定手机号 </view>
|
||||
<!-- #ifndef MP-WEIXIN -->
|
||||
<view class="pb-[100rpx] pt-[50rpx]">
|
||||
<u-form borderBottom :label-width="150">
|
||||
<u-form-item label="手机号" borderBottom>
|
||||
<u-input
|
||||
class="flex-1"
|
||||
v-model="formData.mobile"
|
||||
:border="false"
|
||||
placeholder="请输入手机号码"
|
||||
/>
|
||||
</u-form-item>
|
||||
<u-form-item label="验证码" borderBottom>
|
||||
<u-input
|
||||
class="flex-1"
|
||||
v-model="formData.code"
|
||||
placeholder="请输入验证码"
|
||||
:border="false"
|
||||
/>
|
||||
<view
|
||||
class="border-l border-solid border-0 border-light pl-3 text-muted leading-4 ml-3 w-[180rpx]"
|
||||
@click="sendSms"
|
||||
>
|
||||
<u-verification-code
|
||||
ref="uCodeRef"
|
||||
:seconds="60"
|
||||
@change="codeChange"
|
||||
change-text="x秒"
|
||||
/>
|
||||
{{ codeTips }}
|
||||
</view>
|
||||
</u-form-item>
|
||||
</u-form>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<view class="py-[100rpx] flex flex-col items-center">
|
||||
<view class="text-[36rpx]"> 绑定手机号 </view>
|
||||
<view class="text-muted mt-[20rpx]">
|
||||
绑定手机号,以获取更好的体验
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
<view class="mt-[40rpx]">
|
||||
<!-- #ifndef MP-WEIXIN -->
|
||||
<u-button
|
||||
type="primary"
|
||||
shape="circle"
|
||||
@click="handleConfirm"
|
||||
>
|
||||
确定
|
||||
</u-button>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<u-button
|
||||
type="primary"
|
||||
shape="circle"
|
||||
hover-class="none"
|
||||
open-type="getPhoneNumber"
|
||||
@getphonenumber="getPhoneNumber"
|
||||
>
|
||||
<!-- <u-icon name="weixin-fill" size="40" />-->
|
||||
<text class="ml-[10rpx]"> 授权手机号</text>
|
||||
</u-button>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
</view>
|
||||
</u-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { userBindMobile, userMnpMobile } from '@/api/user'
|
||||
import { smsSend } from '@/api/app'
|
||||
import { SMSEnum } from '@/enums/appEnums'
|
||||
import { computed, reactive, ref, shallowRef } from 'vue'
|
||||
import { useUserStore } from '@/stores/user'
|
||||
|
||||
const props = defineProps({
|
||||
show: {
|
||||
type: Boolean
|
||||
},
|
||||
userInfo: {
|
||||
type: Object
|
||||
}
|
||||
})
|
||||
const emit = defineEmits<{
|
||||
(event: 'update:show', show: boolean): void
|
||||
(event: 'success'): void
|
||||
(event: 'close'): void
|
||||
}>()
|
||||
|
||||
const showPopup = computed({
|
||||
get() {
|
||||
return props.show
|
||||
},
|
||||
set(val) {
|
||||
emit('update:show', val)
|
||||
}
|
||||
})
|
||||
const uCodeRef = shallowRef()
|
||||
const codeTips = ref('')
|
||||
|
||||
const userStore = useUserStore()
|
||||
const codeChange = (text: string) => {
|
||||
codeTips.value = text
|
||||
}
|
||||
|
||||
const formData = reactive({
|
||||
type: 'bind',
|
||||
mobile: '',
|
||||
code: ''
|
||||
})
|
||||
const sendSms = async () => {
|
||||
if (!formData.mobile) return uni.$u.toast('请输入手机号码')
|
||||
if (uCodeRef.value?.canGetCode) {
|
||||
await smsSend({
|
||||
scene: SMSEnum.BIND_MOBILE,
|
||||
mobile: formData.mobile
|
||||
})
|
||||
uni.$u.toast('发送成功')
|
||||
uCodeRef.value?.start()
|
||||
}
|
||||
}
|
||||
const handleConfirm = async () => {
|
||||
if (!formData.mobile) return uni.$u.toast('请输入手机号码')
|
||||
if (!formData.code) return uni.$u.toast('请输入验证码')
|
||||
await userBindMobile(formData, { token: props.userInfo?.token })
|
||||
uni.$u.toast('绑定成功')
|
||||
emit('success')
|
||||
}
|
||||
|
||||
const getPhoneNumber = async (e: any): Promise<void> => {
|
||||
const { encryptedData, iv, code } = e.detail
|
||||
const data = {
|
||||
code,
|
||||
encrypted_data: encryptedData,
|
||||
iv
|
||||
}
|
||||
if (encryptedData) {
|
||||
await userMnpMobile(
|
||||
{
|
||||
...data
|
||||
},
|
||||
{ token: props.userInfo?.token }
|
||||
)
|
||||
uni.$u.toast('绑定成功')
|
||||
emit('success')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
265
business_uniapp/src/pages/login/component/mobile.vue
Normal file
265
business_uniapp/src/pages/login/component/mobile.vue
Normal file
@@ -0,0 +1,265 @@
|
||||
<template>
|
||||
<view class="flex flex-col min-h-0 h-full">
|
||||
<view
|
||||
class="flex flex-col justify-end items-stretch"
|
||||
style="height: 25%; padding-left: 32px; padding-bottom: 22px"
|
||||
>
|
||||
<view class="text-[40rpx] font-medium"> HELLO, </view>
|
||||
<view class="mt-2 text-[40rpx] font-medium">
|
||||
欢迎来到{{ config?.shop_name || '' }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="p-[30rpx] bg-white" style="height: 65%; border-radius: 24rpx 24rpx 0 0">
|
||||
<view class="grid grid-cols-2 gap-x-2">
|
||||
<button
|
||||
v-if="true"
|
||||
class="account-button"
|
||||
:class="[isPasswordLogin ? 'active' : 'inactive']"
|
||||
@click="changeLoginScene(MobileSceneEnum.PASSWORD)"
|
||||
>
|
||||
账号登录
|
||||
</button>
|
||||
<button
|
||||
v-if="true"
|
||||
class="code-button"
|
||||
:class="[isCodeLogin ? 'active' : 'inactive']"
|
||||
@click="changeLoginScene(MobileSceneEnum.CODE)"
|
||||
>
|
||||
验证码登录
|
||||
</button>
|
||||
</view>
|
||||
|
||||
<view class="mt-4 login-form">
|
||||
<u-form :border-bottom="false">
|
||||
<u-form-item :border-bottom="false">
|
||||
<u-icon
|
||||
class="mr-2"
|
||||
:size="36"
|
||||
name="/static/images/icon/icon_mobile.png"
|
||||
/>
|
||||
<u-input
|
||||
class="flex-1"
|
||||
v-model="formData.account"
|
||||
:border="false"
|
||||
placeholder="请输入手机号码"
|
||||
/>
|
||||
</u-form-item>
|
||||
<u-form-item v-if="isCodeLogin" class="mt-4" :border-bottom="false">
|
||||
<u-icon class="mr-2" :size="36" name="/static/images/icon/icon_code.png" />
|
||||
<u-input
|
||||
class="flex-1"
|
||||
v-model="formData.code"
|
||||
placeholder="请输入验证码"
|
||||
:border="false"
|
||||
/>
|
||||
<view class="px-3 leading-4 w-[200rpx]" @click="sendSms">
|
||||
<u-verification-code
|
||||
ref="uCodeRef"
|
||||
:seconds="60"
|
||||
@change="codeChange"
|
||||
change-text="x秒"
|
||||
/>
|
||||
<text class="text-primary">
|
||||
{{ codeTips }}
|
||||
</text>
|
||||
</view>
|
||||
</u-form-item>
|
||||
<u-form-item v-if="isPasswordLogin" class="mt-4" :border-bottom="false">
|
||||
<u-icon
|
||||
class="mr-2"
|
||||
:size="36"
|
||||
name="/static/images/icon/icon_password.png"
|
||||
/>
|
||||
<u-input
|
||||
class="flex-1"
|
||||
v-model="formData.password"
|
||||
type="password"
|
||||
placeholder="请输入密码"
|
||||
:border="false"
|
||||
/>
|
||||
<router-navigate to="/pages/forget_pwd/forget_pwd?type=2">
|
||||
<view class="px-3 text-primary leading-4"> 忘记密码? </view>
|
||||
</router-navigate>
|
||||
</u-form-item>
|
||||
</u-form>
|
||||
</view>
|
||||
|
||||
<view class="flex-1 mt-4">
|
||||
<u-button
|
||||
type="primary"
|
||||
:custom-style="{
|
||||
flex: 1,
|
||||
'font-weight': 500
|
||||
}"
|
||||
@click="handleLogin"
|
||||
>
|
||||
立即登录
|
||||
</u-button>
|
||||
<!-- <view class="py-4 text-muted text-center"> OR </view>-->
|
||||
<!-- <u-button-->
|
||||
<!-- :custom-style="{-->
|
||||
<!-- flex: 1,-->
|
||||
<!-- background: '#fff'-->
|
||||
<!-- }"-->
|
||||
<!-- @click="togglePhone"-->
|
||||
<!-- >-->
|
||||
<!-- 快捷登录-->
|
||||
<!-- </u-button>-->
|
||||
</view>
|
||||
|
||||
<view class="flex justify-center py-4 text-muted text-center">
|
||||
没有账户?
|
||||
<view class="text-primary" @click.stop>
|
||||
<router-navigate class="text-primary" to="/pages/register/register">
|
||||
去注册
|
||||
</router-navigate>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="bg-white py-[30rpx] flex justify-center" style="height: 10%">
|
||||
<agreement ref="agreementRef" />
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
export default {
|
||||
options: {
|
||||
styleIsolation: 'shared'
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<script setup lang="ts">
|
||||
import { shallowRef, ref, reactive, computed } from 'vue'
|
||||
import { smsSend } from '@/api/app'
|
||||
import { SMSEnum } from '@/enums/appEnums'
|
||||
|
||||
defineProps<{
|
||||
loading: boolean
|
||||
config: any
|
||||
}>()
|
||||
const emit = defineEmits<{
|
||||
(event: 'login'): void
|
||||
(event: 'toggle'): void
|
||||
}>()
|
||||
|
||||
enum MobileSceneEnum {
|
||||
CODE = 2,
|
||||
PASSWORD = 1
|
||||
}
|
||||
|
||||
const agreementRef = shallowRef()
|
||||
const uCodeRef = shallowRef()
|
||||
const codeTips = ref('')
|
||||
const formData = reactive({
|
||||
scene: MobileSceneEnum.PASSWORD,
|
||||
account: '',
|
||||
code: '',
|
||||
password: ''
|
||||
})
|
||||
|
||||
const isCodeLogin = computed(() => formData.scene === MobileSceneEnum.CODE)
|
||||
const isPasswordLogin = computed(() => formData.scene === MobileSceneEnum.PASSWORD)
|
||||
const isValidMobile = computed(() => uni.$u.test.mobile(formData.account))
|
||||
|
||||
const changeLoginScene = (scene: MobileSceneEnum) => {
|
||||
formData.scene = scene
|
||||
}
|
||||
|
||||
const codeChange = (text: string) => {
|
||||
codeTips.value = text
|
||||
}
|
||||
|
||||
const sendSms = async () => {
|
||||
if (!formData.account || !isValidMobile.value) return
|
||||
|
||||
if (uCodeRef.value?.canGetCode) {
|
||||
await smsSend({
|
||||
scene: SMSEnum.LOGIN,
|
||||
mobile: formData.account
|
||||
})
|
||||
uni.$u.toast('发送成功')
|
||||
uCodeRef.value?.start()
|
||||
}
|
||||
}
|
||||
|
||||
const handleLogin = () => {
|
||||
if (!agreementRef.value?.checkAgreement()) {
|
||||
return
|
||||
}
|
||||
if (!formData.account) return uni.$u.toast('请输入手机号码')
|
||||
if (formData.scene == MobileSceneEnum.PASSWORD) {
|
||||
if (!formData.password) return uni.$u.toast('请输入密码')
|
||||
}
|
||||
if (formData.scene == MobileSceneEnum.CODE) {
|
||||
if (!formData.code) return uni.$u.toast('请输入验证码')
|
||||
}
|
||||
emit('login', formData)
|
||||
}
|
||||
|
||||
const togglePhone = () => {
|
||||
emit('toggle')
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.active {
|
||||
@apply bg-primary text-white;
|
||||
}
|
||||
|
||||
.inactive {
|
||||
@apply bg-primary-light-9 text-primary;
|
||||
}
|
||||
|
||||
.account-button {
|
||||
flex: 1;
|
||||
border: none;
|
||||
margin: 0 0;
|
||||
padding: 10rpx 0;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
font-size: 28rpx;
|
||||
font-weight: bold;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
transition: all 0.3s ease;
|
||||
border-radius: 16rpx 18rpx 36rpx 16rpx;
|
||||
clip-path: polygon(0 0, 100% 0, 96% 100%, 0% 100%);
|
||||
}
|
||||
|
||||
.account-button::after {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.code-button {
|
||||
flex: 1;
|
||||
border: none;
|
||||
margin: 0 0;
|
||||
padding: 10rpx 0;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
font-size: 28rpx;
|
||||
font-weight: bold;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
transition: all 0.3s ease;
|
||||
border-radius: 36rpx 16rpx 16rpx 18rpx;
|
||||
clip-path: polygon(5% 0, 100% 0, 100% 100%, 0% 100%);
|
||||
}
|
||||
|
||||
.code-button::after {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.login-form {
|
||||
:deep(.u-form-item) {
|
||||
background: #f6f6f6;
|
||||
border-radius: 24rpx;
|
||||
padding-left: 30rpx;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
123
business_uniapp/src/pages/login/component/update-user-info.vue
Normal file
123
business_uniapp/src/pages/login/component/update-user-info.vue
Normal file
@@ -0,0 +1,123 @@
|
||||
<template>
|
||||
<view>
|
||||
<u-popup
|
||||
v-model="showPopup"
|
||||
mode="bottom"
|
||||
border-radius="14"
|
||||
:mask-close-able="false"
|
||||
>
|
||||
<view class="h-[1000rpx] p-[40rpx]">
|
||||
<view class="flex items-center">
|
||||
<image
|
||||
class="w-[100rpx] h-[100rpx] rounded"
|
||||
mode="heightFix"
|
||||
:src="logo"
|
||||
></image>
|
||||
<text class="text-3xl ml-5 font-medium">{{ title }}</text>
|
||||
</view>
|
||||
<view class="mt-5 text-muted">
|
||||
建议使用您的微信头像和昵称,以便获得更好的体验
|
||||
</view>
|
||||
<view class="mt-[30rpx]">
|
||||
<form @submit="handleSubmit">
|
||||
<u-form-item required label="头像" :labelWidth="120">
|
||||
<view class="flex-1">
|
||||
<avatar-upload
|
||||
v-model="avatar"
|
||||
@upload="uploadImg"
|
||||
></avatar-upload>
|
||||
</view>
|
||||
</u-form-item>
|
||||
<u-form-item required label="昵称" :labelWidth="120">
|
||||
<input
|
||||
class="flex-1 h-[60rpx]"
|
||||
name="nickname"
|
||||
type="nickname"
|
||||
placeholder="请输入昵称"
|
||||
/>
|
||||
</u-form-item>
|
||||
<view class="mt-[80rpx]">
|
||||
<button
|
||||
class="bg-primary rounded-full text-white text-lg h-[80rpx] leading-[80rpx]"
|
||||
hover-class="none"
|
||||
form-type="submit"
|
||||
>
|
||||
确定
|
||||
</button>
|
||||
</view>
|
||||
|
||||
<view class="flex justify-center mt-[60rpx]">
|
||||
<view class="text-muted" @click="showPopup = false">
|
||||
暂不登录
|
||||
</view>
|
||||
</view>
|
||||
</form>
|
||||
</view>
|
||||
</view>
|
||||
</u-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { uploadImage } from '@/api/app'
|
||||
import { computed, ref } from 'vue'
|
||||
const props = defineProps({
|
||||
show: {
|
||||
type: Boolean
|
||||
},
|
||||
logo: {
|
||||
type: String
|
||||
},
|
||||
title: {
|
||||
type: String
|
||||
},
|
||||
userInfo: {
|
||||
type: Object
|
||||
}
|
||||
})
|
||||
const emit = defineEmits<{
|
||||
(event: 'update:show', show: boolean): void
|
||||
(event: 'update', value: any): void
|
||||
}>()
|
||||
|
||||
const showPopup = computed({
|
||||
get() {
|
||||
return props.show
|
||||
},
|
||||
set(val) {
|
||||
emit('update:show', val)
|
||||
}
|
||||
})
|
||||
|
||||
const avatar = ref()
|
||||
|
||||
const uploadImg = async (file: string) => {
|
||||
uni.showLoading({
|
||||
title: '正在上传中...'
|
||||
})
|
||||
try {
|
||||
console.log('propsprops', props)
|
||||
const res: any = await uploadImage(file, props.userInfo?.token)
|
||||
console.log(res)
|
||||
avatar.value = res.uri
|
||||
console.log(res)
|
||||
uni.hideLoading()
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
uni.hideLoading()
|
||||
uni.$u.toast('上传失败,请重试')
|
||||
}
|
||||
}
|
||||
|
||||
const handleSubmit = (e: any) => {
|
||||
const { nickname } = e.detail.value
|
||||
if (!avatar.value) return uni.$u.toast('请添加头像')
|
||||
if (!nickname) return uni.$u.toast('请输入昵称')
|
||||
emit('update', {
|
||||
avatar: avatar.value,
|
||||
nickname
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
80
business_uniapp/src/pages/login/component/wechat.vue
Normal file
80
business_uniapp/src/pages/login/component/wechat.vue
Normal file
@@ -0,0 +1,80 @@
|
||||
<template>
|
||||
<view class="flex flex-col min-h-0 h-full">
|
||||
|
||||
<view
|
||||
class="flex flex-col justify-center items-center"
|
||||
style="height: 70%;"
|
||||
>
|
||||
<view>
|
||||
<u-image
|
||||
:src="config.shop_logo"
|
||||
mode="widthFix"
|
||||
height="172"
|
||||
width="172"
|
||||
border-radius="20"
|
||||
/>
|
||||
</view>
|
||||
<view class="mt-4 text-2xl font-medium">
|
||||
{{ config.shop_name }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view
|
||||
class="px-[30rpx]"
|
||||
style="height: 20%;"
|
||||
>
|
||||
<u-button
|
||||
type="primary"
|
||||
:custom-style="{
|
||||
'flex': 1
|
||||
}"
|
||||
@click="handleLogin"
|
||||
>
|
||||
<!-- #ifndef MP -->
|
||||
<u-icon name="weixin-fill" size="40" color="#fff" />
|
||||
<text class="ml-[10rpx]"> 微信登录</text>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef MP -->
|
||||
<text>用户一键登录</text>
|
||||
<!-- #endif -->
|
||||
</u-button>
|
||||
<view class="py-4 text-muted text-center">
|
||||
OR
|
||||
</view>
|
||||
<u-button
|
||||
:custom-style="{
|
||||
'flex': 1,
|
||||
'background': '#fff'
|
||||
}"
|
||||
@click="togglePhone"
|
||||
>
|
||||
手机号登录
|
||||
</u-button>
|
||||
</view>
|
||||
|
||||
<view class="py-[30rpx] flex justify-center">
|
||||
<agreement ref="agreementRef" />
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { shallowRef } from 'vue'
|
||||
defineProps<{
|
||||
loading: boolean,
|
||||
config: any
|
||||
}>()
|
||||
const emit = defineEmits<{
|
||||
(event: 'login'): void
|
||||
(event: 'toggle'): void
|
||||
}>()
|
||||
const agreementRef = shallowRef()
|
||||
const handleLogin = () => {
|
||||
if (agreementRef.value?.checkAgreement()) {
|
||||
emit('login')
|
||||
}
|
||||
}
|
||||
|
||||
const togglePhone = () => {
|
||||
emit('toggle')
|
||||
}
|
||||
</script>
|
||||
336
business_uniapp/src/pages/login/login.vue
Normal file
336
business_uniapp/src/pages/login/login.vue
Normal file
@@ -0,0 +1,336 @@
|
||||
<template>
|
||||
<page-meta :page-style="$theme.pageStyle">
|
||||
<!-- #ifndef H5 -->
|
||||
<navigation-bar
|
||||
:front-color="$theme.navColor"
|
||||
:background-color="$theme.navBgColor"
|
||||
/>
|
||||
<!-- #endif -->
|
||||
</page-meta>
|
||||
<view class="login flex flex-col min-h-0 flex-1">
|
||||
<!-- #ifndef H5 -->
|
||||
<u-sticky h5-nav-height="0" bg-color="transparent">
|
||||
<u-navbar
|
||||
:is-back="true"
|
||||
:is-fixed="true"
|
||||
title="登录"
|
||||
:border-bottom="false"
|
||||
:title-bold="false"
|
||||
:background="{ background: `rgba(256,256, 256, 0)` }"
|
||||
:title-color="'#000'"
|
||||
>
|
||||
</u-navbar>
|
||||
</u-sticky>
|
||||
<!-- #endif -->
|
||||
|
||||
<!-- 微信登陆 -->
|
||||
<!-- <wechat
|
||||
v-if="LoginWayEnum.WECHAT == loginWay"
|
||||
class="flex flex-col min-h-0 flex-1 h-full"
|
||||
:loading="wechatLock"
|
||||
:config="appStore.config"
|
||||
@login="wxLoginLock"
|
||||
@toggle="loginWay = LoginWayEnum.MOBILE"
|
||||
/> -->
|
||||
|
||||
<!-- 手机/验证码登陆 -->
|
||||
<mobile
|
||||
class="flex flex-col min-h-0 flex-1 h-full"
|
||||
:loading="mobileLock"
|
||||
:config="appStore.config"
|
||||
@login="mobileLoginLock"
|
||||
@toggle="loginWay = LoginWayEnum.WECHAT"
|
||||
/>
|
||||
|
||||
<!-- 绑定手机号 -->
|
||||
<!-- <bind-mobile
|
||||
v-model:show="showBindMobilePopup"
|
||||
:userInfo="loginData"
|
||||
@close="removeWxQuery"
|
||||
@success="bindMobileSuccess"
|
||||
/> -->
|
||||
|
||||
<!-- 更新用户信息 -->
|
||||
<!-- <update-user-info
|
||||
v-model:show="showLoginPopup"
|
||||
:logo="appStore.config.shop_logo"
|
||||
:title="appStore.config.shop_name"
|
||||
:userInfo="loginData"
|
||||
@update="handleUpdateUser"
|
||||
/> -->
|
||||
|
||||
<!-- 审核状态 -->
|
||||
<modal-popup
|
||||
v-model:show="showModel"
|
||||
:title="auditStatus == AuditStatusEnum.WAIT ? '审核中' : '审核不通过'"
|
||||
>
|
||||
<template #content>
|
||||
<view :class="auditStatus == AuditStatusEnum.WAIT ? 'login-bg-wait' : 'login-bg-reject'">
|
||||
<!-- 审核中 -->
|
||||
<view v-if="auditStatus == AuditStatusEnum.WAIT ">
|
||||
<view class="">
|
||||
谢您对我们平台工作的支持,我们将
|
||||
</view>
|
||||
<view class="">
|
||||
在1~3个工作日内审核
|
||||
</view>
|
||||
</view>
|
||||
<!-- 审核不通过 -->
|
||||
<view v-if="auditStatus == AuditStatusEnum.REJECT">
|
||||
<view class="">
|
||||
抱歉,您的申请未通过,请完善您的商
|
||||
</view>
|
||||
<view class="">
|
||||
家申请信息后再次提交
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<template #footer>
|
||||
<!-- 审核中 -->
|
||||
<view v-if="auditStatus == AuditStatusEnum.WAIT ">
|
||||
<u-button @click="showModel = false">确认</u-button>
|
||||
</view>
|
||||
<!-- 审核不通过 -->
|
||||
<view v-if="auditStatus == AuditStatusEnum.REJECT">
|
||||
<u-button type="primary" @click="toApply(auditStatus)">重新申请</u-button>
|
||||
</view>
|
||||
</template>
|
||||
</modal-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {
|
||||
login,
|
||||
mnpLogin as mnpLoginApi,
|
||||
apiWechatAuthLogin as OALogin,
|
||||
updateUser
|
||||
} from '@/api/account'
|
||||
import { BACK_URL } from '@/enums/cacheEnums'
|
||||
import { useLockFn } from '@/hooks/useLockFn'
|
||||
import { useAppStore } from '@/stores/app'
|
||||
import { useUserStore } from '@/stores/user'
|
||||
import cache from '@/utils/cache'
|
||||
import { TOKEN_KEY } from '@/enums/constantEnums'
|
||||
import { isWeixinClient } from '@/utils/client'
|
||||
import { series } from '@/utils/util'
|
||||
// #ifdef H5
|
||||
import wechatOa, { UrlScene } from '@/utils/wechat'
|
||||
// #endif
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import { useRoute, useRouter } from 'uniapp-router-next'
|
||||
import { ref, watch, nextTick } from 'vue'
|
||||
|
||||
import wechat from './component/wechat.vue'
|
||||
import mobile from './component/mobile.vue'
|
||||
import updateUserInfo from './component/update-user-info.vue'
|
||||
import BindMobile from './component/bind-mobile.vue'
|
||||
import { AuditStatusEnum } from '@/enums/auditEnum'
|
||||
|
||||
|
||||
enum LoginWayEnum {
|
||||
ACCOUNT = 1,
|
||||
MOBILE = 2,
|
||||
WECHAT = 3
|
||||
}
|
||||
|
||||
const isWeixin = ref(true)
|
||||
// #ifdef H5
|
||||
isWeixin.value = isWeixinClient()
|
||||
// #endif
|
||||
|
||||
const userStore = useUserStore()
|
||||
const appStore = useAppStore()
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
|
||||
const loginData = ref()
|
||||
const showLoginPopup = ref(false)
|
||||
const showBindMobilePopup = ref(false)
|
||||
const loginWay = ref<string | number>(0)
|
||||
|
||||
|
||||
const showModel = ref(false)
|
||||
|
||||
// 商家审核状态
|
||||
const auditStatus = ref(AuditStatusEnum.NO)
|
||||
|
||||
// 去重新申请
|
||||
const toApply = (auditStatus?: number) => {
|
||||
showModel.value = false
|
||||
uni.navigateTo({
|
||||
url: `/packages/pages/apply/apply?auditStatus=${auditStatus}`
|
||||
})
|
||||
}
|
||||
|
||||
const checkIsBindMobile = async () => {
|
||||
loginHandle()
|
||||
}
|
||||
|
||||
const loginHandle = async () => {
|
||||
const { token } = loginData.value
|
||||
userStore.login(token)
|
||||
userStore.getUser()
|
||||
// #ifdef APP-PLUS
|
||||
router.navigateBack()
|
||||
// #endif
|
||||
// #ifndef APP-PLUS
|
||||
const pages = getCurrentPages()
|
||||
if (pages.length > 1) {
|
||||
const prevPage = pages[pages.length - 2]
|
||||
await router.navigateBack()
|
||||
// @ts-ignore
|
||||
const { onLoad, options } = prevPage
|
||||
// 刷新上一个页面
|
||||
onLoad && onLoad(options)
|
||||
} else if (cache.get(BACK_URL)) {
|
||||
try {
|
||||
router.redirectTo(cache.get(BACK_URL))
|
||||
} finally {
|
||||
router.switchTab(cache.get(BACK_URL))
|
||||
}
|
||||
} else {
|
||||
router.reLaunch('/pages/index/index')
|
||||
}
|
||||
cache.remove(BACK_URL)
|
||||
// #endif
|
||||
}
|
||||
|
||||
const loginAfter = (() => {
|
||||
const updateUsers = async () => {
|
||||
if (loginData.value.is_new_user && !showLoginPopup.value) {
|
||||
try {
|
||||
await updateUser(
|
||||
{
|
||||
avatar: loginData.value.avatar,
|
||||
nickname: loginData.value.nickname
|
||||
},
|
||||
{ token: loginData.value.token }
|
||||
)
|
||||
} catch (error) {}
|
||||
} else if (showLoginPopup.value) {
|
||||
return Promise.reject()
|
||||
}
|
||||
}
|
||||
|
||||
return series(updateUsers, checkIsBindMobile)
|
||||
})()
|
||||
|
||||
const { lockFn: mobileLoginLock, isLock: mobileLock } = useLockFn(async (formData: any) => {
|
||||
uni.showLoading({
|
||||
title: '请稍后...'
|
||||
})
|
||||
try {
|
||||
const data = await login(formData)
|
||||
loginData.value = data
|
||||
|
||||
auditStatus.value = data.audit_status
|
||||
console.log('auditStatus.value', auditStatus.value)
|
||||
// 入驻审核通过直接登录
|
||||
if(auditStatus.value === AuditStatusEnum.PASS){
|
||||
await loginAfter()
|
||||
uni.hideLoading()
|
||||
}else if (auditStatus.value === AuditStatusEnum.WAIT || auditStatus.value === AuditStatusEnum.REJECT) {
|
||||
// 入驻审核待审核、拒绝,不可登录,打开弹窗
|
||||
// 使用临时token,申请页面需要用到
|
||||
userStore.temToken = loginData.value.token
|
||||
await nextTick()
|
||||
console.log('userStore.temToken=>', userStore.temToken)
|
||||
uni.hideLoading()
|
||||
showModel.value = true
|
||||
}else { // 未提交入驻不可登录,跳转申请入驻
|
||||
// 使用临时token,申请页面需要用到
|
||||
userStore.temToken = loginData.value.token
|
||||
await nextTick()
|
||||
console.log('userStore.temToken=>', userStore.temToken)
|
||||
uni.hideLoading()
|
||||
toApply(auditStatus.value)
|
||||
}
|
||||
// await loginAfter()
|
||||
// uni.hideLoading()
|
||||
} catch (error: any) {
|
||||
uni.hideLoading()
|
||||
uni.$u.toast(error)
|
||||
}
|
||||
})
|
||||
|
||||
watch(
|
||||
() => appStore.config,
|
||||
(value) => {
|
||||
// if (value.third_auth && value.wechat_auth == 1) {
|
||||
// loginWay.value = LoginWayEnum.WECHAT
|
||||
// return
|
||||
// }
|
||||
// if (value.login_way) {
|
||||
// loginWay.value = value.login_way[0]
|
||||
// return
|
||||
// }
|
||||
},
|
||||
{
|
||||
immediate: true
|
||||
}
|
||||
)
|
||||
|
||||
const removeWxQuery = () => {
|
||||
const options = route.query
|
||||
if (options.code && options.state) {
|
||||
delete options.code
|
||||
delete options.state
|
||||
router.redirectTo({ path: route.path, query: options })
|
||||
}
|
||||
}
|
||||
|
||||
onLoad(async () => {
|
||||
//#ifdef H5
|
||||
const options = wechatOa.getAuthData()
|
||||
try {
|
||||
if (options.code && options.scene === UrlScene.LOGIN) {
|
||||
uni.showLoading({
|
||||
title: '请稍后...'
|
||||
})
|
||||
const data = await oaLogin(options)
|
||||
if (data) {
|
||||
loginData.value = data
|
||||
|
||||
await loginAfter()
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
removeWxQuery()
|
||||
} finally {
|
||||
uni.hideLoading()
|
||||
//清除保存的授权数据
|
||||
wechatOa.setAuthData()
|
||||
}
|
||||
//#endif
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
page {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.login {
|
||||
height: 100%;
|
||||
background-image: url('@/static/images/user/login_bg.png');
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.login-bg-wait {
|
||||
height: 386rpx;
|
||||
background-image: url('@/static/images/login/bg_audit_wait.png');
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.login-bg-reject {
|
||||
height: 386rpx;
|
||||
background-image: url('@/static/images/login/bg_audit_reject.png');
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
</style>
|
||||
65
business_uniapp/src/pages/news/component/news-list.vue
Normal file
65
business_uniapp/src/pages/news/component/news-list.vue
Normal file
@@ -0,0 +1,65 @@
|
||||
<template>
|
||||
<z-paging
|
||||
auto-show-back-to-top
|
||||
:auto="i == index"
|
||||
ref="paging"
|
||||
v-model="dataList"
|
||||
:data-key="i"
|
||||
@query="queryList"
|
||||
:fixed="false"
|
||||
height="100%"
|
||||
>
|
||||
<block v-for="(newsItem, newsIndex) in dataList" :key="newsIndex">
|
||||
<news-card :item="newsItem" :newsId="newsItem.id"></news-card>
|
||||
</block>
|
||||
</z-paging>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, watch, nextTick, shallowRef } from 'vue'
|
||||
import { getArticleList } from '@/api/news'
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
cid: number
|
||||
i: number
|
||||
index: number
|
||||
}>(),
|
||||
{
|
||||
cid: 0
|
||||
}
|
||||
)
|
||||
|
||||
const paging = shallowRef<any>(null)
|
||||
const dataList = ref([])
|
||||
const isFirst = ref<boolean>(true)
|
||||
|
||||
watch(
|
||||
() => props.index,
|
||||
async () => {
|
||||
await nextTick()
|
||||
if (props.i == props.index && isFirst.value) {
|
||||
isFirst.value = false
|
||||
paging.value?.reload()
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
const queryList = async (page_no, page_size) => {
|
||||
try {
|
||||
const { lists } = await getArticleList({
|
||||
cid: props.cid,
|
||||
page_no,
|
||||
page_size
|
||||
})
|
||||
paging.value.complete(lists)
|
||||
} catch (e) {
|
||||
console.log('报错=>', e)
|
||||
//TODO handle the exception
|
||||
paging.value.complete(false)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
85
business_uniapp/src/pages/news/news.vue
Normal file
85
business_uniapp/src/pages/news/news.vue
Normal file
@@ -0,0 +1,85 @@
|
||||
<template>
|
||||
<page-meta :page-style="$theme.pageStyle">
|
||||
<!-- #ifndef H5 -->
|
||||
<navigation-bar
|
||||
:front-color="$theme.navColor"
|
||||
:background-color="$theme.navBgColor"
|
||||
/>
|
||||
<!-- #endif -->
|
||||
</page-meta>
|
||||
<!-- #ifndef H5 -->
|
||||
<u-sticky
|
||||
h5-nav-height="0"
|
||||
bg-color="transparent"
|
||||
>
|
||||
<u-navbar
|
||||
:is-back="false"
|
||||
:is-fixed="false"
|
||||
title="资讯"
|
||||
:border-bottom="false"
|
||||
:title-bold="true"
|
||||
:title-color="$theme.navColor"
|
||||
:background="{ background: $theme.navBgColor }"
|
||||
>
|
||||
</u-navbar>
|
||||
</u-sticky>
|
||||
<!-- #endif -->
|
||||
<view class="news">
|
||||
<!-- 搜索 -->
|
||||
<navigator class="news-search px-[24rpx] py-[14rpx] bg-white" url="/pages/search/search">
|
||||
<u-search placeholder="请输入关键词搜索" disabled :show-action="false"></u-search>
|
||||
</navigator>
|
||||
|
||||
<!-- 内容 -->
|
||||
<tabs
|
||||
:current="current"
|
||||
@change="handleChange"
|
||||
height="80"
|
||||
bar-width="60"
|
||||
:barStyle="{ bottom: '0' }"
|
||||
>
|
||||
<tab v-for="(item, i) in tabList" :key="i" :name="item.name">
|
||||
<view class="news-list pt-[20rpx]">
|
||||
<news-list :cid="item.id" :i="i" :index="current"></news-list>
|
||||
</view>
|
||||
</tab>
|
||||
</tabs>
|
||||
<tabbar />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, computed } from 'vue'
|
||||
import { onLoad, onShow, onReady } from '@dcloudio/uni-app'
|
||||
import NewsList from './component/news-list.vue'
|
||||
import { getArticleCate } from '@/api/news'
|
||||
|
||||
const tabList = ref<any>([])
|
||||
const current = ref<number>(0)
|
||||
|
||||
const handleChange = (index: number) => {
|
||||
console.log(index)
|
||||
current.value = Number(index)
|
||||
}
|
||||
|
||||
const getData = async () => {
|
||||
const data = await getArticleCate()
|
||||
tabList.value = [{ name: '全部', id: '' }].concat(data)
|
||||
}
|
||||
|
||||
onLoad((options) => {
|
||||
getData()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.news {
|
||||
&-search {
|
||||
margin-bottom: 2rpx;
|
||||
}
|
||||
|
||||
&-list {
|
||||
height: calc(100vh - 272rpx - env(safe-area-inset-bottom));
|
||||
}
|
||||
}
|
||||
</style>
|
||||
108
business_uniapp/src/pages/news_detail/news_detail.vue
Normal file
108
business_uniapp/src/pages/news_detail/news_detail.vue
Normal file
@@ -0,0 +1,108 @@
|
||||
<template>
|
||||
<page-meta :page-style="$theme.pageStyle">
|
||||
<!-- #ifndef H5 -->
|
||||
<navigation-bar
|
||||
:front-color="$theme.navColor"
|
||||
:background-color="$theme.navBgColor"
|
||||
/>
|
||||
<!-- #endif -->
|
||||
</page-meta>
|
||||
<view class="news-detail bg-white">
|
||||
<!-- 标题信心 -->
|
||||
<view class="news-detail-header py-[20rpx] px-[30rpx]">
|
||||
<view class="text-3xl font-medium">{{ newsData.title }}</view>
|
||||
<view class="flex mt-[20rpx] text-xs">
|
||||
<view class="mr-[40rpx]" v-if="newsData.author">作者: {{ newsData.author }}</view>
|
||||
<view class="text-muted mr-[40rpx] flex-1">{{ newsData.create_time }}</view>
|
||||
<view class="flex items-center text-muted flex-none">
|
||||
<image
|
||||
src="/static/images/icon/icon_visit.png"
|
||||
class="w-[30rpx] h-[30rpx]"
|
||||
></image>
|
||||
<view class="ml-[10rpx]">{{ newsData.click }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 咨询内容 -->
|
||||
<view class="news-detail-section bg-white p-[24rpx]">
|
||||
<!-- 摘要 -->
|
||||
<view class="summary p-[20rpx] text-base" v-if="newsData.abstract">
|
||||
<text class="font-medium">摘要: </text> {{ newsData.abstract }}
|
||||
</view>
|
||||
<!-- 内容 -->
|
||||
<view class="mt-[20rpx]">
|
||||
<u-parse :html="newsData.content"></u-parse>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="panel-btn flex items-center px-[34rpx]" @click="handleAddCollect(newsData.id)">
|
||||
<u-icon
|
||||
:name="newsData.collect ? 'star-fill' : 'star'"
|
||||
size="40"
|
||||
:color="newsData.collect ? '#F7BA47' : '#333'"
|
||||
></u-icon>
|
||||
<text class="ml-[10rpx]">收藏</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import { getArticleDetail, addCollect, cancelCollect } from '@/api/news'
|
||||
|
||||
const newsData = ref<any>({})
|
||||
let newsId = ''
|
||||
|
||||
const getData = async (id) => {
|
||||
newsData.value = await getArticleDetail({ id })
|
||||
}
|
||||
|
||||
const handleAddCollect = async (id: number) => {
|
||||
try {
|
||||
if (newsData.value.collect) {
|
||||
await cancelCollect({ id })
|
||||
uni.$u.toast('已取消收藏')
|
||||
} else {
|
||||
await addCollect({ id })
|
||||
uni.$u.toast('收藏成功')
|
||||
}
|
||||
getData(newsId)
|
||||
} catch (e) {
|
||||
//TODO handle the exception
|
||||
}
|
||||
}
|
||||
|
||||
onLoad((options: any) => {
|
||||
newsId = options.id
|
||||
getData(newsId)
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.news-detail {
|
||||
height: 100%;
|
||||
|
||||
&-header {
|
||||
border-bottom: 2rpx solid #f8f8f8;
|
||||
}
|
||||
|
||||
&-section {
|
||||
.summary {
|
||||
border-radius: 12rpx;
|
||||
background-color: #f7f7f7;
|
||||
}
|
||||
}
|
||||
|
||||
.panel-btn {
|
||||
position: fixed;
|
||||
right: 30rpx;
|
||||
height: 80rpx;
|
||||
bottom: 80rpx;
|
||||
border-radius: 40rpx;
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.16);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
63
business_uniapp/src/pages/order/components/orderList.vue
Normal file
63
business_uniapp/src/pages/order/components/orderList.vue
Normal file
@@ -0,0 +1,63 @@
|
||||
<template>
|
||||
<z-paging
|
||||
auto-show-back-to-top
|
||||
:auto="i == index"
|
||||
ref="paging"
|
||||
v-model="dataList"
|
||||
:data-key="i"
|
||||
@query="queryList"
|
||||
:fixed="false"
|
||||
height="100%"
|
||||
>
|
||||
<block v-for="(item, index) in dataList" :key="index">
|
||||
<orderCard :data="item"></orderCard>
|
||||
</block>
|
||||
</z-paging>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, watch, nextTick, shallowRef } from 'vue'
|
||||
import orderCard from '@/components/orderCard/index.vue'
|
||||
import { getOrderList } from '@/api/app'
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
cid: number
|
||||
i: number
|
||||
index: number
|
||||
}>(),
|
||||
{
|
||||
cid: 0
|
||||
}
|
||||
)
|
||||
|
||||
const paging = shallowRef<any>(null)
|
||||
const dataList = ref([])
|
||||
const isFirst = ref<boolean>(true)
|
||||
|
||||
watch(
|
||||
() => props.index,
|
||||
async () => {
|
||||
await nextTick()
|
||||
if (props.i == props.index && isFirst.value) {
|
||||
isFirst.value = false
|
||||
paging.value?.reload()
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
const queryList = async (page_no: any, page_size: any) => {
|
||||
try {
|
||||
const { lists } = await getOrderList({ page_no, page_size, order_status: props.index })
|
||||
|
||||
paging.value.complete(lists)
|
||||
} catch (e) {
|
||||
console.log('报错=>', e)
|
||||
//TODO handle the exception
|
||||
paging.value.complete(false)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
74
business_uniapp/src/pages/order/order.vue
Normal file
74
business_uniapp/src/pages/order/order.vue
Normal file
@@ -0,0 +1,74 @@
|
||||
<template>
|
||||
<page-meta :page-style="$theme.pageStyle">
|
||||
<!-- #ifndef H5 -->
|
||||
<navigation-bar :front-color="$theme.navColor" :background-color="$theme.navBgColor"/>
|
||||
<!-- #endif -->
|
||||
</page-meta>
|
||||
<view class="">
|
||||
<tabs
|
||||
:isScroll="false"
|
||||
:current="current"
|
||||
@change="handleChange"
|
||||
height="80"
|
||||
bar-width="60"
|
||||
:barStyle="{ bottom: '0' }"
|
||||
>
|
||||
<tab v-for="(item, i) in tabList" :key="i" :name="item.name">
|
||||
<view v-if="userStore.isLogin" class="orderList pt-[20rpx] px-[30rpx]">
|
||||
<orderList :cid="item.id" :i="i+1" :index="current + 1"></orderList>
|
||||
</view>
|
||||
<view v-if="!userStore.isLogin">
|
||||
<no-login></no-login>
|
||||
</view>
|
||||
</tab>
|
||||
</tabs>
|
||||
<tabbar />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, computed } from 'vue'
|
||||
import { onLoad, onShow, onReady } from '@dcloudio/uni-app'
|
||||
import orderList from './components/orderList.vue'
|
||||
import noLogin from '@/components/no-login/no-login.vue'
|
||||
import { getArticleCate } from '@/api/news'
|
||||
import { useUserStore } from '@/stores/user'
|
||||
|
||||
const userStore = useUserStore()
|
||||
|
||||
const tabList = ref<any>([
|
||||
{
|
||||
name: '待接单'
|
||||
},
|
||||
{
|
||||
name: '进行中'
|
||||
},
|
||||
{
|
||||
name: '已完成'
|
||||
},
|
||||
{
|
||||
name: '售后单'
|
||||
},
|
||||
])
|
||||
const current = ref<number>(0)
|
||||
|
||||
const handleChange = (index: number) => {
|
||||
console.log(index)
|
||||
current.value = Number(index)
|
||||
}
|
||||
|
||||
// const getData = async () => {
|
||||
// const data = await getArticleCate()
|
||||
// tabList.value = [{ name: '全部', id: '' }].concat(data)
|
||||
// }
|
||||
|
||||
onLoad((options) => {
|
||||
// getData()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.orderList {
|
||||
height: calc(100vh - 180rpx - env(safe-area-inset-bottom));
|
||||
}
|
||||
</style>
|
||||
172
business_uniapp/src/pages/payment_result/payment_result.vue
Normal file
172
business_uniapp/src/pages/payment_result/payment_result.vue
Normal file
@@ -0,0 +1,172 @@
|
||||
<template>
|
||||
<page-meta :page-style="$theme.pageStyle">
|
||||
<!-- #ifndef H5 -->
|
||||
<navigation-bar
|
||||
:front-color="$theme.navColor"
|
||||
:background-color="$theme.navBgColor"
|
||||
/>
|
||||
<!-- #endif -->
|
||||
</page-meta>
|
||||
<!-- 页面状态 -->
|
||||
<page-status :status="status">
|
||||
<template #error>
|
||||
<u-empty text="订单不存在" mode="order"></u-empty>
|
||||
</template>
|
||||
<template #default>
|
||||
<view class="payment-result p-[20rpx]">
|
||||
<view class="result bg-white p-[20rpx] rounded-md">
|
||||
<view class="flex flex-col items-center my-[40rpx]">
|
||||
<!-- 支付状态图片 -->
|
||||
<u-image
|
||||
class="status-image"
|
||||
:src="paymentStatus['image']"
|
||||
width="100"
|
||||
height="100"
|
||||
shape="circle"
|
||||
/>
|
||||
<!-- 支付状态文字 -->
|
||||
<text class="text-2xl font-medium mt-[20rpx]">{{
|
||||
paymentStatus['text']
|
||||
}}
|
||||
</text>
|
||||
<view class="text-3xl font-medium mt-[20rpx]">
|
||||
¥ {{ orderInfo?.order_amount }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 支付信息 -->
|
||||
<view class="result-info">
|
||||
<view class="result-info__item">
|
||||
<text>订单编号</text>
|
||||
<text>{{ orderInfo?.sn || '-' }}</text>
|
||||
</view>
|
||||
<view class="result-info__item">
|
||||
<text>付款时间</text>
|
||||
<text>{{ orderInfo.pay_time || '-' }}</text>
|
||||
</view>
|
||||
<view class="result-info__item">
|
||||
<text>支付方式</text>
|
||||
<template v-if="orderInfo.pay_status">
|
||||
<text>{{ orderInfo?.pay_way_desc || '-' }}</text>
|
||||
</template>
|
||||
<template v-else>
|
||||
<text>未支付</text>
|
||||
</template>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="mt-[40rpx]">
|
||||
<view class="mb-[20rpx]">
|
||||
<u-button
|
||||
v-if="pageOptions.from == 'deposit'"
|
||||
type="primary"
|
||||
shape="circle"
|
||||
hover-class="none"
|
||||
@click="goDeposit"
|
||||
>
|
||||
继续充值
|
||||
</u-button>
|
||||
</view>
|
||||
<view class="mb-[20rpx]">
|
||||
<u-button
|
||||
type="primary"
|
||||
plain
|
||||
shape="circle"
|
||||
hover-class="none"
|
||||
@click="goHome"
|
||||
>
|
||||
返回首页
|
||||
</u-button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</page-status>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {getPayResult} from '@/api/pay'
|
||||
import {PageStatusEnum} from '@/enums/appEnums'
|
||||
import {onLoad} from '@dcloudio/uni-app'
|
||||
import {computed, reactive, ref} from 'vue'
|
||||
import {useRouter} from "uniapp-router-next";
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
const mapStatus = {
|
||||
succeed: {
|
||||
text: '支付成功',
|
||||
image: '/static/images/payment/icon_succeed.png'
|
||||
},
|
||||
waiting: {
|
||||
text: '等待支付',
|
||||
image: '/static/images/payment/icon_waiting.png'
|
||||
}
|
||||
}
|
||||
const status = ref(PageStatusEnum['LOADING'])
|
||||
const pageOptions = ref({
|
||||
id: '',
|
||||
from: ''
|
||||
})
|
||||
const orderInfo = reactive<any>({
|
||||
order: {}
|
||||
})
|
||||
const paymentStatus = computed(() => {
|
||||
const status = !!orderInfo.pay_status
|
||||
return mapStatus[status ? 'succeed' : 'waiting']
|
||||
})
|
||||
|
||||
const initPageData = () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
getPayResult({
|
||||
order_id: pageOptions.value.id,
|
||||
from: pageOptions.value.from
|
||||
})
|
||||
.then((data) => {
|
||||
Object.assign(orderInfo, data)
|
||||
resolve(data)
|
||||
})
|
||||
.catch((err) => {
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const goHome = () => {
|
||||
router.reLaunch('/pages/index/index')
|
||||
}
|
||||
|
||||
const goOrder = () => {
|
||||
switch (pageOptions.value.from) {
|
||||
case 'recharge':
|
||||
router.navigateBack()
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
const goDeposit = () => {
|
||||
router.redirectTo('/packages/pages/bond/bond')
|
||||
}
|
||||
|
||||
onLoad(async (options: any) => {
|
||||
try {
|
||||
if (!options.id) throw new Error('订单不存在')
|
||||
pageOptions.value = options
|
||||
await initPageData()
|
||||
status.value = PageStatusEnum['NORMAL']
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
status.value = PageStatusEnum['ERROR']
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.result-info {
|
||||
.result-info__item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
197
business_uniapp/src/pages/register/register.vue
Normal file
197
business_uniapp/src/pages/register/register.vue
Normal file
@@ -0,0 +1,197 @@
|
||||
<template>
|
||||
<page-meta :page-style="$theme.pageStyle">
|
||||
<!-- #ifndef H5 -->
|
||||
<navigation-bar :front-color="$theme.navColor" :background-color="$theme.navBgColor" />
|
||||
<!-- #endif -->
|
||||
</page-meta>
|
||||
<view class="register flex flex-col min-h-0 flex-1">
|
||||
<!-- #ifndef H5 -->
|
||||
<u-sticky h5-nav-height="0" bg-color="transparent">
|
||||
<u-navbar
|
||||
:is-back="true"
|
||||
:is-fixed="true"
|
||||
title="注册"
|
||||
:border-bottom="false"
|
||||
:title-bold="false"
|
||||
:background="{ background: `rgba(256,256, 256, 0)` }"
|
||||
:title-color="'#000'"
|
||||
>
|
||||
</u-navbar>
|
||||
</u-sticky>
|
||||
<!-- #endif -->
|
||||
|
||||
<view
|
||||
class="flex flex-col justify-end items-stretch"
|
||||
style="height: 25%; padding-left: 32px; padding-bottom: 22px"
|
||||
>
|
||||
<view class="text-[40rpx] font-medium"> HELLO, </view>
|
||||
<view class="mt-2 text-[40rpx] font-medium">
|
||||
欢迎来到{{ appStore.config.shop_name }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="p-[30rpx] bg-white" style="height: 65%; border-radius: 24rpx 24rpx 0 0">
|
||||
<view class="mt-4 register-form">
|
||||
<u-form :border-bottom="false">
|
||||
<u-form-item :border-bottom="false">
|
||||
<u-icon
|
||||
class="mr-2"
|
||||
:size="36"
|
||||
name="/static/images/icon/icon_mobile.png"
|
||||
/>
|
||||
<u-input
|
||||
class="flex-1"
|
||||
v-model="formData.account"
|
||||
:border="false"
|
||||
placeholder="请输入手机号码"
|
||||
/>
|
||||
</u-form-item>
|
||||
<u-form-item :border-bottom="false">
|
||||
<u-icon
|
||||
class="mr-2"
|
||||
:size="36"
|
||||
name="/static/images/icon/icon_password.png"
|
||||
/>
|
||||
<u-input
|
||||
class="flex-1"
|
||||
v-model="formData.password"
|
||||
:border="false"
|
||||
placeholder="请输入密码"
|
||||
/>
|
||||
</u-form-item>
|
||||
<u-form-item class="mt-4" :border-bottom="false">
|
||||
<u-icon class="mr-2" :size="36" name="/static/images/icon/icon_code.png" />
|
||||
<u-input
|
||||
class="flex-1"
|
||||
v-model="formData.code"
|
||||
placeholder="请输入验证码"
|
||||
:border="false"
|
||||
/>
|
||||
<view class="px-3 leading-4 w-[200rpx]" @click="sendSms">
|
||||
<u-verification-code
|
||||
ref="uCodeRef"
|
||||
:seconds="60"
|
||||
@change="codeChange"
|
||||
change-text="x秒"
|
||||
/>
|
||||
<text class="text-primary">
|
||||
{{ codeTips }}
|
||||
</text>
|
||||
</view>
|
||||
</u-form-item>
|
||||
</u-form>
|
||||
</view>
|
||||
|
||||
<view class="flex-1 mt-4">
|
||||
<u-button
|
||||
type="primary"
|
||||
:custom-style="{
|
||||
flex: 1,
|
||||
'font-weight': 500
|
||||
}"
|
||||
@click="accountRegister"
|
||||
>
|
||||
立即注册
|
||||
</u-button>
|
||||
</view>
|
||||
|
||||
<view class="flex justify-center py-4 text-muted text-center">
|
||||
已有账号?
|
||||
<view class="text-primary" @click.stop="router.navigateBack()"> 去登录 </view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="bg-white py-[30rpx] flex justify-center" style="height: 10%">
|
||||
<agreement ref="agreementRef" />
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
options: {
|
||||
styleIsolation: 'shared'
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<script setup lang="ts">
|
||||
import { register } from '@/api/account'
|
||||
import { useAppStore } from '@/stores/app'
|
||||
import { reactive, shallowRef, ref } from 'vue'
|
||||
import { validateInput } from '@/utils/util'
|
||||
import { useRouter } from 'uniapp-router-next'
|
||||
import { smsSend } from '@/api/app'
|
||||
import { SMSEnum } from '@/enums/appEnums'
|
||||
|
||||
const appStore = useAppStore()
|
||||
const router = useRouter()
|
||||
const agreementRef = shallowRef()
|
||||
const uCodeRef = shallowRef()
|
||||
const codeTips = ref('')
|
||||
|
||||
const formData = reactive({
|
||||
account: '',
|
||||
password: '',
|
||||
code: ''
|
||||
})
|
||||
|
||||
const codeChange = (text: string) => {
|
||||
codeTips.value = text
|
||||
}
|
||||
|
||||
const sendSms = async () => {
|
||||
if (!formData.account) return uni.$u.toast('请输入手机号码')
|
||||
if (uCodeRef.value?.canGetCode) {
|
||||
await smsSend({
|
||||
scene: SMSEnum.REGISTER,
|
||||
mobile: formData.account
|
||||
})
|
||||
uni.$u.toast('发送成功')
|
||||
uCodeRef.value?.start()
|
||||
}
|
||||
}
|
||||
|
||||
const accountRegister = async () => {
|
||||
if (!agreementRef.value?.checkAgreement()) {
|
||||
return
|
||||
}
|
||||
if (!formData.account) return uni.$u.toast('请输入账号')
|
||||
if (!formData.password) return uni.$u.toast('请输入密码')
|
||||
if (!formData.code) return uni.$u.toast('请输入验证码')
|
||||
// if (formData.password != formData.password_confirm) return uni.$u.toast('两次输入的密码不一致')
|
||||
if (!validateInput(formData.password)) return uni.$u.toast('密码应为6-20位数字+英文')
|
||||
await register(formData)
|
||||
|
||||
uni.$u.toast('注册成功!')
|
||||
setTimeout(() => {
|
||||
uni.redirectTo({
|
||||
// url: '/packages/pages/apply/apply'
|
||||
url: '/pages/login/login'
|
||||
})
|
||||
}, 1000)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
page {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.register {
|
||||
height: 100%;
|
||||
background-image: url('@/static/images/user/login_bg.png');
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.register-form {
|
||||
:deep(.u-form-item) {
|
||||
background: #f6f6f6;
|
||||
border-radius: 24rpx;
|
||||
padding-left: 30rpx;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
87
business_uniapp/src/pages/search/component/suggest.vue
Normal file
87
business_uniapp/src/pages/search/component/suggest.vue
Normal file
@@ -0,0 +1,87 @@
|
||||
<template>
|
||||
<view class="suggest bg-white">
|
||||
<!-- 热门搜索 -->
|
||||
<view class="hot" v-if="hot_search.status == 1 && searchData.length">
|
||||
<view class="font-medium pl-[24rpx] pt-[26rpx] pb-[6rpx] text-lg">热门搜索</view>
|
||||
|
||||
<view class="w-full px-[24rpx]">
|
||||
<block v-for="(hotItem, index) in searchData" :key="index">
|
||||
<view
|
||||
class="keyword truncate max-w-full"
|
||||
@click="handleHistoreSearch(hotItem.name)"
|
||||
>
|
||||
{{ hotItem.name }}
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view
|
||||
class="mx-[24rpx] my-[40rpx] border-b border-solid border-0 border-light"
|
||||
v-if="hot_search.status == 1 && searchData.length && his_search.length"
|
||||
></view>
|
||||
|
||||
<!-- 历史搜索 -->
|
||||
<view class="history" v-if="his_search.length">
|
||||
<view class="flex justify-between px-[24rpx] pb-[6rpx] pt-[26rpx]">
|
||||
<view class="text-lg font-medium">历史搜索</view>
|
||||
<view class="text-xs text-muted" @click="() => emit('clear')">清空</view>
|
||||
</view>
|
||||
|
||||
<view class="w-full px-[24rpx]">
|
||||
<block v-for="(hisItem, index) in his_search" :key="index">
|
||||
<view class="keyword truncate" @click="handleHistoreSearch(hisItem)">{{
|
||||
hisItem
|
||||
}}</view>
|
||||
</block>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed } from 'vue'
|
||||
|
||||
const emit = defineEmits<{
|
||||
(event: 'search', value: string): void
|
||||
(event: 'clear', value: void): void
|
||||
}>()
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
hot_search?: {
|
||||
data: any[]
|
||||
status: number
|
||||
}
|
||||
his_search?: string[]
|
||||
}>(),
|
||||
{
|
||||
hot_search: () => ({
|
||||
data: [],
|
||||
status: 0
|
||||
}),
|
||||
his_search: () => []
|
||||
}
|
||||
)
|
||||
|
||||
const searchData = computed(() => {
|
||||
return props.hot_search.data.filter((item) => item.name)
|
||||
})
|
||||
|
||||
const handleHistoreSearch = (text: string) => {
|
||||
emit('search', text)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.suggest {
|
||||
height: 100%;
|
||||
.keyword {
|
||||
display: inline-block;
|
||||
margin: 24rpx 16rpx 0 0;
|
||||
padding: 8rpx 24rpx;
|
||||
border-radius: 26rpx;
|
||||
background-color: #f4f4f4;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
142
business_uniapp/src/pages/search/search.vue
Normal file
142
business_uniapp/src/pages/search/search.vue
Normal file
@@ -0,0 +1,142 @@
|
||||
<template>
|
||||
<page-meta :page-style="$theme.pageStyle">
|
||||
<!-- #ifndef H5 -->
|
||||
<navigation-bar
|
||||
:front-color="$theme.navColor"
|
||||
:background-color="$theme.navBgColor"
|
||||
/>
|
||||
<!-- #endif -->
|
||||
</page-meta>
|
||||
<view class="search">
|
||||
<!-- 搜索框 -->
|
||||
<view class="px-[24rpx] py-[14rpx] bg-white">
|
||||
<u-search
|
||||
v-model="keyword"
|
||||
placeholder="请输入关键词搜索"
|
||||
height="72"
|
||||
@search="handleSearch"
|
||||
@custom="handleSearch"
|
||||
@clear="search.searching = false"
|
||||
></u-search>
|
||||
</view>
|
||||
|
||||
<!-- 搜索 -->
|
||||
<view class="search-content">
|
||||
<!-- -->
|
||||
<suggest
|
||||
v-show="!search.searching"
|
||||
@search="handleSearch"
|
||||
@clear="handleClear"
|
||||
:hot_search="search.hot_search"
|
||||
:his_search="search.his_search"
|
||||
></suggest>
|
||||
|
||||
<!-- -->
|
||||
<view class="search-content-s pt-[20rpx]" v-show="search.searching">
|
||||
<z-paging
|
||||
ref="paging"
|
||||
v-model="search.result"
|
||||
@query="queryList"
|
||||
:fixed="false"
|
||||
height="100%"
|
||||
>
|
||||
<block v-for="item in search.result" :key="item.id">
|
||||
<news-card :item="item" :newsId="item.id"></news-card>
|
||||
</block>
|
||||
</z-paging>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, shallowRef } from 'vue'
|
||||
import Suggest from './component/suggest.vue'
|
||||
import { HISTORY } from '@/enums/constantEnums'
|
||||
import { getHotSearch } from '@/api/shop'
|
||||
import cache from '@/utils/cache'
|
||||
import { getArticleList } from '@/api/news'
|
||||
|
||||
interface Search {
|
||||
hot_search: {
|
||||
data: any[]
|
||||
status: number
|
||||
}
|
||||
his_search: string[]
|
||||
result: any
|
||||
searching: boolean
|
||||
}
|
||||
|
||||
const search = reactive<Search>({
|
||||
hot_search: {
|
||||
data: [],
|
||||
status: 1
|
||||
},
|
||||
his_search: [],
|
||||
result: [],
|
||||
searching: false
|
||||
})
|
||||
const keyword = ref<string>('')
|
||||
const paging = shallowRef()
|
||||
|
||||
const handleSearch = (value: string) => {
|
||||
keyword.value = value
|
||||
if (keyword.value) {
|
||||
if (!search.his_search.includes(keyword.value)) {
|
||||
search.his_search.unshift(keyword.value)
|
||||
cache.set(HISTORY, search.his_search)
|
||||
}
|
||||
}
|
||||
paging.value.reload()
|
||||
search.searching = true
|
||||
}
|
||||
|
||||
const getHotSearchFunc = async () => {
|
||||
try {
|
||||
search.hot_search = await getHotSearch()
|
||||
} catch (e) {
|
||||
//TODO handle the exception
|
||||
console.log('获取热门搜索失败=>', e)
|
||||
}
|
||||
}
|
||||
|
||||
const handleClear = async (): Promise<void> => {
|
||||
const resModel: any = await uni.showModal({
|
||||
title: '温馨提示',
|
||||
content: '是否清空历史记录?'
|
||||
})
|
||||
if (resModel.confirm) {
|
||||
cache.set(HISTORY, '')
|
||||
search.his_search = []
|
||||
}
|
||||
}
|
||||
|
||||
const queryList = async (page_no: number, page_size: number) => {
|
||||
try {
|
||||
const { lists } = await getArticleList({
|
||||
keyword: keyword.value,
|
||||
page_no,
|
||||
page_size
|
||||
})
|
||||
paging.value.complete(lists)
|
||||
} catch (e) {
|
||||
console.log('报错=>', e)
|
||||
//TODO handle the exception
|
||||
paging.value.complete(false)
|
||||
}
|
||||
}
|
||||
|
||||
getHotSearchFunc()
|
||||
search.his_search = cache.get(HISTORY) || []
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.search {
|
||||
&-content {
|
||||
height: calc(100vh - 46px - env(safe-area-inset-bottom));
|
||||
&-s {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
73
business_uniapp/src/pages/user/components/info.vue
Normal file
73
business_uniapp/src/pages/user/components/info.vue
Normal file
@@ -0,0 +1,73 @@
|
||||
<template>
|
||||
<view class="p-[15rpx] rounded-lg bg-white mt-[-15rpx] mx-[20rpx]">
|
||||
<view class="flex items-center justify-between">
|
||||
<view class="flex flex-col items-center justify-center flex-1" @click="toMyMaster">
|
||||
<text class="font-bold text-lg">{{ userStore?.userInfo?.coach_count || '0' }}</text>
|
||||
<text class="text-info mt-1">我的技师</text>
|
||||
</view>
|
||||
<view
|
||||
class="flex flex-col items-center justify-center flex-1"
|
||||
@click="toPlatformProject"
|
||||
>
|
||||
<text class="font-bold text-lg">{{ userStore?.userInfo?.goods_count || '0' }}</text>
|
||||
<text class="text-info mt-1">平台项目</text>
|
||||
</view>
|
||||
<view class="flex flex-col items-center justify-center flex-1" @click="toMyProject">
|
||||
<text class="font-bold text-lg">{{
|
||||
userStore?.userInfo?.shop_goods_count || '-'
|
||||
}}</text>
|
||||
<text class="text-info mt-1">店铺项目</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex mt-4">
|
||||
<view class="flex-1 p-[24rpx] rounded-lg bg-[#d9e6fd] text-[#4A65A3]" @click="toBond">
|
||||
<view class="font-bold text-sm">{{ userStore?.userInfo?.deposit || '0' }}</view>
|
||||
<view class="mt-1">我的保证金 ></view>
|
||||
</view>
|
||||
<view
|
||||
class="flex-1 p-[24rpx] rounded-lg bg-[#bcecfb] ml-2 text-[#2DA9BC]"
|
||||
@click="toBalance"
|
||||
>
|
||||
<view class="font-bold text-sm">{{ userStore?.userInfo?.money || '-' }}</view>
|
||||
<view class="mt-1">我的账户余额 ></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useUserStore } from '@/stores/user'
|
||||
|
||||
const userStore = useUserStore()
|
||||
|
||||
//跳转至我的技师列表
|
||||
const toMyMaster = () => {
|
||||
uni.navigateTo({
|
||||
url: '/packages/pages/my_master/my_master'
|
||||
})
|
||||
}
|
||||
//跳转至保证金页面
|
||||
const toBond = () => {
|
||||
uni.navigateTo({
|
||||
url: '/packages/pages/bond/bond'
|
||||
})
|
||||
}
|
||||
//跳转至余额
|
||||
const toBalance = () => {
|
||||
uni.navigateTo({
|
||||
url: '/packages/pages/balance/balance'
|
||||
})
|
||||
}
|
||||
//跳转至平台项目
|
||||
const toPlatformProject = () => {
|
||||
uni.navigateTo({
|
||||
url: '/packages/pages/platform_project/platform_project'
|
||||
})
|
||||
}
|
||||
//跳转至我的项目
|
||||
const toMyProject = () => {
|
||||
uni.navigateTo({
|
||||
url: '/packages/pages/my_project/my_project'
|
||||
})
|
||||
}
|
||||
</script>
|
||||
119
business_uniapp/src/pages/user/user.vue
Normal file
119
business_uniapp/src/pages/user/user.vue
Normal file
@@ -0,0 +1,119 @@
|
||||
<template>
|
||||
<page-meta :page-style="$theme.pageStyle">
|
||||
<!-- #ifndef H5 -->
|
||||
<navigation-bar
|
||||
:front-color="$theme.navColor"
|
||||
:background-color="$theme.navBgColor"
|
||||
/>
|
||||
<!-- #endif -->
|
||||
</page-meta>
|
||||
<view class="user h-full bg-no-repeat" :style="pageStyle">
|
||||
<!-- #ifndef H5 -->
|
||||
<u-sticky h5-nav-height="0" bg-color="transparent">
|
||||
<u-navbar
|
||||
:is-back="false"
|
||||
:is-fixed="true"
|
||||
:title="state.meta.title"
|
||||
:custom-title="state.meta.title_type == 2"
|
||||
:border-bottom="false"
|
||||
:title-bold="true"
|
||||
:background="{ background: `rgba(256,256, 256, 0)` }"
|
||||
:title-color="state.meta.text_color == 1 ? '#fff' : '#000'"
|
||||
>
|
||||
<template #title>
|
||||
<image
|
||||
class="!h-[54rpx]"
|
||||
:src="state.meta.title_img"
|
||||
mode="widthFix"
|
||||
></image>
|
||||
</template>
|
||||
</u-navbar>
|
||||
</u-sticky>
|
||||
<!-- #endif -->
|
||||
<view v-for="(item, index) in state.pages" :key="index">
|
||||
<template v-if="item.name == 'shop-user-info'">
|
||||
<w-user-info
|
||||
:content="item.content"
|
||||
:styles="item.styles"
|
||||
:user-info="userInfo"
|
||||
:is-login="userStore.isLogin"
|
||||
/>
|
||||
</template>
|
||||
<template v-if="item.name == 'shop-user-service'">
|
||||
<w-user-service
|
||||
:content="item.content"
|
||||
:styles="item.styles"
|
||||
/>
|
||||
</template>
|
||||
<template v-if="item.name == 'shop-user-banner'">
|
||||
<w-user-banner
|
||||
:content="item.content"
|
||||
:styles="item.styles"
|
||||
/>
|
||||
</template>
|
||||
</view>
|
||||
<tabbar/>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {getDecoratePage} from '@/api/decorate'
|
||||
import {useUserStore} from '@/stores/user'
|
||||
import {useAppStore} from '@/stores/app'
|
||||
import {onShow} from '@dcloudio/uni-app'
|
||||
import {reactive, ref, computed} from 'vue'
|
||||
|
||||
const userStore = useUserStore()
|
||||
const {getImageUrl} = useAppStore()
|
||||
let userInfo = ref<any>({
|
||||
nickname: '',
|
||||
is_staff: 0,
|
||||
avatar: '',
|
||||
mobile: '',
|
||||
service_num: 0,
|
||||
wait_pay_num: 0,
|
||||
staff_wait_num: 0,
|
||||
finish_num: 0,
|
||||
appoint_num: 0,
|
||||
decorate_page: []
|
||||
})
|
||||
const state = reactive<{
|
||||
pages: any[]
|
||||
meta: any
|
||||
}>({
|
||||
pages: [],
|
||||
meta: {}
|
||||
})
|
||||
|
||||
userInfo = computed(() => userStore.userInfo)
|
||||
// 根页面样式
|
||||
const pageStyle = computed(() => {
|
||||
const {bg_type, bg_color, bg_image} = state.meta ?? {}
|
||||
return bg_type == 1 ?
|
||||
{'background-color': bg_color} :
|
||||
{'background-image': `url(${getImageUrl(bg_image)})`}
|
||||
})
|
||||
|
||||
const initUserInfo = async (): Promise<void> => {
|
||||
await userStore.getUser()
|
||||
userInfo.value = userStore.userInfo
|
||||
}
|
||||
|
||||
const getData = async () => {
|
||||
const data = await getDecoratePage({type: 2})
|
||||
state.meta = JSON.parse(data.meta)[0].content
|
||||
state.pages = JSON.parse(data.data)
|
||||
|
||||
console.log(state.meta)
|
||||
uni.setNavigationBarTitle({
|
||||
title: state.meta.title
|
||||
})
|
||||
}
|
||||
|
||||
onShow(() => {
|
||||
initUserInfo()
|
||||
getData()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style></style>
|
||||
262
business_uniapp/src/pages/user_data/user_data.vue
Normal file
262
business_uniapp/src/pages/user_data/user_data.vue
Normal file
@@ -0,0 +1,262 @@
|
||||
<template>
|
||||
<page-meta :page-style="$theme.pageStyle">
|
||||
<!-- #ifndef H5 -->
|
||||
<navigation-bar
|
||||
:front-color="$theme.navColor"
|
||||
:background-color="$theme.navBgColor"
|
||||
/>
|
||||
<!-- #endif -->
|
||||
</page-meta>
|
||||
<!-- Main Start -->
|
||||
|
||||
<view class="user-data p-[30rpx]">
|
||||
<u-sticky h5-nav-height="0" bg-color="transparent">
|
||||
<u-navbar
|
||||
:is-back="true"
|
||||
:is-fixed="true"
|
||||
title="个人资料"
|
||||
:border-bottom="false"
|
||||
:title-bold="false"
|
||||
:background="{ background: `rgba(256,256, 256, 0)` }"
|
||||
:title-color="'#000'"
|
||||
>
|
||||
</u-navbar>
|
||||
</u-sticky>
|
||||
|
||||
<!-- 头像 -->
|
||||
<view
|
||||
class="item rounded-t-[20rpx] mt-[20rpx] btn-border flex flex-1 justify-between items-center"
|
||||
>
|
||||
<view class="label">头像</view>
|
||||
|
||||
<u-image :src="userInfo?.logo" width="80" height="80" border-radius="50%"></u-image>
|
||||
</view>
|
||||
|
||||
<!-- 昵称 -->
|
||||
<view
|
||||
class="item flex flex-1 justify-between items-center"
|
||||
>
|
||||
<view class="label">姓名</view>
|
||||
<view class="content text-right">{{ userInfo?.name }}</view>
|
||||
</view>
|
||||
|
||||
<!-- 手机号 -->
|
||||
<view class="item flex flex-1 justify-between items-center">
|
||||
<view class="label">手机号</view>
|
||||
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<!-- <view class="content">
|
||||
{{ userInfo?.mobile == '' ? '未绑定手机号' : userInfo?.mobile }}
|
||||
</view>
|
||||
<u-button
|
||||
open-type="getPhoneNumber"
|
||||
@getphonenumber="getPhoneNumber"
|
||||
type="primary"
|
||||
shape="circle"
|
||||
size="mini"
|
||||
:plain="true"
|
||||
>
|
||||
{{ userInfo?.mobile == '' ? '绑定手机号' : '更换手机号' }}
|
||||
</u-button> -->
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef MP-WEIXIN -->
|
||||
<!-- <view class="content" @click="showMobilePop = true">
|
||||
{{ userInfo?.mobile == '' ? '未绑定手机号' : userInfo?.mobile }}
|
||||
</view>
|
||||
<view @click="showMobilePop = true">
|
||||
<u-icon name="arrow-right" size="22" color="#666"></u-icon>
|
||||
</view> -->
|
||||
<!-- #endif -->
|
||||
|
||||
<view class="content" @click="toBindMobile">
|
||||
{{ userInfo?.mobile }}
|
||||
</view>
|
||||
<view @click="toBindMobile">
|
||||
<u-icon name="arrow-right" size="22" color="#666"></u-icon>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 入驻时间 -->
|
||||
<view
|
||||
class="item flex flex-1 justify-between items-center rounded-b-[20rpx]"
|
||||
>
|
||||
<view class="label">入驻时间</view>
|
||||
<view class="content">{{ userInfo?.create_time }}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 账号修改组件 -->
|
||||
<!-- <u-popup v-model="showMobilePop" :closeable="true" mode="center" border-radius="20">
|
||||
<view class="px-[50rpx] py-[40rpx] bg-white" style="width: 85vw">
|
||||
<view class="mb-[70rpx] text-xl text-center">{{ userInfo?.mobile == '' ? '绑定手机号' : '更换手机号' }}</view>
|
||||
<u-form-item borderBottom>
|
||||
<u-input
|
||||
class="flex-1"
|
||||
v-model="newMobile"
|
||||
placeholder="请输入新的手机号码"
|
||||
:border="false"
|
||||
/>
|
||||
</u-form-item>
|
||||
<u-form-item borderBottom>
|
||||
<u-input
|
||||
class="flex-1"
|
||||
v-model="mobileCode"
|
||||
placeholder="请输入验证码"
|
||||
:border="false"
|
||||
/>
|
||||
<view
|
||||
class="border-l border-solid border-0 border-light pl-3 text-muted leading-4 ml-3 w-[180rpx]"
|
||||
@click="sendSms"
|
||||
>
|
||||
<u-verification-code
|
||||
ref="uCodeRef"
|
||||
:seconds="60"
|
||||
@change="codeChange"
|
||||
change-text="x秒"
|
||||
/>
|
||||
{{ codeTips }}
|
||||
</view>
|
||||
</u-form-item>
|
||||
<view class="mt-[80rpx]">
|
||||
<u-button @click="changeCodeMobile" type="primary" shape="circle"> 确定 </u-button>
|
||||
</view>
|
||||
</view>
|
||||
</u-popup> -->
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, shallowRef } from 'vue'
|
||||
import { onShow, onUnload } from '@dcloudio/uni-app'
|
||||
import { getUserInfo, userEdit, userBindMobile, userMnpMobile } from '@/api/user'
|
||||
import { smsSend } from '@/api/app'
|
||||
import { FieldType, SMSEnum } from '@/enums/appEnums'
|
||||
|
||||
// 用户信息
|
||||
const userInfo = ref<any>({})
|
||||
// 用户信息的枚举
|
||||
const fieldType = ref(FieldType.NONE)
|
||||
|
||||
//显示性别选择弹窗
|
||||
const showPicker = ref<boolean | null>(false)
|
||||
// 显示手机号验证码调整弹窗 非小程序才需要
|
||||
const showMobilePop = ref<boolean | null>(false)
|
||||
|
||||
//新的手机号码
|
||||
const newMobile = ref<string>('')
|
||||
|
||||
//修改手机验证码
|
||||
const mobileCode = ref<string>('')
|
||||
const codeTips = ref('')
|
||||
const uCodeRef = shallowRef()
|
||||
|
||||
// 跳转更换手机号码页面
|
||||
const toBindMobile = () => {
|
||||
uni.navigateTo({
|
||||
url: `/pages/bind_mobile/bind_mobile?mobile=${userInfo.value.mobile}`
|
||||
})
|
||||
}
|
||||
|
||||
// 获取用户信息
|
||||
const getUser = async (): Promise<void> => {
|
||||
userInfo.value = await getUserInfo()
|
||||
}
|
||||
|
||||
// 获取验证码显示字段
|
||||
const codeChange = (text: string) => {
|
||||
codeTips.value = text
|
||||
}
|
||||
|
||||
// 发送验证码
|
||||
const sendSms = async () => {
|
||||
if (!newMobile.value) return uni.$u.toast('请输入新的手机号码')
|
||||
if (uCodeRef.value?.canGetCode) {
|
||||
await smsSend({
|
||||
scene: userInfo.value.mobile ? SMSEnum.CHANGE_MOBILE : SMSEnum.BIND_MOBILE,
|
||||
mobile: newMobile.value
|
||||
})
|
||||
uni.$u.toast('发送成功')
|
||||
uCodeRef.value?.start()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 验证码修改手机号-非微信小程序
|
||||
const changeCodeMobile = async () => {
|
||||
await userBindMobile({
|
||||
type: userInfo.value.mobile ? 'change' : 'bind',
|
||||
mobile: newMobile.value,
|
||||
code: mobileCode.value
|
||||
})
|
||||
uni.$u.toast('操作成功')
|
||||
showMobilePop.value = false
|
||||
getUser()
|
||||
}
|
||||
|
||||
// 修改用户信息
|
||||
const setUserInfoFun = async (value: string): Promise<void> => {
|
||||
await userEdit({
|
||||
field: fieldType.value,
|
||||
value: value
|
||||
})
|
||||
uni.$u.toast('操作成功')
|
||||
getUser()
|
||||
}
|
||||
|
||||
// 显示修改用户性别弹窗
|
||||
const changeSex = () => {
|
||||
showPicker.value = true
|
||||
fieldType.value = FieldType.SEX
|
||||
}
|
||||
|
||||
// 微信小程序 绑定||修改用户手机号
|
||||
const getPhoneNumber = async (e): Promise<void> => {
|
||||
const { encryptedData, iv, code } = e.detail
|
||||
const data = {
|
||||
code,
|
||||
encrypted_data: encryptedData,
|
||||
iv
|
||||
}
|
||||
if (encryptedData) {
|
||||
await userMnpMobile({
|
||||
...data
|
||||
})
|
||||
uni.$u.toast('操作成功')
|
||||
getUser()
|
||||
}
|
||||
}
|
||||
|
||||
onShow(async () => {
|
||||
getUser()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.header {
|
||||
width: 100%;
|
||||
|
||||
image {
|
||||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
.item {
|
||||
margin-top: 2rpx;
|
||||
padding: 40rpx 20rpx;
|
||||
background-color: #ffffff;
|
||||
|
||||
.label {
|
||||
width: 150rpx;
|
||||
@apply text-main text-base font-medium;
|
||||
}
|
||||
|
||||
.content {
|
||||
flex: 1;
|
||||
width: 80%;
|
||||
padding-right: 12rpx;
|
||||
@apply text-content text-base font-medium text-right;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
257
business_uniapp/src/pages/user_set/user_set copy.vue
Normal file
257
business_uniapp/src/pages/user_set/user_set copy.vue
Normal file
@@ -0,0 +1,257 @@
|
||||
<template>
|
||||
<page-meta :page-style="$theme.pageStyle">
|
||||
<!-- #ifndef H5 -->
|
||||
<navigation-bar :front-color="$theme.navColor" :background-color="$theme.navBgColor" />
|
||||
<!-- #endif -->
|
||||
</page-meta>
|
||||
<view class="user-set">
|
||||
<navigator :url="`/pages/user_data/user_data`">
|
||||
<view class="item flex bg-white mt-[20rpx]">
|
||||
<u-avatar :src="userInfo.logo" shape="square" :size="100"></u-avatar>
|
||||
<view class="ml-[20rpx] flex flex-1 justify-between items-center">
|
||||
<view>
|
||||
<view class="mb-[15rpx] text-xl font-medium">{{ userInfo.name }}</view>
|
||||
<view class="text-content text-xs">账号:{{ userInfo.sn }}</view>
|
||||
</view>
|
||||
<u-icon name="arrow-right" color="#666"></u-icon>
|
||||
</view>
|
||||
</view>
|
||||
</navigator>
|
||||
<view
|
||||
class="item bg-white mt-[20rpx] btn-border flex flex-1 justify-between"
|
||||
@click="handlePwd"
|
||||
>
|
||||
<view class="">登录密码</view>
|
||||
<u-icon name="arrow-right" color="#666"></u-icon>
|
||||
</view>
|
||||
<!-- #ifdef H5 || MP-WEIXIN -->
|
||||
<view
|
||||
v-if="isWeixin"
|
||||
class="item bg-white flex flex-1 justify-between"
|
||||
@click="bindWechatLock"
|
||||
>
|
||||
<view class="">绑定微信</view>
|
||||
<view class="flex justify-between">
|
||||
<view class="text-muted mr-[20rpx]">
|
||||
{{ userInfo.is_auth ? '已绑定' : '未绑定' }}
|
||||
</view>
|
||||
<u-icon v-if="userInfo.is_auth == 0" name="arrow-right" color="#666"></u-icon>
|
||||
</view>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
|
||||
<navigator url="/packages/pages/entry_info/entry_info">
|
||||
<view class="item bg-white btn-border flex flex-1 justify-between mt-[20rpx]">
|
||||
<view class="">入驻信息</view>
|
||||
<u-icon name="arrow-right" color="#666"></u-icon>
|
||||
</view>
|
||||
</navigator>
|
||||
<navigator url="/packages/pages/shop_info/shop_info">
|
||||
<view class="item bg-white btn-border flex flex-1 justify-between">
|
||||
<view class="">店铺资料</view>
|
||||
<u-icon name="arrow-right" color="#666"></u-icon>
|
||||
</view>
|
||||
</navigator>
|
||||
<navigator :url="`/pages/agreement/agreement?type=${AgreementEnum.PRIVACY}`">
|
||||
<view class="item bg-white btn-border flex flex-1 justify-between">
|
||||
<view class="">隐私政策</view>
|
||||
<u-icon name="arrow-right" color="#666"></u-icon>
|
||||
</view>
|
||||
</navigator>
|
||||
<navigator :url="`/pages/agreement/agreement?type=${AgreementEnum.SERVICE}`">
|
||||
<view class="item bg-white btn-border flex flex-1 justify-between">
|
||||
<view class="">服务协议</view>
|
||||
<u-icon name="arrow-right" color="#666"></u-icon>
|
||||
</view>
|
||||
</navigator>
|
||||
<navigator url="/pages/as_us/as_us">
|
||||
<view class="item bg-white flex flex-1 justify-between">
|
||||
<view class="">关于我们</view>
|
||||
<view class="flex justify-between">
|
||||
<view class="text-muted mr-[20rpx]">
|
||||
{{ appStore.config.version }}
|
||||
</view>
|
||||
<u-icon name="arrow-right" color="#666"></u-icon>
|
||||
</view>
|
||||
</view>
|
||||
</navigator>
|
||||
|
||||
<view class="mt-[60rpx] mx-[26rpx]">
|
||||
<u-button type="error" @click="showLogout = true"> 退出登录</u-button>
|
||||
</view>
|
||||
|
||||
<u-action-sheet
|
||||
:list="list"
|
||||
v-model="show"
|
||||
@click="handleClick"
|
||||
:safe-area-inset-bottom="true"
|
||||
></u-action-sheet>
|
||||
|
||||
<u-popup
|
||||
class="pay-popup"
|
||||
v-model="showLogout"
|
||||
round
|
||||
mode="center"
|
||||
borderRadius="10"
|
||||
:maskCloseAble="false"
|
||||
>
|
||||
<view class="content bg-white w-[560rpx] p-[40rpx]">
|
||||
<view class="text-2xl font-medium text-center"> 温馨提示</view>
|
||||
<view class="pt-[30rpx] pb-[40rpx]">
|
||||
<view> 是否清除当前登录信息,退出登录?</view>
|
||||
</view>
|
||||
<view class="flex">
|
||||
<view class="flex-1 mr-[20rpx]">
|
||||
<u-button
|
||||
shape="circle"
|
||||
type="primary"
|
||||
plain
|
||||
size="medium"
|
||||
hover-class="none"
|
||||
:customStyle="{ width: '100%' }"
|
||||
@click="showLogout = false"
|
||||
>
|
||||
取消
|
||||
</u-button>
|
||||
</view>
|
||||
<view class="flex-1">
|
||||
<u-button
|
||||
shape="circle"
|
||||
type="primary"
|
||||
size="medium"
|
||||
hover-class="none"
|
||||
:customStyle="{ width: '100%' }"
|
||||
@click="logoutHandle"
|
||||
>
|
||||
确认
|
||||
</u-button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</u-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onLoad, onShow } from '@dcloudio/uni-app'
|
||||
import { computed, ref } from 'vue'
|
||||
import { useAppStore } from '@/stores/app'
|
||||
import { useUserStore } from '@/stores/user'
|
||||
import { AgreementEnum } from '@/enums/agreementEnums'
|
||||
import { isWeixinClient } from '@/utils/client'
|
||||
import { mnpAuthBind, oaAuthBind } from '@/api/account'
|
||||
import { useLockFn } from '@/hooks/useLockFn'
|
||||
import { useRouter } from 'uniapp-router-next'
|
||||
// #ifdef H5
|
||||
import wechatOa from '@/utils/wechat'
|
||||
// #endif
|
||||
|
||||
const router = useRouter()
|
||||
const appStore = useAppStore()
|
||||
const userStore = useUserStore()
|
||||
const userInfo = computed(() => userStore.userInfo)
|
||||
|
||||
const list = ref([
|
||||
{
|
||||
text: '修改密码'
|
||||
},
|
||||
{
|
||||
text: '忘记密码'
|
||||
}
|
||||
])
|
||||
|
||||
const isWeixin = ref(true)
|
||||
// #ifdef H5
|
||||
isWeixin.value = isWeixinClient()
|
||||
// #endif
|
||||
|
||||
const show = ref(false)
|
||||
const showLogout = ref(false)
|
||||
|
||||
// 修改/忘记密码
|
||||
const handleClick = (index: number) => {
|
||||
switch (index) {
|
||||
case 0:
|
||||
router.navigateTo('/pages/change_password/change_password')
|
||||
break
|
||||
case 1:
|
||||
router.navigateTo('/pages/forget_pwd/forget_pwd')
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
const handlePwd = () => {
|
||||
if (!userInfo.value.has_password)
|
||||
return router.navigateTo('/pages/change_password/change_password?type=set')
|
||||
show.value = true
|
||||
}
|
||||
|
||||
// 退出登录
|
||||
const logoutHandle = () => {
|
||||
userStore.logout()
|
||||
router.redirectTo('/pages/login/login')
|
||||
}
|
||||
|
||||
const bindWechat = async () => {
|
||||
if (userInfo.value.is_auth) return
|
||||
try {
|
||||
uni.showLoading({
|
||||
title: '请稍后...'
|
||||
})
|
||||
// #ifdef MP-WEIXIN
|
||||
const { code }: any = await uni.login({
|
||||
provider: 'weixin'
|
||||
})
|
||||
await mnpAuthBind({
|
||||
code: code
|
||||
})
|
||||
//#endif
|
||||
// #ifdef H5
|
||||
if (isWeixin.value) {
|
||||
wechatOa.getUrl()
|
||||
}
|
||||
// #endif
|
||||
await userStore.getUser()
|
||||
uni.hideLoading()
|
||||
} catch (e) {
|
||||
uni.hideLoading()
|
||||
uni.$u.toast(e)
|
||||
}
|
||||
}
|
||||
const { lockFn: bindWechatLock } = useLockFn(bindWechat)
|
||||
|
||||
onShow(() => {
|
||||
userStore.getUser()
|
||||
})
|
||||
|
||||
onLoad(async (options) => {
|
||||
// #ifdef H5
|
||||
const { code } = options
|
||||
if (!isWeixin.value) return
|
||||
if (code) {
|
||||
uni.showLoading({
|
||||
title: '请稍后...'
|
||||
})
|
||||
try {
|
||||
await oaAuthBind({ code })
|
||||
await userStore.getUser()
|
||||
} catch (error) {}
|
||||
//用于清空code
|
||||
router.redirectTo('/pages/user_set/user_set')
|
||||
}
|
||||
|
||||
// #endif
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.user-set {
|
||||
.item {
|
||||
padding: 30rpx;
|
||||
}
|
||||
|
||||
.btn-border {
|
||||
border-bottom: 2rpx solid #f8f8f8;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
269
business_uniapp/src/pages/user_set/user_set.vue
Normal file
269
business_uniapp/src/pages/user_set/user_set.vue
Normal file
@@ -0,0 +1,269 @@
|
||||
<template>
|
||||
<page-meta :page-style="$theme.pageStyle">
|
||||
<!-- #ifndef H5 -->
|
||||
<navigation-bar
|
||||
:front-color="$theme.navColor"
|
||||
:background-color="$theme.navBgColor"
|
||||
/>
|
||||
<!-- #endif -->
|
||||
</page-meta>
|
||||
<view class="user-set flex flex-col min-h-0 h-full">
|
||||
<u-sticky h5-nav-height="0" bg-color="transparent">
|
||||
<u-navbar
|
||||
:is-back="true"
|
||||
:is-fixed="true"
|
||||
title="个人设置"
|
||||
:border-bottom="false"
|
||||
:title-bold="false"
|
||||
:background="{ background: `rgba(256,256, 256, 0)` }"
|
||||
:title-color="'#000'"
|
||||
>
|
||||
</u-navbar>
|
||||
</u-sticky>
|
||||
|
||||
<view class="flex-1 px-[30rpx]">
|
||||
<navigator :url="`/pages/user_data/user_data`" v-if="userInfo.audit_status != null">
|
||||
<view class="item flex bg-white rounded-[20rpx] my-[20rpx]">
|
||||
<u-avatar :src="userInfo.logo" shape="square" :size="100"></u-avatar>
|
||||
<view class="ml-[20rpx] flex flex-1 justify-between items-center">
|
||||
<view>
|
||||
<view class="mb-[15rpx] text-xl font-medium">{{ userInfo.name }}</view>
|
||||
<view class="text-content text-xs">工号:{{ userInfo.sn }}</view>
|
||||
</view>
|
||||
<u-icon name="arrow-right" color="#999"></u-icon>
|
||||
</view>
|
||||
</view>
|
||||
</navigator>
|
||||
<view
|
||||
class="item bg-white rounded-[24rpx] mt-[20rpx] btn-border flex flex-1 justify-between"
|
||||
@click="handlePwd"
|
||||
>
|
||||
<view class="">登录密码</view>
|
||||
<view class="flex justify-between">
|
||||
<!-- <view class="text-muted mr-[20rpx]">
|
||||
{{ userInfo.has_password ? '已设置' : '未设置' }}
|
||||
</view> -->
|
||||
<u-icon name="arrow-right" color="#999"></u-icon>
|
||||
</view>
|
||||
</view>
|
||||
<!-- #ifdef H5 || MP-WEIXIN -->
|
||||
<!-- <view-->
|
||||
<!-- class="item bg-white rounded-b-[20rpx] flex flex-1 justify-between"-->
|
||||
<!-- v-if="isWeixin"-->
|
||||
<!-- @click="bindWechatLock"-->
|
||||
<!-- >-->
|
||||
<!-- <view class="">绑定微信</view>-->
|
||||
<!-- <view class="flex justify-between">-->
|
||||
<!-- <view class="text-muted mr-[20rpx]">-->
|
||||
<!-- {{ userInfo.is_auth ? '已绑定' : '未绑定' }}-->
|
||||
<!-- </view>-->
|
||||
<!-- <u-icon v-if="userInfo.is_auth == 0" name="arrow-right" color="#999"></u-icon>-->
|
||||
<!-- </view>-->
|
||||
<!-- </view>-->
|
||||
<!-- #endif -->
|
||||
|
||||
<view
|
||||
v-if="userInfo.audit_status !== null"
|
||||
class="item bg-white rounded-t-[20rpx] mt-[20rpx] btn-border flex flex-1 justify-between"
|
||||
@click="router.navigate('/packages/pages/shop_info/shop_info')"
|
||||
>
|
||||
<view class="">店铺资料</view>
|
||||
<u-icon name="arrow-right" color="#999"></u-icon>
|
||||
</view>
|
||||
|
||||
<view
|
||||
v-if="userInfo.audit_status !== null"
|
||||
class="item bg-white btn-border flex flex-1 justify-between"
|
||||
@click="router.navigate('/packages/pages/entry_info/entry_info')"
|
||||
>
|
||||
<view class="">入驻信息</view>
|
||||
<u-icon name="arrow-right" color="#999"></u-icon>
|
||||
</view>
|
||||
|
||||
<view
|
||||
class="item bg-white btn-border flex flex-1 justify-between"
|
||||
@click="router.navigate(`/pages/agreement/agreement?type=${AgreementEnum.PRIVACY}`)"
|
||||
>
|
||||
<view class="">隐私政策</view>
|
||||
<u-icon name="arrow-right" color="#999"></u-icon>
|
||||
</view>
|
||||
<view
|
||||
class="item bg-white btn-border flex flex-1 justify-between"
|
||||
@click="router.navigate(`/pages/agreement/agreement?type=${AgreementEnum.SERVICE}`)"
|
||||
>
|
||||
<view class="">服务协议</view>
|
||||
<u-icon name="arrow-right" color="#999"></u-icon>
|
||||
</view>
|
||||
|
||||
<view
|
||||
class="item bg-white rounded-b-[20rpx] flex flex-1 justify-between"
|
||||
@click="router.navigate('/pages/as_us/as_us')"
|
||||
>
|
||||
<view class="">关于我们</view>
|
||||
<view class="flex justify-between">
|
||||
<view class="text-muted mr-[20rpx]"> v{{ appStore.config.version }}</view>
|
||||
<u-icon name="arrow-right" color="#999"></u-icon>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view
|
||||
class="footer bg-white p-[30rpx]"
|
||||
style="box-shadow: 0 -4rpx 48rpx 0 #1423191f;"
|
||||
>
|
||||
<u-button type="error" @click="showLogout = true">
|
||||
退出登录
|
||||
</u-button>
|
||||
</view>
|
||||
|
||||
<u-action-sheet
|
||||
:list="list"
|
||||
v-model="show"
|
||||
@click="handleClick"
|
||||
:safe-area-inset-bottom="true"
|
||||
></u-action-sheet>
|
||||
|
||||
|
||||
<!-- 推出登录弹窗 -->
|
||||
<modal-popup
|
||||
v-model:show="showLogout"
|
||||
title="温馨提示"
|
||||
content="确认退出当前登录吗?"
|
||||
@confirm="logoutHandle"
|
||||
>
|
||||
</modal-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {onLoad, onShow} from '@dcloudio/uni-app'
|
||||
import {computed, ref} from 'vue'
|
||||
import {useAppStore} from '@/stores/app'
|
||||
import {useUserStore} from '@/stores/user'
|
||||
import {AgreementEnum} from '@/enums/agreementEnums'
|
||||
import {isWeixinClient} from '@/utils/client'
|
||||
import {mnpAuthBind, oaAuthBind} from '@/api/account'
|
||||
import {useLockFn} from '@/hooks/useLockFn'
|
||||
import {useRouter} from 'uniapp-router-next'
|
||||
// #ifdef H5
|
||||
import wechatOa from '@/utils/wechat'
|
||||
// #endif
|
||||
|
||||
const router = useRouter()
|
||||
const appStore = useAppStore()
|
||||
const userStore = useUserStore()
|
||||
const userInfo = computed(() => userStore.userInfo)
|
||||
|
||||
const list = ref([
|
||||
{
|
||||
text: '修改密码'
|
||||
},
|
||||
{
|
||||
text: '忘记密码'
|
||||
}
|
||||
])
|
||||
|
||||
const isWeixin = ref(true)
|
||||
// #ifdef H5
|
||||
isWeixin.value = isWeixinClient()
|
||||
// #endif
|
||||
|
||||
const show = ref(false)
|
||||
const showLogout = ref(false)
|
||||
|
||||
// 修改/忘记密码
|
||||
const handleClick = (index: number) => {
|
||||
switch (index) {
|
||||
case 0:
|
||||
router.navigateTo('/pages/change_password/change_password')
|
||||
break
|
||||
case 1:
|
||||
router.navigateTo('/pages/forget_pwd/forget_pwd')
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
const handlePwd = () => {
|
||||
// if (!userInfo.value.has_password)
|
||||
// return router.navigateTo('/pages/change_password/change_password?type=set')
|
||||
// show.value = true
|
||||
// 去修改密码
|
||||
handleClick(0)
|
||||
}
|
||||
|
||||
// 退出登录
|
||||
const logoutHandle = () => {
|
||||
userStore.logout()
|
||||
router.redirectTo('/pages/login/login')
|
||||
}
|
||||
|
||||
const bindWechat = async () => {
|
||||
if (userInfo.value.is_auth) return
|
||||
try {
|
||||
uni.showLoading({
|
||||
title: '请稍后...'
|
||||
})
|
||||
// #ifdef MP-WEIXIN
|
||||
const {code}: any = await uni.login({
|
||||
provider: 'weixin'
|
||||
})
|
||||
await mnpAuthBind({
|
||||
code: code
|
||||
})
|
||||
//#endif
|
||||
// #ifdef H5
|
||||
if (isWeixin.value) {
|
||||
wechatOa.getUrl()
|
||||
}
|
||||
// #endif
|
||||
await userStore.getUser()
|
||||
uni.hideLoading()
|
||||
} catch (e) {
|
||||
uni.hideLoading()
|
||||
uni.$u.toast(e)
|
||||
}
|
||||
}
|
||||
const {lockFn: bindWechatLock} = useLockFn(bindWechat)
|
||||
|
||||
onShow(() => {
|
||||
userStore.getUser()
|
||||
})
|
||||
|
||||
onLoad(async (options) => {
|
||||
// #ifdef H5
|
||||
const {code} = options
|
||||
if (!isWeixin.value) return
|
||||
if (code) {
|
||||
uni.showLoading({
|
||||
title: '请稍后...'
|
||||
})
|
||||
try {
|
||||
await oaAuthBind({code})
|
||||
await userStore.getUser()
|
||||
} catch (error) {
|
||||
}
|
||||
//用于清空code
|
||||
router.redirectTo('/pages/user_set/user_set')
|
||||
}
|
||||
|
||||
// #endif
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.user-set {
|
||||
.item {
|
||||
padding: 30rpx;
|
||||
}
|
||||
|
||||
.btn-border {
|
||||
border-bottom: 2rpx solid #f8f8f8;
|
||||
}
|
||||
|
||||
// 底部按钮
|
||||
.footer {
|
||||
box-shadow: 0 -4rpx 48rpx 0 #1423191f;
|
||||
padding-bottom: calc(env(safe-area-inset-bottom) + 30rpx);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
16
business_uniapp/src/pages/webview/webview.vue
Normal file
16
business_uniapp/src/pages/webview/webview.vue
Normal file
@@ -0,0 +1,16 @@
|
||||
<template>
|
||||
<web-view :src="url" />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import { ref } from 'vue'
|
||||
|
||||
const url = ref('')
|
||||
|
||||
onLoad((options) => {
|
||||
url.value = decodeURIComponent(options.url!)
|
||||
})
|
||||
</script>
|
||||
|
||||
<style></style>
|
||||
Reference in New Issue
Block a user