diff --git a/components/analytics/AnalyticsUserGenderSection.uvue b/components/analytics/AnalyticsUserGenderSection.uvue index 41f67ab7..a653e688 100644 --- a/components/analytics/AnalyticsUserGenderSection.uvue +++ b/components/analytics/AnalyticsUserGenderSection.uvue @@ -3,7 +3,7 @@ 用户性别比例 - + @@ -16,102 +16,155 @@ - \ No newline at end of file diff --git a/pages/mall/analytics/profile.uvue b/pages/mall/analytics/profile.uvue index d0d6c65c..3b4c99d4 100644 --- a/pages/mall/analytics/profile.uvue +++ b/pages/mall/analytics/profile.uvue @@ -1013,8 +1013,6 @@ function goToFeedback() { font-size: 22rpx; color: #8c929b; } - color: #999; -} .trend-legend { display: flex; diff --git a/pages/user/login.uvue b/pages/user/login.uvue index 6276d66a..a0ffd7e6 100644 --- a/pages/user/login.uvue +++ b/pages/user/login.uvue @@ -143,6 +143,7 @@ import { ref, onMounted } from 'vue' import supa from '@/components/supadb/aksupainstance.uts' import { IS_TEST_MODE } from '@/ak/config.uts' import { getCurrentUser, logout } from '@/utils/store.uts' +import { ensureUserProfile } from '@/utils/sapi.uts' const cssVars = { '--bg': '#f5f6f8', @@ -256,8 +257,8 @@ const getCode = async () => { const handleLogin = async () => { if (!validateAccount()) return - // 特殊账号处理:admin/admin 直接跳转 - if (account.value === 'admin' && password.value === 'admin') { + // 特殊账号处理:仅在测试模式允许本地绕过登录(不推荐生产使用) + if (IS_TEST_MODE && account.value === 'admin' && password.value === 'admin') { setIsLoggedIn(true) const adminProfile = { id: 'admin', @@ -277,7 +278,7 @@ const handleLogin = async () => { } as UserProfile setUserProfile(adminProfile) - uni.showToast({ title: '管理员登录成功', icon: 'success' }) + uni.showToast({ title: '管理员登录成功(测试模式)', icon: 'success' }) setTimeout(() => { uni.switchTab({ url: '/pages/mall/consumer/index' }) }, 500) @@ -328,12 +329,26 @@ const handleLogin = async () => { return } - // 尝试获取/补全用户资料,但失败时不再阻塞登录 + // 登录成功后强制同步用户资料到 ak_users(确保 auth_id 与 role 落表) try { - const profile = await getCurrentUser() - console.log('current user profile:', profile) + const sessionInfo = supa.getSession() + if (sessionInfo?.user != null) { + const syncResult = await ensureUserProfile(sessionInfo.user) + console.log('ensureUserProfile sync result:', syncResult) + } } catch (e) { - console.error('获取用户信息失败(忽略,不阻塞登录):', e) + console.error('同步用户资料到 ak_users 失败(不阻塞登录):', e) + } + + // 登录成功后按 redirect 参数跳转(守卫放在需要权限的页面入口) + const pages = getCurrentPages() as any[] + const currentPage = pages.length > 0 ? pages[pages.length - 1] : null + const opts = currentPage?.options as any + const redirect = opts?.redirect as string | null + if (redirect != null && redirect.length > 0) { + uni.redirectTo({ url: decodeURIComponent(redirect) }) + } else { + uni.switchTab({ url: '/pages/mall/consumer/index' }) } // 显式保存用户ID到本地存储,确保页面刷新或重启后 SupabaseService 能恢复身份 diff --git a/pages_default_temp.json b/pages_default_temp.json deleted file mode 100644 index 896c6e7c..00000000 --- a/pages_default_temp.json +++ /dev/null @@ -1,1320 +0,0 @@ -{ - "pages": [ - { - "path": "pages/mall/admin/homePage/index", - "style": { - "navigationBarTitleText": "绠$悊鍚庡彴", - "navigationStyle": "custom" - } - }, - { - "path": "pages/user/login", - "style": { - "navigationBarTitleText": "鐢ㄦ埛鐧诲綍", - "navigationStyle": "custom" - } - }, - { - "path": "pages/user/boot", - "style": { - "navigationBarTitleText": "" - } - }, - { - "path": "pages/user/register", - "style": { - "navigationBarTitleText": "娉ㄥ唽" - } - }, - { - "path": "pages/user/forgot-password", - "style": { - "navigationBarTitleText": "蹇樿瀵嗙爜" - } - }, - { - "path": "pages/user/terms", - "style": { - "navigationBarTitleText": "鐢ㄦ埛鍗忚涓庨殣绉佹斂绛? - } - }, - { - "path": "pages/user/center", - "style": { - "navigationBarTitleText": "鐢ㄦ埛涓績" - } - }, - { - "path": "pages/user/profile", - "style": { - "navigationBarTitleText": "涓汉璧勬枡" - } - }, - { - "path": "pages/mall/consumer/index", - "style": { - "navigationBarTitleText": "棣栭〉", - "navigationStyle": "custom", - "enablePullDownRefresh": true - } - }, - { - "path": "pages/mall/consumer/category", - "style": { - "navigationBarTitleText": "鍒嗙被" - } - }, - { - "path": "pages/mall/consumer/messages", - "style": { - "navigationBarTitleText": "娑堟伅", - "enablePullDownRefresh": true - } - }, - { - "path": "pages/mall/consumer/cart", - "style": { - "navigationBarTitleText": "璐墿杞? - } - }, - { - "path": "pages/mall/consumer/profile", - "style": { - "navigationBarTitleText": "鎴戠殑" - } - } - ], - "subPackages": [ - { - "root": "pages/mall/consumer", - "pages": [ - { - "path": "settings", - "style": { - "navigationBarTitleText": "璁剧疆" - } - }, - { - "path": "wallet", - "style": { - "navigationBarTitleText": "鎴戠殑閽卞寘" - } - }, - { - "path": "search", - "style": { - "navigationBarTitleText": "鎼滅储", - "navigationStyle": "custom" - } - }, - { - "path": "product-detail", - "style": { - "navigationBarTitleText": "鍟嗗搧璇︽儏" - } - }, - { - "path": "shop-detail", - "style": { - "navigationBarTitleText": "搴楅摵璇︽儏" - } - }, - { - "path": "coupons", - "style": { - "navigationBarTitleText": "鎴戠殑浼樻儬鍒? - } - }, - { - "path": "favorites", - "style": { - "navigationBarTitleText": "鎴戠殑鏀惰棌" - } - }, - { - "path": "footprint", - "style": { - "navigationBarTitleText": "鎴戠殑瓒宠抗" - } - }, - { - "path": "address-list", - "style": { - "navigationBarTitleText": "鏀惰揣鍦板潃" - } - }, - { - "path": "address-edit", - "style": { - "navigationBarTitleText": "缂栬緫鍦板潃" - } - }, - { - "path": "checkout", - "style": { - "navigationBarTitleText": "纭璁㈠崟" - } - }, - { - "path": "payment", - "style": { - "navigationBarTitleText": "鏀堕摱鍙? - } - }, - { - "path": "payment-success", - "style": { - "navigationBarTitleText": "鏀粯鎴愬姛", - "navigationStyle": "custom" - } - }, - { - "path": "orders", - "style": { - "navigationBarTitleText": "鎴戠殑璁㈠崟", - "enablePullDownRefresh": true - } - }, - { - "path": "order-detail", - "style": { - "navigationBarTitleText": "璁㈠崟璇︽儏" - } - }, - { - "path": "logistics", - "style": { - "navigationBarTitleText": "鐗╂祦璇︽儏" - } - }, - { - "path": "review", - "style": { - "navigationBarTitleText": "璇勪环鏅掑崟" - } - }, - { - "path": "refund", - "style": { - "navigationBarTitleText": "閫€娆?鍞悗" - } - }, - { - "path": "apply-refund", - "style": { - "navigationBarTitleText": "鐢宠鍞悗" - } - }, - { - "path": "refund-review", - "style": { - "navigationBarTitleText": "鏈嶅姟璇勪环" - } - }, - { - "path": "chat", - "style": { - "navigationBarTitleText": "瀹㈡湇鑱婂ぉ", - "navigationStyle": "custom" - } - }, - { - "path": "subscription/plan-list", - "style": { - "navigationBarTitleText": "杞欢璁㈤槄" - } - }, - { - "path": "subscription/plan-detail", - "style": { - "navigationBarTitleText": "璁㈤槄璇︽儏" - } - }, - { - "path": "subscription/subscribe-checkout", - "style": { - "navigationBarTitleText": "纭璁㈤槄" - } - }, - { - "path": "subscription/my-subscriptions", - "style": { - "navigationBarTitleText": "鎴戠殑璁㈤槄" - } - } - ] - }, - { - "root": "pages/mall/delivery", - "pages": [ - { - "path": "index", - "style": { - "navigationBarTitleText": "閰嶉€佷腑蹇?, - "navigationStyle": "custom" - } - }, - { - "path": "order-detail", - "style": { - "navigationBarTitleText": "璁㈠崟璇︽儏椤?, - "navigationStyle": "custom" - } - }, - { - "path": "profile", - "style": { - "navigationBarTitleText": "閰嶉€佷釜浜轰腑蹇?, - "navigationStyle": "custom" - } - }, - { - "path": "order-history", - "style": { - "navigationBarTitleText": "鍘嗗彶璁板綍", - "navigationStyle": "custom" - } - }, - { - "path": "earnings", - "style": { - "navigationBarTitleText": "鏀跺叆鏄庣粏", - "navigationStyle": "custom" - } - }, - { - "path": "tasks", - "style": { - "navigationBarTitleText": "鍏ㄩ儴浠诲姟", - "navigationStyle": "custom" - } - }, - { - "path": "task-detail", - "style": { - "navigationBarTitleText": "浠诲姟璇︽儏", - "navigationStyle": "custom" - } - }, - { - "path": "profile-edit", - "style": { - "navigationBarTitleText": "缂栬緫涓汉璧勬枡", - "navigationStyle": "custom" - } - }, - { - "path": "ratings", - "style": { - "navigationBarTitleText": "璇勪环", - "navigationStyle": "custom" - } - }, - { - "path": "vehicle", - "style": { - "navigationBarTitleText": "杞﹁締绠$悊", - "navigationStyle": "custom" - } - }, - { - "path": "vehicle-add", - "style": { - "navigationBarTitleText": "娣诲姞杞﹁締", - "navigationStyle": "custom" - } - }, - { - "path": "vehicle-edit", - "style": { - "navigationBarTitleText": "缂栬緫杞﹁締", - "navigationStyle": "custom" - } - }, - { - "path": "settings", - "style": { - "navigationBarTitleText": "璁剧疆", - "navigationStyle": "custom" - } - } - ] - }, - { - "root": "pages/mall/analytics", - "pages": [ - { - "path": "index", - "style": { - "navigationBarTitleText": "鏁版嵁鍒嗘瀽", - "navigationStyle": "custom" - } - }, - { - "path": "profile", - "style": { - "navigationBarTitleText": "鏁版嵁鍒嗘瀽涓汉涓績" - } - }, - { - "path": "sales-report", - "style": { - "navigationBarTitleText": "閿€鍞姤琛? - } - }, - { - "path": "user-analysis", - "style": { - "navigationBarTitleText": "鐢ㄦ埛鍒嗘瀽" - } - }, - { - "path": "product-insights", - "style": { - "navigationBarTitleText": "鍟嗗搧娲炲療" - } - }, - { - "path": "delivery-analysis", - "style": { - "navigationBarTitleText": "閰嶉€佹晥鐜囧垎鏋? - } - }, - { - "path": "coupon-analysis", - "style": { - "navigationBarTitleText": "浼樻儬鍒告晥鏋滃垎鏋? - } - }, - { - "path": "market-trends", - "style": { - "navigationBarTitleText": "甯傚満瓒嬪娍" - } - }, - { - "path": "custom-report", - "style": { - "navigationBarTitleText": "鑷畾涔夋姤琛? - } - }, - { - "path": "report-detail", - "style": { - "navigationBarTitleText": "鎶ヨ〃璇︽儏", - "enablePullDownRefresh": false - } - }, - { - "path": "data-detail", - "style": { - "navigationBarTitleText": "鏁版嵁鍒嗘瀽璇︽儏", - "enablePullDownRefresh": false - } - }, - { - "path": "insight-detail", - "style": { - "navigationBarTitleText": "鏁版嵁娲炲療璇︽儏", - "enablePullDownRefresh": false - } - }, - { - "path": "test/test-connection", - "style": { - "navigationBarTitleText": "Supabase 杩炴帴娴嬭瘯" - } - } - ] - }, - { - "root": "pages/mall/admin", - "pages": [ - { - "path": "content/index", - "style": { - "navigationBarTitleText": "鏂囩珷绠$悊", - "navigationStyle": "custom" - } - }, - { - "path": "article/index", - "style": { - "navigationBarTitleText": "鏂囩珷绠$悊", - "navigationStyle": "custom" - } - }, - { - "path": "article/category", - "style": { - "navigationBarTitleText": "鏂囩珷鍒嗙被", - "navigationStyle": "custom" - } - }, - { - "path": "article/create", - "style": { - "navigationBarTitleText": "娣诲姞鏂囩珷", - "navigationStyle": "custom" - } - }, - { - "path": "article/edit", - "style": { - "navigationBarTitleText": "缂栬緫鏂囩珷", - "navigationStyle": "custom" - } - }, - - { - "path": "service/index", - "style": { - "navigationBarTitleText": "瀹㈡湇鍒楄〃", - "navigationStyle": "custom" - } - }, - { - "path": "service/script", - "style": { - "navigationBarTitleText": "瀹㈡湇璇濇湳", - "navigationStyle": "custom" - } - }, - { - "path": "service/message", - "style": { - "navigationBarTitleText": "鐢ㄦ埛鐣欒█", - "navigationStyle": "custom" - } - }, - { - "path": "service/autoReply", - "style": { - "navigationBarTitleText": "鑷姩鍥炲", - "navigationStyle": "custom" - } - }, - { - "path": "service/config", - "style": { - "navigationBarTitleText": "瀹㈡湇閰嶇疆", - "navigationStyle": "custom" - } - }, - - { - "path": "design/index", - "style": { - "navigationBarTitleText": "椤甸潰瑁呬慨", - "navigationStyle": "custom" - } - }, - { - "path": "design/homepage", - "style": { - "navigationBarTitleText": "棣栭〉瑁呬慨", - "navigationStyle": "custom" - } - }, - { - "path": "design/category", - "style": { - "navigationBarTitleText": "鍒嗙被椤佃淇?, - "navigationStyle": "custom" - } - }, - { - "path": "design/product", - "style": { - "navigationBarTitleText": "鍟嗗搧椤佃淇?, - "navigationStyle": "custom" - } - }, - { - "path": "design/custom", - "style": { - "navigationBarTitleText": "鑷畾涔夐〉闈?, - "navigationStyle": "custom" - } - }, - { - "path": "design/templates", - "style": { - "navigationBarTitleText": "妯℃澘搴?, - "navigationStyle": "custom" - } - }, - { - "path": "design/components", - "style": { - "navigationBarTitleText": "缁勪欢搴?, - "navigationStyle": "custom" - } - }, - { - "path": "maintain/data/city-data", - "style": { - "navigationBarTitleText": "鍩庡競鏁版嵁", - "navigationStyle": "custom" - } - }, - { - "path": "maintain/data/clear-data", - "style": { - "navigationBarTitleText": "娓呴櫎鏁版嵁", - "navigationStyle": "custom" - } - }, - { - "path": "maintain/data/logistics-company", - "style": { - "navigationBarTitleText": "鐗╂祦鍏徃", - "navigationStyle": "custom" - } - }, - { - "path": "maintain/dev-config/category", - "style": { - "navigationBarTitleText": "閰嶇疆鍒嗙被", - "navigationStyle": "custom" - } - }, - { - "path": "maintain/dev-config/combination-data", - "style": { - "navigationBarTitleText": "缁勫悎鏁版嵁", - "navigationStyle": "custom" - } - }, - { - "path": "maintain/dev-config/cron-job", - "style": { - "navigationBarTitleText": "瀹氭椂浠诲姟", - "navigationStyle": "custom" - } - }, - { - "path": "maintain/dev-config/custom-event", - "style": { - "navigationBarTitleText": "鑷畾浜嬩欢", - "navigationStyle": "custom" - } - }, - { - "path": "maintain/dev-config/module-config", - "style": { - "navigationBarTitleText": "妯″潡閰嶇疆", - "navigationStyle": "custom" - } - }, - { - "path": "maintain/dev-config/permission", - "style": { - "navigationBarTitleText": "鏉冮檺缁存姢", - "navigationStyle": "custom" - } - }, - { - "path": "maintain/dev-tools/api", - "style": { - "navigationBarTitleText": "鎺ュ彛绠$悊", - "navigationStyle": "custom" - } - }, - { - "path": "maintain/dev-tools/codegen", - "style": { - "navigationBarTitleText": "浠g爜鐢熸垚", - "navigationStyle": "custom" - } - }, - { - "path": "maintain/dev-tools/data-dict", - "style": { - "navigationBarTitleText": "鏁版嵁瀛楀吀", - "navigationStyle": "custom" - } - }, - { - "path": "maintain/dev-tools/database", - "style": { - "navigationBarTitleText": "鏁版嵁搴撶鐞?, - "navigationStyle": "custom" - } - }, - { - "path": "maintain/dev-tools/file", - "style": { - "navigationBarTitleText": "鏂囦欢绠$悊", - "navigationStyle": "custom" - } - }, - { - "path": "maintain/external/account", - "style": { - "navigationBarTitleText": "璐﹀彿绠$悊", - "navigationStyle": "custom" - } - }, - { - "path": "maintain/i18n/language-detail", - "style": { - "navigationBarTitleText": "璇█璇︽儏", - "navigationStyle": "custom" - } - }, - { - "path": "maintain/i18n/language-list", - "style": { - "navigationBarTitleText": "璇█鍒楄〃", - "navigationStyle": "custom" - } - }, - { - "path": "maintain/i18n/region-list", - "style": { - "navigationBarTitleText": "鍦板尯鍒楄〃", - "navigationStyle": "custom" - } - }, - { - "path": "maintain/i18n/translate-config", - "style": { - "navigationBarTitleText": "缈昏瘧閰嶇疆", - "navigationStyle": "custom" - } - }, - { - "path": "maintain/security/online-upgrade", - "style": { - "navigationBarTitleText": "鍦ㄧ嚎鍗囩骇", - "navigationStyle": "custom" - } - }, - { - "path": "maintain/security/refresh-cache", - "style": { - "navigationBarTitleText": "鍒锋柊缂撳瓨", - "navigationStyle": "custom" - } - }, - { - "path": "maintain/security/system-log", - "style": { - "navigationBarTitleText": "绯荤粺鏃ュ織", - "navigationStyle": "custom" - } - }, - { - "path": "maintain/system-info", - "style": { - "navigationBarTitleText": "绯荤粺淇℃伅", - "navigationStyle": "custom" - } - }, - { - "path": "marketing/index", - "style": { - "navigationBarTitleText": "钀ラ攢绠$悊", - "navigationStyle": "custom" - } - }, - - { - "path": "marketing/coupon/list", - "style": { - "navigationBarTitleText": "浼樻儬鍒稿垪琛?, - "navigationStyle": "custom" - } - }, - { - "path": "marketing/coupon/receive", - "style": { - "navigationBarTitleText": "鐢ㄦ埛棰嗗彇璁板綍", - "navigationStyle": "custom" - } - }, - - { - "path": "marketing/points/index", - "style": { - "navigationBarTitleText": "绉垎绠$悊", - "navigationStyle": "custom" - } - }, - - { - "path": "marketing/points/stats", - "style": { - "navigationBarTitleText": "绉垎缁熻", - "navigationStyle": "custom" - } - }, - { - "path": "marketing/points/goods", - "style": { - "navigationBarTitleText": "绉垎鍟嗗搧", - "navigationStyle": "custom" - } - }, - { - "path": "marketing/points/order", - "style": { - "navigationBarTitleText": "绉垎璁㈠崟", - "navigationStyle": "custom" - } - }, - { - "path": "marketing/points/record", - "style": { - "navigationBarTitleText": "绉垎璁板綍", - "navigationStyle": "custom" - } - }, - { - "path": "marketing/points/config", - "style": { - "navigationBarTitleText": "绉垎閰嶇疆", - "navigationStyle": "custom" - } - }, - - { - "path": "marketing/lottery/list", - "style": { - "navigationBarTitleText": "鎶藉鍒楄〃", - "navigationStyle": "custom" - } - }, - { - "path": "marketing/lottery/config", - "style": { - "navigationBarTitleText": "鎶藉閰嶇疆", - "navigationStyle": "custom" - } - }, - - { - "path": "marketing/groupbuy/goods", - "style": { - "navigationBarTitleText": "鎷煎洟鍟嗗搧", - "navigationStyle": "custom" - } - }, - { - "path": "marketing/groupbuy/list", - "style": { - "navigationBarTitleText": "鎷煎洟鍒楄〃", - "navigationStyle": "custom" - } - }, - - { - "path": "marketing/seckill/goods", - "style": { - "navigationBarTitleText": "绉掓潃鍟嗗搧", - "navigationStyle": "custom" - } - }, - { - "path": "marketing/seckill/list", - "style": { - "navigationBarTitleText": "绉掓潃鍒楄〃", - "navigationStyle": "custom" - } - }, - { - "path": "marketing/seckill/config", - "style": { - "navigationBarTitleText": "绉掓潃閰嶇疆", - "navigationStyle": "custom" - } - }, - - { - "path": "marketing/member/type", - "style": { - "navigationBarTitleText": "浼氬憳绫诲瀷", - "navigationStyle": "custom" - } - }, - { - "path": "marketing/member/rights", - "style": { - "navigationBarTitleText": "浼氬憳鏉冪泭", - "navigationStyle": "custom" - } - }, - { - "path": "marketing/member/card", - "style": { - "navigationBarTitleText": "鍗″瘑浼氬憳", - "navigationStyle": "custom" - } - }, - { - "path": "marketing/member/record", - "style": { - "navigationBarTitleText": "浼氬憳璁板綍", - "navigationStyle": "custom" - } - }, - { - "path": "marketing/member/config", - "style": { - "navigationBarTitleText": "浼氬憳閰嶇疆", - "navigationStyle": "custom" - } - }, - - { - "path": "marketing/live/room", - "style": { - "navigationBarTitleText": "鐩存挱闂寸鐞?, - "navigationStyle": "custom" - } - }, - { - "path": "marketing/live/goods", - "style": { - "navigationBarTitleText": "鐩存挱鍟嗗搧绠$悊", - "navigationStyle": "custom" - } - }, - { - "path": "marketing/live/anchor", - "style": { - "navigationBarTitleText": "涓绘挱绠$悊", - "navigationStyle": "custom" - } - }, - - { - "path": "marketing/recharge/amount", - "style": { - "navigationBarTitleText": "鍏呭€奸噾棰濊缃?, - "navigationStyle": "custom" - } - }, - { - "path": "marketing/recharge/config", - "style": { - "navigationBarTitleText": "鍏呭€奸厤缃?, - "navigationStyle": "custom" - } - }, - { - "path": "marketing/recharge/record", - "style": { - "navigationBarTitleText": "鍏呭€艰褰?, - "navigationStyle": "custom" - } - }, - - { - "path": "marketing/signin/rule", - "style": { - "navigationBarTitleText": "绛惧埌瑙勫垯", - "navigationStyle": "custom" - } - }, - { - "path": "marketing/signin/record", - "style": { - "navigationBarTitleText": "绛惧埌璁板綍", - "navigationStyle": "custom" - } - }, - - { - "path": "marketing/newcomer", - "style": { - "navigationBarTitleText": "鏂颁汉绀?, - "navigationStyle": "custom" - } - }, - - { - "path": "order/order-statistics/index", - "style": { - "navigationBarTitleText": "璁㈠崟缁熻", - "navigationStyle": "custom" - } - }, - { - "path": "order/order-management/index", - "style": { - "navigationBarTitleText": "璁㈠崟绠$悊", - "navigationStyle": "custom" - } - }, - { - "path": "order/aftersales-order/index", - "style": { - "navigationBarTitleText": "鍞悗璁㈠崟", - "navigationStyle": "custom" - } - }, - { - "path": "order/cashier-order/index", - "style": { - "navigationBarTitleText": "鏀堕摱璁㈠崟", - "navigationStyle": "custom" - } - }, - { - "path": "order/write-off-records/index", - "style": { - "navigationBarTitleText": "鏍搁攢璁板綍", - "navigationStyle": "custom" - } - }, - { - "path": "order/order-configuration/index", - "style": { - "navigationBarTitleText": "璁㈠崟閰嶇疆", - "navigationStyle": "custom" - } - }, - { - "path": "product/product-classification/index", - "style": { - "navigationBarTitleText": "鍟嗗搧鍒嗙被", - "navigationStyle": "custom" - } - }, - { - "path": "product/product-label/index", - "style": { - "navigationBarTitleText": "鍟嗗搧鏍囩", - "navigationStyle": "custom" - } - }, - { - "path": "product/product-management/index", - "style": { - "navigationBarTitleText": "鍟嗗搧绠$悊", - "navigationStyle": "custom" - } - }, - { - "path": "product/product-param/index", - "style": { - "navigationBarTitleText": "鍟嗗搧鍙傛暟", - "navigationStyle": "custom" - } - }, - { - "path": "product/product-protection/index", - "style": { - "navigationBarTitleText": "鍟嗗搧淇濋殰", - "navigationStyle": "custom" - } - }, - { - "path": "product/product-reviews/index", - "style": { - "navigationBarTitleText": "鍟嗗搧瀹℃牳" - } - }, - { - "path": "product/product-specifications/index", - "style": { - "navigationBarTitleText": "鍟嗗搧瑙勬牸", - "navigationStyle": "custom" - } - }, - { - "path": "product/product-statistics/index", - "style": { - "navigationBarTitleText": "鍟嗗搧缁熻", - "navigationStyle": "custom" - } - }, - - { - "path": "subscription/plan-management", - "style": { - "navigationBarTitleText": "璁㈤槄鏂规绠$悊" - } - }, - { - "path": "subscription/user-subscriptions", - "style": { - "navigationBarTitleText": "鐢ㄦ埛璁㈤槄绠$悊" - } - }, - { - "path": "system/index", - "style": { - "navigationBarTitleText": "绯荤粺璁剧疆", - "navigationStyle": "custom" - } - }, - { - "path": "system/agreement-settings", - "style": { - "navigationBarTitleText": "鍗忚璁剧疆", - "navigationStyle": "custom" - } - }, - { - "path": "system/api/collect", - "style": { - "navigationBarTitleText": "鍟嗗搧閲囬泦閰嶇疆", - "navigationStyle": "custom" - } - }, - { - "path": "system/api/logistics", - "style": { - "navigationBarTitleText": "鐗╂祦鏌ヨ閰嶇疆", - "navigationStyle": "custom" - } - }, - { - "path": "system/api/pay", - "style": { - "navigationBarTitleText": "鍟嗗煄鏀粯閰嶇疆", - "navigationStyle": "custom" - } - }, - { - "path": "system/api/sms", - "style": { - "navigationBarTitleText": "鐭俊鎺ュ彛閰嶇疆", - "navigationStyle": "custom" - } - }, - { - "path": "system/api/storage", - "style": { - "navigationBarTitleText": "绯荤粺瀛樺偍閰嶇疆", - "navigationStyle": "custom" - } - }, - { - "path": "system/api/waybill", - "style": { - "navigationBarTitleText": "鐢靛瓙闈㈠崟閰嶇疆", - "navigationStyle": "custom" - } - }, - { - "path": "system/api/yht/config", - "style": { - "navigationBarTitleText": "涓€鍙烽€氶厤缃?, - "navigationStyle": "custom" - } - }, - { - "path": "system/api/yht/page", - "style": { - "navigationBarTitleText": "涓€鍙烽€氶〉闈?, - "navigationStyle": "custom" - } - }, - { - "path": "system/message-management", - "style": { - "navigationBarTitleText": "娑堟伅绠$悊", - "navigationStyle": "custom" - } - }, - { - "path": "system/permission/admin-list", - "style": { - "navigationBarTitleText": "绠$悊鍛樺垪琛?, - "navigationStyle": "custom" - } - }, - { - "path": "system/permission/permission-setting", - "style": { - "navigationBarTitleText": "鏉冮檺璁剧疆", - "navigationStyle": "custom" - } - }, - { - "path": "system/permission/role", - "style": { - "navigationBarTitleText": "瑙掕壊绠$悊", - "navigationStyle": "custom" - } - }, - { - "path": "system/receipt-settings", - "style": { - "navigationBarTitleText": "灏忕エ閰嶇疆", - "navigationStyle": "custom" - } - }, - { - "path": "system/shipping/courier", - "style": { - "navigationBarTitleText": "閰嶉€佸憳绠$悊", - "navigationStyle": "custom" - } - }, - { - "path": "system/shipping/freight-template", - "style": { - "navigationBarTitleText": "杩愯垂妯℃澘", - "navigationStyle": "custom" - } - }, - { - "path": "system/shipping/pickup/points", - "style": { - "navigationBarTitleText": "鎻愯揣鐐?, - "navigationStyle": "custom" - } - }, - { - "path": "system/shipping/pickup/verifiers", - "style": { - "navigationBarTitleText": "鏍搁攢鍛?, - "navigationStyle": "custom" - } - }, - { - "path": "user/user-management/index", - "style": { - "navigationBarTitleText": "鐢ㄦ埛绠$悊", - "navigationStyle": "custom" - } - }, - { - "path": "user/user-grouping/index", - "style": { - "navigationBarTitleText": "鐢ㄦ埛鍒嗙粍", - "navigationStyle": "custom" - } - }, - { - "path": "user/user-label/index", - "style": { - "navigationBarTitleText": "鐢ㄦ埛鏍囩", - "navigationStyle": "custom" - } - }, - { - "path": "user/user-level/index", - "style": { - "navigationBarTitleText": "鐢ㄦ埛绛夌骇", - "navigationStyle": "custom" - } - }, - { - "path": "user/user-configuration/index", - "style": { - "navigationBarTitleText": "鐢ㄦ埛閰嶇疆", - "navigationStyle": "custom" - } - }, - { - "path": "user/user-statistics/index", - "style": { - "navigationBarTitleText": "鐢ㄦ埛缁熻", - "navigationStyle": "custom" - } - } - ] - }, - { - "root": "pages/mall/merchant", - "pages": [ - { - "path": "index", - "style": { - "navigationBarTitleText": "鍟嗗涓績", - "navigationStyle": "custom" - } - }, - { - "path": "product-detail", - "style": { - "navigationBarTitleText": "鍟嗗搧绠$悊璇︽儏", - "enablePullDownRefresh": false - } - }, - { - "path": "profile", - "style": { - "navigationBarTitleText": "涓汉璧勬枡" - } - } - ] - }, - { - "root": "pages/mall/service", - "pages": [ - { - "path": "index", - "style": { - "navigationBarTitleText": "瀹㈡湇宸ヤ綔鍙?, - "navigationStyle": "custom" - } - }, - { - "path": "profile", - "style": { - "navigationBarTitleText": "瀹㈡湇涓汉涓績" - } - }, - { - "path": "ticket-detail", - "style": { - "navigationBarTitleText": "宸ュ崟璇︽儏", - "enablePullDownRefresh": false - } - } - ] - } - ], - "tabBar": { - "color": "#999999", - "selectedColor": "#ff5000", - "backgroundColor": "#ffffff", - "borderStyle": "black", - "list": [ - { - "pagePath": "pages/mall/consumer/index", - "text": "棣栭〉", - "iconPath": "static/tabbar/home.png", - "selectedIconPath": "static/tabbar/home-active.png" - }, - { - "pagePath": "pages/mall/consumer/category", - "text": "鍒嗙被", - "iconPath": "static/tabbar/category.png", - "selectedIconPath": "static/tabbar/category-active.png" - }, - { - "pagePath": "pages/mall/consumer/messages", - "text": "娑堟伅", - "iconPath": "static/tabbar/messages.png", - "selectedIconPath": "static/tabbar/messages-active.png" - }, - { - "pagePath": "pages/mall/consumer/cart", - "text": "璐墿杞?, - "iconPath": "static/tabbar/cart.png", - "selectedIconPath": "static/tabbar/cart-active.png" - }, - { - "pagePath": "pages/mall/consumer/profile", - "text": "鎴戠殑", - "iconPath": "static/tabbar/profile.png", - "selectedIconPath": "static/tabbar/profile-active.png" - } - ] - }, - "globalStyle": { - "navigationBarTextStyle": "black", - "navigationBarTitleText": "mall", - "navigationBarBackgroundColor": "#FFFFFF", - "backgroundColor": "#F8F8F8" - } -} - diff --git a/services/admin/AdminUserService.uts b/services/admin/AdminUserService.uts new file mode 100644 index 00000000..3efe6664 --- /dev/null +++ b/services/admin/AdminUserService.uts @@ -0,0 +1,236 @@ +import { supa } from '@/utils/supabaseService.uts' +import type { AkReqResponse } from '@/uni_modules/ak-req/interface.uts' + +// Admin 用户管理相关类型定义 +export type AdminUserItem = { + id: string + auth_id: string + username: string + email: string + role: string + profile_status?: number + real_name?: string + credit_score?: number + verification_status?: number + created_at: string + updated_at: string + balance: number // 固定 0 + is_member: boolean + member_plan_name?: string + member_end_date?: string +} + +export type AdminUserDetail = { + id: string + auth_id: string + username: string + email: string + role: string + profile_status?: number + real_name?: string + credit_score?: number + verification_status?: number + preferences?: UTSJSONObject + emergency_contact?: string + service_areas?: UTSJSONObject + created_at: string + updated_at: string + balance: number // 固定 0 + is_member: boolean + member_info?: { + plan_name: string + plan_code: string + billing_period: string + price: number + features: UTSJSONObject + status: string + start_date: string + end_date?: string + next_billing_date?: string + auto_renew: boolean + } + addresses?: Array<{ + id: string + receiver_name: string + receiver_phone: string + province: string + city: string + district: string + address_detail: string + postal_code?: string + is_default: boolean + label?: string + latitude?: number + longitude?: number + delivery_instructions?: string + business_hours?: string + status: number + created_at: string + updated_at: string + }> +} + +export type AdminUserListParams = { + page?: number + limit?: number + search?: string + role?: string + status?: number + is_member?: boolean +} + +export type AdminUserListResponse = { + total: number + page: number + limit: number + has_more: boolean + items: Array +} + +/** + * Admin 用户管理服务 + * 封装对 admin 用户管理相关 RPC 的调用 + * 符合项目规范:页面/组件不得直接访问 supabase client,必须通过 services + */ +export class AdminUserService { + /** + * 获取用户列表(分页+筛选) + * @param params 查询参数 + * @returns Promise + */ + static async getUserList(params: AdminUserListParams = {}): Promise { + try { + const rpcParams = { + p_page: params.page ?? 1, + p_limit: params.limit ?? 20, + p_search: params.search ?? null, + p_role: params.role ?? null, + p_status: params.status ?? null, + p_is_member: params.is_member ?? null + } as UTSJSONObject + + const response = await supa.rpc('rpc_admin_user_list', rpcParams) + + if (response.error != null) { + throw new Error(`RPC 调用失败: ${response.error.message}`) + } + + const data = response.data as UTSJSONObject + return { + total: data.getNumber('total') ?? 0, + page: data.getNumber('page') ?? 1, + limit: data.getNumber('limit') ?? 20, + has_more: data.getBoolean('has_more') ?? false, + items: (data.getArray('items') as Array)?.map(item => ({ + id: item.getString('id') ?? '', + auth_id: item.getString('auth_id') ?? '', + username: item.getString('username') ?? '', + email: item.getString('email') ?? '', + role: item.getString('role') ?? '', + profile_status: item.getNumber('profile_status'), + real_name: item.getString('real_name'), + credit_score: item.getNumber('credit_score'), + verification_status: item.getNumber('verification_status'), + created_at: item.getString('created_at') ?? '', + updated_at: item.getString('updated_at') ?? '', + balance: item.getNumber('balance') ?? 0, + is_member: item.getBoolean('is_member') ?? false, + member_plan_name: item.getString('member_plan_name'), + member_end_date: item.getString('member_end_date') + })) ?? [] + } + } catch (error) { + console.error('[AdminUserService] getUserList error:', error) + throw error + } + } + + /** + * 获取用户详情 + * @param userId 用户ID(ak_users.id) + * @returns Promise + */ + static async getUserDetail(userId: string): Promise { + try { + const response = await supa.rpc('rpc_admin_user_detail', { p_user_id: userId } as UTSJSONObject) + + if (response.error != null) { + throw new Error(`RPC 调用失败: ${response.error.message}`) + } + + const data = response.data as UTSJSONObject + if (data == null) { + return null + } + + // 解析会员信息 + let memberInfo: any = null + const memberInfoObj = data.getJSONObject('member_info') + if (memberInfoObj != null) { + memberInfo = { + plan_name: memberInfoObj.getString('plan_name') ?? '', + plan_code: memberInfoObj.getString('plan_code') ?? '', + billing_period: memberInfoObj.getString('billing_period') ?? '', + price: memberInfoObj.getNumber('price') ?? 0, + features: memberInfoObj.getJSONObject('features') ?? {}, + status: memberInfoObj.getString('status') ?? '', + start_date: memberInfoObj.getString('start_date') ?? '', + end_date: memberInfoObj.getString('end_date'), + next_billing_date: memberInfoObj.getString('next_billing_date'), + auto_renew: memberInfoObj.getBoolean('auto_renew') ?? false + } + } + + // 解析地址列表 + let addresses: any[] = [] + const addressesArray = data.getArray('addresses') as Array + if (addressesArray != null) { + addresses = addressesArray.map(addr => ({ + id: addr.getString('id') ?? '', + receiver_name: addr.getString('receiver_name') ?? '', + receiver_phone: addr.getString('receiver_phone') ?? '', + province: addr.getString('province') ?? '', + city: addr.getString('city') ?? '', + district: addr.getString('district') ?? '', + address_detail: addr.getString('address_detail') ?? '', + postal_code: addr.getString('postal_code'), + is_default: addr.getBoolean('is_default') ?? false, + label: addr.getString('label'), + latitude: addr.getNumber('latitude'), + longitude: addr.getNumber('longitude'), + delivery_instructions: addr.getString('delivery_instructions'), + business_hours: addr.getString('business_hours'), + status: addr.getNumber('status') ?? 1, + created_at: addr.getString('created_at') ?? '', + updated_at: addr.getString('updated_at') ?? '' + })) + } + + return { + id: data.getString('id') ?? '', + auth_id: data.getString('auth_id') ?? '', + username: data.getString('username') ?? '', + email: data.getString('email') ?? '', + role: data.getString('role') ?? '', + profile_status: data.getNumber('profile_status'), + real_name: data.getString('real_name'), + credit_score: data.getNumber('credit_score'), + verification_status: data.getNumber('verification_status'), + preferences: data.getJSONObject('preferences'), + emergency_contact: data.getString('emergency_contact'), + service_areas: data.getJSONObject('service_areas'), + created_at: data.getString('created_at') ?? '', + updated_at: data.getString('updated_at') ?? '', + balance: data.getNumber('balance') ?? 0, + is_member: data.getBoolean('is_member') ?? false, + member_info: memberInfo, + addresses: addresses + } + } catch (error) { + console.error('[AdminUserService] getUserDetail error:', error) + throw error + } + } +} + +export default AdminUserService \ No newline at end of file diff --git a/uni_modules/ak-req/ak-req.uts b/uni_modules/ak-req/ak-req.uts index 0afd8653..564ec98b 100644 --- a/uni_modules/ak-req/ak-req.uts +++ b/uni_modules/ak-req/ak-req.uts @@ -194,6 +194,27 @@ export class AkReq { resolve(result); }, fail: (err) => { + // 失败诊断:输出 URL / 关键 headers / errCode / errMsg,便于定位“网络不可达 vs 401/403”等问题 + try { + let apikeyMasked: string | null = null; + try { + if (headers != null && typeof (headers as any).getString === 'function') { + const k = (headers as any).getString('apikey') as string | null; + if (k != null && k.length > 8) apikeyMasked = k.substring(0, 6) + '...' + k.substring(k.length - 4); + else apikeyMasked = k; + } + } catch (e) {} + console.error('[AkReq][fail]', { + url: options.url, + method: options.method ?? 'GET', + timeout, + errCode: (err as any).errCode, + errMsg: (err as any).errMsg, + apikey: apikeyMasked, + hasAuth: (AkReq.getToken() != null && AkReq.getToken() !== '') + }); + } catch (e) {} + const result = AkReq.createResponse( err.errCode, err.data ?? {}, diff --git a/utils/sapi.uts b/utils/sapi.uts index 4662a564..df9f6f15 100644 --- a/utils/sapi.uts +++ b/utils/sapi.uts @@ -56,10 +56,12 @@ export async function ensureUserProfile(sessionUser: UTSJSONObject): Promise { state.userProfile = { username: '', email: '' } state.isLoggedIn = false // 未登录 return null - } // 查询 ak_users 表补全 profile - const res = await supa.from('ak_users').select('*', {}).eq('id', userId).execute() + } // 查询 ak_users 表补全 profile(权威关联字段:auth_id = auth.uid()) + const res = await supa.from('ak_users').select('*', {}).eq('auth_id', userId).execute() console.log(res) if (res.status >= 200 && res.status < 300 && (res.data != null)) { let user : UTSJSONObject | null = null; @@ -182,13 +182,11 @@ export function getUserStore() { }, getUserRole() : string | null { - // Default role logic - can be enhanced based on your needs - const sessionInfo = supa.getSession() - if (sessionInfo.user == null) return null - - // You can add role detection logic here - // For now, return a default role - return 'teacher' // or determine from user profile/database + const profile = state.userProfile + if (profile != null && profile.role != null) { + return profile.role + } + return null }, getProfile() : UserProfile | null { diff --git a/utils/supabaseService.uts b/utils/supabaseService.uts index beecb3bb..20f82cbb 100644 --- a/utils/supabaseService.uts +++ b/utils/supabaseService.uts @@ -1,6 +1,9 @@ import supa from '@/components/supadb/aksupainstance.uts' import type { AkReqResponse } from '@/uni_modules/ak-req/index.uts' +// 导出 supa 实例,供 services 层统一使用 +export { supa } + // 使用单例 Supabase 客户端 // const supa = createClient(SUPA_URL, SUPA_KEY)