调试接口

This commit is contained in:
wangxiaowei
2025-12-30 01:05:27 +08:00
parent 338a99a54a
commit f69536a7e4
9 changed files with 430 additions and 478 deletions

12
env/.env vendored
View File

@ -1,5 +1,5 @@
VITE_APP_TITLE = '茶艺师管理端' VITE_APP_TITLE = '茶艺师管理端'
VITE_APP_PORT = 9003 VITE_APP_PORT = 9002
VITE_UNI_APPID = '__UNI__932EB7D' VITE_UNI_APPID = '__UNI__932EB7D'
VITE_WX_APPID = 'wx1a89a1b47d08b83e' VITE_WX_APPID = 'wx1a89a1b47d08b83e'
@ -10,17 +10,17 @@ VITE_APP_PUBLIC_BASE=/
# 登录页面 # 登录页面
VITE_LOGIN_URL = '/pages/login/login' VITE_LOGIN_URL = '/pages/login/login'
# 第一个请求地址 # 第一个请求地址
VITE_SERVER_BASEURL = 'https://76458.com' VITE_SERVER_BASEURL = 'https://cz.stnav.com'
VITE_UPLOAD_BASEURL = 'https://76458.com/upload' VITE_UPLOAD_BASEURL = 'https://cz.stnav.com/upload'
# h5是否需要配置代理 # h5是否需要配置代理
VITE_APP_PROXY=true VITE_APP_PROXY=true
VITE_APP_PROXY_PREFIX = '/storeapi' VITE_APP_PROXY_PREFIX = '/storeapi'
# 第二个请求地址 (目前alova中可以使用) # 第二个请求地址 (目前alova中可以使用)
VITE_SERVER_BASEURL = 'https://76458.com' VITE_SERVER_BASEURL = 'https://cz.stnav.com'
# 上传图片请求地址 # 上传图片请求地址
VITE_UPLOAD_BASEURL = 'https://76458.com/storeapi/upload/image' VITE_UPLOAD_BASEURL = 'https://cz.stnav.com/storeapi/upload/image'
VITE_UPLOAD_IMAGE_URL = 'https://76458.com/' VITE_UPLOAD_IMAGE_URL = 'https://cz.stnav.com/'

View File

@ -43,7 +43,7 @@ export function login(loginForm: ILoginForm) {
* @param loginForm 登录表单 * @param loginForm 登录表单
*/ */
export function mobileLogin(loginForm: IMobileLoginForm) { export function mobileLogin(loginForm: IMobileLoginForm) {
return http.Post<IUserLogin>('/storeapi/storeLogin/account', return http.Post<IUserLogin>('/teamapi/TeamLogin/account',
loginForm, loginForm,
{ {
meta: { ignoreAuth: true } // 忽略认证 meta: { ignoreAuth: true } // 忽略认证
@ -51,19 +51,11 @@ export function mobileLogin(loginForm: IMobileLoginForm) {
) )
} }
/**
* 获取用户信息
*/
export function getUserInfo() {
return http.Post<IUserInfoVo>('/storeapi/user/info')
}
/** /**
* 退出登录 * 退出登录
*/ */
export function logout() { export function logout() {
return http.Post('/storeapi/storeLogin/logout') return http.Post('/teamapi/TeamLogin/logout')}
}
/** /**
* 获取微信登录凭证 * 获取微信登录凭证

View File

@ -3,14 +3,6 @@ import type { IUserAddressListResult, IUserAddressDetailsResult, IUserCouponList
import type { IOrderListResult } from '@/api/types/teaSpecialist-order' import type { IOrderListResult } from '@/api/types/teaSpecialist-order'
import type { IUserResult } from '@/api/types/user' import type { IUserResult } from '@/api/types/user'
/**
* 获取用户个人信息
*/
export function getUserInfo() {
return http.Post<IUserResult>('/storeapi/user/info')
}
/** /**
* 修改用户信息 * 修改用户信息
*/ */
@ -27,6 +19,14 @@ export function updateUserInfo(data: IUpdateUserInfoParams) {
return http.Post('/storeapi/user/updateUser', data) return http.Post('/storeapi/user/updateUser', data)
} }
/**
* 获取用户信息
*/
export function getUserInfo() {
return http.Post<any>('/teamapi/user/info')
}
/** /**
* 获取流水明细 * 获取流水明细
*/ */

View File

@ -1,7 +1,7 @@
<!-- 使用 type="home" 属性设置首页其他页面不需要设置默认为page --> <!-- 使用 type="home" 属性设置首页其他页面不需要设置默认为page -->
<route lang="jsonc" type="home">{ <route lang="jsonc" type="home">{
"layout": "tabbar", "layout": "tabbar",
"needLogin": false, "needLogin": true,
"style": { "style": {
// 'custom' 表示开启自定义导航栏,默认 'default' // 'custom' 表示开启自定义导航栏,默认 'default'
"navigationStyle": "custom", "navigationStyle": "custom",
@ -12,27 +12,11 @@
<template> <template>
<view class="home-bg pb-200rpx"> <view class="home-bg pb-200rpx">
<!-- 顶部导航栏 --> <!-- 顶部导航栏 -->
<!-- <view class="navbar-wrapper" :style="{ paddingTop: `${statusBarHeight}px` }">
<view class="navbar-content">
<view class="greeting-text">
你好, {{ userInfo.nickname || '茶艺师' }}
</view>
<view class="navbar-icons">
<view class="icon-btn" @click="handleMenuClick">
<image class="menu-icon" :src="menuIcon" mode="aspectFit" />
</view>
<view class="icon-btn" @click="router.navigateTo('/pages/my/my')">
<wd-img width="48rpx" height="48rpx"
:src="userInfo.avatar || `${OSS}images/store/my/image1.png`" mode="aspectFill" round />
</view>
</view>
</view>
</view> -->
<view class="home-bg w-[100%] fixed top-0 left-0 z-100"> <view class="home-bg w-[100%] fixed top-0 left-0 z-100">
<wd-navbar safeAreaInsetTop :bordered="false" custom-style="background-color: transparent !important;"> <wd-navbar safeAreaInsetTop :bordered="false" custom-style="background-color: transparent !important;">
<template #left> <template #left>
<view class="flex items-center line-1 w-450rpx" @click="router.navigateTo('/bundle/account/switch')"> <view class="flex items-center line-1 w-450rpx" @click="router.navigateTo('/bundle/account/switch')">
<view class="mr-10rpx font-400 leading-44rpx text-32rpx pl-10rpx line-1">你好123, {{ userInfo.nickname || '茶艺师' }}</view> <view class="mr-10rpx font-400 leading-44rpx text-32rpx pl-10rpx line-1">你好, {{ userInfo.nickname || '茶艺师' }}</view>
</view> </view>
</template> </template>
</wd-navbar> </wd-navbar>
@ -238,249 +222,240 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { inject, onMounted, ref } from 'vue' import { inject, onMounted, ref } from 'vue'
import { router } from '@/utils/tools' import { router } from '@/utils/tools'
import { useUserStore } from '@/store'
const OSS = inject('OSS') const OSS = inject('OSS')
const navbarHeight = inject('navbarHeight') const navbarHeight = inject('navbarHeight')
// 获取状态栏高度(用于自定义导航栏的安全区域适配) // 用户信息
const statusBarHeight = ref(0) const userStore = useUserStore()
onMounted(() => { const userInfo = userStore.userInfo
const systemInfo = uni.getWindowInfo()
statusBarHeight.value = systemInfo.statusBarHeight || 0
})
// 用户信息(模拟数据)
const userInfo = ref({
nickname: '茶艺师昵称',
avatar: '',
})
// 等级信息(模拟数据 - 5个等级 // 等级信息(模拟数据 - 5个等级
const levelList = ref([ const levelList = ref([
{ {
level: 1, level: 1,
performanceCommission: 50, performanceCommission: 50,
overtimeCommission: 55, overtimeCommission: 55,
currentPerformance: 150, currentPerformance: 150,
targetPerformance: 1000, targetPerformance: 1000,
remainingPerformance: 850, remainingPerformance: 850,
progressPercent: 0, progressPercent: 0,
icon: `${OSS}icon/icon_level1.png` icon: `${OSS}icon/icon_level1.png`
}, },
{ {
level: 2, level: 2,
performanceCommission: 60, performanceCommission: 60,
overtimeCommission: 65, overtimeCommission: 65,
currentPerformance: 300, currentPerformance: 300,
targetPerformance: 2000, targetPerformance: 2000,
remainingPerformance: 1700, remainingPerformance: 1700,
progressPercent: 0, progressPercent: 0,
icon: `${OSS}icon/icon_level2.png` icon: `${OSS}icon/icon_level2.png`
}, },
// { // {
// level: 3, // level: 3,
// performanceCommission: 70, // performanceCommission: 70,
// overtimeCommission: 75, // overtimeCommission: 75,
// currentPerformance: 1500, // currentPerformance: 1500,
// targetPerformance: 5000, // targetPerformance: 5000,
// remainingPerformance: 3500, // remainingPerformance: 3500,
// progressPercent: 0, // progressPercent: 0,
// icon: `${OSS}icon/icon_level3.png` // icon: `${OSS}icon/icon_level3.png`
// }, // },
// { // {
// level: 4, // level: 4,
// performanceCommission: 80, // performanceCommission: 80,
// overtimeCommission: 85, // overtimeCommission: 85,
// currentPerformance: 3000, // currentPerformance: 3000,
// targetPerformance: 10000, // targetPerformance: 10000,
// remainingPerformance: 7000, // remainingPerformance: 7000,
// progressPercent: 0, // progressPercent: 0,
// icon: `${OSS}icon/icon_level4.png` // icon: `${OSS}icon/icon_level4.png`
// }, // },
// { // {
// level: 5, // level: 5,
// performanceCommission: 90, // performanceCommission: 90,
// overtimeCommission: 95, // overtimeCommission: 95,
// currentPerformance: 8000, // currentPerformance: 8000,
// targetPerformance: 20000, // targetPerformance: 20000,
// remainingPerformance: 12000, // remainingPerformance: 12000,
// progressPercent: 0, // progressPercent: 0,
// icon: `${OSS}icon/icon_level5.png` // icon: `${OSS}icon/icon_level5.png`
// }, // },
]) ])
// 当前等级索引 // 当前等级索引
const currentLevelIndex = ref(1) // 默认显示第2个等级索引1 const currentLevelIndex = ref(1) // 默认显示第2个等级索引1
// 当前显示的等级信息(用于兼容旧代码) // 当前显示的等级信息(用于兼容旧代码)
const levelInfo = computed(() => levelList.value[currentLevelIndex.value]) const levelInfo = computed(() => levelList.value[currentLevelIndex.value])
// 今日订单列表(模拟数据) // 今日订单列表(模拟数据)
const todayOrders = ref<Array<any>>([ const todayOrders = ref<Array<any>>([
{ {
id: 1, id: 1,
date: '2025-09-21', date: '2025-09-21',
start_time: '15:00', start_time: '15:00',
end_time: '18:00', end_time: '18:00',
location: '苓苑共享茶室空间', location: '苓苑共享茶室空间',
address: '上海浦东新区新金桥路58号新银东大厦15楼F室', address: '上海浦东新区新金桥路58号新银东大厦15楼F室',
service_type: '到店服务', service_type: '到店服务',
status: '待服务', status: '待服务',
latitude: 31.2304, latitude: 31.2304,
longitude: 121.4737, longitude: 121.4737,
}, },
{ {
id: 2, id: 2,
date: '2025-09-22', date: '2025-09-22',
start_time: '15:00', start_time: '15:00',
end_time: '18:00', end_time: '18:00',
location: '苓苑共享茶室空间', location: '苓苑共享茶室空间',
address: '上海浦东新区新金桥路58号新银东大厦15楼F室', address: '上海浦东新区新金桥路58号新银东大厦15楼F室',
service_type: '到店服务', service_type: '到店服务',
status: '待服务', status: '待服务',
latitude: 31.2304, latitude: 31.2304,
longitude: 121.4737, longitude: 121.4737,
}, },
]) ])
// 公告列表(模拟数据) // 公告列表(模拟数据)
const announcements = ref<Array<any>>([ const announcements = ref<Array<any>>([
{ {
id: 1, id: 1,
title: '必备课,茶文化基础与通识,了解茶的起源?', title: '必备课,茶文化基础与通识,了解茶的起源?',
time: '2025-08-09 17:21', time: '2025-08-09 17:21',
image: `${OSS}images/banner1.png`, image: `${OSS}images/banner1.png`,
type: 'image', type: 'image',
}, },
{ {
id: 2, id: 2,
title: '行为举止要领,茶艺师职业礼仪与行茶举止规范?', title: '行为举止要领,茶艺师职业礼仪与行茶举止规范?',
time: '2025-08-09 17:21', time: '2025-08-09 17:21',
image: `${OSS}images/banner1.png`, image: `${OSS}images/banner1.png`,
type: 'video', type: 'video',
}, },
{ {
id: 3, id: 3,
title: '行为举止要领,茶艺师职业礼仪与行茶举止规范?', title: '行为举止要领,茶艺师职业礼仪与行茶举止规范?',
time: '2025-08-09 17:21', time: '2025-08-09 17:21',
image: `${OSS}images/banner1.png`, image: `${OSS}images/banner1.png`,
type: 'image', type: 'image',
}, },
{ {
id: 4, id: 4,
title: '行为举止要领,茶艺师职业礼仪与行茶举止规范?', title: '行为举止要领,茶艺师职业礼仪与行茶举止规范?',
time: '2025-08-09 17:21', time: '2025-08-09 17:21',
image: `${OSS}images/banner1.png`, image: `${OSS}images/banner1.png`,
type: 'image', type: 'image',
}, },
]) ])
onLoad(() => { onLoad(() => {
calculateProgress() calculateProgress()
})
// 计算进度百分比
function calculateProgress() {
levelList.value.forEach((level) => {
const { currentPerformance, targetPerformance } = level
level.progressPercent = Math.min((currentPerformance / targetPerformance) * 100, 100)
}) })
}
// 页面加载时计算进度 // 计算进度百分比
onMounted(() => { function calculateProgress() {
calculateProgress() levelList.value.forEach((level) => {
}) const { currentPerformance, targetPerformance } = level
level.progressPercent = Math.min((currentPerformance / targetPerformance) * 100, 100)
// 处理等级卡片滑动
function handleLevelScroll(e: any) {
// const scrollLeft = e.detail.scrollLeft
// const systemInfo = uni.getSystemInfoSync()
// // 每个卡片项的宽度100vw - 120rpx加上左右margin各30rpx
// // 1rpx = windowWidth / 750
// const rpxToPx = systemInfo.windowWidth / 750
// // 卡片宽度 + 左右margin = (100vw - 120rpx) + 60rpx = 100vw - 60rpx
// const itemWidthPx = systemInfo.windowWidth - (60 * rpxToPx)
// const index = Math.round(scrollLeft / itemWidthPx)
// if (index >= 0 && index < levelList.value.length) {
// currentLevelIndex.value = index
// }
}
// 格式化日期
function formatDate(dateStr: string, type: 'day' | 'month') {
if (!dateStr)
return ''
// 处理格式如 "2025-09-21" 的日期字符串
const parts = dateStr.split('-')
if (parts.length >= 3) {
if (type === 'day') {
return Number.parseInt(parts[2]).toString()
}
else {
return Number.parseInt(parts[1]).toString()
}
}
// 如果不是标准格式尝试使用Date对象解析
const date = new Date(dateStr)
if (!Number.isNaN(date.getTime())) {
if (type === 'day') {
return date.getDate().toString()
}
else {
return (date.getMonth() + 1).toString()
}
}
return ''
}
// 菜单点击
function handleMenuClick() {
console.log('菜单点击')
}
// 当前订单索引(用于指示点)
const currentOrderIndex = ref(0)
// 滚动事件处理
function handleScroll(e: any) {
const scrollLeft = e.detail.scrollLeft
const systemInfo = uni.getWindowInfo()
// 每个订单项的宽度100vw - 120rpx转换为 px
// 1rpx = windowWidth / 750
const rpxToPx = systemInfo.windowWidth / 750
const itemWidthPx = systemInfo.windowWidth - (120 * rpxToPx) + (20 * rpxToPx) // 加上间距
const index = Math.round(scrollLeft / itemWidthPx)
if (index >= 0 && index < todayOrders.value.length) {
currentOrderIndex.value = index
}
}
// 导航点击
function handleNavigate(order: any) {
if (order.latitude && order.longitude) {
uni.openLocation({
latitude: order.latitude,
longitude: order.longitude,
name: order.location,
address: order.address,
}) })
} }
}
// 更多公告 // 页面加载时计算进度
function handleMoreAnnouncement() { onMounted(() => {
console.log('更多公告') calculateProgress()
} })
// 公告点击 // 处理等级卡片滑动
function handleAnnouncementClick(item: any) { function handleLevelScroll(e: any) {
console.log('公告点击', item) // const scrollLeft = e.detail.scrollLeft
} // const systemInfo = uni.getSystemInfoSync()
// // 每个卡片项的宽度100vw - 120rpx加上左右margin各30rpx
// // 1rpx = windowWidth / 750
// const rpxToPx = systemInfo.windowWidth / 750
// // 卡片宽度 + 左右margin = (100vw - 120rpx) + 60rpx = 100vw - 60rpx
// const itemWidthPx = systemInfo.windowWidth - (60 * rpxToPx)
// const index = Math.round(scrollLeft / itemWidthPx)
// if (index >= 0 && index < levelList.value.length) {
// currentLevelIndex.value = index
// }
}
// 格式化日期
function formatDate(dateStr: string, type: 'day' | 'month') {
if (!dateStr)
return ''
// 处理格式如 "2025-09-21" 的日期字符串
const parts = dateStr.split('-')
if (parts.length >= 3) {
if (type === 'day') {
return Number.parseInt(parts[2]).toString()
}
else {
return Number.parseInt(parts[1]).toString()
}
}
// 如果不是标准格式尝试使用Date对象解析
const date = new Date(dateStr)
if (!Number.isNaN(date.getTime())) {
if (type === 'day') {
return date.getDate().toString()
}
else {
return (date.getMonth() + 1).toString()
}
}
return ''
}
// 菜单点击
function handleMenuClick() {
console.log('菜单点击')
}
// 当前订单索引(用于指示点)
const currentOrderIndex = ref(0)
// 滚动事件处理
function handleScroll(e: any) {
const scrollLeft = e.detail.scrollLeft
const systemInfo = uni.getWindowInfo()
// 每个订单项的宽度100vw - 120rpx转换为 px
// 1rpx = windowWidth / 750
const rpxToPx = systemInfo.windowWidth / 750
const itemWidthPx = systemInfo.windowWidth - (120 * rpxToPx) + (20 * rpxToPx) // 加上间距
const index = Math.round(scrollLeft / itemWidthPx)
if (index >= 0 && index < todayOrders.value.length) {
currentOrderIndex.value = index
}
}
// 导航点击
function handleNavigate(order: any) {
if (order.latitude && order.longitude) {
uni.openLocation({
latitude: order.latitude,
longitude: order.longitude,
name: order.location,
address: order.address,
})
}
}
// 更多公告
function handleMoreAnnouncement() {
console.log('更多公告')
}
// 公告点击
function handleAnnouncementClick(item: any) {
console.log('公告点击', item)
}
</script> </script>
<style lang="scss"> <style lang="scss">

View File

@ -106,10 +106,6 @@
}) })
/** 结束 **/ /** 结束 **/
/** 服务协议和隐私政策 **/
const agree = ref<boolean>(false)
/** 结束 **/
onLoad((args) => { onLoad((args) => {
// 从个人登录页面进入 // 从个人登录页面进入
if (args.type === 'edit') { if (args.type === 'edit') {
@ -122,13 +118,18 @@
}) })
const mobile = { const mobile = {
// 验证手机号 /**
* 验证手机号
* @param e
*/
handleInputMobile: (e: {value: string}) => { handleInputMobile: (e: {value: string}) => {
model.mobile = e.value model.mobile = e.value
disabled.value = !testMobile(model.mobile) disabled.value = !testMobile(model.mobile)
}, },
// 发送验证码 /**
* 发送验证码
*/
handleCountDown: () => { handleCountDown: () => {
if (disabled.value) { if (disabled.value) {
toast.show({ toast.show({
@ -147,7 +148,9 @@
}) })
}, },
// 验证码倒计时结束 /**
* 验证码倒计时结束
*/
handleFinishCountDown: () => { handleFinishCountDown: () => {
startCountDown.value = false startCountDown.value = false
}, },
@ -155,7 +158,6 @@
// 登录 // 登录
handleToLogin: () => { handleToLogin: () => {
// TODO 如果是edit的话就是修改手机号 // TODO 如果是edit的话就是修改手机号
if (!testMobile(model.mobile)) { if (!testMobile(model.mobile)) {
toast.show({ toast.show({
iconClass: 'info-circle', iconClass: 'info-circle',
@ -174,7 +176,7 @@
return return
} }
router.navigateTo('/pages/login/set-password') router.navigateTo(`/pages/login/set-password?type=${pageType}&mobile=${model.mobile}&userId=${userId.value}`)
}, },
// 获取手机号 // 获取手机号
@ -182,21 +184,6 @@
console.log("🚀 ~ e:", e) console.log("🚀 ~ e:", e)
}, },
handleAgree: (e: any) => {
console.log('e', e)
},
// 跳转到服务协议页面
handleToService: () => {
disabled.value = !disabled.value
console.log("🚀 ~ disabled:", disabled)
},
// 跳转到隐私政策页面
handleToPrivacy: () => {
},
// 修改手机成功后返回 // 修改手机成功后返回
handleToBack: () => { handleToBack: () => {
uni.navigateBack() uni.navigateBack()

View File

@ -20,37 +20,35 @@
<view class="font-400 text-30rpx text-[#606266] leading-44rpx">密码</view> <view class="font-400 text-30rpx text-[#606266] leading-44rpx">密码</view>
<view class="mt-20rpx"> <view class="mt-20rpx">
<wd-input <wd-input
v-model="model.mobile" v-model="model.password"
type="text" type="text"
placeholder="请输入密码" placeholder="请输入密码"
inputmode="numeric" inputmode="numeric"
no-border no-border
custom-class="!bg-[#F6F7F8] !border !border-solid !border-[#EAECF0] !rounded-16rpx" custom-class="!bg-[#F6F7F8] !border !border-solid !border-[#EAECF0] !rounded-16rpx"
custom-input-class="!px-32rpx !h-104rpx" custom-input-class="!px-32rpx !h-104rpx"
@input="mobile.handleInputMobile"
/> />
</view> </view>
</view> </view>
<view> <view class="mt-40rpx">
<view class="font-400 text-30rpx text-[#606266] leading-44rpx">再次确认</view> <view class="font-400 text-30rpx text-[#606266] leading-44rpx">再次确认</view>
<view class="mt-20rpx"> <view class="mt-20rpx">
<wd-input <wd-input
v-model="model.mobile" v-model="model.password_confirm"
type="text" type="text"
placeholder="再次确认新的密码" placeholder="再次确认新的密码"
inputmode="numeric" inputmode="numeric"
no-border no-border
custom-class="!bg-[#F6F7F8] !border !border-solid !border-[#EAECF0] !rounded-16rpx" custom-class="!bg-[#F6F7F8] !border !border-solid !border-[#EAECF0] !rounded-16rpx"
custom-input-class="!px-32rpx !h-104rpx" custom-input-class="!px-32rpx !h-104rpx"
@input="mobile.handleInputMobile"
/> />
</view> </view>
</view> </view>
</wd-form> </wd-form>
</view> </view>
<view class="h-90rpx leading-90rpx mx-60rpx rounded-8rpx text-center mt-112rpx bg-[#4C9F44] text-[#fff]" :class="disabled ? 'opacity-40' : ''" @click="mobile.handleToLogin">确定</view> <view class="h-90rpx leading-90rpx mx-60rpx rounded-8rpx text-center mt-112rpx bg-[#4C9F44] text-[#fff]" :class="disabled ? 'opacity-40' : ''" @click="Mobile.handleToLogin">确定</view>
<!-- 手机号修改成功 --> <!-- 手机号修改成功 -->
<wd-popup v-model="showEditSuccessPopup" lock-scroll custom-style="border-radius: 32rpx 32rpx 0rpx 0rpx;" position="bottom"> <wd-popup v-model="showEditSuccessPopup" lock-scroll custom-style="border-radius: 32rpx 32rpx 0rpx 0rpx;" position="bottom">
@ -62,7 +60,7 @@
</view> </view>
<view class="text-[#303133] text-36rpx leading-46rpx text-center mt-48rpx">密码修改成功</view> <view class="text-[#303133] text-36rpx leading-46rpx text-center mt-48rpx">密码修改成功</view>
<view class="text-[#9CA3AF] text-28rpx leading-44rpx mt-16rpx text-center">请记住你的登录密码</view> <view class="text-[#9CA3AF] text-28rpx leading-44rpx mt-16rpx text-center">请记住你的登录密码</view>
<view class="w-630rpx h-90rpx leading-90rpx text-center bg-[#4C9F44] rounded-8rpx text-[#fff] mt-174rpx mx-auto" @click="mobile.handleToBack">好的</view> <view class="w-630rpx h-90rpx leading-90rpx text-center bg-[#4C9F44] rounded-8rpx text-[#fff] mt-174rpx mx-auto" @click="router.reLaunch('/pages/login/login')">好的</view>
</view> </view>
</wd-popup> </wd-popup>
</view> </view>
@ -70,59 +68,34 @@
<script lang="ts" setup> <script lang="ts" setup>
import {mobile as testMobile} from '@/utils/test' import { mobile } from '@/utils/test'
import { useToast } from 'wot-design-uni' import { useToast } from 'wot-design-uni'
import { router } from '@/utils/tools'
import { resetPassword } from '@/api/user'
const OSS = inject('OSS') const OSS = inject('OSS')
const toast = useToast() const toast = useToast()
const disabled = ref<boolean>(true) const disabled = ref<boolean>(true)
/** 页面 **/ // 手机号修改成功弹窗
let pageType = 'login' // 页面类型 login:登录 edit:修改手机号 const showEditSuccessPopup = ref<boolean>(false)
const page = ref<{title: string, desc: string}>({title: '其他手机号登录', desc: '请输入你要登录的手机号'})
const showEditSuccessPopup = ref<boolean>(false) // 显示手机号修改成功弹窗
const userId = ref<number>(0) // 用户ID修改手机号时需要传
/** 验证码倒计时 **/ const model = ref({
const countDownTime = ref<number>(1 * 60 * 1000) // 60s倒计时
const startCountDown = ref<boolean>(false) // 是否开始倒计时
const countDown = ref<any>(null) // 倒计时组件
/** 表单相关 **/
const model = reactive<{
mobile: string
code: string
}>({
mobile: '', mobile: '',
code: '' code: '',
password: '',
password_confirm: ''
}) })
/** 结束 **/
/** 服务协议和隐私政策 **/
const agree = ref<boolean>(false)
/** 结束 **/
onLoad((args) => { onLoad((args) => {
// 从个人登录页面进入
if (args.type === 'edit') {
userId.value = Number(args.userId) || 0 // userId仅做测试使用实际请传真实用户ID
page.value.title = '修改手机号'
page.value.desc = '手机号一年内可修改2次'
pageType = 'edit'
}
}) })
const mobile = { const Mobile = {
// 验证手机号 // 重置密码
handleInputMobile: (e: {value: string}) => { handleToLogin: async () => {
model.mobile = e.value if (!mobile(model.value.mobile)) {
disabled.value = !testMobile(model.mobile)
},
// 发送验证码
handleCountDown: () => {
if (disabled.value) {
toast.show({ toast.show({
iconClass: 'info-circle', iconClass: 'info-circle',
msg: '手机号码错误请重新输入', msg: '手机号码错误请重新输入',
@ -131,74 +104,46 @@
return return
} }
startCountDown.value = true if (!model.value.code) {
nextTick(() => { toast.show({
countDown.value?.start() iconClass: 'info-circle',
msg: '验证码不存在',
direction: 'vertical'
})
return
}
// 发送验证码请求 if (!model.value.password) {
toast.show({
iconClass: 'info-circle',
msg: '请输入新密码',
direction: 'vertical'
})
return
}
if (model.value.password !== model.value.password_confirm) {
toast.show({
iconClass: 'info-circle',
msg: '两次输入密码不一致',
direction: 'vertical'
})
return
}
const res = await resetPassword({
mobile: model.value.mobile,
code: model.value.code,
password: model.value.password,
password_confirm: model.value.password_confirm
}) })
},
// 验证码倒计时结束
handleFinishCountDown: () => {
startCountDown.value = false
},
// 登录
handleToLogin: () => {
// TODO 如果是edit的话就是修改手机号
if (pageType === 'login' && !agree.value) {
toast.show({
iconClass: 'info-circle',
msg: '请同意服务协议和隐私政策',
direction: 'vertical'
})
return
}
if (!testMobile(model.mobile)) {
toast.show({
iconClass: 'info-circle',
msg: '手机号码错误请重新输入',
direction: 'vertical'
})
return
}
if (!model.code) {
toast.show({
iconClass: 'info-circle',
msg: '验证码错误',
direction: 'vertical'
})
return
}
},
// 获取手机号
handleGetPhoneNumber: (e: object) => {
console.log("🚀 ~ e:", e)
},
handleAgree: (e: any) => {
console.log('e', e)
},
// 跳转到服务协议页面
handleToService: () => {
disabled.value = !disabled.value
console.log("🚀 ~ disabled:", disabled)
},
// 跳转到隐私政策页面
handleToPrivacy: () => {
showEditSuccessPopup.value = true
}, },
// 修改手机成功后返回 // 修改手机成功后返回
handleToBack: () => { handleToBack: () => {
uni.navigateBack() router.navigateBack()
} }
} }
</script> </script>

View File

@ -15,14 +15,14 @@
<template #right> <template #right>
<view class="right-slot mr-16rpx flex items-center"> <view class="right-slot mr-16rpx flex items-center">
<!-- 消息图标带红点 --> <!-- 消息图标带红点 -->
<view class="nav-icon-item relative mr-30rpx" @click="router.navigateTo('/bundle/notice/notice')"> <!-- <view class="nav-icon-item relative mr-30rpx" @click="router.navigateTo('/bundle/notice/notice')">
<wd-img :src="`${OSS}icon/icon_notify.png`" width="36rpx" height="36rpx"></wd-img> <wd-img :src="`${OSS}icon/icon_notify.png`" width="36rpx" height="36rpx"></wd-img>
<view class="message-dot absolute right-6rpx top-10rpx h-16rpx w-16rpx border-2rpx border-[#fff] rounded-full border-solid bg-[#FF0000]" /> <view class="message-dot absolute right-6rpx top-10rpx h-16rpx w-16rpx border-2rpx border-[#fff] rounded-full border-solid bg-[#FF0000]" />
<text <text
class="icon-label text-20rpx text-[#606266] top-20rpx"> class="icon-label text-20rpx text-[#606266] top-20rpx">
消息 消息
</text> </text>
</view> </view> -->
<!-- 设置图标 --> <!-- 设置图标 -->
<view class="nav-icon-item relative mr-24rpx" @click="router.navigateTo('/bundle/store/setting')"> <view class="nav-icon-item relative mr-24rpx" @click="router.navigateTo('/bundle/store/setting')">
<wd-img :src="`${OSS}icon/icon_setting.png`" width="36rpx" height="36rpx"></wd-img> <wd-img :src="`${OSS}icon/icon_setting.png`" width="36rpx" height="36rpx"></wd-img>
@ -47,19 +47,19 @@
<view class="flex items-center"> <view class="flex items-center">
<!-- 头像 --> <!-- 头像 -->
<view class="avatar-wrapper"> <view class="avatar-wrapper">
<wd-img width="120rpx" height="120rpx" :src="`${OSS}images/chayishi/avatar.png`" <wd-img width="120rpx" height="120rpx" :src="userInfo.avatar || `${OSS}images/chayishi/avatar.png`"
mode="aspectFill" round /> mode="aspectFill" round />
</view> </view>
<!-- 昵称和账号 --> <!-- 昵称和账号 -->
<view class="ml-22rpx flex-1" @click="router.navigateTo('/bundle/profile/profile')"> <view class="ml-22rpx flex-1" @click="My.handleToProfile">
<view class="flex items-center"> <view class="flex items-center">
<text class="nickname text-36rpx text-[#303133] font-bold leading-50rpx">Jasmine</text> <text class="nickname text-36rpx text-[#303133] font-bold leading-50rpx">{{ userInfo.nickname || '请登录' }}</text>
<view> <view>
<wd-icon name="arrow-right" size="24rpx" color="#303133" class="ml-8rpx" /> <wd-icon name="arrow-right" size="24rpx" color="#303133" class="ml-8rpx" />
</view> </view>
</view> </view>
<view class="mt-8rpx text-24rpx text-[#303133] leading-34rpx"> <view class="mt-8rpx text-24rpx text-[#303133] leading-34rpx" v-if="userInfo.account">
账号: 152****3412 账号: {{ hidePhoneMiddle(userInfo.account) }}
</view> </view>
</view> </view>
</view> </view>
@ -86,7 +86,7 @@
<!-- 可提现金额 --> <!-- 可提现金额 -->
<view class="flex-1 text-center"> <view class="flex-1 text-center">
<view class=""> <view class="">
<price-format color="#000000" :first-size="32" :second-size="32" :subscript-size="20" :price="23.02"></price-format> <price-format color="#000000" :first-size="32" :second-size="32" :subscript-size="20" :price="otherInfo.user_money"></price-format>
</view> </view>
<view class="mt-8rpx text-24rpx text-[#909399] leading-34rpx"> <view class="mt-8rpx text-24rpx text-[#909399] leading-34rpx">
可提现金额 可提现金额
@ -95,7 +95,7 @@
<!-- 不可提现金额 --> <!-- 不可提现金额 -->
<view class="flex-1 text-center"> <view class="flex-1 text-center">
<view> <view>
<price-format color="#000000" :first-size="32" :second-size="32" :subscript-size="20" :price="23.02"></price-format> <price-format color="#000000" :first-size="32" :second-size="32" :subscript-size="20" :price="otherInfo.no_reflect_amount"></price-format>
</view> </view>
<view class="mt-8rpx text-24rpx text-[#909399] leading-34rpx"> <view class="mt-8rpx text-24rpx text-[#909399] leading-34rpx">
不可提现金额 不可提现金额
@ -117,12 +117,12 @@
}" class="work-schedule-card mx-30rpx mt-30rpx rounded-24rpx bg-white p-30rpx"> }" class="work-schedule-card mx-30rpx mt-30rpx rounded-24rpx bg-white p-30rpx">
<!-- 标题和免费出行按钮 --> <!-- 标题和免费出行按钮 -->
<view class="mb-24rpx flex items-center justify-between"> <view class="mb-24rpx flex items-center justify-between">
<view class="flex items-center"> <view class="flex items-center" v-if="otherInfo.is_mileage == 1">
<wd-img width="32rpx" height="32rpx" :src="`${OSS}images/chayishi/work_task.png`" <wd-img width="32rpx" height="32rpx" :src="`${OSS}images/chayishi/work_task.png`"
class="mr-12rpx" /> class="mr-12rpx" />
<text class="text-32rpx text-[#303133] font-bold">上班安排</text> <text class="text-32rpx text-[#303133] font-bold">上班安排</text>
</view> </view>
<view @click="My.handleFreeTravel"> <view @click="My.handleFreeTravel" v-if="otherInfo.is_mileage == 0">
<wd-img width="180rpx" height="64rpx" :src="`${OSS}images/chayishi/free_go.png`" <wd-img width="180rpx" height="64rpx" :src="`${OSS}images/chayishi/free_go.png`"
class="mr-12rpx" /> class="mr-12rpx" />
</view> </view>
@ -144,17 +144,17 @@
<!-- 工作日 --> <!-- 工作日 -->
<view class="schedule-item mb-20rpx flex items-center"> <view class="schedule-item mb-20rpx flex items-center">
<text class="label-text w-140rpx text-24rpx text-[#606266] leading-40rpx">工作日:</text> <text class="label-text w-140rpx text-24rpx text-[#606266] leading-40rpx">工作日:</text>
<text class="flex-1 text-24rpx text-[#303133] leading-40rpx">周一,周二,周三,周四,周五,周六</text> <text class="flex-1 text-24rpx text-[#303133] leading-40rpx">{{ otherInfo.work || '-' }}</text>
</view> </view>
<!-- 工作时间 --> <!-- 工作时间 -->
<view class="schedule-item mb-20rpx flex items-center"> <view class="schedule-item mb-20rpx flex items-center">
<text class="label-text w-140rpx text-24rpx text-[#606266] leading-40rpx">工作时间:</text> <text class="label-text w-140rpx text-24rpx text-[#606266] leading-40rpx">工作时间:</text>
<text class="flex-1 text-24rpx text-[#303133] leading-40rpx">08:00~20:00</text> <text class="flex-1 text-24rpx text-[#303133] leading-40rpx">{{ otherInfo.work_time }}</text>
</view> </view>
<!-- 住址 --> <!-- 住址 -->
<view class="schedule-item flex items-start"> <view class="schedule-item flex items-start">
<text class="label-text w-140rpx pt-4rpx text-24rpx text-[#606266] leading-40rpx">住址:</text> <text class="label-text w-140rpx pt-4rpx text-24rpx text-[#606266] leading-40rpx">住址:</text>
<text class="flex-1 text-24rpx text-[#303133] leading-40rpx">上海浦东新区新金桥路58号新银东大厦15楼F室</text> <text class="flex-1 text-24rpx text-[#303133] leading-40rpx">{{ otherInfo.address || '-' }}</text>
</view> </view>
<!-- 上下班状态 --> <!-- 上下班状态 -->
<view class="schedule-item flex items-center mt-20rpx"> <view class="schedule-item flex items-center mt-20rpx">
@ -253,82 +253,127 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { router } from '@/utils/tools' import { router, hidePhoneMiddle } from '@/utils/tools'
import { useUserStore } from '@/store'
import { getUserInfo } from '@/api/user'
const OSS = inject('OSS') const OSS = inject('OSS')
const navbarHeight = inject('navbarHeight') const navbarHeight = inject('navbarHeight')
const rightPadding = inject('capsuleOffset') const rightPadding = inject('capsuleOffset')
// 上下班切换 // 用户信息
const isWork = ref<boolean>(true) const userStore = useUserStore()
const userInfo = userStore.userInfo
const otherInfo = ref<{
user_money: number // 可提现金额
no_reflect_amount: number // 不可提现金额
work: string // 工作日
address: string // 住址
work_time: string // 工作时间
is_mileage: number // 是否开启里程
}>({
user_money: 0,
no_reflect_amount: 0,
work: '',
address: '',
work_time: '',
is_mileage: 0
})
// 模拟是否有个人信息静态页面后续可以替换为实际的API判断 // 上下班切换
const hasProfileInfo = ref(true) // 改为 false 可以测试跳转到填写页面 const isWork = ref<boolean>(true)
const My = { // 模拟是否有个人信息静态页面后续可以替换为实际的API判断
// 跳转到消息页面 const hasProfileInfo = ref(true) // 改为 false 可以测试跳转到填写页面
handleToMessage: () => {
// TODO: 跳转到消息页面
console.log('跳转到消息页面')
},
// 跳转到设置页面
handleToSettings: () => {
// TODO: 跳转到设置页面
console.log('跳转到设置页面')
},
// 跳转到个人信息 onShow(() => {
handleToProfile: () => { My.handleGetUserInfo()
// TODO: 跳转到个人信息页面 })
console.log('跳转到个人信息页面')
},
// 跳转到提现页面 const My = {
handleToWithdraw: () => { /**
// TODO: 跳转到提现页面 * 获取个人信息
console.log('跳转到提现页面') */
}, handleGetUserInfo: async () => {
const res = await getUserInfo()
otherInfo.value = res
},
// 免费出行 /**
handleFreeTravel: () => { * 跳转到消息页面
// TODO: 免费出行功能 */
console.log('免费出行') handleToMessage: () => {
}, // TODO: 跳转到消息页面
console.log('跳转到消息页面')
},
// 服务点击事件 /**
handleServiceClick: (type: string) => { * 跳转到设置页面
if (type === 'profile') { */
// 如果有个人信息,跳转到展示页面;否则跳转到填写页面 handleToSettings: () => {
if (hasProfileInfo.value) { // TODO: 跳转到设置页面
router.navigateTo('/pages/my/profile-display') console.log('跳转到设置页面')
},
/**
* 跳转到个人信息
*/
handleToProfile: () => {
// TODO: 跳转到个人信息页面
console.log('跳转到个人信息页面')
if (userStore.isLoggedIn) {
router.navigateTo('/bundle/profile/profile')
} else {
router.navigateTo('/pages/login/login')
}
},
// 跳转到提现页面
handleToWithdraw: () => {
// TODO: 跳转到提现页面
console.log('跳转到提现页面')
},
// 免费出行
handleFreeTravel: () => {
// TODO: 免费出行功能
console.log('免费出行')
},
// 服务点击事件
handleServiceClick: (type: string) => {
if (type === 'profile') {
// 如果有个人信息,跳转到展示页面;否则跳转到填写页面
if (hasProfileInfo.value) {
router.navigateTo('/pages/my/profile-display')
}
else {
router.navigateTo('/pages/my/profile-edit')
}
}
else if (type === 'service') {
// 跳转到服务方式页面
router.navigateTo('/pages/my/service-method')
}
else if (type === 'worktime') {
// 跳转到工作时间页面
router.navigateTo('/pages/my/work-time')
}
else if (type === 'upload') {
// 跳转到上传资料页面
router.navigateTo('/pages/my/upload-data')
}
else if (type === 'record') {
// 跳转到行程记录页面
router.navigateTo('/pages/my/travel-record')
} }
else { else {
router.navigateTo('/pages/my/profile-edit') // TODO: 根据类型跳转到对应页面
console.log('点击服务:', type)
} }
} },
else if (type === 'service') { }
// 跳转到服务方式页面
router.navigateTo('/pages/my/service-method')
}
else if (type === 'worktime') {
// 跳转到工作时间页面
router.navigateTo('/pages/my/work-time')
}
else if (type === 'upload') {
// 跳转到上传资料页面
router.navigateTo('/pages/my/upload-data')
}
else if (type === 'record') {
// 跳转到行程记录页面
router.navigateTo('/pages/my/travel-record')
}
else {
// TODO: 根据类型跳转到对应页面
console.log('点击服务:', type)
}
},
}
</script> </script>

View File

@ -1,8 +1,8 @@
import type { IUserInfoVo } from '@/api/types/login' import type { IUserInfoVo } from '@/api/types/login'
import { defineStore } from 'pinia' import { defineStore } from 'pinia'
import { ref } from 'vue' import { ref } from 'vue'
import { getUserInfo as _getUserInfo } from '@/api/user'
import { import {
getUserInfo as _getUserInfo,
login as _login, login as _login,
logout as _logout, logout as _logout,
wxLogin as _wxLogin, wxLogin as _wxLogin,

View File

@ -158,3 +158,11 @@ export function getCurrentDate() {
return `${year}-${month}-${day}`; return `${year}-${month}-${day}`;
} }
/**
* 隐藏手机号中间四位
* @param phone 手机号
* @returns 隐藏中间四位的手机号
*/
export function hidePhoneMiddle(phone: string): string {
return phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2');
}