From 3da97eb797bb4ad30e2a8802c68196ac3b1303d1 Mon Sep 17 00:00:00 2001 From: Echo <1711788888@qq.com> Date: Mon, 18 Aug 2025 23:49:43 +0800 Subject: [PATCH] =?UTF-8?q?:art:=20=E4=BC=98=E5=8C=96=E6=A0=B8=E5=BF=83?= =?UTF-8?q?=E7=BB=84=E4=BB=B6=EF=BC=8C=E4=BC=98=E5=8C=96=E7=99=BB=E5=BD=95?= =?UTF-8?q?=E5=92=8C=E9=A6=96=E9=A1=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env | 1 + src/App.vue | 29 +- src/api/http.js | 111 ------ src/api/index.js | 19 + src/api/modules/test.js | 12 - src/api/request.js | 150 +++++++ src/config/index.js | 18 + src/manifest.json | 6 +- src/pages.json | 111 +++++- src/pages/checkin/checkin.vue | 577 +++++++++++++++++++++++++++ src/pages/components/components.vue | 46 --- src/pages/diary/diary.vue | 457 +++++++++++++++++++++ src/pages/functions/functions.vue | 50 --- src/pages/home/home.vue | 457 ++++++++++++++++++++- src/pages/order/order.vue | 562 ++++++++++++++++++++++++++ src/pages/profile/profile.vue | 567 ++++++++++++++++++++++++++ src/pages/recipe/recipe.vue | 338 ++++++++++++++++ src/pages/user/login.vue | 526 ++++++++++++++++++++++++ src/pages/user/setup.vue | 328 +++++++++++++++ src/static/images/checkin-active.png | Bin 0 -> 4384 bytes src/static/images/checkin.png | Bin 0 -> 4376 bytes src/static/images/diary-active.png | Bin 0 -> 4681 bytes src/static/images/diary.png | Bin 0 -> 6934 bytes src/static/images/home-active.png | Bin 0 -> 4603 bytes src/static/images/home.png | Bin 0 -> 4612 bytes src/static/images/profile-active.png | Bin 0 -> 3893 bytes src/static/images/profile.png | Bin 0 -> 3855 bytes src/static/images/recipe-active.png | Bin 0 -> 5741 bytes src/static/images/recipe.png | Bin 0 -> 6612 bytes src/store/user.js | 105 ++++- 30 files changed, 4213 insertions(+), 257 deletions(-) create mode 100644 .env delete mode 100644 src/api/http.js create mode 100644 src/api/index.js delete mode 100644 src/api/modules/test.js create mode 100644 src/api/request.js create mode 100644 src/config/index.js create mode 100644 src/pages/checkin/checkin.vue delete mode 100644 src/pages/components/components.vue create mode 100644 src/pages/diary/diary.vue delete mode 100644 src/pages/functions/functions.vue create mode 100644 src/pages/order/order.vue create mode 100644 src/pages/profile/profile.vue create mode 100644 src/pages/recipe/recipe.vue create mode 100644 src/pages/user/login.vue create mode 100644 src/pages/user/setup.vue create mode 100644 src/static/images/checkin-active.png create mode 100644 src/static/images/checkin.png create mode 100644 src/static/images/diary-active.png create mode 100644 src/static/images/diary.png create mode 100644 src/static/images/home-active.png create mode 100644 src/static/images/home.png create mode 100644 src/static/images/profile-active.png create mode 100644 src/static/images/profile.png create mode 100644 src/static/images/recipe-active.png create mode 100644 src/static/images/recipe.png diff --git a/.env b/.env new file mode 100644 index 0000000..b1f7c87 --- /dev/null +++ b/.env @@ -0,0 +1 @@ +VITE_BASE_URL = http://127.0.0.1:8888 \ No newline at end of file diff --git a/src/App.vue b/src/App.vue index 5d229d9..71e4840 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,12 +1,37 @@ diff --git a/src/api/http.js b/src/api/http.js deleted file mode 100644 index d0889a6..0000000 --- a/src/api/http.js +++ /dev/null @@ -1,111 +0,0 @@ -import Request from 'luch-request' -const tokeyKey = 'Authorization' -const env = import.meta.env - -// 创建实例 -const axiosInstance = new Request({ - baseURL: env.VITE_BASE_URL, - timeout: 30 * 1000, // 超时配置 - headers: { - 'Content-Type': 'application/json;charset=UTF-8' - } -}) - -// 请求拦截 -axiosInstance.interceptors.request.use( - config => { - const token = '' - if (token) { - config.headers[tokeyKey] = '' - } - return config - }, - error => { - return Promise.reject(error) - } -) - -// 响应拦截 -axiosInstance.interceptors.response.use( - response => { - // console.log('response=>', response) - const { status, data, config } = response - if (status === 200) { - const { code, message, data: resData } = data - if (code === '0000') { - return resData - } - // 文件 - if (config?.responseType === 'blob') { - return response - } - // token过期 - if (code === '5010') { - uni.showToast({ - title: 'token过期,请重新登陆!', - icon: 'none' - }) - // userStore.logout(false) - return - } - uni.showToast({ - title: message || '接口请求异常', - icon: 'none' - }) - return Promise.reject(data) - } - uni.showToast({ - title: `${status}服务器响应异常`, - icon: 'none' - }) - return Promise.reject(data) - }, - error => { - // 如果是取消请求,返回空的Promise,避免触发异常处理 - if (axiosInstance.isCancel(error)) { - return new Promise(() => {}) - } - const { response, code, message, config } = error - if (!response) { - uni.showToast({ - title: '连接超时,请稍后重试', - icon: 'none' - }) - } else { - const { _retry } = config - const { status } = response - if (code === 'ECONNABORTED' && message.indexOf('timeout') !== -1 && !_retry) { - uni.showToast({ - title: '连接超时,请稍后重试', - icon: 'none' - }) - } else { - uni.showToast({ - title: `${status}`, - icon: 'none' - }) - } - } - return Promise.reject(error) - } -) - -/** - * 上传文件 - * @param {*} url - * @param {*} data - * @returns - */ -export const upload = (url, data) => { - let formData = new FormData() - Object.keys(data || []).forEach(key => { - formData.append(key, data[key]) - }) - return axiosInstance.post(url, formData, { - headers: { - 'Content-Type': 'multipart/form-data' - } - }) -} - -export default axiosInstance diff --git a/src/api/index.js b/src/api/index.js new file mode 100644 index 0000000..7b3ee86 --- /dev/null +++ b/src/api/index.js @@ -0,0 +1,19 @@ +import net from './request.js'; + +// import store from '../store'; + +const API = { + /* + 用户相关 + */ + login: data => net.post('/user/login', data, false), // 登录 + getUserInfo: () => net.get('/user/info', {}, true), // 获取用户信息 + getUserInfoById: id => net.get(`/user/info/id`, {}, true), // 获取用户信息 + updateUserInfo: data => net.put('/user/info', data, true), // 更新用户信息 + upload: data => net.post('/user/upload', data, true), // 上传头像 + getLoverInfo: () => net.get('/user/lover', {}, true), // 获取另一半信息 + +}; + +export default API + diff --git a/src/api/modules/test.js b/src/api/modules/test.js deleted file mode 100644 index 6c7b64d..0000000 --- a/src/api/modules/test.js +++ /dev/null @@ -1,12 +0,0 @@ -import http from '@/api/http.js' -const VITE_BASE_URL_AUTH = import.meta.env.VITE_BASE_URL_AUTH // 认证中心 -export default { - login: data => { - return http.request({ - baseURL: VITE_BASE_URL_AUTH, - url: '/login', - method: 'post', - data - }) - } -} diff --git a/src/api/request.js b/src/api/request.js new file mode 100644 index 0000000..ac4443f --- /dev/null +++ b/src/api/request.js @@ -0,0 +1,150 @@ +import config from '../config' + +const LOGIN_PAGE = '/pages/user/login' + +/** + * 获取本地 token + */ +function getToken() { + return uni.getStorageSync('token') || '' +} + +/** + * 统一处理未登录或被踢下线 + */ +function handleAuthFail(checkLogin = true) { + console.log('开始清理登录信息并跳转登录页') + uni.removeStorageSync('token') + uni.removeStorageSync('tokenExpiresAt') + uni.removeStorageSync('userInfo') + if (checkLogin) { + console.log('准备跳转到登录页:', LOGIN_PAGE) + // 使用 reLaunch 强制跳转到登录页,避免用户返回到已失效的页面 + uni.reLaunch({ + url: LOGIN_PAGE, + success: () => { + console.log('跳转登录页成功') + }, + fail: (err) => { + console.log('跳转登录页失败:', err) + } + }) + } +} + +/** + * 构建请求头 + */ +function buildHeaders(customHeaders = {}) { + return { + 'Content-Type': 'application/json', + 'Authorization': getToken(), + ...customHeaders + } +} + +/** + * 通用请求方法 + */ +function baseRequest({ url, method = 'GET', data = {}, checkLogin = true, headers = {} }) { + return new Promise((resolve, reject) => { + // 确保URL拼接正确,避免重复的斜杠 + const fullUrl = config.baseUrl.replace(/\/$/, '') + '/' + url.replace(/^\//, '') + console.log('请求URL:', fullUrl) + + uni.request({ + url: fullUrl, + method, + data, + header: buildHeaders(headers), + success: (res) => { + const { statusCode, data: resData } = res + if (statusCode === 200 && resData) { + // 账号在其他设备登录 + if (resData.code === 409) { + uni.showModal({ + title: '提示', + content: '您的账号已在其他设备登录,已强制下线!', + showCancel: false, + success: () => handleAuthFail(checkLogin) + }) + resolve(resData) + return + } + // 用户认证失败 + if (resData.code === 5) { + handleAuthFail(checkLogin) + resolve(resData) + return + } + // 授权已过期 + if (resData.code === 5) { + console.log('检测到授权过期,code=7,准备跳转登录页') + uni.showToast({ + title: '授权已过期,请重新登录', + icon: 'none' + }) + handleAuthFail(checkLogin) + resolve(resData) + return + } + resolve(resData) + } else { + reject({ + code: statusCode, + msg: res.errMsg || '网络错误', + data: null + }) + } + }, + fail: (err) => { + console.log('请求失败:', err) + // 处理401未授权错误 + if (err.statusCode === 401 || err.code === 401) { + console.log('检测到401未授权,准备跳转登录页') + uni.showToast({ + title: '授权已过期,请重新登录', + icon: 'none' + }) + handleAuthFail(true) + reject({ + code: 7, + msg: '授权已过期', + data: null + }) + return + } + reject({ + code: 0, + msg: err.errMsg || '请求失败', + data: null + }) + } + }) + }) +} + +/** + * 导出常用请求方法 + */ +const request = { + get(url, data = {}, checkLogin = true, headers = {}) { + return baseRequest({ url, method: 'GET', data, checkLogin, headers }) + }, + post(url, data = {}, checkLogin = true, headers = {}) { + return baseRequest({ url, method: 'POST', data, checkLogin, headers }) + }, + put(url, data = {}, checkLogin = true, headers = {}) { + return baseRequest({ url, method: 'PUT', data, checkLogin, headers }) + }, + delete(url, data = {}, checkLogin = true, headers = {}) { + return baseRequest({ url, method: 'DELETE', data, checkLogin, headers }) + }, + + // 兼容原有的http.request方法 + request: ({ url, method = 'GET', data = {}, headers = {} }) => { + return baseRequest({ url, method, data, checkLogin: true, headers }) + } +} + +export default request \ No newline at end of file diff --git a/src/config/index.js b/src/config/index.js new file mode 100644 index 0000000..b5e4167 --- /dev/null +++ b/src/config/index.js @@ -0,0 +1,18 @@ +// isdev 为 true 表示开发环境 false 表示发布环境 +const isdev = true; + +// 开发环境使用代理,生产环境使用完整URL +const baseUrl = isdev ? 'http://127.0.0.1:8888/' : 'http://lckt.hnlc5588.cn/';// 开发环境代理 & 生产环境 + +const shareUrl = isdev ? 'https://h5.gwkjxb.com/' : 'http://test_h5.gwkjxb.com/'; + +const config = { + appName: '小呆呆的私人菜谱', + baseUrl, + appVersion: '1.0.0', + developer: '小呆呆的私人菜谱', + shareUrl, + appID:'wx8ed262fbd9eaaf74', + isdev +} +export default config diff --git a/src/manifest.json b/src/manifest.json index 7093534..55121f6 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -1,6 +1,6 @@ { - "name" : "zy", - "appid" : "", + "name" : "xdd-menu", + "appid" : "__UNI__3FD9A6A", "description" : "", "versionName" : "1.0.0", "versionCode" : "100", @@ -44,7 +44,7 @@ }, "quickapp" : {}, "mp-weixin" : { - "appid" : "", + "appid" : "wx8ed262fbd9eaaf74", "mergeVirtualHostAttributes" : true, "setting" : { "urlCheck" : false, diff --git a/src/pages.json b/src/pages.json index c62bddf..19d6580 100644 --- a/src/pages.json +++ b/src/pages.json @@ -2,7 +2,6 @@ "easycom": { "autoscan": true, "custom": { - // uni-ui 规则如下配置 "^uni-(.*)": "@dcloudio/uni-ui/lib/uni-$1/uni-$1.vue", "^u--(.*)": "uview-plus/components/u-$1/u-$1.vue", "^u-([^-].*)": "uview-plus/components/u-$1/u-$1.vue", @@ -12,59 +11,135 @@ } }, "pages": [ - //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages + { + "path": "pages/user/login", + "style": { + "navigationBarTitleText": "登录", + "enablePullDownRefresh": false, + "navigationStyle": "custom" + } + }, + { + "path": "pages/user/setup", + "style": { + "navigationBarTitleText": "完善信息", + "enablePullDownRefresh": false, + "navigationStyle": "custom" + } + }, { "path": "pages/home/home", "style": { - "navigationBarTitleText": "", + "navigationBarTitleText": "我们的纪念日", + "enablePullDownRefresh": false, + "navigationStyle": "custom" + } + }, + { + "path": "pages/recipe/recipe", + "style": { + "navigationBarTitleText": "私人菜谱", "enablePullDownRefresh": false } }, { - "path": "pages/components/components", + "path": "pages/recipe/create", "style": { - "navigationBarTitleText": "", + "navigationBarTitleText": "创建菜品", "enablePullDownRefresh": false } }, { - "path": "pages/functions/functions", + "path": "pages/recipe/detail", "style": { - "navigationBarTitleText": "", + "navigationBarTitleText": "菜品详情", "enablePullDownRefresh": false } }, { - "path": "pages/uploadDemo/uploadDemo", + "path": "pages/order/order", "style": { - "navigationBarTitleText": "", + "navigationBarTitleText": "点餐", + "enablePullDownRefresh": false + } + }, + { + "path": "pages/diary/diary", + "style": { + "navigationBarTitleText": "我们的日志", + "enablePullDownRefresh": false + } + }, + { + "path": "pages/diary/create", + "style": { + "navigationBarTitleText": "写日志", + "enablePullDownRefresh": false + } + }, + { + "path": "pages/checkin/checkin", + "style": { + "navigationBarTitleText": "打卡目标", + "enablePullDownRefresh": false + } + }, + { + "path": "pages/checkin/create", + "style": { + "navigationBarTitleText": "创建目标", + "enablePullDownRefresh": false + } + }, + { + "path": "pages/profile/profile", + "style": { + "navigationBarTitleText": "个人中心", "enablePullDownRefresh": false } } ], "globalStyle": { "navigationBarBackgroundColor": "#fff", - "navigationBarTitleText": "订单中心", - "navigationStyle": "custom", + "navigationBarTitleText": "情侣菜谱", + "navigationStyle": "default", "navigationBarTextStyle": "black" }, "tabBar": { - "color": "#333333", - "selectedColor": "#2E69FF", + "color": "#999999", + "selectedColor": "#FF6B9D", "borderStyle": "white", "backgroundColor": "#ffffff", "list": [ { "pagePath": "pages/home/home", - "text": "首页" + "text": "首页", + "iconPath": "./static/images/home.png", + "selectedIconPath": "./static/images/home-active.png" }, { - "pagePath": "pages/components/components", - "text": "组件" + "pagePath": "pages/recipe/recipe", + "text": "菜谱", + "iconPath": "./static/images/recipe.png", + "selectedIconPath": "./static/images/recipe-active.png" }, { - "pagePath": "pages/functions/functions", - "text": "功能" + "pagePath": "pages/diary/diary", + "text": "日志", + "iconPath": "./static/images/diary.png", + "selectedIconPath": "./static/images/diary-active.png" + }, + { + "pagePath": "pages/checkin/checkin", + "text": "打卡", + "iconPath": "./static/images/checkin.png", + "selectedIconPath": "./static/images/checkin-active.png" + }, + { + "pagePath": "pages/profile/profile", + "text": "我的", + "iconPath": "./static/images/profile.png", + "selectedIconPath": "./static/images/profile-active.png" } ] } diff --git a/src/pages/checkin/checkin.vue b/src/pages/checkin/checkin.vue new file mode 100644 index 0000000..72efe3f --- /dev/null +++ b/src/pages/checkin/checkin.vue @@ -0,0 +1,577 @@ + + + + + \ No newline at end of file diff --git a/src/pages/components/components.vue b/src/pages/components/components.vue deleted file mode 100644 index 89f3590..0000000 --- a/src/pages/components/components.vue +++ /dev/null @@ -1,46 +0,0 @@ - - - - diff --git a/src/pages/diary/diary.vue b/src/pages/diary/diary.vue new file mode 100644 index 0000000..d59e4e1 --- /dev/null +++ b/src/pages/diary/diary.vue @@ -0,0 +1,457 @@ + + + + + \ No newline at end of file diff --git a/src/pages/functions/functions.vue b/src/pages/functions/functions.vue deleted file mode 100644 index ab2d20c..0000000 --- a/src/pages/functions/functions.vue +++ /dev/null @@ -1,50 +0,0 @@ - - - - diff --git a/src/pages/home/home.vue b/src/pages/home/home.vue index ce8975a..4482726 100644 --- a/src/pages/home/home.vue +++ b/src/pages/home/home.vue @@ -1,15 +1,450 @@ - - + + + \ No newline at end of file diff --git a/src/pages/order/order.vue b/src/pages/order/order.vue new file mode 100644 index 0000000..aff09b7 --- /dev/null +++ b/src/pages/order/order.vue @@ -0,0 +1,562 @@ + + + + + \ No newline at end of file diff --git a/src/pages/profile/profile.vue b/src/pages/profile/profile.vue new file mode 100644 index 0000000..aa06291 --- /dev/null +++ b/src/pages/profile/profile.vue @@ -0,0 +1,567 @@ + + + + + \ No newline at end of file diff --git a/src/pages/recipe/recipe.vue b/src/pages/recipe/recipe.vue new file mode 100644 index 0000000..22b8871 --- /dev/null +++ b/src/pages/recipe/recipe.vue @@ -0,0 +1,338 @@ + + + + + \ No newline at end of file diff --git a/src/pages/user/login.vue b/src/pages/user/login.vue new file mode 100644 index 0000000..da45a5a --- /dev/null +++ b/src/pages/user/login.vue @@ -0,0 +1,526 @@ + + + + + diff --git a/src/pages/user/setup.vue b/src/pages/user/setup.vue new file mode 100644 index 0000000..62e25aa --- /dev/null +++ b/src/pages/user/setup.vue @@ -0,0 +1,328 @@ + + + + + diff --git a/src/static/images/checkin-active.png b/src/static/images/checkin-active.png new file mode 100644 index 0000000000000000000000000000000000000000..b68cca6e0ebc609d1fc9753cac1e907f929f8d3b GIT binary patch literal 4384 zcmZu#c|4Te7oX=b6HS(}jO-1@Hd?$PL_EWkJ?q#>mWn7_WPfZ!h_PlXvWAf2Me-(V z$eN1CGPW!wlzsV4|Ns8D_uS99=bU@b=id9h-_LnqcvX`H&4)%H5G>kSBxAaK|F}%Tx->lqv&n?tX*rI`FgUgo~FSPDZs1$Y>wRn z+1uZ>Hi|0lZw?;!P7FgTj~rVvGcxSV2PygWTQ(uXrT5omVla?C zxJ2AeLl4t!@5$Hep*Fd2IC;9=E9NzYhO;Z5zGz}?roJ3E`KW4A{&8=2JF>bmwy z*>Rw8Sq$g=-08sdsxQfXVxPnVoxL|$#ss0#G=*^oLWrxB9z^OY>8X;=1eh}ga}nLE z2BY$oEuG#Sb@Es>`7{F|Dy^{E+?G^U;hWvndmW8Sx2w9nUjKZSbL8P!6r8fP z@dCVKos2>Xx+^TkHaR<$n;aF5NRLmN?*A^j^%CCZNS(W?3xG79{&Bv}`8eKo39Q;y z1QFWAPWurIO<;JqZOS16d{8BVdytFpIjRSdv-PUuS@mEFfSft7P44Ygt8ti|tADz| z`lBShLnBR=0R4K8d{Ug||L57}nB$_C8m&Q><6V`Ql7Sa^CwKja*9z6Y{T=Zj)ne}Q z?(3Efdo{JmiG%%p^WO>-d*{f# zdA>^829NoI&an8A$bkvF&WLt&8}=(_QM-hFakm-4-6p6%@FdEA^b7&QQStj9hlVid zl+T?sk$O^ZxRn^UVLk%sZfrxGjl{?>XX}gqV9Oc=V}D!TVLa-rc?Tr%Y3yRFq+9t~ zf4wR|oJ}<@7@4EicG<(ti!VPz(Se%0Ay2_o^oVq+zKqrAoQnVCH%}J~G*B4+ky1;U zE~y23gm=a1al}8#Q+BL+TH;OfO!K~HN4k5VP)LuMs_!v9@toN21&A!0Y25K+Ow-@J z&wJ$FK(!D#keJ^}ZAPC3L_mo%s1@wtW1fghR$>>@HrT1fHmu82h&=&T(CbSCI?n*q zV!dHFG9`%Ntw;_OK&QWCA`IjqaPKbHUr*^KRKfNZSD&}BoXYgf2Sd1;FOQtWPawkH z<&7ocPp6?*Bt3qXm(H(mVosQqf9kYodinx@_MC~K;izPU9OGV}0hYih`GZK7oebP>= zn!?ehWPKv8m@H1)nENuBcrE12&l}6DppLI7dWt44d!T)BWl~O;%t-p_f4@Q40$vMd zt(HgGTVBUP`!|-`S!hz4o1UH~2d6m5Q1{hj-yhXs85lFcdpqy(sCsykfQK zlIGq0>*b$34*rJ;0lwW+17o^jZ%&!*DiMg(!ACe~3+t20TY`@w;l{DR;K9X`x0iQpJjKaaU9^L{JQB3F`(*G!ao zx){P$Np&d_p*a;N@1x1e+;%;>?FR1bDU8T)+N_j8fQo?svs1ruqUsx?0XFiC`{l-j z5VJ$q5689i+eZV|aEl-g*Hz5_p@{PC?Qp`u{DzMD>%wM!GNs^gE#v9p zSGIJlx5YXh7Sf?!J1V=+mkh%`$OT57@h?&LpWi&K09&}rVr>eW*-<@SNLf*~5 z6$@xfj>84prA}i@`uhki*OY}w{O%M1*ui!AnEQkk6t^@$w7F=@+nq7K)hxI{K7-b; z((sM6e}1^KZmfAfcFm21gH(9M>pIvIDugbCx-3<>)#>lB0hwMt?FuZ4g*=%n~pp4|Pm4U#xV1cu-=U+)a&toT`w<8&j(d3IVN>Z8Llky)n z&i?0`V4NTA^<+36*29g%4E<(1K65K`ed&<5_!L zdqQMpCaofpdqT=7nJE`D%OUX?uo zjK-Dc{H_m$YwC*DmK)%jmhVP0W{J`Vt%Yug;@E&=ik*3yxUTZd2 z62lJ}?RXSB_N?P2L_Z5N0HfG)a&L8G&!)AE7Sf^GbF6Jl$l{32m9@oaQ3uiyi{-4^ zAG$j)$WhH+%Wtf9!eF&Fv*Ng>tvI+|d8Is5Be;K}ewHQqWv*zg=8UJj*_~OtPMd-} zsWc)qQ6N=dvU*J*eOMR}80ueJ4upzbPRoSX6c+yIKFLz{OXTLSLc^TN;;ex z+l46^#!a}g3lw4ThpWliv$<93GGE0(V?tEO`%&GWd!q#f)a@vS1lrl1mbyg60VfWi zH0mWh`zQb3?oJ0${Pn3R+x1F73>O#+a9Gam5gHk~KF(G6yx$2*`!4j21o5dG``Sl9 z;i26eoZCTZF_;+=#7Yw5!e6+%|1g2U?4DikLit7Ae;esX@X2w(8mHx(P`V>lXPL23 zF846u`DxHg1m_q<`nwKiwfn0~xW>@MjfzR&Cc0-v!8KfH>g;FI(H+T_!Si`%Ua?ct z)rI*dez7azgZ@K@8S5bn3o@$JK@X#zdp;7oD;oS-Pyh+1uC*ORPE`DNlpevTRM8!_aJz?a< zTQ)5w&4>ZOj2&Yj61sb^3pbAOwR5tvVE57n*{C6%IJVwK63QF=0|7CjT8x81YU8p-_CAL=V|W)!3zz&PBpHc zej=w77!6?rJR|6*M+CrR_0&bjyC??+(y|{Ic%ntH6tV@d z&_HG7$)%U^rxHC!bN3Ri0oeZX~*Mr(-CdGt`?_sRQ#-Y)gbe0_D^|AuWS>}LJV3VdtwJ) z#fv@E1S$@r??3laC4dfxqE|}wvdr1B5f)k)RP2cYva7>#&8=a?;H_1%5p^*7Zj{BR ztdWHp1C6jpvW>%%jLx&4%WPhJLP(7T5r1tH`QlSTO#%sFPR<(?BJwj_=k>LmWz= zN?O0p>-KP;1{uiVWH-^>uBY5)Nq^)x$q^bz)&*q^!(3I*)0)Y-GRcbCa1tC zRr-VZanCF7O`J@o*f5{Lqig2%+x{Lp75=EPVc^}7ywlx3X&hEYY@)0LsY9l+>dnvg$bcTye;m;ktb$*Z773l>-X@0aSG!dNjpSFiNaJK)$Q=SbdZv&iu==)UP7uR% z-um2ts*}kH2bof-sq#r91sNusVjeU!Uz`2DTP_6kCJ^WGA^4B-QU@agl2HtA7}iA& zGxTWg%Y&z2G5ksj#9Um7c2jQwX2Kc5BhdJ{o@|yqF-op4dN#4%9g}ZKuDgkW>=9S$ zW?h^6l-uktmLYz6fA~DPQ19*`R}lR$0syah$TyRT>4UQl?jq_QWzukN)W}gq>aOom zPXq{Vd5|-@WIT+rXH|2-j_Hh!g63X5R~8#mw4A>OL|70;BH0b+=YK>ymsRAHJZ;_t zrR-0yxHUoL4jy#{K%p_Mr|Rvgn_hDm!;z#aQs&`4k#qGv~zl)L(RLrRxK%>8P8qt(nNf5>K-p4`PKt(bS6~p+^ z0*~df1Hkh^%(sYbfB98}#zzXBvoW7yu) IQr$lMf1Nq-7ytkO literal 0 HcmV?d00001 diff --git a/src/static/images/checkin.png b/src/static/images/checkin.png new file mode 100644 index 0000000000000000000000000000000000000000..aa5442f830c1c9537f59cc20eca6cbfb0c7addce GIT binary patch literal 4376 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 Khptq$3;Q2n_>mw0 literal 0 HcmV?d00001 diff --git a/src/static/images/diary.png b/src/static/images/diary.png new file mode 100644 index 0000000000000000000000000000000000000000..cb537ab562edabea6be4335434ec060991049518 GIT binary patch literal 6934 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 literal 0 HcmV?d00001 diff --git a/src/static/images/home-active.png b/src/static/images/home-active.png new file mode 100644 index 0000000000000000000000000000000000000000..036f4952fa210f775676ad7d9b79825cea815747 GIT binary patch literal 4603 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 L>WankX2JghdAeI^ literal 0 HcmV?d00001 diff --git a/src/static/images/profile-active.png b/src/static/images/profile-active.png new file mode 100644 index 0000000000000000000000000000000000000000..2efe615e0af544b0093ff3f0ab3b07d8554f851b GIT binary patch literal 3893 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 P@H`N*u_dw8(2enbwYuE^ literal 0 HcmV?d00001 diff --git a/src/static/images/recipe-active.png b/src/static/images/recipe-active.png new file mode 100644 index 0000000000000000000000000000000000000000..2ccafbdc613711b2a6d46eb4c35dd657a2718687 GIT binary patch literal 5741 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 { return { - token: '', + token: uni.getStorageSync('token') || '', // 从缓存读取token userInfo: {}, // 用户信息 appInfo: {}, // 应用信息 // 按钮权限编码 @@ -12,10 +12,107 @@ export const useUserStore = defineStore({ // 权限菜单 menuList: [], // 权限路由 - permissionRoutes: [] + permissionRoutes: [], + // 是否已登录 + isLoggedIn: !!uni.getStorageSync('token') } }, unistorage: true, - getters: {}, - actions: {} + getters: { + // 获取用户昵称 + nickname: (state) => state.userInfo.nickname || '未登录', + + // 获取用户头像 + avatar: (state) => state.userInfo.avatar || '/static/images/default-avatar.png', + + // 获取用户ID + userId: (state) => state.userInfo.userId || '', + + // 检查是否已登录 + hasLogin: (state) => state.isLoggedIn && !!state.token, + + // 检查是否首次登录 + isFirstLogin: (state) => state.userInfo.isFirstLogin || false + }, + actions: { + // 设置用户信息 + setUserInfo(userInfo) { + this.userInfo = userInfo + this.isLoggedIn = true + }, + + // 设置token + setToken(token) { + this.token = token + // 同时保存到本地缓存 + uni.setStorageSync('token', token) + }, + + // 登录 + async login(loginData) { + try { + // 这里可以调用登录API + // const result = await userApi.login(loginData) + + // 模拟登录成功 + const mockUserInfo = { + userId: '10086', + nickname: '小美', + avatar: '/static/images/default-avatar.png', + level: 'LV.5 美食达人' + } + + this.setUserInfo(mockUserInfo) + this.setToken('mock_token_' + Date.now()) + + return { + success: true, + data: mockUserInfo + } + } catch (error) { + console.error('登录失败:', error) + return { + success: false, + message: error.message || '登录失败' + } + } + }, + + // 登出 + logout() { + this.token = '' + this.userInfo = {} + this.isLoggedIn = false + this.permissionCodes = [] + this.menuList = [] + this.permissionRoutes = [] + // 清除本地缓存 + uni.removeStorageSync('token') + }, + + // 更新用户信息 + updateUserInfo(userInfo) { + this.userInfo = { ...this.userInfo, ...userInfo } + // 如果更新了昵称,清除首次登录状态 + if (userInfo.nickname) { + this.userInfo.isFirstLogin = false + } + }, + + // 检查登录状态 + checkLoginStatus() { + // 从缓存重新读取token + const cachedToken = uni.getStorageSync('token') + if (cachedToken && cachedToken !== this.token) { + this.token = cachedToken + this.isLoggedIn = true + } + return this.hasLogin + }, + + // 清除首次登录状态 + clearFirstLogin() { + this.userInfo.isFirstLogin = false + } + } })