diff --git a/.hbuilderx/launch.json b/.hbuilderx/launch.json
index 15db785..a5db135 100644
--- a/.hbuilderx/launch.json
+++ b/.hbuilderx/launch.json
@@ -2,8 +2,13 @@
"version" : "1.0",
"configurations" : [
{
+ "customPlaygroundType" : "device",
"playground" : "standard",
"type" : "uni-app:app-ios"
+ },
+ {
+ "playground" : "standard",
+ "type" : "uni-app:app-android"
}
]
}
diff --git a/.prettierrc.js b/.prettierrc.cjs
similarity index 97%
rename from .prettierrc.js
rename to .prettierrc.cjs
index 8ecac9d..def7884 100644
--- a/.prettierrc.js
+++ b/.prettierrc.cjs
@@ -1,4 +1,3 @@
-// @ts-check
module.exports = {
printWidth: 74,
diff --git a/api/index.js b/api/index.js
index fa765f9..a4a8777 100644
--- a/api/index.js
+++ b/api/index.js
@@ -1 +1,27 @@
-// 各模块api
\ No newline at end of file
+import http from '@/utils/request'
+
+/** 注册 */
+export const userRegister = data => {
+ return http({
+ url: '/api/register',
+ method: 'post',
+ data
+ })
+}
+
+/** 登录 */
+export const userLogin = data => {
+ return http({
+ url: '/api/login',
+ method: 'post',
+ data
+ })
+}
+
+/** 获取用户信息 */
+export const getUserData = () => {
+ return http({
+ url: '/api/userInfo',
+ method: 'get'
+ })
+}
diff --git a/components/cb-search/cb-search.vue b/components/cb-search/cb-search.vue
new file mode 100644
index 0000000..d226799
--- /dev/null
+++ b/components/cb-search/cb-search.vue
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/register-app/register-app.vue b/components/register-app/register-app.vue
index 6344a8a..c4947bb 100644
--- a/components/register-app/register-app.vue
+++ b/components/register-app/register-app.vue
@@ -1,6 +1,16 @@
+
+
+ 通讯录
+
+
+
diff --git a/pages/discover/discover.vue b/pages/discover/discover.vue
new file mode 100644
index 0000000..b1475ba
--- /dev/null
+++ b/pages/discover/discover.vue
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+
+ {{ item.name }}
+
+
+
+
+
+
+
diff --git a/pages/index/index.vue b/pages/index/index.vue
index b536876..bffa7c5 100644
--- a/pages/index/index.vue
+++ b/pages/index/index.vue
@@ -1,59 +1,67 @@
-
-
-
-
- {{ title }}
-
-
-
-
+
+
+
+
+ {{ title }}
+
+
+
+
diff --git a/pages/login/forgot-password/forgot-password.vue b/pages/login/forgot-password/forgot-password.vue
index ea9358d..40d481f 100644
--- a/pages/login/forgot-password/forgot-password.vue
+++ b/pages/login/forgot-password/forgot-password.vue
@@ -1,5 +1,8 @@
@@ -38,14 +51,14 @@
v-model="formData.username"
placeholder="请输入手机号/邮箱"
>
-
+ > -->
{
- showToast('登录成功')
- console.log('登录:', formData)
+ const onLogin = async () => {
+ if (!formData.agreement) {
+ showToast('请同意协议')
+ return
+ }
+ const res = await userLogin({
+ account: formData.username,
+ password: formData.password
+ })
+ setToken(res.token)
+ await fetchUserInfo()
+ reLaunch('/pages/news-list/news-list')
}
const onRegister = () => {
@@ -26,7 +40,7 @@
}
onLoad(e => {
- console.log('接收==:', e.id)
+ console.log('接收参数,返回对应页面的时候使用', e)
})
@@ -50,9 +64,7 @@
登录
diff --git a/pages/mall/confirm-order.vue b/pages/mall/confirm-order.vue
new file mode 100644
index 0000000..017fa36
--- /dev/null
+++ b/pages/mall/confirm-order.vue
@@ -0,0 +1,7 @@
+
+
+
+ 确认订单
+
+
+
diff --git a/pages/mall/detail.vue b/pages/mall/detail.vue
new file mode 100644
index 0000000..46c7b74
--- /dev/null
+++ b/pages/mall/detail.vue
@@ -0,0 +1,7 @@
+
+
+
+ 商品详情
+
+
+
diff --git a/pages/mall/list.vue b/pages/mall/list.vue
new file mode 100644
index 0000000..714f0ed
--- /dev/null
+++ b/pages/mall/list.vue
@@ -0,0 +1,78 @@
+
+
+
+
+
+
+
+ {{ item.name }}
+
+
+
+
+
+
diff --git a/pages/my-index/my-index.vue b/pages/my-index/my-index.vue
new file mode 100644
index 0000000..3175cb3
--- /dev/null
+++ b/pages/my-index/my-index.vue
@@ -0,0 +1,221 @@
+
+
+
+
+
+
+
+
+ {{ userInfo.userName }}
+ ID:{{ userInfo.userId }}
+
+
+
+
+
+
+
+
+ 账户积分
+ 2933
+
+
+
+
+
+
+
+
+
+
+ {{ item.name }}
+
+
+
+
+
+
+
+
diff --git a/pages/news-list/news-list.vue b/pages/news-list/news-list.vue
new file mode 100644
index 0000000..ca6dbf3
--- /dev/null
+++ b/pages/news-list/news-list.vue
@@ -0,0 +1,12 @@
+
+
+
+ 消息列表
+
+
+
diff --git a/static/images/discover/circle.png b/static/images/discover/circle.png
new file mode 100644
index 0000000..6b57de8
Binary files /dev/null and b/static/images/discover/circle.png differ
diff --git a/static/images/discover/company.png b/static/images/discover/company.png
new file mode 100644
index 0000000..eb09a97
Binary files /dev/null and b/static/images/discover/company.png differ
diff --git a/static/images/discover/grade.png b/static/images/discover/grade.png
new file mode 100644
index 0000000..9cf4a45
Binary files /dev/null and b/static/images/discover/grade.png differ
diff --git a/static/images/discover/mall.png b/static/images/discover/mall.png
new file mode 100644
index 0000000..efae5d2
Binary files /dev/null and b/static/images/discover/mall.png differ
diff --git a/static/images/discover/project.png b/static/images/discover/project.png
new file mode 100644
index 0000000..2523676
Binary files /dev/null and b/static/images/discover/project.png differ
diff --git a/static/images/discover/sign.png b/static/images/discover/sign.png
new file mode 100644
index 0000000..82ccdcc
Binary files /dev/null and b/static/images/discover/sign.png differ
diff --git a/static/images/discover/team.png b/static/images/discover/team.png
new file mode 100644
index 0000000..09c748e
Binary files /dev/null and b/static/images/discover/team.png differ
diff --git a/static/images/my-index/circle.png b/static/images/my-index/circle.png
new file mode 100644
index 0000000..77e2987
Binary files /dev/null and b/static/images/my-index/circle.png differ
diff --git a/static/images/my-index/collection.png b/static/images/my-index/collection.png
new file mode 100644
index 0000000..4c8a6b2
Binary files /dev/null and b/static/images/my-index/collection.png differ
diff --git a/static/images/my-index/customer.png b/static/images/my-index/customer.png
new file mode 100644
index 0000000..5f85168
Binary files /dev/null and b/static/images/my-index/customer.png differ
diff --git a/static/images/my-index/meeting.png b/static/images/my-index/meeting.png
new file mode 100644
index 0000000..410266b
Binary files /dev/null and b/static/images/my-index/meeting.png differ
diff --git a/static/images/my-index/my-card-bg.png b/static/images/my-index/my-card-bg.png
new file mode 100644
index 0000000..0bb677f
Binary files /dev/null and b/static/images/my-index/my-card-bg.png differ
diff --git a/static/images/my-index/system.png b/static/images/my-index/system.png
new file mode 100644
index 0000000..9e31ba0
Binary files /dev/null and b/static/images/my-index/system.png differ
diff --git a/static/images/my-index/team.png b/static/images/my-index/team.png
new file mode 100644
index 0000000..6073754
Binary files /dev/null and b/static/images/my-index/team.png differ
diff --git a/static/images/my-index/wallet.png b/static/images/my-index/wallet.png
new file mode 100644
index 0000000..1965571
Binary files /dev/null and b/static/images/my-index/wallet.png differ
diff --git a/static/images/public/right-arrow.png b/static/images/public/right-arrow.png
new file mode 100644
index 0000000..e79cde8
Binary files /dev/null and b/static/images/public/right-arrow.png differ
diff --git a/static/images/public/search.png b/static/images/public/search.png
new file mode 100644
index 0000000..09bbacf
Binary files /dev/null and b/static/images/public/search.png differ
diff --git a/static/images/tabBar/contacts.png b/static/images/tabBar/contacts.png
new file mode 100644
index 0000000..3639cef
Binary files /dev/null and b/static/images/tabBar/contacts.png differ
diff --git a/static/images/tabBar/contactsHL.png b/static/images/tabBar/contactsHL.png
new file mode 100644
index 0000000..1bbf5a2
Binary files /dev/null and b/static/images/tabBar/contactsHL.png differ
diff --git a/static/images/tabBar/discover.png b/static/images/tabBar/discover.png
new file mode 100644
index 0000000..3ec9939
Binary files /dev/null and b/static/images/tabBar/discover.png differ
diff --git a/static/images/tabBar/discoverHL.png b/static/images/tabBar/discoverHL.png
new file mode 100644
index 0000000..ad5ed4b
Binary files /dev/null and b/static/images/tabBar/discoverHL.png differ
diff --git a/static/images/tabBar/my.png b/static/images/tabBar/my.png
new file mode 100644
index 0000000..b980a76
Binary files /dev/null and b/static/images/tabBar/my.png differ
diff --git a/static/images/tabBar/myHL.png b/static/images/tabBar/myHL.png
new file mode 100644
index 0000000..4868631
Binary files /dev/null and b/static/images/tabBar/myHL.png differ
diff --git a/static/images/tabBar/news.png b/static/images/tabBar/news.png
new file mode 100644
index 0000000..b6526a1
Binary files /dev/null and b/static/images/tabBar/news.png differ
diff --git a/static/images/tabBar/newsHL.png b/static/images/tabBar/newsHL.png
new file mode 100644
index 0000000..907915a
Binary files /dev/null and b/static/images/tabBar/newsHL.png differ
diff --git a/stores/token.js b/stores/token.js
index fa4d009..8c99915 100644
--- a/stores/token.js
+++ b/stores/token.js
@@ -1,42 +1,48 @@
-import { defineStore } from 'pinia';
-import { ref } from 'vue';
-import { STORAGE_KEYS } from '@/constants/storage-keys';
-import { getToken, removeToken } from '@/utils/storage';
+import { defineStore } from 'pinia'
+import { ref } from 'vue'
+import { STORAGE_KEYS } from '@/constants/storage-keys'
+import { setTokenData, getToken, removeToken } from '@/utils/storage'
/** 登录状态 */
export const useTokenStore = defineStore(STORAGE_KEYS.TOKEN, () => {
+ // 从本地存储获取token
+ const token = ref(getToken() || null)
+ const isLogin = ref(!!token.value)
- // 从本地存储获取token
- const token = ref(getToken() || null);
- const isLogin = ref(!!token.value);
+ /** 设置token并保存到本地 */
+ const setToken = newToken => {
+ token.value = newToken
+ isLogin.value = true
+ setTokenData(newToken)
+ }
- /** 设置token并保存到本地 */
- const setToken = (newToken) => {
- token.value = newToken;
- isLogin.value = true;
- setToken(newToken);
- };
+ /** 清除token */
+ const clearToken = () => {
+ token.value = null
+ isLogin.value = false
+ removeToken()
+ }
- /** 清除token */
- const clearToken = () => {
- token.value = null;
- isLogin.value = false;
- removeToken()
- };
+ /** 检查token是否有效(可扩展过期时间判断) */
+ const checkToken = () => {
+ // 简单判断:token存在且不为空
+ return !!token.value
+ }
- /** 检查token是否有效(可扩展过期时间判断) */
- const checkToken = () => {
- // 简单判断:token存在且不为空
- return !!token.value;
- };
+ /** 验证token是否过期(实际项目中可添加过期时间判断) */
+ const isTokenExpired = () => {
+ // 示例:如果token中包含过期时间,这里可以判断
+ // 例如:const expireTime = parseInt(token.value.split('.')[1]);
+ // return Date.now() > expireTime * 1000;
+ return false // 默认不过期
+ }
- /** 验证token是否过期(实际项目中可添加过期时间判断) */
- const isTokenExpired = () => {
- // 示例:如果token中包含过期时间,这里可以判断
- // 例如:const expireTime = parseInt(token.value.split('.')[1]);
- // return Date.now() > expireTime * 1000;
- return false; // 默认不过期
- };
-
- return { token, isLogin, setToken, clearToken, checkToken, isTokenExpired };
-})
\ No newline at end of file
+ return {
+ token,
+ isLogin,
+ setToken,
+ clearToken,
+ checkToken,
+ isTokenExpired
+ }
+})
diff --git a/stores/user.js b/stores/user.js
new file mode 100644
index 0000000..b6dc35a
--- /dev/null
+++ b/stores/user.js
@@ -0,0 +1,70 @@
+import { defineStore } from 'pinia'
+import {
+ getToken,
+ getUserInfoData,
+ setUserInfoData,
+ removeUserInfoData
+} from '@/utils/storage'
+import { useTokenStore } from './token'
+import { getUserData } from '@/api'
+import { ref } from 'vue'
+
+export const useUserStore = defineStore('user', () => {
+ const { clearToken } = useTokenStore()
+
+ /** 用户信息对象 */
+ const userInfo = ref(JSON.parse(getUserInfoData()) || null)
+
+ /**
+ * 获取用户信息(可从缓存或接口)
+ */
+ const fetchUserInfo = async () => {
+ // 示例:先尝试从本地缓存读取
+ const cachedToken = getToken()
+ const cachedUserInfo = getUserInfoData()
+
+ if (cachedToken && cachedUserInfo) {
+ userInfo.value = JSON.parse(cachedUserInfo)
+ return
+ }
+ const res = await getUserData()
+ await setUserInfo(res.data)
+ return
+ }
+
+ /**
+ * 设置用户信息
+ */
+ const setUserInfo = async data => {
+ console.log('存储数据到userInfo==', data)
+ userInfo.value = data
+ // 同步到本地存储
+ setUserInfoData(data)
+ }
+
+ /**
+ * 清除用户信息(退出登录)
+ */
+ const clearUserInfo = () => {
+ userInfo.value = null
+ clearToken()
+ removeUserInfoData()
+ }
+
+ /**
+ * 更新部分用户信息(例如昵称、头像)
+ */
+ const updateUserInfo = partialData => {
+ if (!userInfo.value) return
+ userInfo.value = { ...userInfo.value, ...partialData }
+ setUserInfoData(userInfo.value)
+ }
+
+ return {
+ userInfo: userInfo.value,
+ fetchUserInfo,
+ setUserInfo,
+ clearUserInfo,
+ updateUserInfo
+ }
+})
diff --git a/utils/request.js b/utils/request.js
index 1cd03e7..490582d 100644
--- a/utils/request.js
+++ b/utils/request.js
@@ -1,75 +1,81 @@
-import { getToken, removeToken } from './storage';
+import { getToken, removeToken } from './storage'
-const BASE_URL = 'xxxxx'
+const BASE_URL = 'http://c36bd4b4.natappfree.cc'
/**
* 网络请求封装
* @param {Object} options 请求参数
* @returns {Promise}
*/
-const request = (options) => {
- // 默认配置
- const defaultOptions = {
- url: '',
- method: 'GET',
- data: {},
- header: {
- 'Content-Type': 'application/json' // 默认请求内容类型
- }
- }
+const request = options => {
+ // 默认配置
+ const defaultOptions = {
+ url: '',
+ method: 'GET',
+ data: {},
+ header: {
+ 'Content-Type': 'application/json' // 默认请求内容类型
+ }
+ }
- // 合并配置
- const config = { ...defaultOptions, ...options }
+ // 合并配置
+ const config = { ...defaultOptions, ...options }
- // 请求拦截:添加token等通用header
- if (getToken()) {
- config.header['Authorization'] = 'Bearer ' + getToken()
- }
+ // 请求拦截:添加token等通用header
+ if (getToken()) {
+ config.header['Authorization'] = 'Bearer ' + getToken()
+ }
- // 显示加载状态(可选)
- if (options.loading !== false) {
- uni.showLoading({
- title: '加载中...',
- mask: true
- })
- };
+ // 显示加载状态(可选)
+ if (options.loading !== false) {
+ uni.showLoading({
+ title: '加载中...',
+ mask: true
+ })
+ }
- return new Promise((resolve, reject) => {
- uni.request({
- url: BASE_URL + config.url,
- method: config.method,
- data: config.data,
- timeout: 10000, // 请求超时时间
- header: config.header,
- success: (response) => {
- // 响应拦截:根据状态码处理
- if (response.statusCode === 200) {
- // 这里可以根据后端数据格式调整
- // 例如:if (response.data.code === 0) {...}
- resolve(response.data)
- } else {
- // 状态码错误处理
- handleError(response.statusCode, response.data)
- reject(response)
- }
- },
- fail: (error) => {
- // 网络错误处理
- uni.showToast({
- title: '网络异常,请检查网络连接',
- icon: 'none',
- duration: 2000
- })
- reject(error)
- },
- complete: () => {
- // 隐藏加载状态
- if (options.loading !== false) {
- uni.hideLoading()
- }
- }
- })
- })
+ return new Promise((resolve, reject) => {
+ uni.request({
+ url: BASE_URL + config.url,
+ method: config.method,
+ data: config.data,
+ timeout: 10000, // 请求超时时间
+ header: config.header,
+ success: response => {
+ console.log(response)
+ // 响应拦截:根据状态码处理
+ if (response.statusCode === 200) {
+ // 这里可以根据后端数据格式调整
+ // 例如:if (response.data.code === 0) {...}
+ if (response.data.code === 200) {
+ resolve(response.data)
+ } else {
+ handleError(response.data.code, response.data)
+ }
+ } else {
+ // 状态码错误处理
+ handleError(response.statusCode, response.data)
+ reject(response)
+ }
+ },
+ fail: error => {
+ // 网络错误处理
+ uni.showToast({
+ title: '网络异常,请检查网络连接',
+ icon: 'none',
+ duration: 2000,
+ mask: true
+ })
+ reject(error)
+ },
+ complete: () => {
+ // 隐藏加载状态
+ if (options.loading !== false) {
+ uni.hideLoading()
+ }
+ }
+ })
+ })
}
/**
@@ -78,49 +84,53 @@ const request = (options) => {
* @param {Object} data 响应数据
*/
const handleError = (statusCode, data) => {
- switch (statusCode) {
- case 401:
- uni.showModal({
- title: '提示',
- content: '登录已过期,请重新登录',
- showCancel: false,
- success: () => {
- // 清除本地存储的token并跳转到登录页
- removeToken()
- uni.navigateTo({
- url: '/pages/login/index'
- })
- }
- })
- break
- case 403:
- uni.showToast({
- title: '没有权限访问',
- icon: 'none',
- duration: 2000
- })
- break
- case 404:
- uni.showToast({
- title: '请求资源不存在',
- icon: 'none',
- duration: 2000
- })
- break
- case 500:
- uni.showToast({
- title: '服务器内部错误',
- icon: 'none',
- duration: 2000
- })
- break
- default:
- uni.showToast({
- title: data.message || '请求失败,请重试',
- icon: 'none',
- duration: 2000
- })
- }
+ switch (statusCode) {
+ case 401:
+ uni.showModal({
+ title: '提示',
+ content: '登录已过期,请重新登录',
+ showCancel: false,
+ success: () => {
+ // 清除本地存储的token并跳转到登录页
+ removeToken()
+ uni.navigateTo({
+ url: '/pages/login/index'
+ })
+ }
+ })
+ break
+ case 403:
+ uni.showToast({
+ title: '没有权限访问',
+ icon: 'none',
+ duration: 2000,
+ mask: true
+ })
+ break
+ case 404:
+ uni.showToast({
+ title: '请求资源不存在',
+ icon: 'none',
+ duration: 2000,
+ mask: true
+ })
+ break
+ case 500:
+ uni.showToast({
+ title: data.msg || '服务器内部错误',
+ icon: 'none',
+ duration: 2000,
+ mask: true
+ })
+ break
+ default:
+ uni.showToast({
+ title: data.msg || '请求失败,请重试',
+ icon: 'none',
+ duration: 2000,
+ mask: true
+ })
+ }
}
-export default request
\ No newline at end of file
+export default request
diff --git a/utils/storage.js b/utils/storage.js
index e7155af..9716994 100644
--- a/utils/storage.js
+++ b/utils/storage.js
@@ -1,16 +1,31 @@
import { STORAGE_KEYS } from '@/constants/storage-keys'
/** 保存 token */
-export const setToken = (v) => {
- return uni.setStorageSync(STORAGE_KEYS.TOKEN, v)
+export const setTokenData = v => {
+ return uni.setStorageSync(STORAGE_KEYS.TOKEN, v)
}
/** 获取 token */
export const getToken = () => {
- return uni.getStorageSync(STORAGE_KEYS.TOKEN) || ''
+ return uni.getStorageSync(STORAGE_KEYS.TOKEN) || ''
}
/** 清楚 token */
export const removeToken = () => {
- return uni.removeStorageSync(STORAGE_KEYS.TOKEN)
-}
\ No newline at end of file
+ return uni.removeStorageSync(STORAGE_KEYS.TOKEN)
+}
+
+/** 保存用户信息 */
+export const setUserInfoData = v => {
+ return uni.setStorageSync(STORAGE_KEYS.USER, JSON.stringify(v))
+}
+
+/** 获取用户信息 */
+export const getUserInfoData = () => {
+ return uni.getStorageSync(STORAGE_KEYS.USER) || ''
+}
+
+/** 删除用户信息 */
+export const removeUserInfoData = () => {
+ return uni.removeStorageSync(STORAGE_KEYS.USER)
+}
diff --git a/utils/use-ui.js b/utils/use-ui.js
index 738464c..16edc7a 100644
--- a/utils/use-ui.js
+++ b/utils/use-ui.js
@@ -37,11 +37,14 @@ const showToast = (message, type = 'none', duration = 2000) => {
if (type === 'error') icon = 'error'
if (type === 'warning') icon = 'none'
- uni.showToast({
- title: message,
- icon,
- duration,
- mask: true
+ return new Promise(resolve => {
+ uni.showToast({
+ title: message,
+ icon,
+ duration,
+ mask: true
+ })
+ setTimeout(() => resolve(), duration)
})
}
diff --git a/utils/validate.js b/utils/validate.js
new file mode 100644
index 0000000..d5b91d6
--- /dev/null
+++ b/utils/validate.js
@@ -0,0 +1,84 @@
+// 正则
+
+/** 手机号正则(中国大陆) */
+const PHONE_REGEX = /^1[3-9]\d{9}$/
+
+/** 邮箱正则 */
+const EMAIL_REGEX = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/
+
+/** 身份证号(简化版) */
+const ID_CARD_REGEX = /(^\d{15}$)|(^\d{18}$)|(^\d{17}[\dXx]$)/
+
+/** 密码强度(至少8位,包含数字和字母) */
+const PASSWORD_REGEX = /^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d@$!%*#?&]{8,}$/
+
+/**
+ * 校验手机号
+ * @param {string} phone - 待校验的手机号
+ * @returns {{ valid: boolean, message: string }}
+ */
+export const validatePhone = phone => {
+ if (!phone) return { valid: false, message: '手机号不能为空' }
+ if (!PHONE_REGEX.test(phone)) {
+ return { valid: false, message: '手机号格式不正确' }
+ }
+ return { valid: true, message: '' }
+}
+
+/**
+ * 校验邮箱
+ * @param {string} email - 待校验的邮箱
+ * @returns {{ valid: boolean, message: string }}
+ */
+export const validateEmail = email => {
+ if (!email) return { valid: false, message: '邮箱不能为空' }
+ if (!EMAIL_REGEX.test(email)) {
+ return { valid: false, message: '邮箱格式不正确' }
+ }
+ return { valid: true, message: '' }
+}
+
+/**
+ * 校验密码强度
+ * @param {string} password - 待校验的密码
+ * @returns {{ valid: boolean, message: string }}
+ */
+export const validatePassword = password => {
+ if (!password) return { valid: false, message: '密码不能为空' }
+ if (password.length < 8) {
+ return { valid: false, message: '密码长度不能少于8位' }
+ }
+ if (!PASSWORD_REGEX.test(password)) {
+ return { valid: false, message: '密码需包含字母和数字' }
+ }
+ return { valid: true, message: '' }
+}
+
+/**
+ * 校验确认密码是否与原密码一致
+ * @param {string} password - 原始密码
+ * @param {string} confirmPassword - 确认密码
+ * @returns {{ valid: boolean, message: string }}
+ */
+export function validateConfirmPassword(password, confirmPassword) {
+ if (!confirmPassword) {
+ return { valid: false, message: '请再次输入密码' }
+ }
+ if (password !== confirmPassword) {
+ return { valid: false, message: '两次输入的密码不一致' }
+ }
+ return { valid: true, message: '' }
+}
+
+/**
+ * 校验身份证号(仅格式校验,不验证真实性)
+ * @param {string} idCard - 待校验的身份证号
+ * @returns {{ valid: boolean, message: string }}
+ */
+export const validateIdCard = idCard => {
+ if (!idCard) return { valid: false, message: '身份证号不能为空' }
+ if (!ID_CARD_REGEX.test(idCard)) {
+ return { valid: false, message: '身份证号格式不正确' }
+ }
+ return { valid: true, message: '' }
+}