const { request, ensureLogin, cents } = require('../../utils/api.js') const roleLabels = { CLEANER: '保洁员', STAFF: '门店员工', STORE_ADMIN: '门店管理员', TENANT_ADMIN: '租户管理员', PLATFORM_ADMIN: '平台管理员', } Page({ data: { loading: false, detailLoading: false, errorMessage: '', tab: 'members', query: '', members: [], staff: [], selectedMember: null, }, async onLoad() { await this.loadData() }, selectTab(event) { const tab = event.currentTarget.dataset.tab if (!tab || tab === this.data.tab) return this.setData({ tab, selectedMember: null, errorMessage: '' }) this.loadData() }, inputQuery(event) { this.setData({ query: String(event.detail.value || '').trim() }) }, search() { this.loadData() }, async loadData() { this.setData({ loading: true, errorMessage: '' }) try { await ensureLogin() const search = this.data.query ? `&search=${encodeURIComponent(this.data.query)}` : '' if (this.data.tab === 'members') { const response = await request(`/management/members?page=1&pageSize=50${search}`) this.setData({ members: (response.data?.items || []).map((item) => this.presentMember(item)), }) } else { const response = await request(`/management/staff?page=1&pageSize=50${search}`) this.setData({ staff: (response.data?.items || []).map((item) => this.presentStaff(item)), }) } } catch (error) { this.setData({ errorMessage: error.message || '人员数据加载失败' }) } finally { this.setData({ loading: false }) } }, async openMember(event) { const memberId = event.currentTarget.dataset.memberId if (!memberId || this.data.detailLoading) return this.setData({ detailLoading: true, errorMessage: '' }) try { const response = await request(`/management/members/${encodeURIComponent(memberId)}`) const member = this.presentMember(response.data || {}) member.recentLedger = (response.data?.recentLedger || []).map((item) => ({ ...item, deltaText: this.deltaText(item), createdText: this.formatTime(item.createdAt), })) this.setData({ selectedMember: member }) } catch (error) { this.setData({ errorMessage: error.message || '会员详情加载失败' }) } finally { this.setData({ detailLoading: false }) } }, closeMember() { this.setData({ selectedMember: null }) }, presentMember(item) { return { ...item, displayName: item.nickname || '未命名会员', balanceText: cents(item.wallet?.totalBalanceCents), paidText: cents(item.orders?.paidAmountCents), registeredText: this.formatTime(item.registeredAt), } }, presentStaff(item) { return { ...item, displayName: item.nickname || '未命名员工', rolesText: (item.roles || []).map((role) => roleLabels[role] || role).join(' / ') || '未分配角色', storesText: (item.storeIds || []).length ? `门店 ${item.storeIds.join('、')}` : '全部门店/未绑定门店', statusText: item.status === 'ACTIVE' ? '在职' : '已停用', lastLoginText: item.lastLoginAt ? this.formatTime(item.lastLoginAt) : '从未登录', } }, deltaText(item) { const cash = Number(item.cashDeltaCents || 0) const gift = Number(item.giftDeltaCents || 0) const total = cash + gift return `${total >= 0 ? '+' : '-'}${cents(Math.abs(total))}` }, formatTime(value) { const date = new Date(value) if (Number.isNaN(date.getTime())) return String(value || '') const pad = (part) => String(part).padStart(2, '0') return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}` }, })