refactor: Enhance store and user management features

- Updated user information retrieval to support store-specific points and ladder user data.
- Refactored store initialization logic to prioritize last selected store.
- Improved API endpoints for fetching matches and user data, ensuring compatibility with store context.
- Adjusted UI components to display store-related information consistently across various pages.
- Enhanced error handling and data fetching logic for better user experience.
This commit is contained in:
ethanfly 2026-02-07 11:09:37 +08:00
parent a684b617f2
commit 98f9e64d91
22 changed files with 292 additions and 192 deletions

View File

@ -2,288 +2,300 @@
"hash": "481070f0", "hash": "481070f0",
"configHash": "0bd4dba1", "configHash": "0bd4dba1",
"lockfileHash": "aa252f00", "lockfileHash": "aa252f00",
"browserHash": "f45a29de", "browserHash": "aa056658",
"optimized": { "optimized": {
"@element-plus/icons-vue": { "@element-plus/icons-vue": {
"src": "../../@element-plus/icons-vue/dist/index.js", "src": "../../@element-plus/icons-vue/dist/index.js",
"file": "@element-plus_icons-vue.js", "file": "@element-plus_icons-vue.js",
"fileHash": "303763e5", "fileHash": "c76bcc44",
"needsInterop": false "needsInterop": false
}, },
"@wangeditor/editor-for-vue": { "@wangeditor/editor-for-vue": {
"src": "../../@wangeditor/editor-for-vue/dist/index.esm.js", "src": "../../@wangeditor/editor-for-vue/dist/index.esm.js",
"file": "@wangeditor_editor-for-vue.js", "file": "@wangeditor_editor-for-vue.js",
"fileHash": "f00791f0", "fileHash": "37aca601",
"needsInterop": false "needsInterop": false
}, },
"axios": { "axios": {
"src": "../../axios/index.js", "src": "../../axios/index.js",
"file": "axios.js", "file": "axios.js",
"fileHash": "82f2009c", "fileHash": "3f28a8a9",
"needsInterop": false "needsInterop": false
}, },
"dayjs": { "dayjs": {
"src": "../../dayjs/dayjs.min.js", "src": "../../dayjs/dayjs.min.js",
"file": "dayjs.js", "file": "dayjs.js",
"fileHash": "5645dea7", "fileHash": "d74a620b",
"needsInterop": true "needsInterop": true
}, },
"element-plus": { "element-plus": {
"src": "../../element-plus/es/index.mjs", "src": "../../element-plus/es/index.mjs",
"file": "element-plus.js", "file": "element-plus.js",
"fileHash": "e550aa25", "fileHash": "5589b60e",
"needsInterop": false "needsInterop": false
}, },
"element-plus/dist/locale/zh-cn.mjs": { "element-plus/dist/locale/zh-cn.mjs": {
"src": "../../element-plus/dist/locale/zh-cn.mjs", "src": "../../element-plus/dist/locale/zh-cn.mjs",
"file": "element-plus_dist_locale_zh-cn__mjs.js", "file": "element-plus_dist_locale_zh-cn__mjs.js",
"fileHash": "3b744d4a", "fileHash": "c0fd1204",
"needsInterop": false "needsInterop": false
}, },
"pinia": { "pinia": {
"src": "../../pinia/dist/pinia.mjs", "src": "../../pinia/dist/pinia.mjs",
"file": "pinia.js", "file": "pinia.js",
"fileHash": "8c748394", "fileHash": "dc1f88e8",
"needsInterop": false "needsInterop": false
}, },
"qrcode": { "qrcode": {
"src": "../../qrcode/lib/browser.js", "src": "../../qrcode/lib/browser.js",
"file": "qrcode.js", "file": "qrcode.js",
"fileHash": "e1329e14", "fileHash": "6c0a34f3",
"needsInterop": true "needsInterop": true
}, },
"vue": { "vue": {
"src": "../../vue/dist/vue.runtime.esm-bundler.js", "src": "../../vue/dist/vue.runtime.esm-bundler.js",
"file": "vue.js", "file": "vue.js",
"fileHash": "853300f0", "fileHash": "868e6988",
"needsInterop": false "needsInterop": false
}, },
"vue-router": { "vue-router": {
"src": "../../vue-router/dist/vue-router.mjs", "src": "../../vue-router/dist/vue-router.mjs",
"file": "vue-router.js", "file": "vue-router.js",
"fileHash": "d904f03a", "fileHash": "b4f98d74",
"needsInterop": false "needsInterop": false
}, },
"element-plus/es": { "element-plus/es": {
"src": "../../element-plus/es/index.mjs", "src": "../../element-plus/es/index.mjs",
"file": "element-plus_es.js", "file": "element-plus_es.js",
"fileHash": "29301e56", "fileHash": "8a699395",
"needsInterop": false "needsInterop": false
}, },
"element-plus/es/components/base/style/css": { "element-plus/es/components/base/style/css": {
"src": "../../element-plus/es/components/base/style/css.mjs", "src": "../../element-plus/es/components/base/style/css.mjs",
"file": "element-plus_es_components_base_style_css.js", "file": "element-plus_es_components_base_style_css.js",
"fileHash": "1d49b62e", "fileHash": "ad6081a9",
"needsInterop": false "needsInterop": false
}, },
"element-plus/es/components/dialog/style/css": { "element-plus/es/components/dialog/style/css": {
"src": "../../element-plus/es/components/dialog/style/css.mjs", "src": "../../element-plus/es/components/dialog/style/css.mjs",
"file": "element-plus_es_components_dialog_style_css.js", "file": "element-plus_es_components_dialog_style_css.js",
"fileHash": "5bba98de", "fileHash": "ebd107ef",
"needsInterop": false "needsInterop": false
}, },
"element-plus/es/components/button/style/css": { "element-plus/es/components/button/style/css": {
"src": "../../element-plus/es/components/button/style/css.mjs", "src": "../../element-plus/es/components/button/style/css.mjs",
"file": "element-plus_es_components_button_style_css.js", "file": "element-plus_es_components_button_style_css.js",
"fileHash": "fd8b0f8b", "fileHash": "ff2f2a5b",
"needsInterop": false "needsInterop": false
}, },
"element-plus/es/components/form/style/css": { "element-plus/es/components/form/style/css": {
"src": "../../element-plus/es/components/form/style/css.mjs", "src": "../../element-plus/es/components/form/style/css.mjs",
"file": "element-plus_es_components_form_style_css.js", "file": "element-plus_es_components_form_style_css.js",
"fileHash": "2ee6e663", "fileHash": "df7fdb18",
"needsInterop": false "needsInterop": false
}, },
"element-plus/es/components/form-item/style/css": { "element-plus/es/components/form-item/style/css": {
"src": "../../element-plus/es/components/form-item/style/css.mjs", "src": "../../element-plus/es/components/form-item/style/css.mjs",
"file": "element-plus_es_components_form-item_style_css.js", "file": "element-plus_es_components_form-item_style_css.js",
"fileHash": "cf1450df", "fileHash": "e9c6d01b",
"needsInterop": false "needsInterop": false
}, },
"element-plus/es/components/input/style/css": { "element-plus/es/components/input/style/css": {
"src": "../../element-plus/es/components/input/style/css.mjs", "src": "../../element-plus/es/components/input/style/css.mjs",
"file": "element-plus_es_components_input_style_css.js", "file": "element-plus_es_components_input_style_css.js",
"fileHash": "6aca7cf0", "fileHash": "e2b09618",
"needsInterop": false "needsInterop": false
}, },
"element-plus/es/components/container/style/css": { "element-plus/es/components/container/style/css": {
"src": "../../element-plus/es/components/container/style/css.mjs", "src": "../../element-plus/es/components/container/style/css.mjs",
"file": "element-plus_es_components_container_style_css.js", "file": "element-plus_es_components_container_style_css.js",
"fileHash": "4717aecb", "fileHash": "c0984641",
"needsInterop": false "needsInterop": false
}, },
"element-plus/es/components/main/style/css": { "element-plus/es/components/main/style/css": {
"src": "../../element-plus/es/components/main/style/css.mjs", "src": "../../element-plus/es/components/main/style/css.mjs",
"file": "element-plus_es_components_main_style_css.js", "file": "element-plus_es_components_main_style_css.js",
"fileHash": "f3ba5b99", "fileHash": "a73569af",
"needsInterop": false "needsInterop": false
}, },
"element-plus/es/components/header/style/css": { "element-plus/es/components/header/style/css": {
"src": "../../element-plus/es/components/header/style/css.mjs", "src": "../../element-plus/es/components/header/style/css.mjs",
"file": "element-plus_es_components_header_style_css.js", "file": "element-plus_es_components_header_style_css.js",
"fileHash": "96b2ed2f", "fileHash": "b592e09f",
"needsInterop": false "needsInterop": false
}, },
"element-plus/es/components/dropdown/style/css": { "element-plus/es/components/dropdown/style/css": {
"src": "../../element-plus/es/components/dropdown/style/css.mjs", "src": "../../element-plus/es/components/dropdown/style/css.mjs",
"file": "element-plus_es_components_dropdown_style_css.js", "file": "element-plus_es_components_dropdown_style_css.js",
"fileHash": "d0a6dac3", "fileHash": "f7bb8b58",
"needsInterop": false "needsInterop": false
}, },
"element-plus/es/components/dropdown-menu/style/css": { "element-plus/es/components/dropdown-menu/style/css": {
"src": "../../element-plus/es/components/dropdown-menu/style/css.mjs", "src": "../../element-plus/es/components/dropdown-menu/style/css.mjs",
"file": "element-plus_es_components_dropdown-menu_style_css.js", "file": "element-plus_es_components_dropdown-menu_style_css.js",
"fileHash": "35005d29", "fileHash": "60954d93",
"needsInterop": false "needsInterop": false
}, },
"element-plus/es/components/dropdown-item/style/css": { "element-plus/es/components/dropdown-item/style/css": {
"src": "../../element-plus/es/components/dropdown-item/style/css.mjs", "src": "../../element-plus/es/components/dropdown-item/style/css.mjs",
"file": "element-plus_es_components_dropdown-item_style_css.js", "file": "element-plus_es_components_dropdown-item_style_css.js",
"fileHash": "82f476ab", "fileHash": "018afb10",
"needsInterop": false "needsInterop": false
}, },
"element-plus/es/components/avatar/style/css": { "element-plus/es/components/avatar/style/css": {
"src": "../../element-plus/es/components/avatar/style/css.mjs", "src": "../../element-plus/es/components/avatar/style/css.mjs",
"file": "element-plus_es_components_avatar_style_css.js", "file": "element-plus_es_components_avatar_style_css.js",
"fileHash": "a9f261cc", "fileHash": "6a7d147e",
"needsInterop": false "needsInterop": false
}, },
"element-plus/es/components/breadcrumb/style/css": { "element-plus/es/components/breadcrumb/style/css": {
"src": "../../element-plus/es/components/breadcrumb/style/css.mjs", "src": "../../element-plus/es/components/breadcrumb/style/css.mjs",
"file": "element-plus_es_components_breadcrumb_style_css.js", "file": "element-plus_es_components_breadcrumb_style_css.js",
"fileHash": "3f3f3b42", "fileHash": "a2b08aeb",
"needsInterop": false "needsInterop": false
}, },
"element-plus/es/components/breadcrumb-item/style/css": { "element-plus/es/components/breadcrumb-item/style/css": {
"src": "../../element-plus/es/components/breadcrumb-item/style/css.mjs", "src": "../../element-plus/es/components/breadcrumb-item/style/css.mjs",
"file": "element-plus_es_components_breadcrumb-item_style_css.js", "file": "element-plus_es_components_breadcrumb-item_style_css.js",
"fileHash": "a5e97d32", "fileHash": "df52cc96",
"needsInterop": false "needsInterop": false
}, },
"element-plus/es/components/aside/style/css": { "element-plus/es/components/aside/style/css": {
"src": "../../element-plus/es/components/aside/style/css.mjs", "src": "../../element-plus/es/components/aside/style/css.mjs",
"file": "element-plus_es_components_aside_style_css.js", "file": "element-plus_es_components_aside_style_css.js",
"fileHash": "64e45da0", "fileHash": "ac5e261e",
"needsInterop": false "needsInterop": false
}, },
"element-plus/es/components/menu/style/css": { "element-plus/es/components/menu/style/css": {
"src": "../../element-plus/es/components/menu/style/css.mjs", "src": "../../element-plus/es/components/menu/style/css.mjs",
"file": "element-plus_es_components_menu_style_css.js", "file": "element-plus_es_components_menu_style_css.js",
"fileHash": "2f316cd2", "fileHash": "4e7cd965",
"needsInterop": false "needsInterop": false
}, },
"element-plus/es/components/menu-item/style/css": { "element-plus/es/components/menu-item/style/css": {
"src": "../../element-plus/es/components/menu-item/style/css.mjs", "src": "../../element-plus/es/components/menu-item/style/css.mjs",
"file": "element-plus_es_components_menu-item_style_css.js", "file": "element-plus_es_components_menu-item_style_css.js",
"fileHash": "afb95054", "fileHash": "51fb1a5d",
"needsInterop": false "needsInterop": false
}, },
"element-plus/es/components/icon/style/css": { "element-plus/es/components/icon/style/css": {
"src": "../../element-plus/es/components/icon/style/css.mjs", "src": "../../element-plus/es/components/icon/style/css.mjs",
"file": "element-plus_es_components_icon_style_css.js", "file": "element-plus_es_components_icon_style_css.js",
"fileHash": "9d19ab9f", "fileHash": "ceb23baa",
"needsInterop": false "needsInterop": false
}, },
"element-plus/es/components/loading/style/css": { "element-plus/es/components/loading/style/css": {
"src": "../../element-plus/es/components/loading/style/css.mjs", "src": "../../element-plus/es/components/loading/style/css.mjs",
"file": "element-plus_es_components_loading_style_css.js", "file": "element-plus_es_components_loading_style_css.js",
"fileHash": "8679a851", "fileHash": "19b92455",
"needsInterop": false "needsInterop": false
}, },
"element-plus/es/components/pagination/style/css": { "element-plus/es/components/pagination/style/css": {
"src": "../../element-plus/es/components/pagination/style/css.mjs", "src": "../../element-plus/es/components/pagination/style/css.mjs",
"file": "element-plus_es_components_pagination_style_css.js", "file": "element-plus_es_components_pagination_style_css.js",
"fileHash": "e7d9082b", "fileHash": "94ca04a5",
"needsInterop": false "needsInterop": false
}, },
"element-plus/es/components/table/style/css": { "element-plus/es/components/table/style/css": {
"src": "../../element-plus/es/components/table/style/css.mjs", "src": "../../element-plus/es/components/table/style/css.mjs",
"file": "element-plus_es_components_table_style_css.js", "file": "element-plus_es_components_table_style_css.js",
"fileHash": "c2ed39c2", "fileHash": "624bb620",
"needsInterop": false "needsInterop": false
}, },
"element-plus/es/components/tag/style/css": { "element-plus/es/components/tag/style/css": {
"src": "../../element-plus/es/components/tag/style/css.mjs", "src": "../../element-plus/es/components/tag/style/css.mjs",
"file": "element-plus_es_components_tag_style_css.js", "file": "element-plus_es_components_tag_style_css.js",
"fileHash": "cb057059", "fileHash": "20423d57",
"needsInterop": false "needsInterop": false
}, },
"element-plus/es/components/image/style/css": { "element-plus/es/components/image/style/css": {
"src": "../../element-plus/es/components/image/style/css.mjs", "src": "../../element-plus/es/components/image/style/css.mjs",
"file": "element-plus_es_components_image_style_css.js", "file": "element-plus_es_components_image_style_css.js",
"fileHash": "351b3909", "fileHash": "994dd216",
"needsInterop": false "needsInterop": false
}, },
"element-plus/es/components/table-column/style/css": { "element-plus/es/components/table-column/style/css": {
"src": "../../element-plus/es/components/table-column/style/css.mjs", "src": "../../element-plus/es/components/table-column/style/css.mjs",
"file": "element-plus_es_components_table-column_style_css.js", "file": "element-plus_es_components_table-column_style_css.js",
"fileHash": "6eb55fa5", "fileHash": "1b6a0c06",
"needsInterop": false "needsInterop": false
}, },
"element-plus/es/components/select/style/css": { "element-plus/es/components/select/style/css": {
"src": "../../element-plus/es/components/select/style/css.mjs", "src": "../../element-plus/es/components/select/style/css.mjs",
"file": "element-plus_es_components_select_style_css.js", "file": "element-plus_es_components_select_style_css.js",
"fileHash": "daf87f44", "fileHash": "c8ac9a5a",
"needsInterop": false "needsInterop": false
}, },
"element-plus/es/components/option/style/css": { "element-plus/es/components/option/style/css": {
"src": "../../element-plus/es/components/option/style/css.mjs", "src": "../../element-plus/es/components/option/style/css.mjs",
"file": "element-plus_es_components_option_style_css.js", "file": "element-plus_es_components_option_style_css.js",
"fileHash": "8cdd90ba", "fileHash": "ee3e00ce",
"needsInterop": false "needsInterop": false
}, },
"element-plus/es/components/radio-group/style/css": { "element-plus/es/components/radio-group/style/css": {
"src": "../../element-plus/es/components/radio-group/style/css.mjs", "src": "../../element-plus/es/components/radio-group/style/css.mjs",
"file": "element-plus_es_components_radio-group_style_css.js", "file": "element-plus_es_components_radio-group_style_css.js",
"fileHash": "33078822", "fileHash": "56871901",
"needsInterop": false "needsInterop": false
}, },
"element-plus/es/components/radio/style/css": { "element-plus/es/components/radio/style/css": {
"src": "../../element-plus/es/components/radio/style/css.mjs", "src": "../../element-plus/es/components/radio/style/css.mjs",
"file": "element-plus_es_components_radio_style_css.js", "file": "element-plus_es_components_radio_style_css.js",
"fileHash": "aee22efa", "fileHash": "4857765a",
"needsInterop": false "needsInterop": false
}, },
"element-plus/es/components/switch/style/css": { "element-plus/es/components/switch/style/css": {
"src": "../../element-plus/es/components/switch/style/css.mjs", "src": "../../element-plus/es/components/switch/style/css.mjs",
"file": "element-plus_es_components_switch_style_css.js", "file": "element-plus_es_components_switch_style_css.js",
"fileHash": "5d58ccb8", "fileHash": "3bf1b3df",
"needsInterop": false "needsInterop": false
}, },
"element-plus/es/components/input-number/style/css": { "element-plus/es/components/input-number/style/css": {
"src": "../../element-plus/es/components/input-number/style/css.mjs", "src": "../../element-plus/es/components/input-number/style/css.mjs",
"file": "element-plus_es_components_input-number_style_css.js", "file": "element-plus_es_components_input-number_style_css.js",
"fileHash": "8826e069", "fileHash": "70e0ea9b",
"needsInterop": false "needsInterop": false
}, },
"element-plus/es/components/autocomplete/style/css": { "element-plus/es/components/autocomplete/style/css": {
"src": "../../element-plus/es/components/autocomplete/style/css.mjs", "src": "../../element-plus/es/components/autocomplete/style/css.mjs",
"file": "element-plus_es_components_autocomplete_style_css.js", "file": "element-plus_es_components_autocomplete_style_css.js",
"fileHash": "50eaf0f2", "fileHash": "f192d727",
"needsInterop": false "needsInterop": false
}, },
"element-plus/es/components/row/style/css": { "element-plus/es/components/row/style/css": {
"src": "../../element-plus/es/components/row/style/css.mjs", "src": "../../element-plus/es/components/row/style/css.mjs",
"file": "element-plus_es_components_row_style_css.js", "file": "element-plus_es_components_row_style_css.js",
"fileHash": "c8e609ae", "fileHash": "c97af601",
"needsInterop": false "needsInterop": false
}, },
"element-plus/es/components/col/style/css": { "element-plus/es/components/col/style/css": {
"src": "../../element-plus/es/components/col/style/css.mjs", "src": "../../element-plus/es/components/col/style/css.mjs",
"file": "element-plus_es_components_col_style_css.js", "file": "element-plus_es_components_col_style_css.js",
"fileHash": "8683f4d3", "fileHash": "c5850ceb",
"needsInterop": false "needsInterop": false
}, },
"element-plus/es/components/descriptions/style/css": { "element-plus/es/components/descriptions/style/css": {
"src": "../../element-plus/es/components/descriptions/style/css.mjs", "src": "../../element-plus/es/components/descriptions/style/css.mjs",
"file": "element-plus_es_components_descriptions_style_css.js", "file": "element-plus_es_components_descriptions_style_css.js",
"fileHash": "3fde99e8", "fileHash": "fab03c68",
"needsInterop": false "needsInterop": false
}, },
"element-plus/es/components/descriptions-item/style/css": { "element-plus/es/components/descriptions-item/style/css": {
"src": "../../element-plus/es/components/descriptions-item/style/css.mjs", "src": "../../element-plus/es/components/descriptions-item/style/css.mjs",
"file": "element-plus_es_components_descriptions-item_style_css.js", "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 "needsInterop": false
} }
}, },
@ -291,6 +303,9 @@
"chunk-4PW274X2": { "chunk-4PW274X2": {
"file": "chunk-4PW274X2.js" "file": "chunk-4PW274X2.js"
}, },
"chunk-JUCAMQ7P": {
"file": "chunk-JUCAMQ7P.js"
},
"chunk-B2YDYSZR": { "chunk-B2YDYSZR": {
"file": "chunk-B2YDYSZR.js" "file": "chunk-B2YDYSZR.js"
}, },
@ -306,42 +321,39 @@
"chunk-R5DNQ3QC": { "chunk-R5DNQ3QC": {
"file": "chunk-R5DNQ3QC.js" "file": "chunk-R5DNQ3QC.js"
}, },
"chunk-NKQWFVTF": {
"file": "chunk-NKQWFVTF.js"
},
"chunk-REWOA3VH": { "chunk-REWOA3VH": {
"file": "chunk-REWOA3VH.js" "file": "chunk-REWOA3VH.js"
}, },
"chunk-TX5YLZ4O": { "chunk-TX5YLZ4O": {
"file": "chunk-TX5YLZ4O.js" "file": "chunk-TX5YLZ4O.js"
}, },
"chunk-YFT6OQ5R": {
"file": "chunk-YFT6OQ5R.js"
},
"chunk-SMFPDFTD": { "chunk-SMFPDFTD": {
"file": "chunk-SMFPDFTD.js" "file": "chunk-SMFPDFTD.js"
}, },
"chunk-JUCAMQ7P": { "chunk-YFT6OQ5R": {
"file": "chunk-JUCAMQ7P.js" "file": "chunk-YFT6OQ5R.js"
},
"chunk-NKQWFVTF": {
"file": "chunk-NKQWFVTF.js"
}, },
"chunk-IV6PSERC": { "chunk-IV6PSERC": {
"file": "chunk-IV6PSERC.js" "file": "chunk-IV6PSERC.js"
}, },
"chunk-ZLPQR2PE": { "chunk-LYXQVMFB": {
"file": "chunk-ZLPQR2PE.js" "file": "chunk-LYXQVMFB.js"
}, },
"chunk-HYZ2CRGS": { "chunk-HYZ2CRGS": {
"file": "chunk-HYZ2CRGS.js" "file": "chunk-HYZ2CRGS.js"
}, },
"chunk-QZC7O2C6": {
"file": "chunk-QZC7O2C6.js"
},
"chunk-OP4ZUAFM": { "chunk-OP4ZUAFM": {
"file": "chunk-OP4ZUAFM.js" "file": "chunk-OP4ZUAFM.js"
}, },
"chunk-H2732BJL": { "chunk-H2732BJL": {
"file": "chunk-H2732BJL.js" "file": "chunk-H2732BJL.js"
}, },
"chunk-QZC7O2C6": {
"file": "chunk-QZC7O2C6.js"
},
"chunk-G3PMV62Z": { "chunk-G3PMV62Z": {
"file": "chunk-G3PMV62Z.js" "file": "chunk-G3PMV62Z.js"
} }

View File

@ -514,11 +514,11 @@ import {
virtualizedScrollbarProps, virtualizedScrollbarProps,
watermarkProps, watermarkProps,
zIndexContextKey zIndexContextKey
} from "./chunk-ZLPQR2PE.js"; } from "./chunk-LYXQVMFB.js";
import "./chunk-HYZ2CRGS.js"; import "./chunk-HYZ2CRGS.js";
import "./chunk-QZC7O2C6.js";
import "./chunk-OP4ZUAFM.js"; import "./chunk-OP4ZUAFM.js";
import "./chunk-H2732BJL.js"; import "./chunk-H2732BJL.js";
import "./chunk-QZC7O2C6.js";
import "./chunk-G3PMV62Z.js"; import "./chunk-G3PMV62Z.js";
var export_dayjs = import_dayjs.default; var export_dayjs = import_dayjs.default;
export { export {

View File

@ -514,11 +514,11 @@ import {
virtualizedScrollbarProps, virtualizedScrollbarProps,
watermarkProps, watermarkProps,
zIndexContextKey zIndexContextKey
} from "./chunk-ZLPQR2PE.js"; } from "./chunk-LYXQVMFB.js";
import "./chunk-HYZ2CRGS.js"; import "./chunk-HYZ2CRGS.js";
import "./chunk-QZC7O2C6.js";
import "./chunk-OP4ZUAFM.js"; import "./chunk-OP4ZUAFM.js";
import "./chunk-H2732BJL.js"; import "./chunk-H2732BJL.js";
import "./chunk-QZC7O2C6.js";
import "./chunk-G3PMV62Z.js"; import "./chunk-G3PMV62Z.js";
var export_dayjs = import_dayjs.default; var export_dayjs = import_dayjs.default;
export { export {

View File

@ -1,9 +1,9 @@
import "./chunk-75C4BP7B.js"; import "./chunk-75C4BP7B.js";
import "./chunk-5KK3TTMN.js"; import "./chunk-5KK3TTMN.js";
import "./chunk-UBLR4G7Q.js"; import "./chunk-UBLR4G7Q.js";
import "./chunk-NKQWFVTF.js";
import "./chunk-REWOA3VH.js"; import "./chunk-REWOA3VH.js";
import "./chunk-TX5YLZ4O.js"; import "./chunk-TX5YLZ4O.js";
import "./chunk-NKQWFVTF.js";
import "./chunk-IV6PSERC.js"; import "./chunk-IV6PSERC.js";
// node_modules/element-plus/es/components/pagination/style/css.mjs // node_modules/element-plus/es/components/pagination/style/css.mjs

View File

@ -15,11 +15,13 @@ App({
}, },
onLaunch() { onLaunch() {
// 从本地存储读取token // 从本地存储读取 token 和上次选择的门店
const token = wx.getStorageSync("token"); const token = wx.getStorageSync("token");
if (token) { if (token) {
this.globalData.token = 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.token = loginRes.data.data.token;
this.globalData.userInfo = loginRes.data.data.userInfo; this.globalData.userInfo = loginRes.data.data.userInfo;
// 处理天梯用户信息 // 处理天梯用户信息(战力按当前门店,当前门店无天梯则不显示)
if ( if (
loginRes.data.data.userInfo.ladderUsers && loginRes.data.data.userInfo.ladderUsers &&
loginRes.data.data.userInfo.ladderUsers.length > 0 loginRes.data.data.userInfo.ladderUsers.length > 0
) { ) {
// 如果有当前门店,优先选择当前门店的天梯用户
if ( if (
this.globalData.currentStore && this.globalData.currentStore &&
this.globalData.currentStore.storeId this.globalData.currentStore.storeId
@ -108,20 +109,12 @@ App({
loginRes.data.data.userInfo.ladderUsers.find( loginRes.data.data.userInfo.ladderUsers.find(
(lu) => lu.storeId === this.globalData.currentStore.storeId, (lu) => lu.storeId === this.globalData.currentStore.storeId,
); );
if (currentStoreLadderUser) { // 仅当当前门店有天梯用户时才显示,否则为 null避免显示其他门店数据
this.globalData.ladderUser = currentStoreLadderUser; this.globalData.ladderUser = currentStoreLadderUser || null;
} else { } else {
// 当前门店没有天梯用户,取第一个 this.globalData.ladderUser = null;
this.globalData.ladderUser =
loginRes.data.data.userInfo.ladderUsers[0];
} }
} else { } else {
// 没有当前门店,取第一个天梯用户
this.globalData.ladderUser =
loginRes.data.data.userInfo.ladderUsers[0];
}
} else {
// 没有天梯用户
this.globalData.ladderUser = null; this.globalData.ladderUser = null;
} }
@ -142,16 +135,16 @@ App({
return this.wxLogin(); return this.wxLogin();
}, },
// 获取用户信息 // 获取用户信息storeId 可选,传入时返回该门店的积分 storePoints
getUserInfo() { getUserInfo(storeId) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.request("/api/user/info") const data = storeId ? { store_id: storeId } : {};
this.request("/api/user/info", data)
.then((res) => { .then((res) => {
this.globalData.userInfo = res.data; this.globalData.userInfo = res.data;
// 处理天梯用户信息 // 处理天梯用户信息(战力按当前门店,当前门店无天梯则不显示)
if (res.data.ladderUsers && res.data.ladderUsers.length > 0) { if (res.data.ladderUsers && res.data.ladderUsers.length > 0) {
// 如果有当前门店,优先选择当前门店的天梯用户
if ( if (
this.globalData.currentStore && this.globalData.currentStore &&
this.globalData.currentStore.storeId this.globalData.currentStore.storeId
@ -159,18 +152,12 @@ App({
const currentStoreLadderUser = res.data.ladderUsers.find( const currentStoreLadderUser = res.data.ladderUsers.find(
(lu) => lu.storeId === this.globalData.currentStore.storeId, (lu) => lu.storeId === this.globalData.currentStore.storeId,
); );
if (currentStoreLadderUser) { // 仅当当前门店有天梯用户时才显示,否则为 null避免显示其他门店数据
this.globalData.ladderUser = currentStoreLadderUser; this.globalData.ladderUser = currentStoreLadderUser || null;
} else { } else {
// 当前门店没有天梯用户,取第一个 this.globalData.ladderUser = null;
this.globalData.ladderUser = res.data.ladderUsers[0];
} }
} else { } else {
// 没有当前门店,取第一个天梯用户
this.globalData.ladderUser = res.data.ladderUsers[0];
}
} else {
// 没有天梯用户
this.globalData.ladderUser = null; 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() { getCurrentStore() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
wx.getLocation({ wx.getLocation({
@ -194,11 +202,9 @@ App({
.then((res) => { .then((res) => {
this.globalData.currentStore = res.data; this.globalData.currentStore = res.data;
// 如果当前门店有 ladderUserId获取该门店的天梯用户信息
if (res.data && res.data.ladderUserId) { if (res.data && res.data.ladderUserId) {
this.getLadderUser(res.data.storeId); this.getLadderUser(res.data.storeId);
} else if (res.data && res.data.storeId) { } else if (res.data && res.data.storeId) {
// 如果当前门店没有 ladderUserId但用户信息中有该门店的天梯用户使用它
if ( if (
this.globalData.userInfo && this.globalData.userInfo &&
this.globalData.userInfo.ladderUsers this.globalData.userInfo.ladderUsers
@ -210,27 +216,21 @@ App({
if (currentStoreLadderUser) { if (currentStoreLadderUser) {
this.globalData.ladderUser = currentStoreLadderUser; this.globalData.ladderUser = currentStoreLadderUser;
} else { } else {
// 当前门店没有天梯用户,清空
this.globalData.ladderUser = null; this.globalData.ladderUser = null;
} }
} }
} }
resolve(res.data); resolve(res.data);
}) })
.catch(reject); .catch(reject);
}, },
fail: () => { fail: () => {
// 无法获取位置,使用默认门店
this.request("/api/user/current-store") this.request("/api/user/current-store")
.then((res) => { .then((res) => {
this.globalData.currentStore = res.data; this.globalData.currentStore = res.data;
// 如果当前门店有 ladderUserId获取该门店的天梯用户信息
if (res.data && res.data.ladderUserId) { if (res.data && res.data.ladderUserId) {
this.getLadderUser(res.data.storeId); this.getLadderUser(res.data.storeId);
} else if (res.data && res.data.storeId) { } else if (res.data && res.data.storeId) {
// 如果当前门店没有 ladderUserId但用户信息中有该门店的天梯用户使用它
if ( if (
this.globalData.userInfo && this.globalData.userInfo &&
this.globalData.userInfo.ladderUsers this.globalData.userInfo.ladderUsers
@ -242,12 +242,10 @@ App({
if (currentStoreLadderUser) { if (currentStoreLadderUser) {
this.globalData.ladderUser = currentStoreLadderUser; this.globalData.ladderUser = currentStoreLadderUser;
} else { } else {
// 当前门店没有天梯用户,清空
this.globalData.ladderUser = null; this.globalData.ladderUser = null;
} }
} }
} }
resolve(res.data); resolve(res.data);
}) })
.catch(reject); .catch(reject);
@ -256,14 +254,13 @@ App({
}); });
}, },
// 获取天梯用户信息 // 获取天梯用户信息(请求失败时 reject便于上层做降级
getLadderUser(storeId) { getLadderUser(storeId) {
return this.request("/api/user/ladder-info", { store_id: storeId }).then( return this.request("/api/user/ladder-info", { store_id: storeId }).then(
(res) => { (res) => {
if (res.data && res.data.length > 0) { if (res.data && res.data.length > 0) {
this.globalData.ladderUser = res.data[0]; this.globalData.ladderUser = res.data[0];
} else { } else {
// 没有天梯用户时清空
this.globalData.ladderUser = null; this.globalData.ladderUser = null;
} }
return res.data; return res.data;

View File

@ -26,10 +26,7 @@ Page({
if (storeId) { if (storeId) {
data.store_id = storeId; data.store_id = storeId;
} }
const res = await app.request("/api/article", { const res = await app.request("/api/article", data);
method: "GET",
data,
});
const raw = res.data || []; const raw = res.data || [];
const articles = raw.map((a) => ({ const articles = raw.map((a) => ({
id: a.id, id: a.id,

View File

@ -61,7 +61,7 @@ Page({
// 获取当前门店 // 获取当前门店
try { try {
const store = await app.getCurrentStore(); const store = await app.ensureCurrentStore();
this.setData({ currentStore: store }); this.setData({ currentStore: store });
this.fetchData(); this.fetchData();
} catch (e) { } catch (e) {

View File

@ -37,7 +37,7 @@ Page({
// 每次显示页面时重新获取门店和天梯信息 // 每次显示页面时重新获取门店和天梯信息
try { try {
await app.getCurrentStore(); await app.ensureCurrentStore();
// 如果有门店,获取该门店的天梯信息 // 如果有门店,获取该门店的天梯信息
if (app.globalData.currentStore && app.globalData.currentStore.storeId) { if (app.globalData.currentStore && app.globalData.currentStore.storeId) {
await app.getLadderUser(app.globalData.currentStore.storeId); await app.getLadderUser(app.globalData.currentStore.storeId);
@ -83,7 +83,7 @@ Page({
try { try {
// 重新获取门店信息 // 重新获取门店信息
await app.getCurrentStore(); await app.ensureCurrentStore();
// 重新获取天梯信息 // 重新获取天梯信息
if (app.globalData.currentStore && app.globalData.currentStore.storeId) { if (app.globalData.currentStore && app.globalData.currentStore.storeId) {

View File

@ -37,16 +37,11 @@ Page({
}, },
async fetchMatches() { async fetchMatches() {
const currentStore = app.globalData.currentStore;
if (!currentStore || !currentStore.storeId) {
return;
}
this.setData({ loading: true }); this.setData({ loading: true });
try { try {
// 不传 store_id获取全部门店的比赛记录
const res = await app.request("/api/match/my-matches", { const res = await app.request("/api/match/my-matches", {
store_id: currentStore.storeId,
page: this.data.page, page: this.data.page,
pageSize: this.data.pageSize, pageSize: this.data.pageSize,
}); });

View File

@ -3,7 +3,10 @@
<view class="history-list" wx:if="{{matches.length > 0}}"> <view class="history-list" wx:if="{{matches.length > 0}}">
<view class="match-item" wx:for="{{matches}}" wx:key="id"> <view class="match-item" wx:for="{{matches}}" wx:key="id">
<view class="match-header"> <view class="match-header">
<view class="match-header-main">
<text class="match-name">{{item.matchName}}</text> <text class="match-name">{{item.matchName}}</text>
<text class="match-store" wx:if="{{item.storeName}}">{{item.storeName}}</text>
</view>
<text class="match-type">{{item.matchType === 1 ? '挑战赛' : '排位赛'}}</text> <text class="match-type">{{item.matchType === 1 ? '挑战赛' : '排位赛'}}</text>
</view> </view>
<view class="match-content"> <view class="match-content">

View File

@ -36,11 +36,22 @@
border-bottom: 2rpx solid rgba(255, 255, 255, 0.2); border-bottom: 2rpx solid rgba(255, 255, 255, 0.2);
} }
.match-header-main {
display: flex;
flex-direction: column;
gap: 8rpx;
flex: 1;
}
.match-name { .match-name {
font-size: 32rpx; font-size: 32rpx;
font-weight: 600; font-weight: 600;
color: #fff; color: #fff;
flex: 1; }
.match-store {
font-size: 24rpx;
color: rgba(255, 255, 255, 0.85);
} }
.match-type { .match-type {

View File

@ -17,7 +17,16 @@ Page({
this.initData(); 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({ this.setData({
userInfo: app.globalData.userInfo, userInfo: app.globalData.userInfo,
currentStore: app.globalData.currentStore, currentStore: app.globalData.currentStore,
@ -52,7 +61,14 @@ Page({
console.error("登录失败:", e); 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({ this.setData({
userInfo: app.globalData.userInfo, userInfo: app.globalData.userInfo,
currentStore: app.globalData.currentStore, currentStore: app.globalData.currentStore,
@ -128,12 +144,17 @@ Page({
wx.hideLoading(); wx.hideLoading();
// 更新用户积分 // 重新获取用户信息(含当前门店积分)
const newPoints = const store = app.globalData.currentStore;
this.data.userInfo.totalPoints - product.pointsRequired; if (store?.storeId) {
app.globalData.userInfo.totalPoints = newPoints; try {
await app.getUserInfo(store.storeId);
} catch (e) {
console.error("刷新积分失败:", e);
}
}
this.setData({ this.setData({
"userInfo.totalPoints": newPoints, userInfo: app.globalData.userInfo,
showProductModal: false, showProductModal: false,
}); });

View File

@ -10,7 +10,7 @@
<view class="points-info"> <view class="points-info">
<text class="points-label">我的积分</text> <text class="points-label">我的积分</text>
<view class="points-value"> <view class="points-value">
<text class="points-number">{{userInfo.totalPoints || 0}}</text> <text class="points-number">{{userInfo.storePoints !== undefined ? userInfo.storePoints : (userInfo.totalPoints || 0)}}</text>
<text class="points-unit">分</text> <text class="points-unit">分</text>
</view> </view>
</view> </view>
@ -48,7 +48,7 @@
<text class="price-value">{{item.pointsRequired}}</text> <text class="price-value">{{item.pointsRequired}}</text>
<text class="price-unit">积分</text> <text class="price-unit">积分</text>
</view> </view>
<view class="exchange-btn {{userInfo.totalPoints < item.pointsRequired || item.stock <= 0 ? 'disabled' : ''}}"> <view class="exchange-btn {{(userInfo.storePoints !== undefined ? userInfo.storePoints : userInfo.totalPoints || 0) < item.pointsRequired || item.stock <= 0 ? 'disabled' : ''}}">
{{item.stock <= 0 ? '售罄' : '兑换'}} {{item.stock <= 0 ? '售罄' : '兑换'}}
</view> </view>
</view> </view>
@ -105,11 +105,11 @@
<view class="modal-footer"> <view class="modal-footer">
<button <button
class="exchange-btn-large {{userInfo.totalPoints < currentProduct.pointsRequired || currentProduct.stock <= 0 ? 'disabled' : ''}}" class="exchange-btn-large {{(userInfo.storePoints !== undefined ? userInfo.storePoints : userInfo.totalPoints || 0) < currentProduct.pointsRequired || currentProduct.stock <= 0 ? 'disabled' : ''}}"
bindtap="exchangeProduct" bindtap="exchangeProduct"
disabled="{{userInfo.totalPoints < currentProduct.pointsRequired || currentProduct.stock <= 0}}" disabled="{{(userInfo.storePoints !== undefined ? userInfo.storePoints : userInfo.totalPoints || 0) < currentProduct.pointsRequired || currentProduct.stock <= 0}}"
> >
{{currentProduct.stock <= 0 ? '已售罄' : userInfo.totalPoints < currentProduct.pointsRequired ? '积分不足' : '立即兑换'}} {{currentProduct.stock <= 0 ? '已售罄' : (userInfo.storePoints !== undefined ? userInfo.storePoints : userInfo.totalPoints || 0) < currentProduct.pointsRequired ? '积分不足' : '立即兑换'}}
</button> </button>
</view> </view>
</view> </view>

View File

@ -4,6 +4,7 @@
<view class="record-item" wx:for="{{records}}" wx:key="id"> <view class="record-item" wx:for="{{records}}" wx:key="id">
<view class="record-info"> <view class="record-info">
<text class="action-name">{{item.actionName}}</text> <text class="action-name">{{item.actionName}}</text>
<text class="record-store" wx:if="{{item.storeName}}">{{item.storeName}}</text>
<text class="record-time">{{item.createdAt}}</text> <text class="record-time">{{item.createdAt}}</text>
</view> </view>
<view class="record-points {{item.points > 0 ? 'positive' : 'negative'}}"> <view class="record-points {{item.points > 0 ? 'positive' : 'negative'}}">

View File

@ -199,6 +199,25 @@
.record-info { .record-info {
flex: 1; flex: 1;
overflow: hidden; 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 { .record-title {

View File

@ -27,9 +27,20 @@ Page({
} }
}, },
// 初始化当前门店信息 // 初始化当前门店信息(优先全局,其次从上次选择恢复)
initCurrentStore() { 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) { if (currentStore) {
this.setData({ this.setData({
currentStoreId: currentStore.storeId, currentStoreId: currentStore.storeId,
@ -59,8 +70,7 @@ Page({
try { try {
const res = await app.request('/api/store/nearby', { const res = await app.request('/api/store/nearby', {
latitude: loc.latitude, latitude: loc.latitude,
longitude: loc.longitude, longitude: loc.longitude
radius: 50000
}) })
this.setData({ this.setData({
stores: res.data || [], stores: res.data || [],
@ -141,6 +151,13 @@ Page({
storeAddress: store.address storeAddress: store.address
} }
// 持久化上次选择的门店,下次启动优先使用
wx.setStorageSync('last_store', {
storeId: store.id,
storeName: store.name,
storeAddress: store.address
})
// 清空旧的天梯用户信息 // 清空旧的天梯用户信息
app.globalData.ladderUser = null app.globalData.ladderUser = null

View File

@ -86,16 +86,14 @@ Page({
if (!app.globalData.token) return; if (!app.globalData.token) return;
try { try {
await app.getUserInfo(); const store = app.globalData.currentStore;
// 传入当前门店 ID获取该门店的积分和天梯信息
await app.getUserInfo(store?.storeId);
// 如果当前门店有 ladderUserId确保获取该门店的天梯用户信息 // 有当前门店时,拉取该门店的天梯用户信息(确保战力数据与当前门店一致)
if ( if (store && store.storeId) {
app.globalData.currentStore &&
app.globalData.currentStore.storeId &&
!app.globalData.ladderUser
) {
try { try {
await app.getLadderUser(app.globalData.currentStore.storeId); await app.getLadderUser(store.storeId);
} catch (e) { } catch (e) {
console.error("获取天梯用户信息失败:", e); console.error("获取天梯用户信息失败:", e);
} }
@ -105,6 +103,7 @@ Page({
userInfo: app.globalData.userInfo, userInfo: app.globalData.userInfo,
ladderUser: this.normalizeLadderUser(app.globalData.ladderUser), ladderUser: this.normalizeLadderUser(app.globalData.ladderUser),
currentStore: app.globalData.currentStore, currentStore: app.globalData.currentStore,
announcements: [], // 先清空,避免切换门店时短暂显示旧门店公告
}); });
await this.fetchAnnouncements(); await this.fetchAnnouncements();
@ -120,11 +119,8 @@ Page({
if (!store || !store.storeId) return; if (!store || !store.storeId) return;
try { try {
const res = await app.request("/api/article", { const res = await app.request("/api/article", {
method: "GET",
data: {
limit: 10, limit: 10,
store_id: store.storeId, store_id: store.storeId,
},
}); });
const raw = res.data || []; const raw = res.data || [];
const list = raw.map((a) => ({ const list = raw.map((a) => ({
@ -177,7 +173,7 @@ Page({
); );
// 获取门店信息 // 获取门店信息
await app.getCurrentStore(); await app.ensureCurrentStore();
const userInfo = app.globalData.userInfo; const userInfo = app.globalData.userInfo;
@ -252,7 +248,7 @@ Page({
this.data.registerGender, this.data.registerGender,
); );
await app.getCurrentStore(); await app.ensureCurrentStore();
const userInfo = app.globalData.userInfo; const userInfo = app.globalData.userInfo;
this.setData({ this.setData({
userInfo: userInfo, userInfo: userInfo,

View File

@ -20,7 +20,7 @@
<text class="nickname">{{userInfo.nickname || '新用户'}}</text> <text class="nickname">{{userInfo.nickname || '新用户'}}</text>
<view class="user-stats"> <view class="user-stats">
<view class="stat-item"> <view class="stat-item">
<text class="stat-value">{{userInfo.totalPoints || 0}}</text> <text class="stat-value">{{userInfo.storePoints !== undefined ? userInfo.storePoints : (userInfo.totalPoints || 0)}}</text>
<text class="stat-label">积分</text> <text class="stat-label">积分</text>
</view> </view>
<view class="stat-divider"></view> <view class="stat-divider"></view>

View File

@ -1288,31 +1288,40 @@ class MatchController {
return this.confirmScore(req, res); return this.confirmScore(req, res);
} }
// 获取我的比赛记录 // 获取我的比赛记录(不传 store_id 时返回全部门店记录)
async getMyMatches(req, res) { async getMyMatches(req, res) {
try { try {
const { store_id, page = 1, pageSize = 20 } = req.query; const { store_id, page = 1, pageSize = 20 } = req.query;
const { limit, offset } = getPagination(page, pageSize); const { limit, offset } = getPagination(page, pageSize);
const user = req.user; const user = req.user;
const ladderUser = await LadderUser.findOne({ const ladderWhere = { user_id: user.id, status: 1 };
where: { user_id: user.id, store_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)); 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({ const { rows, count } = await MatchGame.findAndCountAll({
where: { where: {
[Op.or]: [ [Op.or]: [
{ player1_id: ladderUser.id }, { player1_id: { [Op.in]: ladderUserIds } },
{ player2_id: ladderUser.id } { player2_id: { [Op.in]: ladderUserIds } }
], ],
confirm_status: CONFIRM_STATUS.CONFIRMED confirm_status: CONFIRM_STATUS.CONFIRMED
}, },
include: [ 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']], order: [['confirmed_at', 'DESC']],
limit, limit,
@ -1320,20 +1329,28 @@ class MatchController {
}); });
const list = await Promise.all(rows.map(async game => { 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 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 { return {
id: game.id, id: game.id,
matchId: game.match_id, matchId: game.match_id,
matchName: game.match?.name, matchName: game.match?.name,
matchType: game.match?.type, matchType: game.match?.type,
storeId: myLadderUser?.store_id,
storeName: myLadderUser?.store?.name,
opponentName: opponent?.real_name, opponentName: opponent?.real_name,
myScore: isPlayer1 ? game.player1_score : game.player2_score, myScore: isPlayer1 ? game.player1_score : game.player2_score,
opponentScore: isPlayer1 ? game.player2_score : game.player1_score, opponentScore: isPlayer1 ? game.player2_score : game.player1_score,
isWin: game.winner_id === ladderUser.id, isWin: game.winner_id === myLadderId,
powerChange: game.winner_id === ladderUser.id powerChange: game.winner_id === myLadderId
? game.winner_power_change ? game.winner_power_change
: game.loser_power_change, : game.loser_power_change,
confirmedAt: game.confirmed_at confirmedAt: game.confirmed_at

View File

@ -74,10 +74,10 @@ class StoreController {
} }
} }
// 获取附近门店 // 获取附近门店(默认显示所有门店,按距离由近到远排序)
async getNearby(req, res) { async getNearby(req, res) {
try { try {
const { latitude, longitude, radius = 10000 } = req.query; const { latitude, longitude } = req.query;
if (!latitude || !longitude) { if (!latitude || !longitude) {
return res.status(400).json(error('缺少位置信息', 400)); return res.status(400).json(error('缺少位置信息', 400));
@ -110,8 +110,7 @@ class StoreController {
distance 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)); res.json(success(nearbyStores));
} catch (err) { } catch (err) {

View File

@ -2,7 +2,7 @@ const jwt = require("jsonwebtoken");
const axios = require("axios"); const axios = require("axios");
const crypto = require("crypto"); const crypto = require("crypto");
const QRCode = require("qrcode"); const QRCode = require("qrcode");
const { User, LadderUser, Store, Match, MatchGame } = require("../models"); const { User, LadderUser, Store, Match, MatchGame, PointRecord } = require("../models");
const { const {
generateMemberCode, generateMemberCode,
success, success,
@ -355,10 +355,11 @@ class UserController {
} }
}; };
// 获取用户信息 // 获取用户信息(支持 store_id 查询参数,返回该门店的积分)
getInfo = async (req, res) => { getInfo = async (req, res) => {
try { try {
const user = req.user; const user = req.user;
const { store_id: storeId } = req.query;
// 获取天梯信息 // 获取天梯信息
const ladderUsers = await LadderUser.findAll({ const ladderUsers = await LadderUser.findAll({
@ -366,8 +367,19 @@ class UserController {
include: [{ model: Store, as: "store", attributes: ["id", "name"] }], include: [{ model: Store, as: "store", attributes: ["id", "name"] }],
}); });
res.json( // 按门店的积分:从 PointRecord 汇总该门店的积分变动
success({ 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, id: user.id,
nickname: user.nickname, nickname: user.nickname,
avatar: getFullUrl(user.avatar, req), avatar: getFullUrl(user.avatar, req),
@ -386,8 +398,11 @@ class UserController {
matchCount: lu.match_count, matchCount: lu.match_count,
winCount: lu.win_count, winCount: lu.win_count,
})), })),
}), };
); if (storePoints !== null) {
result.storePoints = storePoints;
}
res.json(success(result));
} catch (err) { } catch (err) {
console.error("获取用户信息失败:", err); console.error("获取用户信息失败:", err);
res.status(500).json(error("获取用户信息失败")); res.status(500).json(error("获取用户信息失败"));

View File

@ -6,13 +6,13 @@ const { authUser } = require('../middlewares/auth');
// 获取门店列表 // 获取门店列表
router.get('/list', storeController.getList); router.get('/list', storeController.getList);
// 获取门店详情 // 获取附近门店(必须放在 /:id 之前,否则 "nearby" 会被当作 id 匹配)
router.get('/:id', storeController.getDetail);
// 获取附近门店
router.get('/nearby', authUser, storeController.getNearby); router.get('/nearby', authUser, storeController.getNearby);
// 获取用户参与天梯的门店 // 获取用户参与天梯的门店
router.get('/ladder-stores', authUser, storeController.getLadderStores); router.get('/ladder-stores', authUser, storeController.getLadderStores);
// 获取门店详情(放在最后,避免 /list、/nearby 等被当作 id
router.get('/:id', storeController.getDetail);
module.exports = router; module.exports = router;