diff --git a/env/.env b/env/.env index c367880..0517a4b 100644 --- a/env/.env +++ b/env/.env @@ -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 + diff --git a/env/.env.development b/env/.env.sky_dev similarity index 63% rename from env/.env.development rename to env/.env.sky_dev index 286b50f..1938e34 100644 --- a/env/.env.development +++ b/env/.env.sky_dev @@ -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' diff --git a/env/.env.test b/env/.env.sky_pre similarity index 56% rename from env/.env.test rename to env/.env.sky_pre index ed9c565..6f66c7c 100644 --- a/env/.env.test +++ b/env/.env.sky_pre @@ -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' diff --git a/env/.env.sky_release b/env/.env.sky_release new file mode 100644 index 0000000..48c9551 --- /dev/null +++ b/env/.env.sky_release @@ -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' diff --git a/env/.env.xhj_dev b/env/.env.xhj_dev new file mode 100644 index 0000000..55cf732 --- /dev/null +++ b/env/.env.xhj_dev @@ -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' diff --git a/env/.env.xhj_pre b/env/.env.xhj_pre new file mode 100644 index 0000000..50bf1ea --- /dev/null +++ b/env/.env.xhj_pre @@ -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' diff --git a/env/.env.production b/env/.env.xhj_release similarity index 65% rename from env/.env.production rename to env/.env.xhj_release index 21bbcba..a233323 100644 --- a/env/.env.production +++ b/env/.env.xhj_release @@ -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' diff --git a/package.json b/package.json index 080be6d..40ca9c7 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/src/constants/regular-expressions.js b/src/constants/regular-expressions.js deleted file mode 100644 index 1fcc6be..0000000 --- a/src/constants/regular-expressions.js +++ /dev/null @@ -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}$/ diff --git a/src/constants/regular-expressions.ts b/src/constants/regular-expressions.ts new file mode 100644 index 0000000..38bb893 --- /dev/null +++ b/src/constants/regular-expressions.ts @@ -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}$/ diff --git a/src/constants/result.ts b/src/constants/result.ts new file mode 100644 index 0000000..4f43081 --- /dev/null +++ b/src/constants/result.ts @@ -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) + } +} diff --git a/src/interceptors/request.ts b/src/interceptors/request.ts index d24db1d..b1ef464 100644 --- a/src/interceptors/request.ts +++ b/src/interceptors/request.ts @@ -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}` } diff --git a/src/pages/code/code.vue b/src/pages/code/code.vue index 731d583..1022d91 100644 --- a/src/pages/code/code.vue +++ b/src/pages/code/code.vue @@ -38,6 +38,14 @@ - - diff --git a/src/pages/home/CustomTab.vue b/src/pages/home/CustomTab.vue index 6db1a09..524f4b2 100644 --- a/src/pages/home/CustomTab.vue +++ b/src/pages/home/CustomTab.vue @@ -39,7 +39,7 @@ const tab = ref(0) - const props = defineProps({ + defineProps({ list: { type: Array, required: true diff --git a/src/pages/home/home.vue b/src/pages/home/home.vue index 8271e29..2750229 100644 --- a/src/pages/home/home.vue +++ b/src/pages/home/home.vue @@ -8,24 +8,24 @@ diff --git a/src/service/index/foo.ts b/src/service/index/foo.ts deleted file mode 100644 index acf5aa8..0000000 --- a/src/service/index/foo.ts +++ /dev/null @@ -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('/foo', { name }) -} - -/** POST 请求 */ -export const postFooAPI = (name: string) => { - return http.post('/foo', { name }, { name }) -} diff --git a/src/service/user.ts b/src/service/user.ts new file mode 100644 index 0000000..eee4867 --- /dev/null +++ b/src/service/user.ts @@ -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 +} + +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) +} diff --git a/src/static/images/bg_table.png b/src/static/images/bg_table.png deleted file mode 100644 index 565f0b2..0000000 Binary files a/src/static/images/bg_table.png and /dev/null differ diff --git a/src/store/user.ts b/src/store/user.ts index 4921ba9..07b3192 100644 --- a/src/store/user.ts +++ b/src/store/user.ts @@ -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({ ...initState }) + const userInfo = ref(null) + const loginStatus = ref(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 } }, { diff --git a/src/typings.ts b/src/typings.ts index 8052235..b52c6dd 100644 --- a/src/typings.ts +++ b/src/typings.ts @@ -1,41 +1,49 @@ // 全局要用的类型放到这里 -type IResData = { +export type IResData = { 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 +} diff --git a/src/utils/http.ts b/src/utils/http.ts index 8cb75a9..aebe4d6 100644 --- a/src/utils/http.ts +++ b/src/utils/http.ts @@ -1,8 +1,10 @@ import { CustomRequestOptions } from '@/interceptors/request' +import { useUserStore } from '@/store' export const http = (options: CustomRequestOptions) => { - // 1. 返回 Promise 对象 return new Promise>((resolve, reject) => { + const timestamp = new Date().getTime() + uni.request({ ...options, dataType: 'json', @@ -11,18 +13,22 @@ export const http = (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) } } else { - // 其他错误 -> 根据后端错误信息轻提示 uni.showToast({ icon: 'none', title: '网络错误,请重试' @@ -32,30 +38,31 @@ export const http = (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 = (url: string, query?: Record) => { - return http({ - url, - query, - method: 'GET' - }) -} - /** * POST 请求 * @param url 后台地址 @@ -76,5 +83,4 @@ export const httpPost = ( }) } -http.get = httpGet http.post = httpPost diff --git a/src/utils/index.ts b/src/utils/index.ts index 591dbe8..4f8f528 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -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 } /**