diff --git a/admin/node_modules/.vite/deps/_metadata.json b/admin/node_modules/.vite/deps/_metadata.json index 385afdcd..8bbc9c71 100644 --- a/admin/node_modules/.vite/deps/_metadata.json +++ b/admin/node_modules/.vite/deps/_metadata.json @@ -2,288 +2,300 @@ "hash": "481070f0", "configHash": "0bd4dba1", "lockfileHash": "aa252f00", - "browserHash": "f45a29de", + "browserHash": "aa056658", "optimized": { "@element-plus/icons-vue": { "src": "../../@element-plus/icons-vue/dist/index.js", "file": "@element-plus_icons-vue.js", - "fileHash": "303763e5", + "fileHash": "c76bcc44", "needsInterop": false }, "@wangeditor/editor-for-vue": { "src": "../../@wangeditor/editor-for-vue/dist/index.esm.js", "file": "@wangeditor_editor-for-vue.js", - "fileHash": "f00791f0", + "fileHash": "37aca601", "needsInterop": false }, "axios": { "src": "../../axios/index.js", "file": "axios.js", - "fileHash": "82f2009c", + "fileHash": "3f28a8a9", "needsInterop": false }, "dayjs": { "src": "../../dayjs/dayjs.min.js", "file": "dayjs.js", - "fileHash": "5645dea7", + "fileHash": "d74a620b", "needsInterop": true }, "element-plus": { "src": "../../element-plus/es/index.mjs", "file": "element-plus.js", - "fileHash": "e550aa25", + "fileHash": "5589b60e", "needsInterop": false }, "element-plus/dist/locale/zh-cn.mjs": { "src": "../../element-plus/dist/locale/zh-cn.mjs", "file": "element-plus_dist_locale_zh-cn__mjs.js", - "fileHash": "3b744d4a", + "fileHash": "c0fd1204", "needsInterop": false }, "pinia": { "src": "../../pinia/dist/pinia.mjs", "file": "pinia.js", - "fileHash": "8c748394", + "fileHash": "dc1f88e8", "needsInterop": false }, "qrcode": { "src": "../../qrcode/lib/browser.js", "file": "qrcode.js", - "fileHash": "e1329e14", + "fileHash": "6c0a34f3", "needsInterop": true }, "vue": { "src": "../../vue/dist/vue.runtime.esm-bundler.js", "file": "vue.js", - "fileHash": "853300f0", + "fileHash": "868e6988", "needsInterop": false }, "vue-router": { "src": "../../vue-router/dist/vue-router.mjs", "file": "vue-router.js", - "fileHash": "d904f03a", + "fileHash": "b4f98d74", "needsInterop": false }, "element-plus/es": { "src": "../../element-plus/es/index.mjs", "file": "element-plus_es.js", - "fileHash": "29301e56", + "fileHash": "8a699395", "needsInterop": false }, "element-plus/es/components/base/style/css": { "src": "../../element-plus/es/components/base/style/css.mjs", "file": "element-plus_es_components_base_style_css.js", - "fileHash": "1d49b62e", + "fileHash": "ad6081a9", "needsInterop": false }, "element-plus/es/components/dialog/style/css": { "src": "../../element-plus/es/components/dialog/style/css.mjs", "file": "element-plus_es_components_dialog_style_css.js", - "fileHash": "5bba98de", + "fileHash": "ebd107ef", "needsInterop": false }, "element-plus/es/components/button/style/css": { "src": "../../element-plus/es/components/button/style/css.mjs", "file": "element-plus_es_components_button_style_css.js", - "fileHash": "fd8b0f8b", + "fileHash": "ff2f2a5b", "needsInterop": false }, "element-plus/es/components/form/style/css": { "src": "../../element-plus/es/components/form/style/css.mjs", "file": "element-plus_es_components_form_style_css.js", - "fileHash": "2ee6e663", + "fileHash": "df7fdb18", "needsInterop": false }, "element-plus/es/components/form-item/style/css": { "src": "../../element-plus/es/components/form-item/style/css.mjs", "file": "element-plus_es_components_form-item_style_css.js", - "fileHash": "cf1450df", + "fileHash": "e9c6d01b", "needsInterop": false }, "element-plus/es/components/input/style/css": { "src": "../../element-plus/es/components/input/style/css.mjs", "file": "element-plus_es_components_input_style_css.js", - "fileHash": "6aca7cf0", + "fileHash": "e2b09618", "needsInterop": false }, "element-plus/es/components/container/style/css": { "src": "../../element-plus/es/components/container/style/css.mjs", "file": "element-plus_es_components_container_style_css.js", - "fileHash": "4717aecb", + "fileHash": "c0984641", "needsInterop": false }, "element-plus/es/components/main/style/css": { "src": "../../element-plus/es/components/main/style/css.mjs", "file": "element-plus_es_components_main_style_css.js", - "fileHash": "f3ba5b99", + "fileHash": "a73569af", "needsInterop": false }, "element-plus/es/components/header/style/css": { "src": "../../element-plus/es/components/header/style/css.mjs", "file": "element-plus_es_components_header_style_css.js", - "fileHash": "96b2ed2f", + "fileHash": "b592e09f", "needsInterop": false }, "element-plus/es/components/dropdown/style/css": { "src": "../../element-plus/es/components/dropdown/style/css.mjs", "file": "element-plus_es_components_dropdown_style_css.js", - "fileHash": "d0a6dac3", + "fileHash": "f7bb8b58", "needsInterop": false }, "element-plus/es/components/dropdown-menu/style/css": { "src": "../../element-plus/es/components/dropdown-menu/style/css.mjs", "file": "element-plus_es_components_dropdown-menu_style_css.js", - "fileHash": "35005d29", + "fileHash": "60954d93", "needsInterop": false }, "element-plus/es/components/dropdown-item/style/css": { "src": "../../element-plus/es/components/dropdown-item/style/css.mjs", "file": "element-plus_es_components_dropdown-item_style_css.js", - "fileHash": "82f476ab", + "fileHash": "018afb10", "needsInterop": false }, "element-plus/es/components/avatar/style/css": { "src": "../../element-plus/es/components/avatar/style/css.mjs", "file": "element-plus_es_components_avatar_style_css.js", - "fileHash": "a9f261cc", + "fileHash": "6a7d147e", "needsInterop": false }, "element-plus/es/components/breadcrumb/style/css": { "src": "../../element-plus/es/components/breadcrumb/style/css.mjs", "file": "element-plus_es_components_breadcrumb_style_css.js", - "fileHash": "3f3f3b42", + "fileHash": "a2b08aeb", "needsInterop": false }, "element-plus/es/components/breadcrumb-item/style/css": { "src": "../../element-plus/es/components/breadcrumb-item/style/css.mjs", "file": "element-plus_es_components_breadcrumb-item_style_css.js", - "fileHash": "a5e97d32", + "fileHash": "df52cc96", "needsInterop": false }, "element-plus/es/components/aside/style/css": { "src": "../../element-plus/es/components/aside/style/css.mjs", "file": "element-plus_es_components_aside_style_css.js", - "fileHash": "64e45da0", + "fileHash": "ac5e261e", "needsInterop": false }, "element-plus/es/components/menu/style/css": { "src": "../../element-plus/es/components/menu/style/css.mjs", "file": "element-plus_es_components_menu_style_css.js", - "fileHash": "2f316cd2", + "fileHash": "4e7cd965", "needsInterop": false }, "element-plus/es/components/menu-item/style/css": { "src": "../../element-plus/es/components/menu-item/style/css.mjs", "file": "element-plus_es_components_menu-item_style_css.js", - "fileHash": "afb95054", + "fileHash": "51fb1a5d", "needsInterop": false }, "element-plus/es/components/icon/style/css": { "src": "../../element-plus/es/components/icon/style/css.mjs", "file": "element-plus_es_components_icon_style_css.js", - "fileHash": "9d19ab9f", + "fileHash": "ceb23baa", "needsInterop": false }, "element-plus/es/components/loading/style/css": { "src": "../../element-plus/es/components/loading/style/css.mjs", "file": "element-plus_es_components_loading_style_css.js", - "fileHash": "8679a851", + "fileHash": "19b92455", "needsInterop": false }, "element-plus/es/components/pagination/style/css": { "src": "../../element-plus/es/components/pagination/style/css.mjs", "file": "element-plus_es_components_pagination_style_css.js", - "fileHash": "e7d9082b", + "fileHash": "94ca04a5", "needsInterop": false }, "element-plus/es/components/table/style/css": { "src": "../../element-plus/es/components/table/style/css.mjs", "file": "element-plus_es_components_table_style_css.js", - "fileHash": "c2ed39c2", + "fileHash": "624bb620", "needsInterop": false }, "element-plus/es/components/tag/style/css": { "src": "../../element-plus/es/components/tag/style/css.mjs", "file": "element-plus_es_components_tag_style_css.js", - "fileHash": "cb057059", + "fileHash": "20423d57", "needsInterop": false }, "element-plus/es/components/image/style/css": { "src": "../../element-plus/es/components/image/style/css.mjs", "file": "element-plus_es_components_image_style_css.js", - "fileHash": "351b3909", + "fileHash": "994dd216", "needsInterop": false }, "element-plus/es/components/table-column/style/css": { "src": "../../element-plus/es/components/table-column/style/css.mjs", "file": "element-plus_es_components_table-column_style_css.js", - "fileHash": "6eb55fa5", + "fileHash": "1b6a0c06", "needsInterop": false }, "element-plus/es/components/select/style/css": { "src": "../../element-plus/es/components/select/style/css.mjs", "file": "element-plus_es_components_select_style_css.js", - "fileHash": "daf87f44", + "fileHash": "c8ac9a5a", "needsInterop": false }, "element-plus/es/components/option/style/css": { "src": "../../element-plus/es/components/option/style/css.mjs", "file": "element-plus_es_components_option_style_css.js", - "fileHash": "8cdd90ba", + "fileHash": "ee3e00ce", "needsInterop": false }, "element-plus/es/components/radio-group/style/css": { "src": "../../element-plus/es/components/radio-group/style/css.mjs", "file": "element-plus_es_components_radio-group_style_css.js", - "fileHash": "33078822", + "fileHash": "56871901", "needsInterop": false }, "element-plus/es/components/radio/style/css": { "src": "../../element-plus/es/components/radio/style/css.mjs", "file": "element-plus_es_components_radio_style_css.js", - "fileHash": "aee22efa", + "fileHash": "4857765a", "needsInterop": false }, "element-plus/es/components/switch/style/css": { "src": "../../element-plus/es/components/switch/style/css.mjs", "file": "element-plus_es_components_switch_style_css.js", - "fileHash": "5d58ccb8", + "fileHash": "3bf1b3df", "needsInterop": false }, "element-plus/es/components/input-number/style/css": { "src": "../../element-plus/es/components/input-number/style/css.mjs", "file": "element-plus_es_components_input-number_style_css.js", - "fileHash": "8826e069", + "fileHash": "70e0ea9b", "needsInterop": false }, "element-plus/es/components/autocomplete/style/css": { "src": "../../element-plus/es/components/autocomplete/style/css.mjs", "file": "element-plus_es_components_autocomplete_style_css.js", - "fileHash": "50eaf0f2", + "fileHash": "f192d727", "needsInterop": false }, "element-plus/es/components/row/style/css": { "src": "../../element-plus/es/components/row/style/css.mjs", "file": "element-plus_es_components_row_style_css.js", - "fileHash": "c8e609ae", + "fileHash": "c97af601", "needsInterop": false }, "element-plus/es/components/col/style/css": { "src": "../../element-plus/es/components/col/style/css.mjs", "file": "element-plus_es_components_col_style_css.js", - "fileHash": "8683f4d3", + "fileHash": "c5850ceb", "needsInterop": false }, "element-plus/es/components/descriptions/style/css": { "src": "../../element-plus/es/components/descriptions/style/css.mjs", "file": "element-plus_es_components_descriptions_style_css.js", - "fileHash": "3fde99e8", + "fileHash": "fab03c68", "needsInterop": false }, "element-plus/es/components/descriptions-item/style/css": { "src": "../../element-plus/es/components/descriptions-item/style/css.mjs", "file": "element-plus_es_components_descriptions-item_style_css.js", - "fileHash": "96d9d5dc", + "fileHash": "3eed0a24", + "needsInterop": false + }, + "element-plus/es/components/divider/style/css": { + "src": "../../element-plus/es/components/divider/style/css.mjs", + "file": "element-plus_es_components_divider_style_css.js", + "fileHash": "dc0118ee", + "needsInterop": false + }, + "element-plus/es/components/text/style/css": { + "src": "../../element-plus/es/components/text/style/css.mjs", + "file": "element-plus_es_components_text_style_css.js", + "fileHash": "7829d239", "needsInterop": false } }, @@ -291,6 +303,9 @@ "chunk-4PW274X2": { "file": "chunk-4PW274X2.js" }, + "chunk-JUCAMQ7P": { + "file": "chunk-JUCAMQ7P.js" + }, "chunk-B2YDYSZR": { "file": "chunk-B2YDYSZR.js" }, @@ -306,42 +321,39 @@ "chunk-R5DNQ3QC": { "file": "chunk-R5DNQ3QC.js" }, - "chunk-NKQWFVTF": { - "file": "chunk-NKQWFVTF.js" - }, "chunk-REWOA3VH": { "file": "chunk-REWOA3VH.js" }, "chunk-TX5YLZ4O": { "file": "chunk-TX5YLZ4O.js" }, - "chunk-YFT6OQ5R": { - "file": "chunk-YFT6OQ5R.js" - }, "chunk-SMFPDFTD": { "file": "chunk-SMFPDFTD.js" }, - "chunk-JUCAMQ7P": { - "file": "chunk-JUCAMQ7P.js" + "chunk-YFT6OQ5R": { + "file": "chunk-YFT6OQ5R.js" + }, + "chunk-NKQWFVTF": { + "file": "chunk-NKQWFVTF.js" }, "chunk-IV6PSERC": { "file": "chunk-IV6PSERC.js" }, - "chunk-ZLPQR2PE": { - "file": "chunk-ZLPQR2PE.js" + "chunk-LYXQVMFB": { + "file": "chunk-LYXQVMFB.js" }, "chunk-HYZ2CRGS": { "file": "chunk-HYZ2CRGS.js" }, - "chunk-QZC7O2C6": { - "file": "chunk-QZC7O2C6.js" - }, "chunk-OP4ZUAFM": { "file": "chunk-OP4ZUAFM.js" }, "chunk-H2732BJL": { "file": "chunk-H2732BJL.js" }, + "chunk-QZC7O2C6": { + "file": "chunk-QZC7O2C6.js" + }, "chunk-G3PMV62Z": { "file": "chunk-G3PMV62Z.js" } diff --git a/admin/node_modules/.vite/deps/element-plus.js b/admin/node_modules/.vite/deps/element-plus.js index 9a9e9235..617ac7ec 100644 --- a/admin/node_modules/.vite/deps/element-plus.js +++ b/admin/node_modules/.vite/deps/element-plus.js @@ -514,11 +514,11 @@ import { virtualizedScrollbarProps, watermarkProps, zIndexContextKey -} from "./chunk-ZLPQR2PE.js"; +} from "./chunk-LYXQVMFB.js"; import "./chunk-HYZ2CRGS.js"; -import "./chunk-QZC7O2C6.js"; import "./chunk-OP4ZUAFM.js"; import "./chunk-H2732BJL.js"; +import "./chunk-QZC7O2C6.js"; import "./chunk-G3PMV62Z.js"; var export_dayjs = import_dayjs.default; export { diff --git a/admin/node_modules/.vite/deps/element-plus_es.js b/admin/node_modules/.vite/deps/element-plus_es.js index c0ecd32f..63501658 100644 --- a/admin/node_modules/.vite/deps/element-plus_es.js +++ b/admin/node_modules/.vite/deps/element-plus_es.js @@ -514,11 +514,11 @@ import { virtualizedScrollbarProps, watermarkProps, zIndexContextKey -} from "./chunk-ZLPQR2PE.js"; +} from "./chunk-LYXQVMFB.js"; import "./chunk-HYZ2CRGS.js"; -import "./chunk-QZC7O2C6.js"; import "./chunk-OP4ZUAFM.js"; import "./chunk-H2732BJL.js"; +import "./chunk-QZC7O2C6.js"; import "./chunk-G3PMV62Z.js"; var export_dayjs = import_dayjs.default; export { diff --git a/admin/node_modules/.vite/deps/element-plus_es_components_pagination_style_css.js b/admin/node_modules/.vite/deps/element-plus_es_components_pagination_style_css.js index ff3bac4c..66f41ea2 100644 --- a/admin/node_modules/.vite/deps/element-plus_es_components_pagination_style_css.js +++ b/admin/node_modules/.vite/deps/element-plus_es_components_pagination_style_css.js @@ -1,9 +1,9 @@ import "./chunk-75C4BP7B.js"; import "./chunk-5KK3TTMN.js"; import "./chunk-UBLR4G7Q.js"; -import "./chunk-NKQWFVTF.js"; import "./chunk-REWOA3VH.js"; import "./chunk-TX5YLZ4O.js"; +import "./chunk-NKQWFVTF.js"; import "./chunk-IV6PSERC.js"; // node_modules/element-plus/es/components/pagination/style/css.mjs diff --git a/miniprogram/app.js b/miniprogram/app.js index 58117c74..ce76aeb9 100644 --- a/miniprogram/app.js +++ b/miniprogram/app.js @@ -15,11 +15,13 @@ App({ }, onLaunch() { - // 从本地存储读取token + // 从本地存储读取 token 和上次选择的门店 const token = wx.getStorageSync("token"); if (token) { this.globalData.token = token; - this.getUserInfo(); + this.ensureCurrentStore() + .then(() => this.getUserInfo(this.globalData.currentStore?.storeId)) + .catch(() => {}); } }, @@ -94,12 +96,11 @@ App({ this.globalData.token = loginRes.data.data.token; this.globalData.userInfo = loginRes.data.data.userInfo; - // 处理天梯用户信息 - if ( - loginRes.data.data.userInfo.ladderUsers && - loginRes.data.data.userInfo.ladderUsers.length > 0 - ) { - // 如果有当前门店,优先选择当前门店的天梯用户 + // 处理天梯用户信息(战力按当前门店,当前门店无天梯则不显示) + if ( + loginRes.data.data.userInfo.ladderUsers && + loginRes.data.data.userInfo.ladderUsers.length > 0 + ) { if ( this.globalData.currentStore && this.globalData.currentStore.storeId @@ -108,20 +109,12 @@ App({ loginRes.data.data.userInfo.ladderUsers.find( (lu) => lu.storeId === this.globalData.currentStore.storeId, ); - if (currentStoreLadderUser) { - this.globalData.ladderUser = currentStoreLadderUser; - } else { - // 当前门店没有天梯用户,取第一个 - this.globalData.ladderUser = - loginRes.data.data.userInfo.ladderUsers[0]; - } + // 仅当当前门店有天梯用户时才显示,否则为 null,避免显示其他门店数据 + this.globalData.ladderUser = currentStoreLadderUser || null; } else { - // 没有当前门店,取第一个天梯用户 - this.globalData.ladderUser = - loginRes.data.data.userInfo.ladderUsers[0]; + this.globalData.ladderUser = null; } } else { - // 没有天梯用户 this.globalData.ladderUser = null; } @@ -142,16 +135,16 @@ App({ return this.wxLogin(); }, - // 获取用户信息 - getUserInfo() { + // 获取用户信息(storeId 可选,传入时返回该门店的积分 storePoints) + getUserInfo(storeId) { return new Promise((resolve, reject) => { - this.request("/api/user/info") + const data = storeId ? { store_id: storeId } : {}; + this.request("/api/user/info", data) .then((res) => { this.globalData.userInfo = res.data; - // 处理天梯用户信息 + // 处理天梯用户信息(战力按当前门店,当前门店无天梯则不显示) if (res.data.ladderUsers && res.data.ladderUsers.length > 0) { - // 如果有当前门店,优先选择当前门店的天梯用户 if ( this.globalData.currentStore && this.globalData.currentStore.storeId @@ -159,18 +152,12 @@ App({ const currentStoreLadderUser = res.data.ladderUsers.find( (lu) => lu.storeId === this.globalData.currentStore.storeId, ); - if (currentStoreLadderUser) { - this.globalData.ladderUser = currentStoreLadderUser; - } else { - // 当前门店没有天梯用户,取第一个 - this.globalData.ladderUser = res.data.ladderUsers[0]; - } + // 仅当当前门店有天梯用户时才显示,否则为 null,避免显示其他门店数据 + this.globalData.ladderUser = currentStoreLadderUser || null; } else { - // 没有当前门店,取第一个天梯用户 - this.globalData.ladderUser = res.data.ladderUsers[0]; + this.globalData.ladderUser = null; } } else { - // 没有天梯用户 this.globalData.ladderUser = null; } @@ -181,7 +168,28 @@ App({ }); }, - // 获取当前门店 + /** + * 优先使用上次选择的门店,没有或失败时再请求最近门店(新用户逻辑) + */ + ensureCurrentStore() { + const lastStore = wx.getStorageSync("last_store"); + if (lastStore && lastStore.storeId) { + this.globalData.currentStore = { + storeId: lastStore.storeId, + storeName: lastStore.storeName || "", + storeAddress: lastStore.storeAddress || "", + }; + return this.getLadderUser(lastStore.storeId) + .then(() => this.globalData.currentStore) + .catch(() => { + wx.removeStorageSync("last_store"); + return this.getCurrentStore(); + }); + } + return this.getCurrentStore(); + }, + + // 获取当前门店(新用户或未选过门店时:按位置取最近门店) getCurrentStore() { return new Promise((resolve, reject) => { wx.getLocation({ @@ -194,11 +202,9 @@ App({ .then((res) => { this.globalData.currentStore = res.data; - // 如果当前门店有 ladderUserId,获取该门店的天梯用户信息 if (res.data && res.data.ladderUserId) { this.getLadderUser(res.data.storeId); } else if (res.data && res.data.storeId) { - // 如果当前门店没有 ladderUserId,但用户信息中有该门店的天梯用户,使用它 if ( this.globalData.userInfo && this.globalData.userInfo.ladderUsers @@ -210,27 +216,21 @@ App({ if (currentStoreLadderUser) { this.globalData.ladderUser = currentStoreLadderUser; } else { - // 当前门店没有天梯用户,清空 this.globalData.ladderUser = null; } } } - resolve(res.data); }) .catch(reject); }, fail: () => { - // 无法获取位置,使用默认门店 this.request("/api/user/current-store") .then((res) => { this.globalData.currentStore = res.data; - - // 如果当前门店有 ladderUserId,获取该门店的天梯用户信息 if (res.data && res.data.ladderUserId) { this.getLadderUser(res.data.storeId); } else if (res.data && res.data.storeId) { - // 如果当前门店没有 ladderUserId,但用户信息中有该门店的天梯用户,使用它 if ( this.globalData.userInfo && this.globalData.userInfo.ladderUsers @@ -242,12 +242,10 @@ App({ if (currentStoreLadderUser) { this.globalData.ladderUser = currentStoreLadderUser; } else { - // 当前门店没有天梯用户,清空 this.globalData.ladderUser = null; } } } - resolve(res.data); }) .catch(reject); @@ -256,14 +254,13 @@ App({ }); }, - // 获取天梯用户信息 + // 获取天梯用户信息(请求失败时 reject,便于上层做降级) getLadderUser(storeId) { return this.request("/api/user/ladder-info", { store_id: storeId }).then( (res) => { if (res.data && res.data.length > 0) { this.globalData.ladderUser = res.data[0]; } else { - // 没有天梯用户时清空 this.globalData.ladderUser = null; } return res.data; diff --git a/miniprogram/pages/article/list/index.js b/miniprogram/pages/article/list/index.js index 9be4569c..0d2bb376 100644 --- a/miniprogram/pages/article/list/index.js +++ b/miniprogram/pages/article/list/index.js @@ -26,10 +26,7 @@ Page({ if (storeId) { data.store_id = storeId; } - const res = await app.request("/api/article", { - method: "GET", - data, - }); + const res = await app.request("/api/article", data); const raw = res.data || []; const articles = raw.map((a) => ({ id: a.id, diff --git a/miniprogram/pages/index/index.js b/miniprogram/pages/index/index.js index 1282c95f..f1b511fe 100644 --- a/miniprogram/pages/index/index.js +++ b/miniprogram/pages/index/index.js @@ -61,7 +61,7 @@ Page({ // 获取当前门店 try { - const store = await app.getCurrentStore(); + const store = await app.ensureCurrentStore(); this.setData({ currentStore: store }); this.fetchData(); } catch (e) { diff --git a/miniprogram/pages/match/challenge/index.js b/miniprogram/pages/match/challenge/index.js index f6e18af7..c01dbece 100644 --- a/miniprogram/pages/match/challenge/index.js +++ b/miniprogram/pages/match/challenge/index.js @@ -37,7 +37,7 @@ Page({ // 每次显示页面时重新获取门店和天梯信息 try { - await app.getCurrentStore(); + await app.ensureCurrentStore(); // 如果有门店,获取该门店的天梯信息 if (app.globalData.currentStore && app.globalData.currentStore.storeId) { await app.getLadderUser(app.globalData.currentStore.storeId); @@ -83,7 +83,7 @@ Page({ try { // 重新获取门店信息 - await app.getCurrentStore(); + await app.ensureCurrentStore(); // 重新获取天梯信息 if (app.globalData.currentStore && app.globalData.currentStore.storeId) { diff --git a/miniprogram/pages/match/history/index.js b/miniprogram/pages/match/history/index.js index 25257b96..b4246a7d 100644 --- a/miniprogram/pages/match/history/index.js +++ b/miniprogram/pages/match/history/index.js @@ -37,16 +37,11 @@ Page({ }, async fetchMatches() { - const currentStore = app.globalData.currentStore; - if (!currentStore || !currentStore.storeId) { - return; - } - this.setData({ loading: true }); try { + // 不传 store_id,获取全部门店的比赛记录 const res = await app.request("/api/match/my-matches", { - store_id: currentStore.storeId, page: this.data.page, pageSize: this.data.pageSize, }); diff --git a/miniprogram/pages/match/history/index.wxml b/miniprogram/pages/match/history/index.wxml index cd7938ec..9634b2b7 100644 --- a/miniprogram/pages/match/history/index.wxml +++ b/miniprogram/pages/match/history/index.wxml @@ -3,7 +3,10 @@ - {{item.matchName}} + + {{item.matchName}} + {{item.storeName}} + {{item.matchType === 1 ? '挑战赛' : '排位赛'}} diff --git a/miniprogram/pages/match/history/index.wxss b/miniprogram/pages/match/history/index.wxss index 7460e4e1..10809d73 100644 --- a/miniprogram/pages/match/history/index.wxss +++ b/miniprogram/pages/match/history/index.wxss @@ -36,11 +36,22 @@ border-bottom: 2rpx solid rgba(255, 255, 255, 0.2); } +.match-header-main { + display: flex; + flex-direction: column; + gap: 8rpx; + flex: 1; +} + .match-name { font-size: 32rpx; font-weight: 600; color: #fff; - flex: 1; +} + +.match-store { + font-size: 24rpx; + color: rgba(255, 255, 255, 0.85); } .match-type { diff --git a/miniprogram/pages/points/mall/index.js b/miniprogram/pages/points/mall/index.js index 397deedc..1763b1f7 100644 --- a/miniprogram/pages/points/mall/index.js +++ b/miniprogram/pages/points/mall/index.js @@ -17,7 +17,16 @@ Page({ this.initData(); }, - onShow() { + async onShow() { + const store = app.globalData.currentStore; + // 获取当前门店的积分 + if (app.globalData.token && store?.storeId) { + try { + await app.getUserInfo(store.storeId); + } catch (e) { + console.error("获取用户信息失败:", e); + } + } this.setData({ userInfo: app.globalData.userInfo, currentStore: app.globalData.currentStore, @@ -52,7 +61,14 @@ Page({ console.error("登录失败:", e); } } - + const store = app.globalData.currentStore; + if (app.globalData.token && store?.storeId) { + try { + await app.getUserInfo(store.storeId); + } catch (e) { + console.error("获取用户信息失败:", e); + } + } this.setData({ userInfo: app.globalData.userInfo, currentStore: app.globalData.currentStore, @@ -128,12 +144,17 @@ Page({ wx.hideLoading(); - // 更新用户积分 - const newPoints = - this.data.userInfo.totalPoints - product.pointsRequired; - app.globalData.userInfo.totalPoints = newPoints; + // 重新获取用户信息(含当前门店积分) + const store = app.globalData.currentStore; + if (store?.storeId) { + try { + await app.getUserInfo(store.storeId); + } catch (e) { + console.error("刷新积分失败:", e); + } + } this.setData({ - "userInfo.totalPoints": newPoints, + userInfo: app.globalData.userInfo, showProductModal: false, }); diff --git a/miniprogram/pages/points/mall/index.wxml b/miniprogram/pages/points/mall/index.wxml index 846cbd06..552f7eb5 100644 --- a/miniprogram/pages/points/mall/index.wxml +++ b/miniprogram/pages/points/mall/index.wxml @@ -10,7 +10,7 @@ 我的积分 - {{userInfo.totalPoints || 0}} + {{userInfo.storePoints !== undefined ? userInfo.storePoints : (userInfo.totalPoints || 0)}} @@ -48,7 +48,7 @@ {{item.pointsRequired}} 积分 - + {{item.stock <= 0 ? '售罄' : '兑换'}} @@ -105,11 +105,11 @@ diff --git a/miniprogram/pages/points/records/index.wxml b/miniprogram/pages/points/records/index.wxml index 6bebae82..273f24e1 100644 --- a/miniprogram/pages/points/records/index.wxml +++ b/miniprogram/pages/points/records/index.wxml @@ -4,6 +4,7 @@ {{item.actionName}} + {{item.storeName}} {{item.createdAt}} diff --git a/miniprogram/pages/points/records/index.wxss b/miniprogram/pages/points/records/index.wxss index 3fa69edd..33fed69e 100644 --- a/miniprogram/pages/points/records/index.wxss +++ b/miniprogram/pages/points/records/index.wxss @@ -199,6 +199,25 @@ .record-info { flex: 1; overflow: hidden; + display: flex; + flex-direction: column; + gap: 6rpx; +} + +.record-info .action-name { + font-size: 28rpx; + font-weight: 600; + color: var(--text-primary); +} + +.record-store { + font-size: 24rpx; + color: var(--text-muted); +} + +.record-info .record-time { + font-size: 24rpx; + color: var(--text-muted); } .record-title { diff --git a/miniprogram/pages/store/index.js b/miniprogram/pages/store/index.js index 24ea5b63..dd6527fe 100644 --- a/miniprogram/pages/store/index.js +++ b/miniprogram/pages/store/index.js @@ -27,9 +27,20 @@ Page({ } }, - // 初始化当前门店信息 + // 初始化当前门店信息(优先全局,其次从上次选择恢复) initCurrentStore() { - const currentStore = app.globalData.currentStore + let currentStore = app.globalData.currentStore + if (!currentStore) { + const lastStore = wx.getStorageSync('last_store') + if (lastStore && lastStore.storeId) { + currentStore = { + storeId: lastStore.storeId, + storeName: lastStore.storeName || '', + storeAddress: lastStore.storeAddress || '' + } + app.globalData.currentStore = currentStore + } + } if (currentStore) { this.setData({ currentStoreId: currentStore.storeId, @@ -59,8 +70,7 @@ Page({ try { const res = await app.request('/api/store/nearby', { latitude: loc.latitude, - longitude: loc.longitude, - radius: 50000 + longitude: loc.longitude }) this.setData({ stores: res.data || [], @@ -141,6 +151,13 @@ Page({ storeAddress: store.address } + // 持久化上次选择的门店,下次启动优先使用 + wx.setStorageSync('last_store', { + storeId: store.id, + storeName: store.name, + storeAddress: store.address + }) + // 清空旧的天梯用户信息 app.globalData.ladderUser = null diff --git a/miniprogram/pages/user/index.js b/miniprogram/pages/user/index.js index 84735b44..0ed1164e 100644 --- a/miniprogram/pages/user/index.js +++ b/miniprogram/pages/user/index.js @@ -86,16 +86,14 @@ Page({ if (!app.globalData.token) return; try { - await app.getUserInfo(); + const store = app.globalData.currentStore; + // 传入当前门店 ID,获取该门店的积分和天梯信息 + await app.getUserInfo(store?.storeId); - // 如果当前门店有 ladderUserId,确保获取该门店的天梯用户信息 - if ( - app.globalData.currentStore && - app.globalData.currentStore.storeId && - !app.globalData.ladderUser - ) { + // 有当前门店时,拉取该门店的天梯用户信息(确保战力数据与当前门店一致) + if (store && store.storeId) { try { - await app.getLadderUser(app.globalData.currentStore.storeId); + await app.getLadderUser(store.storeId); } catch (e) { console.error("获取天梯用户信息失败:", e); } @@ -105,6 +103,7 @@ Page({ userInfo: app.globalData.userInfo, ladderUser: this.normalizeLadderUser(app.globalData.ladderUser), currentStore: app.globalData.currentStore, + announcements: [], // 先清空,避免切换门店时短暂显示旧门店公告 }); await this.fetchAnnouncements(); @@ -120,11 +119,8 @@ Page({ if (!store || !store.storeId) return; try { const res = await app.request("/api/article", { - method: "GET", - data: { - limit: 10, - store_id: store.storeId, - }, + limit: 10, + store_id: store.storeId, }); const raw = res.data || []; const list = raw.map((a) => ({ @@ -177,7 +173,7 @@ Page({ ); // 获取门店信息 - await app.getCurrentStore(); + await app.ensureCurrentStore(); const userInfo = app.globalData.userInfo; @@ -252,7 +248,7 @@ Page({ this.data.registerGender, ); - await app.getCurrentStore(); + await app.ensureCurrentStore(); const userInfo = app.globalData.userInfo; this.setData({ userInfo: userInfo, diff --git a/miniprogram/pages/user/index.wxml b/miniprogram/pages/user/index.wxml index 4b433da1..b8c16c99 100644 --- a/miniprogram/pages/user/index.wxml +++ b/miniprogram/pages/user/index.wxml @@ -20,7 +20,7 @@ {{userInfo.nickname || '新用户'}} - {{userInfo.totalPoints || 0}} + {{userInfo.storePoints !== undefined ? userInfo.storePoints : (userInfo.totalPoints || 0)}} 积分 diff --git a/server/src/controllers/matchController.js b/server/src/controllers/matchController.js index 21220f28..b2c1a9d8 100644 --- a/server/src/controllers/matchController.js +++ b/server/src/controllers/matchController.js @@ -1288,31 +1288,40 @@ class MatchController { return this.confirmScore(req, res); } - // 获取我的比赛记录 + // 获取我的比赛记录(不传 store_id 时返回全部门店记录) async getMyMatches(req, res) { try { const { store_id, page = 1, pageSize = 20 } = req.query; const { limit, offset } = getPagination(page, pageSize); const user = req.user; - const ladderUser = await LadderUser.findOne({ - where: { user_id: user.id, store_id, status: 1 } + const ladderWhere = { user_id: user.id, status: 1 }; + if (store_id) { + ladderWhere.store_id = store_id; + } + const ladderUsers = await LadderUser.findAll({ + where: ladderWhere, + attributes: ['id', 'store_id'], + include: [{ model: Store, as: 'store', attributes: ['id', 'name'] }] }); - if (!ladderUser) { + if (ladderUsers.length === 0) { return res.json(pageResult([], 0, page, pageSize)); } + const ladderUserIds = ladderUsers.map(lu => lu.id); + const ladderUserMap = Object.fromEntries(ladderUsers.map(lu => [lu.id, lu])); + const { rows, count } = await MatchGame.findAndCountAll({ where: { [Op.or]: [ - { player1_id: ladderUser.id }, - { player2_id: ladderUser.id } + { player1_id: { [Op.in]: ladderUserIds } }, + { player2_id: { [Op.in]: ladderUserIds } } ], confirm_status: CONFIRM_STATUS.CONFIRMED }, include: [ - { model: Match, as: 'match', attributes: ['id', 'name', 'type', 'weight'] } + { model: Match, as: 'match', attributes: ['id', 'name', 'type', 'weight', 'store_id'] } ], order: [['confirmed_at', 'DESC']], limit, @@ -1320,20 +1329,28 @@ class MatchController { }); const list = await Promise.all(rows.map(async game => { - const isPlayer1 = game.player1_id === ladderUser.id; + const myLadderId = ladderUserIds.find(id => + game.player1_id === id || game.player2_id === id + ); + const myLadderUser = ladderUserMap[myLadderId]; + const isPlayer1 = game.player1_id === myLadderId; const opponentId = isPlayer1 ? game.player2_id : game.player1_id; - const opponent = await LadderUser.findByPk(opponentId); + const opponent = await LadderUser.findByPk(opponentId, { + include: [{ model: Store, as: 'store', attributes: ['id', 'name'] }] + }); return { id: game.id, matchId: game.match_id, matchName: game.match?.name, matchType: game.match?.type, + storeId: myLadderUser?.store_id, + storeName: myLadderUser?.store?.name, opponentName: opponent?.real_name, myScore: isPlayer1 ? game.player1_score : game.player2_score, opponentScore: isPlayer1 ? game.player2_score : game.player1_score, - isWin: game.winner_id === ladderUser.id, - powerChange: game.winner_id === ladderUser.id + isWin: game.winner_id === myLadderId, + powerChange: game.winner_id === myLadderId ? game.winner_power_change : game.loser_power_change, confirmedAt: game.confirmed_at diff --git a/server/src/controllers/storeController.js b/server/src/controllers/storeController.js index 9a2202d2..8f8095ee 100644 --- a/server/src/controllers/storeController.js +++ b/server/src/controllers/storeController.js @@ -74,10 +74,10 @@ class StoreController { } } - // 获取附近门店 + // 获取附近门店(默认显示所有门店,按距离由近到远排序) async getNearby(req, res) { try { - const { latitude, longitude, radius = 10000 } = req.query; + const { latitude, longitude } = req.query; if (!latitude || !longitude) { return res.status(400).json(error('缺少位置信息', 400)); @@ -110,8 +110,7 @@ class StoreController { distance }; }) - .filter(store => store.distance === null || store.distance <= parseFloat(radius)) - .sort((a, b) => (a.distance || Infinity) - (b.distance || Infinity)); + .sort((a, b) => (a.distance ?? Infinity) - (b.distance ?? Infinity)); res.json(success(nearbyStores)); } catch (err) { diff --git a/server/src/controllers/userController.js b/server/src/controllers/userController.js index 21791a61..847bcd3b 100644 --- a/server/src/controllers/userController.js +++ b/server/src/controllers/userController.js @@ -2,7 +2,7 @@ const jwt = require("jsonwebtoken"); const axios = require("axios"); const crypto = require("crypto"); const QRCode = require("qrcode"); -const { User, LadderUser, Store, Match, MatchGame } = require("../models"); +const { User, LadderUser, Store, Match, MatchGame, PointRecord } = require("../models"); const { generateMemberCode, success, @@ -355,10 +355,11 @@ class UserController { } }; - // 获取用户信息 + // 获取用户信息(支持 store_id 查询参数,返回该门店的积分) getInfo = async (req, res) => { try { const user = req.user; + const { store_id: storeId } = req.query; // 获取天梯信息 const ladderUsers = await LadderUser.findAll({ @@ -366,16 +367,27 @@ class UserController { include: [{ model: Store, as: "store", attributes: ["id", "name"] }], }); - res.json( - success({ - id: user.id, - nickname: user.nickname, - avatar: getFullUrl(user.avatar, req), - phone: user.phone, - gender: user.gender, - memberCode: user.member_code, - totalPoints: user.total_points, - ladderUsers: ladderUsers.map((lu) => ({ + // 按门店的积分:从 PointRecord 汇总该门店的积分变动 + let storePoints = null; + if (storeId) { + const sumResult = await PointRecord.sum("points", { + where: { + user_id: user.id, + store_id: storeId, + }, + }); + storePoints = Number(sumResult) || 0; + } + + const result = { + id: user.id, + nickname: user.nickname, + avatar: getFullUrl(user.avatar, req), + phone: user.phone, + gender: user.gender, + memberCode: user.member_code, + totalPoints: user.total_points, + ladderUsers: ladderUsers.map((lu) => ({ id: lu.id, storeId: lu.store_id, storeName: lu.store?.name, @@ -386,8 +398,11 @@ class UserController { matchCount: lu.match_count, winCount: lu.win_count, })), - }), - ); + }; + if (storePoints !== null) { + result.storePoints = storePoints; + } + res.json(success(result)); } catch (err) { console.error("获取用户信息失败:", err); res.status(500).json(error("获取用户信息失败")); diff --git a/server/src/routes/store.js b/server/src/routes/store.js index e0678498..dbdbcfe2 100644 --- a/server/src/routes/store.js +++ b/server/src/routes/store.js @@ -6,13 +6,13 @@ const { authUser } = require('../middlewares/auth'); // 获取门店列表 router.get('/list', storeController.getList); -// 获取门店详情 -router.get('/:id', storeController.getDetail); - -// 获取附近门店 +// 获取附近门店(必须放在 /:id 之前,否则 "nearby" 会被当作 id 匹配) router.get('/nearby', authUser, storeController.getNearby); // 获取用户参与天梯的门店 router.get('/ladder-stores', authUser, storeController.getLadderStores); +// 获取门店详情(放在最后,避免 /list、/nearby 等被当作 id) +router.get('/:id', storeController.getDetail); + module.exports = router;