Merge remote-tracking branch 'origin/develop' into develop_mzh
This commit is contained in:
commit
e2653a3674
11
env/.env
vendored
11
env/.env
vendored
@ -7,9 +7,14 @@ VITE_WX_APPID='wxa2abb91f64032a2b'
|
||||
# h5部署网站的base,配置到 manifest.config.ts 里的 h5.router.base
|
||||
VITE_APP_PUBLIC_BASE=/
|
||||
|
||||
VITE_SERVER_BASEURL='https://ukw0y1.laf.run'
|
||||
VITE_UPLOAD_BASEURL='https://ukw0y1.laf.run/upload'
|
||||
|
||||
# h5是否需要配置代理
|
||||
VITE_APP_PROXY=false
|
||||
VITE_APP_PROXY_PREFIX='/api'
|
||||
|
||||
VITE_SERVER_BASEURL='https://dev.work.star-lock.cn/api'
|
||||
|
||||
VITE_APP_ENV='XHJ_DEV'
|
||||
|
||||
VITE_APP_VERSION='1.0.0'
|
||||
VITE_APP_BUILD_NUMBER=1
|
||||
|
||||
|
||||
6
env/.env.development → env/.env.sky_dev
vendored
6
env/.env.development → env/.env.sky_dev
vendored
@ -4,3 +4,9 @@ NODE_ENV='development'
|
||||
VITE_DELETE_CONSOLE=false
|
||||
# 是否开启sourcemap
|
||||
VITE_SHOW_SOURCEMAP=true
|
||||
|
||||
VITE_SERVER_BASEURL='https://dev.work.star-lock.cn'
|
||||
|
||||
VITE_APP_TITLE='斯凯签勤_DEV'
|
||||
|
||||
VITE_APP_ENV='SKY_DEV'
|
||||
6
env/.env.test → env/.env.sky_pre
vendored
6
env/.env.test → env/.env.sky_pre
vendored
@ -2,3 +2,9 @@
|
||||
NODE_ENV='development'
|
||||
# 是否去除console 和 debugger
|
||||
VITE_DELETE_CONSOLE=false
|
||||
|
||||
VITE_SERVER_BASEURL='https://pre.work.star-lock.cn'
|
||||
|
||||
VITE_APP_TITLE='斯凯签勤_PRE'
|
||||
|
||||
VITE_APP_ENV='SKY_PRE'
|
||||
12
env/.env.sky_release
vendored
Normal file
12
env/.env.sky_release
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
# 变量必须以 VITE_ 为前缀才能暴露给外部读取
|
||||
NODE_ENV='development'
|
||||
# 是否去除console 和 debugger
|
||||
VITE_DELETE_CONSOLE=true
|
||||
# 是否开启sourcemap
|
||||
VITE_SHOW_SOURCEMAP=false
|
||||
|
||||
VITE_SERVER_BASEURL='https://pre.work.star-lock.cn'
|
||||
|
||||
VITE_APP_TITLE='斯凯签勤'
|
||||
|
||||
VITE_APP_ENV='SKY'
|
||||
12
env/.env.xhj_dev
vendored
Normal file
12
env/.env.xhj_dev
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
# 变量必须以 VITE_ 为前缀才能暴露给外部读取
|
||||
NODE_ENV='development'
|
||||
# 是否去除console 和 debugger
|
||||
VITE_DELETE_CONSOLE=false
|
||||
# 是否开启sourcemap
|
||||
VITE_SHOW_SOURCEMAP=true
|
||||
|
||||
VITE_SERVER_BASEURL='https://dev.work.star-lock.cn'
|
||||
|
||||
VITE_APP_TITLE='星星勤务_DEV'
|
||||
|
||||
VITE_APP_ENV='XHJ_DEV'
|
||||
10
env/.env.xhj_pre
vendored
Normal file
10
env/.env.xhj_pre
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
# 变量必须以 VITE_ 为前缀才能暴露给外部读取
|
||||
NODE_ENV='development'
|
||||
# 是否去除console 和 debugger
|
||||
VITE_DELETE_CONSOLE=false
|
||||
|
||||
VITE_SERVER_BASEURL='https://pre.work.star-lock.cn'
|
||||
|
||||
VITE_APP_TITLE='星星勤务_PRE'
|
||||
|
||||
VITE_APP_ENV='XHJ_PRE'
|
||||
7
env/.env.production → env/.env.xhj_release
vendored
7
env/.env.production → env/.env.xhj_release
vendored
@ -4,3 +4,10 @@ NODE_ENV='development'
|
||||
VITE_DELETE_CONSOLE=true
|
||||
# 是否开启sourcemap
|
||||
VITE_SHOW_SOURCEMAP=false
|
||||
|
||||
|
||||
VITE_SERVER_BASEURL='https://work.star-lock.cn'
|
||||
|
||||
VITE_APP_TITLE='星星勤务'
|
||||
|
||||
VITE_APP_ENV='XHJ'
|
||||
@ -7,6 +7,12 @@
|
||||
"pnpm": ">=7.30"
|
||||
},
|
||||
"scripts": {
|
||||
"build:app-android-xhj_dev": "uni build -p app-android --mode xhj_dev",
|
||||
"build:app-android-sky_dev": "uni build -p app-android --mode sky_dev",
|
||||
"build:app-android-xhj_pre": "uni build -p app-android --mode xhj_pre",
|
||||
"build:app-android-sky_pre": "uni build -p app-android --mode sky_pre",
|
||||
"build:app-android-xhj_release": "uni build -p app-android --mode xhj_release",
|
||||
"build:app-android-sky_release": "uni build -p app-android --mode sky_release",
|
||||
"preinstall": "npx only-allow pnpm",
|
||||
"uvm": "npx @dcloudio/uvm@latest",
|
||||
"uvm-rm": "node ./scripts/postupgrade.js",
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
export const phoneRegExp = /^1[3-9]\d{9}$/
|
||||
|
||||
export const passwordRegExp = /^(?![0-9]+$)(?![a-zA-Z]+$)(?![^0-9a-zA-Z]+$).{8,20}$/
|
||||
5
src/constants/regular-expressions.ts
Normal file
5
src/constants/regular-expressions.ts
Normal file
@ -0,0 +1,5 @@
|
||||
export const phoneRegExp: RegExp = /^1[3-9]\d{9}$/
|
||||
|
||||
export const passwordRegExp: RegExp = /^(?![0-9]+$)(?![a-zA-Z]+$)(?![^0-9a-zA-Z]+$).{8,20}$/
|
||||
|
||||
export const codeRegExp: RegExp = /^[0-9]{6}$/
|
||||
48
src/constants/result.ts
Normal file
48
src/constants/result.ts
Normal file
@ -0,0 +1,48 @@
|
||||
export class Result {
|
||||
static codes = {
|
||||
Success: 0,
|
||||
Fail: -1,
|
||||
NotMore: -2,
|
||||
PaySuccessful: 10003
|
||||
}
|
||||
|
||||
static resultsMap = new Map([
|
||||
[Result.codes.Success, { message: '成功', data: {} }],
|
||||
[Result.codes.Fail, { message: '网络加载失败', data: {} }],
|
||||
[Result.codes.NotMore, { message: '没有更多', data: {} }],
|
||||
[Result.codes.PaySuccessful, { message: '支付成功', data: {} }]
|
||||
])
|
||||
|
||||
constructor(code, data, message) {
|
||||
const result = Result.resultsMap.get(code)
|
||||
if (result) {
|
||||
this.code = code
|
||||
this.message = message || result.message
|
||||
this.data = data || result.data
|
||||
} else {
|
||||
this.code = code
|
||||
this.message = message || ''
|
||||
this.data = data || {}
|
||||
}
|
||||
}
|
||||
|
||||
// 成功
|
||||
static get Success() {
|
||||
return new Result(Result.codes.Success)
|
||||
}
|
||||
|
||||
// 失败(默认错误)
|
||||
static get Fail() {
|
||||
return new Result(Result.codes.Fail)
|
||||
}
|
||||
|
||||
// 没有更多
|
||||
static get NotMore() {
|
||||
return new Result(Result.codes.NotMore)
|
||||
}
|
||||
|
||||
// 支付成功
|
||||
static get PaySuccessful() {
|
||||
return new Result(Result.codes.PaySuccessful)
|
||||
}
|
||||
}
|
||||
@ -17,7 +17,6 @@ const baseUrl = getEnvBaseUrl()
|
||||
const httpInterceptor = {
|
||||
// 拦截前触发
|
||||
invoke(options: CustomRequestOptions) {
|
||||
// 接口请求支持通过 query 参数配置 queryString
|
||||
if (options.query) {
|
||||
const queryStr = qs.stringify(options.query)
|
||||
if (options.url.includes('?')) {
|
||||
@ -26,7 +25,6 @@ const httpInterceptor = {
|
||||
options.url += `?${queryStr}`
|
||||
}
|
||||
}
|
||||
// 非 http 开头需拼接地址
|
||||
if (!options.url.startsWith('http')) {
|
||||
// #ifdef H5
|
||||
// console.log(__VITE_APP_PROXY__)
|
||||
@ -42,16 +40,13 @@ const httpInterceptor = {
|
||||
// #endif
|
||||
// TIPS: 如果需要对接多个后端服务,也可以在这里处理,拼接成所需要的地址
|
||||
}
|
||||
// 1. 请求超时
|
||||
options.timeout = 10000 // 10s
|
||||
// 2. (可选)添加小程序端请求头标识
|
||||
options.timeout = 3000
|
||||
options.header = {
|
||||
platform, // 可选,与 uniapp 定义的平台一致,告诉后台来源
|
||||
platform,
|
||||
version: import.meta.env.VITE_APP_VERSION + '+' + import.meta.env.VITE_APP_BUILD_NUMBER,
|
||||
...options.header
|
||||
}
|
||||
// 3. 添加 token 请求头标识
|
||||
const userStore = useUserStore()
|
||||
const { token } = userStore.userInfo as unknown as IUserInfo
|
||||
const token = uni.getStorageSync('token')
|
||||
if (token) {
|
||||
options.header.Authorization = `Bearer ${token}`
|
||||
}
|
||||
|
||||
@ -38,6 +38,14 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { codeLoginApi, CodeLoginRequest } from '@/service/user'
|
||||
import { PlatId } from '@/typings'
|
||||
import { Result } from '@/constants/result'
|
||||
import { useBasicStore, useUserStore } from '@/store'
|
||||
|
||||
const $basic = useBasicStore()
|
||||
const $user = useUserStore()
|
||||
|
||||
const phone = ref<string>('')
|
||||
|
||||
const code = ref<string>('')
|
||||
@ -48,6 +56,12 @@
|
||||
|
||||
const type = ref<string>('')
|
||||
|
||||
const systemInfo = ref<GetSystemInfoResult>(null)
|
||||
|
||||
onMounted(async () => {
|
||||
systemInfo.value = await $basic.getSystemInfo()
|
||||
})
|
||||
|
||||
onLoad(async options => {
|
||||
phone.value = options.phone
|
||||
type.value = options.type
|
||||
@ -55,14 +69,53 @@
|
||||
countDownStart()
|
||||
})
|
||||
|
||||
watch(code, newVal => {
|
||||
watch(code, async newVal => {
|
||||
if (newVal.length === 6) {
|
||||
// 校验验证码
|
||||
if (type.value === 'login') {
|
||||
console.log('login')
|
||||
await uni.showLoading({
|
||||
title: '登录中',
|
||||
mask: true
|
||||
})
|
||||
try {
|
||||
const result = await codeLoginApi<CodeLoginRequest>({
|
||||
platId: PlatId.app,
|
||||
phone: phone.value,
|
||||
verificationCode: code.value,
|
||||
deviceInfo: {
|
||||
deviceNo: systemInfo.value?.deviceId,
|
||||
deviceName: `${systemInfo.value?.deviceBrand} ${systemInfo.value?.deviceModel}`,
|
||||
deviceBrand: systemInfo.value?.deviceBrand,
|
||||
deviceModel: systemInfo.value?.deviceModel
|
||||
}
|
||||
})
|
||||
uni.hideLoading()
|
||||
if (result.errorCode === Result.Success.code) {
|
||||
uni.setStorageSync('token', result.data.token)
|
||||
$user.getUserInfo()
|
||||
await uni.switchTab({
|
||||
url: '/pages/home/home'
|
||||
})
|
||||
await uni.showToast({
|
||||
title: '登录成功',
|
||||
icon: 'none'
|
||||
})
|
||||
} else {
|
||||
await uni.showToast({
|
||||
title: result.errorMsg,
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
uni.hideLoading()
|
||||
await uni.showToast({
|
||||
title: '登录失败,请稍后再试',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
} else if (type.value === 'reset-password') {
|
||||
uni.navigateTo({
|
||||
url: `/pages/reset-password/reset-password`
|
||||
await uni.redirectTo({
|
||||
url: `/pages/reset-password/reset-password?phone=${phone.value}&code=${code.value}`
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,6 +32,9 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { phoneRegExp } from '@/constants/regular-expressions'
|
||||
import { AccountChannel, CodeType, IResData } from '@/typings'
|
||||
import { getCodeApi, UserGetCodeRequest } from '@/service/user'
|
||||
import { Result } from '@/constants/result'
|
||||
|
||||
const phone = ref<string>('')
|
||||
const phonePass = computed(() => phoneRegExp.test(phone.value))
|
||||
@ -42,18 +45,42 @@
|
||||
}
|
||||
})
|
||||
|
||||
const codeLogin = () => {
|
||||
const codeLogin = async () => {
|
||||
if (!phonePass.value) {
|
||||
return
|
||||
}
|
||||
uni.navigateTo({
|
||||
url: `/pages/code/code?phone=${phone.value}&type=reset-password`
|
||||
await uni.showLoading({
|
||||
title: '加载中',
|
||||
mask: true
|
||||
})
|
||||
try {
|
||||
const result: IResData = await getCodeApi<UserGetCodeRequest>({
|
||||
account: phone.value,
|
||||
channel: AccountChannel.phone,
|
||||
codeType: CodeType.reset
|
||||
})
|
||||
uni.hideLoading()
|
||||
if (result.errorCode === Result.Success.code) {
|
||||
await uni.navigateTo({
|
||||
url: `/pages/reset-password/reset-password?phone=${phone.value}`
|
||||
})
|
||||
} else {
|
||||
await uni.showToast({
|
||||
title: result.errorMsg,
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
uni.hideLoading()
|
||||
await uni.showToast({
|
||||
title: '获取验证码失败,请稍后再试',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const phoneChange = (value: string) => {
|
||||
phone.value = value
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
|
||||
@ -39,7 +39,7 @@
|
||||
|
||||
const tab = ref<number>(0)
|
||||
|
||||
const props = defineProps({
|
||||
defineProps({
|
||||
list: {
|
||||
type: Array<HomeTab>,
|
||||
required: true
|
||||
|
||||
@ -8,24 +8,24 @@
|
||||
</route>
|
||||
<template>
|
||||
<view class="custom-bg-default">
|
||||
<TopNavigation :title="appName"></TopNavigation>
|
||||
<button class="mt-12" @click="toLogin">去登录</button>
|
||||
<CustomTab class="mt-10" :list="featuresList" @clickItem="clickItem"></CustomTab>
|
||||
<view class="pt-10">
|
||||
<CustomTabBar :list="list" :default-index="1" @change="change"></CustomTabBar>
|
||||
<view v-if="$user.loginStatus">
|
||||
<CustomTab class="mt-10" :list="featuresList" @clickItem="clickItem"></CustomTab>
|
||||
<button class="mt-12" @click="$user.logout">退出登录</button>
|
||||
</view>
|
||||
<view v-else>
|
||||
<button class="mt-12" @click="toLogin">去登录</button>
|
||||
</view>
|
||||
<view @click="handleClick">考勤</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useUserStore } from '@/store'
|
||||
import CustomTab from '@/pages/home/CustomTab.vue'
|
||||
import { useUserStore } from '@/store'
|
||||
import { Result } from '@/constants/result'
|
||||
|
||||
const $user = useUserStore()
|
||||
|
||||
const appName = import.meta.env.VITE_APP_TITLE
|
||||
|
||||
const list = ref<Array<TabBarItem>>([
|
||||
{
|
||||
title: '首页',
|
||||
@ -222,19 +222,20 @@
|
||||
}
|
||||
])
|
||||
|
||||
// 测试 uni API 自动引入
|
||||
onLoad(() => {
|
||||
$user.setUserInfo({ nickname: '1', avatar: '1', token: '1' })
|
||||
|
||||
console.log($user.userInfo.nickname)
|
||||
})
|
||||
|
||||
const change = data => {
|
||||
console.log(data.value)
|
||||
if (data.value === 3) {
|
||||
list.value[data.value].value = 0
|
||||
onMounted(async () => {
|
||||
const tokenStorage: string = uni.getStorageSync('token')
|
||||
if (tokenStorage) {
|
||||
const result: boolean = await $user.getUserInfo()
|
||||
if (result.code === Result.Success.code) {
|
||||
console.log('获取用户信息成功')
|
||||
} else {
|
||||
await uni.showToast({
|
||||
title: result.message,
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const toLogin = () => {
|
||||
uni.navigateTo({
|
||||
|
||||
@ -146,12 +146,20 @@
|
||||
</text>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useBasicStore } from '@/store'
|
||||
import { useBasicStore, useUserStore } from '@/store'
|
||||
import { passwordRegExp, phoneRegExp } from '@/constants/regular-expressions'
|
||||
import {
|
||||
getCodeApi,
|
||||
passwordLoginApi,
|
||||
PasswordLoginRequest,
|
||||
UserGetCodeRequest
|
||||
} from '@/service/user'
|
||||
import { AccountChannel, CodeType, IResData, PlatId } from '@/typings'
|
||||
import { Result } from '@/constants/result'
|
||||
|
||||
const $basic = useBasicStore()
|
||||
const $user = useUserStore()
|
||||
|
||||
const appName = import.meta.env.VITE_APP_TITLE
|
||||
|
||||
@ -176,7 +184,7 @@
|
||||
systemInfo.value = await $basic.getSystemInfo()
|
||||
})
|
||||
|
||||
const passwordLogin = () => {
|
||||
const passwordLogin = async () => {
|
||||
if (!phonePass.value || !passwordPass.value) {
|
||||
return
|
||||
}
|
||||
@ -185,10 +193,50 @@
|
||||
agreementModal.value.showModal()
|
||||
return
|
||||
}
|
||||
console.log('登录')
|
||||
await uni.showLoading({
|
||||
title: '登录中',
|
||||
mask: true
|
||||
})
|
||||
try {
|
||||
const result = await passwordLoginApi<PasswordLoginRequest>({
|
||||
platId: PlatId.app,
|
||||
username: phone.value,
|
||||
password: password.value,
|
||||
deviceInfo: {
|
||||
deviceNo: systemInfo.value?.deviceId,
|
||||
deviceName: `${systemInfo.value?.deviceBrand} ${systemInfo.value?.deviceModel}`,
|
||||
deviceBrand: systemInfo.value?.deviceBrand,
|
||||
deviceModel: systemInfo.value?.deviceModel
|
||||
}
|
||||
})
|
||||
uni.hideLoading()
|
||||
if (result.errorCode === Result.Success.code) {
|
||||
uni.setStorageSync('token', result.data.token)
|
||||
$user.getUserInfo()
|
||||
await uni.switchTab({
|
||||
url: '/pages/home/home'
|
||||
})
|
||||
await uni.showToast({
|
||||
title: '登录成功',
|
||||
icon: 'none'
|
||||
})
|
||||
} else {
|
||||
await uni.showToast({
|
||||
title: result.errorMsg,
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
uni.hideLoading()
|
||||
await uni.showToast({
|
||||
title: '获取验证码失败,请稍后再试',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const codeLogin = () => {
|
||||
const codeLogin = async () => {
|
||||
if (!phonePass.value) {
|
||||
return
|
||||
}
|
||||
@ -197,9 +245,35 @@
|
||||
agreementModal.value.showModal()
|
||||
return
|
||||
}
|
||||
uni.navigateTo({
|
||||
url: `/pages/code/code?phone=${phone.value}&type=login`
|
||||
await uni.showLoading({
|
||||
title: '加载中',
|
||||
mask: true
|
||||
})
|
||||
try {
|
||||
const result: IResData = await getCodeApi<UserGetCodeRequest>({
|
||||
account: phone.value,
|
||||
channel: AccountChannel.phone,
|
||||
codeType: CodeType.login
|
||||
})
|
||||
uni.hideLoading()
|
||||
if (result.errorCode === Result.Success.code) {
|
||||
await uni.navigateTo({
|
||||
url: `/pages/code/code?phone=${phone.value}&type=login`
|
||||
})
|
||||
} else {
|
||||
await uni.showToast({
|
||||
title: result.errorMsg,
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
uni.hideLoading()
|
||||
await uni.showToast({
|
||||
title: '获取验证码失败,请稍后再试',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const resetPassword = () => {
|
||||
|
||||
@ -9,8 +9,29 @@
|
||||
<template>
|
||||
<view>
|
||||
<TopNavigation></TopNavigation>
|
||||
<view class="text-6 ml-4 pt-7 custom-color-black font-bold">请输入手机号</view>
|
||||
<view class="text-6 ml-4 pt-7 custom-color-black font-bold">设置新密码</view>
|
||||
<view class="text-3.5 ml-4 mt-2 mb-2 custom-color-grey">
|
||||
<view>已发送验证码至{{ maskedPhone }}</view>
|
||||
</view>
|
||||
<view class="p-5">
|
||||
<wd-input
|
||||
v-model="code"
|
||||
:maxlength="6"
|
||||
class="mt-6"
|
||||
type="number"
|
||||
placeholder="请输入验证码"
|
||||
placeholderClass="text-4 custom-color-grey"
|
||||
size="large"
|
||||
@change="codeChange"
|
||||
use-suffix-slot
|
||||
>
|
||||
<template #suffix>
|
||||
<view v-if="countDown > 0" class="text-4 custom-color-grey">
|
||||
{{ countDown }}s后重新获取
|
||||
</view>
|
||||
<view v-else class="text-4 custom-color-blue" @click="getCode">重新获取</view>
|
||||
</template>
|
||||
</wd-input>
|
||||
<wd-input
|
||||
v-model="password"
|
||||
:maxlength="20"
|
||||
@ -45,7 +66,7 @@
|
||||
:disabled="!(passwordPass && confirmPasswordPass && password === confirmPassword)"
|
||||
:round="false"
|
||||
size="large"
|
||||
@click="codeLogin"
|
||||
@click="resetPassword"
|
||||
>
|
||||
提交
|
||||
</wd-button>
|
||||
@ -54,14 +75,143 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { passwordRegExp } from '@/constants/regular-expressions'
|
||||
import { codeRegExp, passwordRegExp } from '@/constants/regular-expressions'
|
||||
import { getCodeApi, resetPasswordApi, UserGetCodeRequest } from '@/service/user'
|
||||
import { Result } from '@/constants/result'
|
||||
import { AccountChannel, CodeType, IResData } from '@/typings'
|
||||
|
||||
const phone = ref<string>('')
|
||||
const code = ref<string>('')
|
||||
|
||||
const password = ref<string>('')
|
||||
const confirmPassword = ref<string>('')
|
||||
const countDown = ref<number>(60)
|
||||
|
||||
const maskedPhone = computed(() => {
|
||||
if (phone.value.length === 11) {
|
||||
return phone.value.slice(0, 3) + '****' + phone.value.slice(7)
|
||||
}
|
||||
return phone.value
|
||||
})
|
||||
const codePass = computed(() => codeRegExp.test(code.value))
|
||||
const passwordPass = computed(() => passwordRegExp.test(password.value))
|
||||
const confirmPasswordPass = computed(() => password.value === confirmPassword.value)
|
||||
|
||||
onLoad(options => {
|
||||
phone.value = options.phone
|
||||
startCounting()
|
||||
})
|
||||
|
||||
const getCode = async () => {
|
||||
await uni.showLoading({
|
||||
title: '加载中',
|
||||
mask: true
|
||||
})
|
||||
try {
|
||||
const result: IResData = await getCodeApi<UserGetCodeRequest>({
|
||||
account: phone.value,
|
||||
channel: AccountChannel.phone,
|
||||
codeType: CodeType.reset
|
||||
})
|
||||
uni.hideLoading()
|
||||
if (result.errorCode === Result.Success.code) {
|
||||
await uni.showToast({
|
||||
title: '验证码已发送',
|
||||
icon: 'none'
|
||||
})
|
||||
} else {
|
||||
await uni.showToast({
|
||||
title: result.errorMsg,
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
uni.hideLoading()
|
||||
await uni.showToast({
|
||||
title: '获取验证码失败,请稍后再试',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const startCounting = () => {
|
||||
const timestamp: number = new Date().getTime()
|
||||
countDown.value = 60
|
||||
const countDownTimer = setInterval(() => {
|
||||
if (countDown.value > 0) {
|
||||
countDown.value = 60 - Math.floor((new Date().getTime() - timestamp) / 1000)
|
||||
} else {
|
||||
clearInterval(countDownTimer)
|
||||
}
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
const resetPassword = async () => {
|
||||
if (code.value === '') {
|
||||
await uni.showToast({
|
||||
title: '验证码不能为空',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
} else if (!codePass.value) {
|
||||
await uni.showToast({
|
||||
title: '验证码格式不正确',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
} else if (password.value === '' || confirmPassword.value === '') {
|
||||
await uni.showToast({
|
||||
title: '密码不能为空',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
} else if (!passwordPass.value || !confirmPasswordPass.value) {
|
||||
await uni.showToast({
|
||||
title: '密码格式不正确',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
} else if (password.value !== confirmPassword.value) {
|
||||
await uni.showToast({
|
||||
title: '两次密码不一致',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
await uni.showLoading({
|
||||
title: '修改中'
|
||||
})
|
||||
try {
|
||||
const resetPasswordApiResult = await resetPasswordApi({
|
||||
newPassword: password.value,
|
||||
account: phone.value,
|
||||
verificationCode: code.value
|
||||
})
|
||||
uni.hideLoading()
|
||||
if (resetPasswordApiResult.errorCode === Result.Success.code) {
|
||||
await uni.navigateBack({ delta: 2 })
|
||||
await uni.showToast({
|
||||
title: '密码重置成功',
|
||||
icon: 'none'
|
||||
})
|
||||
} else {
|
||||
await uni.showToast({
|
||||
title: resetPasswordApiResult.errorMsg,
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
uni.hideLoading()
|
||||
await uni.showToast({
|
||||
title: '密码重置失败,请稍后再试',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const passwordChange = (value: string) => {
|
||||
password.value = value
|
||||
}
|
||||
@ -69,6 +219,10 @@
|
||||
const confirmPasswordChange = (value: string) => {
|
||||
confirmPassword.value = value
|
||||
}
|
||||
|
||||
const codeChange = (value: string) => {
|
||||
code.value = value
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
|
||||
@ -1,15 +0,0 @@
|
||||
import { http } from '@/utils/http'
|
||||
export interface IFooItem {
|
||||
id: string
|
||||
name: string
|
||||
}
|
||||
|
||||
/** GET 请求 */
|
||||
export const getFooAPI = (name: string) => {
|
||||
return http.get<IFooItem>('/foo', { name })
|
||||
}
|
||||
|
||||
/** POST 请求 */
|
||||
export const postFooAPI = (name: string) => {
|
||||
return http.post<IFooItem>('/foo', { name }, { name })
|
||||
}
|
||||
79
src/service/user.ts
Normal file
79
src/service/user.ts
Normal file
@ -0,0 +1,79 @@
|
||||
import { http } from '@/utils/http'
|
||||
|
||||
export interface UserGetCodeRequest {
|
||||
account: string
|
||||
channel: string
|
||||
codeType: string
|
||||
countryCode?: string
|
||||
}
|
||||
|
||||
// 获取验证码
|
||||
export const getCodeApi = (params: UserGetCodeRequest) => {
|
||||
return http.post('/v1/common/sendValidationCode', params)
|
||||
}
|
||||
|
||||
export interface PasswordLoginRequest {
|
||||
platId: number
|
||||
username: string
|
||||
password: string
|
||||
deviceInfo?: DeviceInfo
|
||||
}
|
||||
|
||||
interface DeviceInfo {
|
||||
deviceNo?: string
|
||||
deviceName?: string
|
||||
deviceBrand?: string
|
||||
deviceModel?: string
|
||||
}
|
||||
|
||||
// 密码登录
|
||||
export const passwordLoginApi = (params: PasswordLoginRequest) => {
|
||||
return http.post('/v1/user/pwdLogin', params)
|
||||
}
|
||||
|
||||
export interface CodeLoginRequest {
|
||||
platId: number
|
||||
phone: string
|
||||
verificationCode: string
|
||||
deviceInfo?: DeviceInfo
|
||||
}
|
||||
|
||||
// 验证码登录
|
||||
export const codeLoginApi = (params: CodeLoginRequest) => {
|
||||
return http.post('/v1/user/codeLogin', params)
|
||||
}
|
||||
|
||||
export interface UserInfo {
|
||||
id?: number
|
||||
accountNo?: string
|
||||
phone?: string
|
||||
nickname?: string
|
||||
headUrl?: string
|
||||
createdAt?: string
|
||||
lastLoginTime?: string
|
||||
currentTeamNo?: string
|
||||
teamList?: Array<TeamInfo>
|
||||
}
|
||||
|
||||
interface TeamInfo {
|
||||
teamNo?: string
|
||||
teamName?: string
|
||||
teamCode?: string
|
||||
}
|
||||
|
||||
// 获取用户信息
|
||||
export const getUserInfoApi = (params: UserInfo) => {
|
||||
return http.post('/v1/user/detail', params)
|
||||
}
|
||||
|
||||
export interface resetPasswordRequest {
|
||||
countryCode?: string
|
||||
account: string
|
||||
verificationCode: number
|
||||
newPassword: string
|
||||
}
|
||||
|
||||
// 重置密码
|
||||
export const resetPasswordApi = (params: resetPasswordRequest) => {
|
||||
return http.post('/v1/user/resetPassword', params)
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 513 B |
@ -1,32 +1,50 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { ref } from 'vue'
|
||||
|
||||
const initState = { nickname: '', avatar: '' }
|
||||
import { getUserInfoApi, UserInfo } from '@/service/user'
|
||||
import { Result } from '@/constants/result'
|
||||
|
||||
export const useUserStore = defineStore(
|
||||
'user',
|
||||
() => {
|
||||
const userInfo = ref<IUserInfo>({ ...initState })
|
||||
const userInfo = ref<UserInfo>(null)
|
||||
const loginStatus = ref<boolean>(false)
|
||||
|
||||
const setUserInfo = (val: IUserInfo) => {
|
||||
userInfo.value = val
|
||||
const getUserInfo = async () => {
|
||||
try {
|
||||
const result = await getUserInfoApi()
|
||||
if (result.errorCode === Result.Success.code) {
|
||||
userInfo.value = result.data
|
||||
loginStatus.value = true
|
||||
uni.setStorageSync('userInfo', userInfo.value)
|
||||
return new Result(result.errorCode, userInfo.value, result.errorMsg)
|
||||
}
|
||||
loginStatus.value = false
|
||||
return Result.Fail
|
||||
} catch (error) {
|
||||
const userInfoStorage = uni.getStorageSync('userInfo')
|
||||
if (userInfoStorage) {
|
||||
userInfo.value = userInfoStorage
|
||||
loginStatus.value = true
|
||||
return new Result(Result.Success.code, userInfo.value, Result.Success.message)
|
||||
} else {
|
||||
loginStatus.value = false
|
||||
return Result.Fail
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const clearUserInfo = () => {
|
||||
userInfo.value = { ...initState }
|
||||
const logout = () => {
|
||||
userInfo.value = null
|
||||
loginStatus.value = false
|
||||
uni.removeStorageSync('userInfo')
|
||||
uni.removeStorageSync('token')
|
||||
}
|
||||
// 一般没有reset需求,不需要的可以删除
|
||||
const reset = () => {
|
||||
userInfo.value = { ...initState }
|
||||
}
|
||||
const isLogined = computed(() => !!userInfo.value.token)
|
||||
|
||||
return {
|
||||
userInfo,
|
||||
setUserInfo,
|
||||
clearUserInfo,
|
||||
isLogined,
|
||||
reset
|
||||
loginStatus,
|
||||
logout,
|
||||
getUserInfo
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -1,41 +1,49 @@
|
||||
// 全局要用的类型放到这里
|
||||
|
||||
type IResData<T> = {
|
||||
export type IResData<T> = {
|
||||
errorCode: number
|
||||
errorMsg: string
|
||||
data: T
|
||||
}
|
||||
|
||||
// uni.uploadFile文件上传参数
|
||||
type IUniUploadFileOptions = {
|
||||
file?: File
|
||||
files?: UniApp.UploadFileOptionFiles[]
|
||||
filePath?: string
|
||||
name?: string
|
||||
formData?: any
|
||||
}
|
||||
|
||||
type IUserInfo = {
|
||||
nickname?: string
|
||||
avatar?: string
|
||||
openid?: string
|
||||
token?: string
|
||||
}
|
||||
|
||||
type TabBarItem = {
|
||||
export type TabBarItem = {
|
||||
icon: string
|
||||
title: string
|
||||
isDot?: boolean
|
||||
value?: number
|
||||
}
|
||||
|
||||
type HomeTabItem = {
|
||||
export type HomeTabItem = {
|
||||
icon: string
|
||||
title: string
|
||||
id: number
|
||||
}
|
||||
|
||||
type HomeTab = {
|
||||
export type HomeTab = {
|
||||
title: string
|
||||
list: HomeTabItem[]
|
||||
}
|
||||
|
||||
export enum AccountChannel {
|
||||
phone = '1',
|
||||
email = '2'
|
||||
}
|
||||
|
||||
export enum CodeType {
|
||||
login = '1',
|
||||
reset = '2',
|
||||
bindPhone = '3',
|
||||
unbindPhone = '4',
|
||||
deleteAccount = '5',
|
||||
bindEmail = '6',
|
||||
unbindEmail = '7',
|
||||
deleteLock = '8',
|
||||
updatePassword = '9'
|
||||
}
|
||||
|
||||
export enum PlatId {
|
||||
web = 1,
|
||||
app = 2,
|
||||
miniProgram = 3,
|
||||
pc = 4
|
||||
}
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
import { CustomRequestOptions } from '@/interceptors/request'
|
||||
import { useUserStore } from '@/store'
|
||||
|
||||
export const http = <T>(options: CustomRequestOptions) => {
|
||||
// 1. 返回 Promise 对象
|
||||
return new Promise<IResData<T>>((resolve, reject) => {
|
||||
const timestamp = new Date().getTime()
|
||||
|
||||
uni.request({
|
||||
...options,
|
||||
dataType: 'json',
|
||||
@ -11,18 +13,22 @@ export const http = <T>(options: CustomRequestOptions) => {
|
||||
// #endif
|
||||
// 响应成功
|
||||
success(res) {
|
||||
// 状态码 2xx,参考 axios 的设计
|
||||
if (res.statusCode >= 200 && res.statusCode < 300) {
|
||||
if (res.data.errorCode === 403) {
|
||||
// 401错误 -> 清理用户信息,跳转到登录页
|
||||
// userStore.clearUserInfo()
|
||||
// uni.navigateTo({ url: '/pages/login/login' })
|
||||
const $user = useUserStore()
|
||||
$user.logout()
|
||||
uni.switchTab({
|
||||
url: '/pages/home/home'
|
||||
})
|
||||
uni.showToast({
|
||||
icon: 'none',
|
||||
title: '登录已过期,请重新登录'
|
||||
})
|
||||
reject(res)
|
||||
} else {
|
||||
resolve(res.data as IResData<T>)
|
||||
}
|
||||
} else {
|
||||
// 其他错误 -> 根据后端错误信息轻提示
|
||||
uni.showToast({
|
||||
icon: 'none',
|
||||
title: '网络错误,请重试'
|
||||
@ -32,30 +38,31 @@ export const http = <T>(options: CustomRequestOptions) => {
|
||||
},
|
||||
// 响应失败
|
||||
fail(err) {
|
||||
console.log('请求失败', err)
|
||||
uni.showToast({
|
||||
icon: 'none',
|
||||
title: '网络错误,请重试'
|
||||
})
|
||||
reject(err)
|
||||
},
|
||||
complete(res) {
|
||||
console.log(options.url, {
|
||||
env: import.meta.env.VITE_APP_ENV,
|
||||
statusCode: res?.statusCode,
|
||||
code: res?.data?.errorCode,
|
||||
baseUrl: import.meta.env.VITE_SERVER_BASEURL,
|
||||
url: options.url,
|
||||
req: options.data,
|
||||
res: res?.data?.data,
|
||||
header: options.header,
|
||||
message: res?.data?.errorMsg,
|
||||
duration: new Date().getTime() - timestamp
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* GET 请求
|
||||
* @param url 后台地址
|
||||
* @param query 请求query参数
|
||||
* @returns
|
||||
*/
|
||||
export const httpGet = <T>(url: string, query?: Record<string, any>) => {
|
||||
return http<T>({
|
||||
url,
|
||||
query,
|
||||
method: 'GET'
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* POST 请求
|
||||
* @param url 后台地址
|
||||
@ -76,5 +83,4 @@ export const httpPost = <T>(
|
||||
})
|
||||
}
|
||||
|
||||
http.get = httpGet
|
||||
http.post = httpPost
|
||||
|
||||
@ -124,28 +124,7 @@ export const needLoginPages: string[] = getAllPages('needLogin').map(page => pag
|
||||
*/
|
||||
export const getEnvBaseUrl = () => {
|
||||
// 请求基准地址
|
||||
let baseUrl = import.meta.env.VITE_SERVER_BASEURL
|
||||
|
||||
// 小程序端环境区分
|
||||
if (isMp) {
|
||||
const {
|
||||
miniProgram: { envVersion }
|
||||
} = uni.getAccountInfoSync()
|
||||
|
||||
switch (envVersion) {
|
||||
case 'develop':
|
||||
baseUrl = 'https://ukw0y1.laf.run'
|
||||
break
|
||||
case 'trial':
|
||||
baseUrl = 'https://ukw0y1.laf.run'
|
||||
break
|
||||
case 'release':
|
||||
baseUrl = 'https://ukw0y1.laf.run'
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return baseUrl
|
||||
return import.meta.env.VITE_SERVER_BASEURL
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user