Commit 844ae2b7c1eba09053d9c17439a637516f9b6d80

Authored by “wangming”
1 parent 112e2f9a

优化个人中心页面:调整用户信息展示样式、个人服务区域布局和间距

Showing 1 changed file with 847 additions and 726 deletions
绿纤uni-app/pages/me/me.vue
1 1 <template>
2 2 <view class="page">
3 3 <!-- 自定义导航栏 -->
4   - <custom-navbar
5   - title="个人中心"
6   - :show-background="true"
7   - background-image="https://zhgw.028wlkj.com/cdwlMall/zsfwzxt/test/file/static/bg.png"
8   - @height-change="handleNavbarHeightChange"
9   - ></custom-navbar>
10   -
11   - <view class="main">
12   - <!-- 用户信息卡片 - 结合my.vue样式和me copy.vue功能 -->
13   - <view class="user-card">
14   - <view class="user-card-bg"></view>
  4 + <custom-navbar title="个人中心" :show-background="false" @height-change="handleNavbarHeightChange"></custom-navbar>
  5 +
  6 + <view class="warpbox">
  7 + <view :style="{ 'height': contentTopMargin }"></view>
  8 +
  9 + <!-- 用户信息卡片 -->
  10 + <view class="warpboxss user-card">
15 11 <view class="user-card-content">
16 12 <view class="user-main">
17 13 <view class="avatar-container">
18   - <view class="avatar-ring"></view>
19   - <image class="avatar" :src="newuserInfo.avatar || '/static/head.png'" mode="aspectFill"></image>
  14 + <image class="avatar" :src="newuserInfo.avatar || '/static/head.png'" mode="aspectFill">
  15 + </image>
20 16 </view>
21 17 <view class="user-info-wrapper">
22 18 <view class="user-name">{{ newuserInfo.realName || newuserInfo.userName || '用户' }}</view>
23 19 <view class="user-meta">
24   - <view class="role-badge">
25   - <text>{{ newuserInfo.gw || '员工' }}</text>
26   - </view>
27   - <view class="store-badge">
  20 + <view class="user-badge user-badge-store">
28 21 <u-icon name="home" size="20" color="#409EFF"></u-icon>
29   - <text>{{ jsjinfo.storeName || '暂无' }}</text>
  22 + <text class="user-badge-text">{{ jsjinfo.storeName || '暂无' }}</text>
30 23 </view>
31   - <view class="store-badge jsj-badge">
  24 + <view class="user-badge user-badge-role">
  25 + <u-icon name="account" size="20" color="#43a047"></u-icon>
  26 + <text class="user-badge-text">{{ newuserInfo.gw || '员工' }}</text>
  27 + </view>
  28 + <view v-if="jsjinfo.jsjName" class="user-badge user-badge-jsj">
32 29 <u-icon name="star" size="20" color="#ff9800"></u-icon>
33   - <text>{{ jsjinfo.jsjName || '暂无' }}</text>
  30 + <text class="user-badge-text">{{ jsjinfo.jsjName || '暂无' }}</text>
34 31 </view>
35 32 </view>
36 33 </view>
... ... @@ -38,72 +35,94 @@
38 35 </view>
39 36 </view>
40 37  
41   - <!-- 统计数据区域 - 来自me copy.vue -->
42   - <view class="stats-section">
43   - <view class="stats-container">
44   - <view v-if="iskjb" class="stat-item" @click="goToPage('/pages/expansion-list/expansion-list')">
45   - <view class="stat-icon icon-circle-bg-1">
  38 + <!-- KPI卡片区域 -->
  39 + <view class="kpi-section">
  40 + <view class="kpi-card kpi-card-1">
  41 + <view class="kpi-title">本月总业绩</view>
  42 + <view class="kpi-value">¥{{ (performanceData.BillingAmount || 0).toFixed(2) }}</view>
  43 + </view>
  44 + <view class="kpi-card kpi-card-2">
  45 + <view class="kpi-title">本月订单数</view>
  46 + <view class="kpi-value">{{ summaryData.hkCount || 0 }}单</view>
  47 + </view>
  48 + </view>
  49 +
  50 + <!-- 四个小数据卡片 -->
  51 + <view class="warpboxss small-stats-section">
  52 + <view class="small-stats-container">
  53 + <view v-if="iskjb" class="small-stat-item"
  54 + @click="goToPage('/pages/expansion-list/expansion-list')">
  55 + <view class="small-stat-icon icon-circle-bg-1">
46 56 <image src="/static/home/expansion.png" mode="heightFix"></image>
47 57 </view>
48   - <view class="stat-info">
49   - <view class="stat-num">{{ summaryData.expansionCount || 0 }}</view>
50   - <view class="stat-name">拓客数</view>
51   - </view>
  58 + <view class="small-stat-num">{{ summaryData.expansionCount || 0 }}</view>
  59 + <view class="small-stat-name">拓客数</view>
52 60 </view>
53   - <view v-if="iskjb" class="stat-item" @click="goToPage('/pages/user-invite-list/user-invite-list')">
54   - <view class="stat-icon icon-circle-bg-2">
  61 + <view v-if="iskjb" class="small-stat-item"
  62 + @click="goToPage('/pages/user-invite-list/user-invite-list')">
  63 + <view class="small-stat-icon icon-circle-bg-2">
55 64 <image src="/static/home/member.png" mode="heightFix"></image>
56 65 </view>
57   - <view class="stat-info">
58   - <view class="stat-num">{{ summaryData.inviteCount || 0 }}</view>
59   - <view class="stat-name">邀约数</view>
60   - </view>
  66 + <view class="small-stat-num">{{ summaryData.inviteCount || 0 }}</view>
  67 + <view class="small-stat-name">邀约数</view>
61 68 </view>
62   - <view v-if="iskjb" class="stat-item" @click="goToPage('/pages/user-appointment-list/user-appointment-list')">
63   - <view class="stat-icon icon-circle-bg-3">
  69 + <view v-if="iskjb" class="small-stat-item"
  70 + @click="goToPage('/pages/user-appointment-list/user-appointment-list')">
  71 + <view class="small-stat-icon icon-circle-bg-3">
64 72 <image src="/static/home/member.png" mode="heightFix"></image>
65 73 </view>
66   - <view class="stat-info">
67   - <view class="stat-num">{{ summaryData.appointmentCount || 0 }}</view>
68   - <view class="stat-name">预约数</view>
69   - </view>
  74 + <view class="small-stat-num">{{ summaryData.appointmentCount || 0 }}</view>
  75 + <view class="small-stat-name">预约数</view>
70 76 </view>
71   - <view class="stat-item" @click="goToPage('/pages/lx-list/lx-list')">
72   - <view class="stat-icon icon-circle-bg-4">
73   - <image src="/static/home/order.png" mode="heightFix"></image>
74   - </view>
75   - <view class="stat-info">
76   - <view class="stat-num">{{ summaryData.hkCount || 0 }}</view>
77   - <view class="stat-name">开单数</view>
  77 + <view class="small-stat-item" @click="goToPage('/pages/refund-list/refund-list')">
  78 + <view class="small-stat-icon icon-circle-bg-4">
  79 + <image src="/static/home/refund-card.png" mode="heightFix"></image>
78 80 </view>
  81 + <view class="small-stat-num">{{ summaryData.refundCount || 0 }}</view>
  82 + <view class="small-stat-name">退卡数</view>
79 83 </view>
80   - <view class="stat-item" @click="goToPage('/pages/consume-list/consume-list')">
81   - <view class="stat-icon icon-circle-bg-5">
82   - <image src="/static/home/consume-card.png" mode="heightFix"></image>
  84 + </view>
  85 + </view>
  86 +
  87 + <!-- 今日数据和耗卡数据卡片 -->
  88 + <view class="data-section">
  89 + <view class="data-card">
  90 + <view class="data-card-title">今日数据</view>
  91 + <view class="data-card-content">
  92 + <view class="data-item">
  93 + <view class="data-label">今日:</view>
  94 + <view class="data-value">{{ todayData.today || 0 }}</view>
83 95 </view>
84   - <view class="stat-info">
85   - <view class="stat-num">{{ summaryData.consumeCount || 0 }}</view>
86   - <view class="stat-name">耗卡数</view>
  96 + <view class="data-item">
  97 + <view class="data-label">本月:</view>
  98 + <view class="data-value">{{ todayData.month || 0 }}</view>
87 99 </view>
88 100 </view>
89   - <view class="stat-item" @click="goToPage('/pages/refund-list/refund-list')">
90   - <view class="stat-icon icon-circle-bg-6">
91   - <image src="/static/home/refund-card.png" mode="heightFix"></image>
  101 + </view>
  102 + <view class="data-card">
  103 + <view class="data-card-title">耗卡数据</view>
  104 + <view class="data-card-content">
  105 + <view class="data-item">
  106 + <view class="data-label">今日:</view>
  107 + <view class="data-value">{{ consumeData.today || 0 }}</view>
92 108 </view>
93   - <view class="stat-info">
94   - <view class="stat-num">{{ summaryData.refundCount || 0 }}</view>
95   - <view class="stat-name">退卡数</view>
  109 + <view class="data-item">
  110 + <view class="data-label">本月:</view>
  111 + <view class="data-value">{{ consumeData.month || 0 }}</view>
96 112 </view>
97 113 </view>
98 114 </view>
99 115 </view>
100 116  
101   - <!-- 账户设置区域 - 来自me copy.vue -->
102   - <view class="settings-section">
103   - <view class="settings-card">
  117 + <!-- 个人服务区域 -->
  118 + <view class="warpboxss settings-section">
  119 + <view class="warpboxs-small-title">
  120 + <view><text class="warpboxs-small-title-line"></text>个人服务</view>
  121 + </view>
  122 + <view class="settings-list">
104 123 <view class="settings-item" @click="showChangePasswordDialog">
105 124 <view class="settings-left">
106   - <view class="settings-icon-wrapper" >
  125 + <view class="settings-icon-wrapper">
107 126 <image src="/static/icon1.png" mode="aspectFit"></image>
108 127 </view>
109 128 <text class="settings-text">修改密码</text>
... ... @@ -112,7 +131,7 @@
112 131 </view>
113 132 <view class="settings-item" @click="handleLogout">
114 133 <view class="settings-left">
115   - <view class="settings-icon-wrapper" >
  134 + <view class="settings-icon-wrapper">
116 135 <image src="/static/icon2.png" mode="aspectFit"></image>
117 136 </view>
118 137 <text class="settings-text">退出登录</text>
... ... @@ -121,42 +140,29 @@
121 140 </view>
122 141 </view>
123 142 </view>
  143 +
  144 + <view style="height: 140rpx;"></view>
124 145 </view>
125 146  
126   - <!-- 修改密码弹窗 - 来自me copy.vue -->
  147 + <!-- 修改密码弹窗 -->
127 148 <u-popup :show="showPasswordDialog" @close="cancelChangePassword" mode="center" border-radius="20">
128 149 <view class="password-dialog">
129 150 <view class="dialog-title">修改密码</view>
130 151 <view class="dialog-content">
131 152 <view class="form-item">
132 153 <text class="form-label">原密码</text>
133   - <input
134   - class="form-input"
135   - type="password"
136   - placeholder="请输入原密码"
137   - v-model="passwordForm.oldPassword"
138   - :password="true"
139   - />
  154 + <input class="form-input" type="password" placeholder="请输入原密码"
  155 + v-model="passwordForm.oldPassword" :password="true" />
140 156 </view>
141 157 <view class="form-item">
142 158 <text class="form-label">新密码</text>
143   - <input
144   - class="form-input"
145   - type="password"
146   - placeholder="请输入新密码"
147   - v-model="passwordForm.newPassword"
148   - :password="true"
149   - />
  159 + <input class="form-input" type="password" placeholder="请输入新密码"
  160 + v-model="passwordForm.newPassword" :password="true" />
150 161 </view>
151 162 <view class="form-item">
152 163 <text class="form-label">确认密码</text>
153   - <input
154   - class="form-input"
155   - type="password"
156   - placeholder="请再次输入新密码"
157   - v-model="passwordForm.confirmPassword"
158   - :password="true"
159   - />
  164 + <input class="form-input" type="password" placeholder="请再次输入新密码"
  165 + v-model="passwordForm.confirmPassword" :password="true" />
160 166 </view>
161 167 </view>
162 168 <view class="dialog-footer">
... ... @@ -165,441 +171,564 @@
165 171 </view>
166 172 </view>
167 173 </u-popup>
168   -
  174 +
169 175 <!-- 自定义 tabBar -->
170 176 <custom-tab-bar />
171 177 </view>
172 178 </template>
173 179  
174 180 <script>
175   - import {
176   - mapState,
177   - mapMutations
178   - } from 'vuex'
179   - import memberApi from '@/apis/modules/member.js'
180   - import oauthApi from '@/apis/modules/oauth.js'
181   - import CustomTabBar from '@/components/custom-tab-bar/index.vue'
182   - import CustomNavbar from '@/components/custom-navbar/custom-navbar.vue'
183   -
184   - export default {
185   - components: {
186   - CustomTabBar,
187   - CustomNavbar
188   - },
189   - data() {
190   - return {
191   - navbarHeightRpx: 0, // 导航栏高度(rpx)
192   - scrollTop: 0,
193   - userInfo: {},
194   - newuserInfo: {},
195   - jsjinfo: {
196   - storeName:'',
197   - jsjName:''
198   - },
199   - summaryData: {
200   - appointmentCount: 0,
201   - inviteCount: 0,
202   - expansionCount: 0,
203   - hkCount: 0,
204   - consumeCount: 0,
205   - refundCount: 0
206   - },
207   - showPasswordDialog: false,
208   - passwordForm: {
209   - oldPassword: '',
210   - newPassword: '',
211   - confirmPassword: ''
212   - }
  181 +import {
  182 + mapState,
  183 + mapMutations
  184 +} from 'vuex'
  185 +import memberApi from '@/apis/modules/member.js'
  186 +import oauthApi from '@/apis/modules/oauth.js'
  187 +import performanceApi from '@/apis/modules/performance.js'
  188 +import CustomTabBar from '@/components/custom-tab-bar/index.vue'
  189 +import CustomNavbar from '@/components/custom-navbar/custom-navbar.vue'
  190 +
  191 +export default {
  192 + components: {
  193 + CustomTabBar,
  194 + CustomNavbar
  195 + },
  196 + data() {
  197 + return {
  198 + navbarHeightRpx: 0,
  199 + scrollTop: 0,
  200 + userInfo: {},
  201 + newuserInfo: {},
  202 + jsjinfo: {
  203 + storeName: '',
  204 + jsjName: ''
  205 + },
  206 + summaryData: {
  207 + appointmentCount: 0,
  208 + inviteCount: 0,
  209 + expansionCount: 0,
  210 + hkCount: 0,
  211 + consumeCount: 0,
  212 + refundCount: 0
  213 + },
  214 + performanceData: {
  215 + BillingAmount: 0,
  216 + OrderCount: 0
  217 + },
  218 + todayData: {
  219 + today: 0,
  220 + month: 0
  221 + },
  222 + consumeData: {
  223 + today: 0,
  224 + month: 0
  225 + },
  226 + showPasswordDialog: false,
  227 + passwordForm: {
  228 + oldPassword: '',
  229 + newPassword: '',
  230 + confirmPassword: ''
213 231 }
214   - },
  232 + }
  233 + },
215 234  
216   - computed: {
217   - iskjb() {
218   - if (this.newuserInfo.gw == '科技老师') {
219   - return false
220   - }
221   - return true
222   - },
223   - // 主内容区域顶部间距
224   - mainMarginTop() {
225   - if (this.navbarHeightRpx > 0) {
226   - // 小程序:导航栏高度 + 背景图高度 + 额外间距
227   - return (this.navbarHeightRpx + 290 + 40) + 'rpx'
228   - }
229   - // H5/APP:固定间距(背景图高度 + 导航栏高度)
230   - return '370rpx'
  235 + computed: {
  236 + iskjb() {
  237 + if (this.newuserInfo.gw == '科技老师') {
  238 + return false
231 239 }
  240 + return true
232 241 },
  242 + contentTopMargin() {
  243 + const info = uni.getSystemInfoSync()
  244 + const pxToRpx = 750 / info.windowWidth
  245 + const safeSpacingPx = 20
  246 + const safeSpacingRpx = Math.ceil(safeSpacingPx * pxToRpx)
  247 + if (this.navbarHeightRpx > 0) {
  248 + return (this.navbarHeightRpx + safeSpacingRpx) + 'rpx'
  249 + }
  250 + return (100 + safeSpacingRpx) + 'rpx'
  251 + }
  252 + },
233 253  
234   - async onLoad() {
235   - this.checkLoginStatus()
236   - await this.init()
237   - },
  254 + async onLoad() {
  255 + this.checkLoginStatus()
  256 + await this.init()
  257 + },
238 258  
239   - async onShow() {
240   - // 页面显示时刷新数据
241   - if (this.userInfo && this.userInfo.userId) {
242   - await this.init()
243   - }
244   - },
  259 + async onShow() {
  260 + if (this.userInfo && this.userInfo.userId) {
  261 + await this.init()
  262 + }
  263 + },
245 264  
246   - onPageScroll(e) {
247   - this.scrollTop = e.scrollTop;
248   - },
  265 + onPageScroll(e) {
  266 + this.scrollTop = e.scrollTop;
  267 + },
249 268  
250   - methods: {
251   - // 初始化
252   - async init() {
253   - if (!this.userInfo || !this.userInfo.userId) {
254   - return
255   - }
  269 + methods: {
  270 + // 初始化
  271 + async init() {
  272 + if (!this.userInfo || !this.userInfo.userId) {
  273 + return
  274 + }
256 275  
257   - // 获取用户信息
258   - this.API.getUsers(this.userInfo.userId).then(res => {
259   - if (res.code === 200) {
260   - this.newuserInfo = res.data
261   - if (this.newuserInfo.enabledMark != '1') {
262   - uni.showToast({
263   - title: '您的账号已被禁用',
264   - icon: 'none'
265   - })
266   - // 清除本地存储
267   - uni.clearStorageSync()
268   - // 跳转到登录页
269   - setTimeout(() => {
270   - uni.reLaunch({
271   - url: '/pages/login/login'
272   - })
273   - }, 1500)
274   - } else {
275   - let formattedDate = this.utils.gettime()
276   - memberApi.getJsjInfoByUserMonth(this.userInfo.userId, formattedDate).then((resjsj) => {
277   - if (resjsj.code == 200) {
278   - this.jsjinfo = resjsj.data
279   - }
  276 + // 获取用户信息
  277 + this.API.getUsers(this.userInfo.userId).then(res => {
  278 + if (res.code === 200) {
  279 + this.newuserInfo = res.data
  280 + if (this.newuserInfo.enabledMark != '1') {
  281 + uni.showToast({
  282 + title: '您的账号已被禁用',
  283 + icon: 'none'
  284 + })
  285 + uni.clearStorageSync()
  286 + setTimeout(() => {
  287 + uni.reLaunch({
  288 + url: '/pages/login/login'
280 289 })
281   - uni.setStorageSync('newuserInfo', this.newuserInfo)
282   - this.getSummaryData()
283   - }
  290 + }, 1500)
  291 + } else {
  292 + let formattedDate = this.utils.gettime()
  293 + memberApi.getJsjInfoByUserMonth(this.userInfo.userId, formattedDate).then((resjsj) => {
  294 + if (resjsj.code == 200) {
  295 + this.jsjinfo = resjsj.data
  296 + }
  297 + })
  298 + uni.setStorageSync('newuserInfo', this.newuserInfo)
  299 + this.getSummaryData()
  300 + this.getPerformanceData()
  301 + this.getTodayAndConsumeData()
284 302 }
285   - })
286   - },
  303 + }
  304 + })
  305 + },
287 306  
288   - // 处理导航栏高度变化
289   - handleNavbarHeightChange(heightInfo) {
290   - this.navbarHeightRpx = heightInfo.rpx || 0
291   - },
  307 + // 处理导航栏高度变化
  308 + handleNavbarHeightChange(heightInfo) {
  309 + this.navbarHeightRpx = heightInfo.rpx || 0
  310 + },
292 311  
293   - // 检查登录状态
294   - checkLoginStatus() {
295   - const token = uni.getStorageSync('token')
  312 + // 检查登录状态
  313 + checkLoginStatus() {
  314 + const token = uni.getStorageSync('token')
296 315  
297   - if (!token) {
298   - uni.reLaunch({
299   - url: '/pages/login/login'
300   - })
301   - return
302   - } else {
303   - this.userInfo = uni.getStorageSync('userInfo')
304   - this.newuserInfo = uni.getStorageSync('newuserInfo') || {}
305   - }
306   - },
  316 + if (!token) {
  317 + uni.reLaunch({
  318 + url: '/pages/login/login'
  319 + })
  320 + return
  321 + } else {
  322 + this.userInfo = uni.getStorageSync('userInfo')
  323 + this.newuserInfo = uni.getStorageSync('newuserInfo') || {}
  324 + }
  325 + },
307 326  
308   - // 获取统计数据
309   - async getSummaryData() {
310   - try {
311   - const currentMonthRange = this.utils.getCurrentMonthRange()
312   - if (this.iskjb) {
313   - let yyinfo = {
314   - pageSize: 1,
315   - currentPage: 1,
316   - yysj: `${currentMonthRange[0]},${currentMonthRange[1]}`
317   - }
318   - let yayinfo = {
319   - pageSize: 1,
320   - yysj: `${currentMonthRange[0]},${currentMonthRange[1]}`
321   - }
322   - let tkinfo = {
323   - pageSize: 1,
324   - expansionTime: `${currentMonthRange[0]},${currentMonthRange[1]}`
325   - }
326   - if (this.newuserInfo.gw == '店助' || this.newuserInfo.gw == '店长') {
327   - yyinfo.djmd = this.newuserInfo.mdid || '暂无'
328   - yayinfo.storeId = this.newuserInfo.mdid || '暂无'
329   - tkinfo.storeId = this.newuserInfo.mdid || '暂无'
330   - } else {
331   - yyinfo.yyr = this.userInfo.userId
332   - yayinfo.yyr = this.userInfo.userId
333   - tkinfo.expansionUserId = this.userInfo.userId
334   - }
335   - // 获取预约数
336   - const appointmentRes = await this.API.getAppointmentList(yyinfo)
337   -
338   - if (appointmentRes.code === 200) {
339   - this.summaryData.appointmentCount = appointmentRes.data.pagination?.total || 0
340   - }
341   -
342   - // 获取邀请数
343   - const inviteRes = await this.API.getInviteList(yayinfo)
344   -
345   - if (inviteRes.code === 200) {
346   - this.summaryData.inviteCount = inviteRes.data.pagination?.total || 0
347   - }
348   -
349   - // 获取拓客数
350   - const expansionRes = await this.API.getExpansionList(tkinfo)
351   -
352   - if (expansionRes.code === 200) {
353   - this.summaryData.expansionCount = expansionRes.data.pagination?.total || 0
354   - }
355   - }
356   - let kainfo = {
  327 + // 获取统计数据
  328 + async getSummaryData() {
  329 + try {
  330 + const currentMonthRange = this.utils.getCurrentMonthRange()
  331 + if (this.iskjb) {
  332 + let yyinfo = {
357 333 pageSize: 1,
358   - kdrq: `${currentMonthRange[0]},${currentMonthRange[1]}`
  334 + currentPage: 1,
  335 + yysj: `${currentMonthRange[0]},${currentMonthRange[1]}`
359 336 }
360   - let hkinfo = {
  337 + let yayinfo = {
361 338 pageSize: 1,
362   - hksj: `${currentMonthRange[0]},${currentMonthRange[1]}`
  339 + yysj: `${currentMonthRange[0]},${currentMonthRange[1]}`
363 340 }
364   - let tkinfonew = {
  341 + let tkinfo = {
365 342 pageSize: 1,
366   - tksj: `${currentMonthRange[0]},${currentMonthRange[1]}`
  343 + expansionTime: `${currentMonthRange[0]},${currentMonthRange[1]}`
367 344 }
368   - if (this.newuserInfo.gw == '科技老师') {
369   - kainfo.kjblsId = this.userInfo.userId
370   - hkinfo.kjblsId = this.userInfo.userId
371   - tkinfonew.kjblsId = this.userInfo.userId
372   - } else if (this.newuserInfo.gw == '健康师') {
373   - kainfo.jksId = this.userInfo.userId
374   - hkinfo.jksId = this.userInfo.userId
375   - tkinfonew.jksId = this.userInfo.userId
376   - } else if (this.newuserInfo.gw == '店助' || this.newuserInfo.gw == '店长') {
377   - kainfo.djmd = this.newuserInfo.mdid || '暂无'
378   - hkinfo.md = this.newuserInfo.mdid || '暂无'
379   - tkinfonew.md = this.newuserInfo.mdid || '暂无'
  345 + if (this.newuserInfo.gw == '店助' || this.newuserInfo.gw == '店长') {
  346 + yyinfo.djmd = this.newuserInfo.mdid || '暂无'
  347 + yayinfo.storeId = this.newuserInfo.mdid || '暂无'
  348 + tkinfo.storeId = this.newuserInfo.mdid || '暂无'
380 349 } else {
381   - kainfo.CreateUser = this.userInfo.userId
382   - hkinfo.czry = this.userInfo.userId
383   - tkinfonew.czry = this.userInfo.userId
  350 + yyinfo.yyr = this.userInfo.userId
  351 + yayinfo.yyr = this.userInfo.userId
  352 + tkinfo.expansionUserId = this.userInfo.userId
384 353 }
385   - // 获取开单数(本月)
386   - const hkRes = await this.API.getLxList(kainfo)
387   -
388   - if (hkRes.code === 200) {
389   - this.summaryData.hkCount = hkRes.data.pagination?.total || 0
  354 + // 获取预约数
  355 + const appointmentRes = await this.API.getAppointmentList(yyinfo)
  356 + if (appointmentRes.code === 200) {
  357 + this.summaryData.appointmentCount = appointmentRes.data.pagination?.total || 0
390 358 }
391   - // 获取耗卡数
392   -
393   - const consumeRes = await this.API.getConsumeList(hkinfo)
394   -
395   - if (consumeRes.code === 200) {
396   - this.summaryData.consumeCount = consumeRes.data.pagination?.total || 0
  359 + // 获取邀请数
  360 + const inviteRes = await this.API.getInviteList(yayinfo)
  361 + if (inviteRes.code === 200) {
  362 + this.summaryData.inviteCount = inviteRes.data.pagination?.total || 0
397 363 }
398   - // 获取退卡数
  364 + // 获取拓客数
  365 + const expansionRes = await this.API.getExpansionList(tkinfo)
  366 + if (expansionRes.code === 200) {
  367 + this.summaryData.expansionCount = expansionRes.data.pagination?.total || 0
  368 + }
  369 + }
  370 + let kainfo = {
  371 + pageSize: 1,
  372 + kdrq: `${currentMonthRange[0]},${currentMonthRange[1]}`
  373 + }
  374 + let hkinfo = {
  375 + pageSize: 1,
  376 + hksj: `${currentMonthRange[0]},${currentMonthRange[1]}`
  377 + }
  378 + let tkinfonew = {
  379 + pageSize: 1,
  380 + tksj: `${currentMonthRange[0]},${currentMonthRange[1]}`
  381 + }
  382 + if (this.newuserInfo.gw == '科技老师') {
  383 + kainfo.kjblsId = this.userInfo.userId
  384 + hkinfo.kjblsId = this.userInfo.userId
  385 + tkinfonew.kjblsId = this.userInfo.userId
  386 + } else if (this.newuserInfo.gw == '健康师') {
  387 + kainfo.jksId = this.userInfo.userId
  388 + hkinfo.jksId = this.userInfo.userId
  389 + tkinfonew.jksId = this.userInfo.userId
  390 + } else if (this.newuserInfo.gw == '店助' || this.newuserInfo.gw == '店长') {
  391 + kainfo.djmd = this.newuserInfo.mdid || '暂无'
  392 + hkinfo.md = this.newuserInfo.mdid || '暂无'
  393 + tkinfonew.md = this.newuserInfo.mdid || '暂无'
  394 + } else {
  395 + kainfo.CreateUser = this.userInfo.userId
  396 + hkinfo.czry = this.userInfo.userId
  397 + tkinfonew.czry = this.userInfo.userId
  398 + }
  399 + // 获取开单数(本月)
  400 + const hkRes = await this.API.getLxList(kainfo)
  401 + if (hkRes.code === 200) {
  402 + this.summaryData.hkCount = hkRes.data.pagination?.total || 0
  403 + }
  404 + // 获取耗卡数
  405 + const consumeRes = await this.API.getConsumeList(hkinfo)
  406 + if (consumeRes.code === 200) {
  407 + this.summaryData.consumeCount = consumeRes.data.pagination?.total || 0
  408 + }
  409 + // 获取退卡数
  410 + const refundRes = await this.API.getRefundList(tkinfonew)
  411 + if (refundRes.code === 200) {
  412 + this.summaryData.refundCount = refundRes.data.pagination?.total || 0
  413 + }
399 414  
400   - const refundRes = await this.API.getRefundList(tkinfonew)
  415 + } catch (error) {
  416 + console.error('获取统计数据失败:', error)
  417 + }
  418 + },
401 419  
402   - if (refundRes.code === 200) {
403   - this.summaryData.refundCount = refundRes.data.pagination?.total || 0
  420 + // 获取业绩数据
  421 + async getPerformanceData() {
  422 + try {
  423 + const statisticsMonth = this.getCurrentMonthStr()
  424 + const currentMonthRange = this.utils.getCurrentMonthRange()
  425 + if (this.newuserInfo.gw == '科技老师') {
  426 + const res = await performanceApi.GetTechTeacherStatistics({
  427 + teacherId: this.userInfo.userId,
  428 + startDate: this.formatDateToISO(currentMonthRange[0]),
  429 + endDate: this.formatDateToISO(currentMonthRange[1])
  430 + })
  431 + if (res.code === 200 && res.data) {
  432 + const data = res.data.length > 0 ? res.data[0] : {}
  433 + this.performanceData.BillingAmount = data.OrderAchievement || 0
  434 + }
  435 + } else {
  436 + const res = await performanceApi.getEmployeePerformanceStatistics({
  437 + userId: this.userInfo.userId,
  438 + statisticsMonth: statisticsMonth
  439 + })
  440 + if (res.code === 200 && res.data) {
  441 + this.performanceData.BillingAmount = res.data.BillingAmount || 0
404 442 }
405   -
406   - } catch (error) {
407   - console.error('获取统计数据失败:', error)
408 443 }
409   - },
  444 + } catch (error) {
  445 + console.error('获取业绩数据失败:', error)
  446 + }
  447 + },
410 448  
411   - // 页面跳转
412   - goToPage(url) {
413   - uni.navigateTo({
414   - url: url
415   - })
416   - },
  449 + // 获取今日和耗卡数据
  450 + async getTodayAndConsumeData() {
  451 + try {
  452 + const today = this.utils.gettime()
  453 + const currentMonthRange = this.utils.getCurrentMonthRange()
417 454  
418   - // 显示修改密码弹窗
419   - showChangePasswordDialog() {
420   - this.passwordForm = {
421   - oldPassword: '',
422   - newPassword: '',
423   - confirmPassword: ''
  455 + // 今日数据(开单数)
  456 + let todayKainfo = {
  457 + pageSize: 1,
  458 + kdrq: `${today},${today}`
  459 + }
  460 + let monthKainfo = {
  461 + pageSize: 1,
  462 + kdrq: `${currentMonthRange[0]},${currentMonthRange[1]}`
424 463 }
425   - this.showPasswordDialog = true
426   - },
427 464  
428   - // 取消修改密码
429   - cancelChangePassword() {
430   - this.showPasswordDialog = false
431   - this.passwordForm = {
432   - oldPassword: '',
433   - newPassword: '',
434   - confirmPassword: ''
  465 + // 耗卡数据
  466 + let todayHkinfo = {
  467 + pageSize: 1,
  468 + hksj: `${today},${today}`
  469 + }
  470 + let monthHkinfo = {
  471 + pageSize: 1,
  472 + hksj: `${currentMonthRange[0]},${currentMonthRange[1]}`
435 473 }
436   - },
437 474  
438   - // 确认修改密码
439   - confirmChangePassword() {
440   - // 验证输入
441   - if (!this.passwordForm.oldPassword) {
442   - uni.showToast({
443   - title: '请输入原密码',
444   - icon: 'none'
445   - })
446   - return
  475 + // 根据角色设置筛选条件
  476 + if (this.newuserInfo.gw == '科技老师') {
  477 + todayKainfo.kjblsId = this.userInfo.userId
  478 + monthKainfo.kjblsId = this.userInfo.userId
  479 + todayHkinfo.kjblsId = this.userInfo.userId
  480 + monthHkinfo.kjblsId = this.userInfo.userId
  481 + } else if (this.newuserInfo.gw == '健康师') {
  482 + todayKainfo.jksId = this.userInfo.userId
  483 + monthKainfo.jksId = this.userInfo.userId
  484 + todayHkinfo.jksId = this.userInfo.userId
  485 + monthHkinfo.jksId = this.userInfo.userId
  486 + } else if (this.newuserInfo.gw == '店助' || this.newuserInfo.gw == '店长') {
  487 + todayKainfo.djmd = this.newuserInfo.mdid || '暂无'
  488 + monthKainfo.djmd = this.newuserInfo.mdid || '暂无'
  489 + todayHkinfo.md = this.newuserInfo.mdid || '暂无'
  490 + monthHkinfo.md = this.newuserInfo.mdid || '暂无'
  491 + } else {
  492 + todayKainfo.CreateUser = this.userInfo.userId
  493 + monthKainfo.CreateUser = this.userInfo.userId
  494 + todayHkinfo.czry = this.userInfo.userId
  495 + monthHkinfo.czry = this.userInfo.userId
447 496 }
448 497  
449   - if (!this.passwordForm.newPassword) {
450   - uni.showToast({
451   - title: '请输入新密码',
452   - icon: 'none'
453   - })
454   - return
  498 + // 获取今日开单数
  499 + const todayKdRes = await this.API.getLxList(todayKainfo)
  500 + if (todayKdRes.code === 200) {
  501 + this.todayData.today = todayKdRes.data.pagination?.total || 0
455 502 }
456 503  
457   - if (this.passwordForm.newPassword.length < 6) {
458   - uni.showToast({
459   - title: '新密码长度不能少于6位',
460   - icon: 'none'
461   - })
462   - return
  504 + // 获取本月开单数
  505 + const monthKdRes = await this.API.getLxList(monthKainfo)
  506 + if (monthKdRes.code === 200) {
  507 + this.todayData.month = monthKdRes.data.pagination?.total || 0
463 508 }
464 509  
465   - if (this.passwordForm.newPassword !== this.passwordForm.confirmPassword) {
466   - uni.showToast({
467   - title: '两次输入的新密码不一致',
468   - icon: 'none'
469   - })
470   - return
  510 + // 获取今日耗卡数
  511 + const todayHkRes = await this.API.getConsumeList(todayHkinfo)
  512 + if (todayHkRes.code === 200) {
  513 + this.consumeData.today = todayHkRes.data.pagination?.total || 0
471 514 }
472 515  
473   - if (this.passwordForm.oldPassword === this.passwordForm.newPassword) {
474   - uni.showToast({
475   - title: '新密码不能与原密码相同',
476   - icon: 'none'
477   - })
478   - return
  516 + // 获取本月耗卡数
  517 + const monthHkRes = await this.API.getConsumeList(monthHkinfo)
  518 + if (monthHkRes.code === 200) {
  519 + this.consumeData.month = monthHkRes.data.pagination?.total || 0
479 520 }
  521 + } catch (error) {
  522 + console.error('获取今日和耗卡数据失败:', error)
  523 + }
  524 + },
480 525  
481   - // 调用修改密码接口
482   - this.changePassword()
483   - },
  526 + // 获取当前月份字符串(格式:YYYYMM)
  527 + getCurrentMonthStr() {
  528 + const now = new Date()
  529 + return uni.$u.timeFormat(now, 'yyyymm')
  530 + },
484 531  
485   - // 修改密码
486   - async changePassword() {
487   - try {
488   - uni.showLoading({
489   - title: '修改中...'
490   - })
  532 + // 格式化日期为 ISO 8601 格式(YYYY-MM-DDTHH:mm:ss)
  533 + formatDateToISO(timestamp) {
  534 + const date = new Date(timestamp)
  535 + return uni.$u.timeFormat(date, 'yyyy-mm-dd hh:MM:ss')
  536 + },
491 537  
492   - // 调用修改密码 API
493   - const res = await oauthApi.changePassword({
494   - userId: this.userInfo.userId,
495   - oldPassword: this.passwordForm.oldPassword,
496   - newPassword: this.passwordForm.newPassword
497   - })
  538 + // 页面跳转
  539 + goToPage(url) {
  540 + uni.navigateTo({
  541 + url: url
  542 + })
  543 + },
498 544  
499   - uni.hideLoading()
  545 + // 显示修改密码弹窗
  546 + showChangePasswordDialog() {
  547 + this.passwordForm = {
  548 + oldPassword: '',
  549 + newPassword: '',
  550 + confirmPassword: ''
  551 + }
  552 + this.showPasswordDialog = true
  553 + },
500 554  
501   - if (res.code === 200) {
502   - uni.showToast({
503   - title: '密码修改成功',
504   - icon: 'success'
505   - })
506   - this.showPasswordDialog = false
507   - this.passwordForm = {
508   - oldPassword: '',
509   - newPassword: '',
510   - confirmPassword: ''
511   - }
512   - } else {
513   - uni.showToast({
514   - title: res.msg || '密码修改失败',
515   - icon: 'none'
516   - })
  555 + // 取消修改密码
  556 + cancelChangePassword() {
  557 + this.showPasswordDialog = false
  558 + this.passwordForm = {
  559 + oldPassword: '',
  560 + newPassword: '',
  561 + confirmPassword: ''
  562 + }
  563 + },
  564 +
  565 + // 确认修改密码
  566 + confirmChangePassword() {
  567 + if (!this.passwordForm.oldPassword) {
  568 + uni.showToast({
  569 + title: '请输入原密码',
  570 + icon: 'none'
  571 + })
  572 + return
  573 + }
  574 +
  575 + if (!this.passwordForm.newPassword) {
  576 + uni.showToast({
  577 + title: '请输入新密码',
  578 + icon: 'none'
  579 + })
  580 + return
  581 + }
  582 +
  583 + if (this.passwordForm.newPassword.length < 6) {
  584 + uni.showToast({
  585 + title: '新密码长度不能少于6位',
  586 + icon: 'none'
  587 + })
  588 + return
  589 + }
  590 +
  591 + if (this.passwordForm.newPassword !== this.passwordForm.confirmPassword) {
  592 + uni.showToast({
  593 + title: '两次输入的新密码不一致',
  594 + icon: 'none'
  595 + })
  596 + return
  597 + }
  598 +
  599 + if (this.passwordForm.oldPassword === this.passwordForm.newPassword) {
  600 + uni.showToast({
  601 + title: '新密码不能与原密码相同',
  602 + icon: 'none'
  603 + })
  604 + return
  605 + }
  606 +
  607 + this.changePassword()
  608 + },
  609 +
  610 + // 修改密码
  611 + async changePassword() {
  612 + try {
  613 + uni.showLoading({
  614 + title: '修改中...'
  615 + })
  616 +
  617 + const res = await oauthApi.changePassword({
  618 + userId: this.userInfo.userId,
  619 + oldPassword: this.passwordForm.oldPassword,
  620 + newPassword: this.passwordForm.newPassword
  621 + })
  622 +
  623 + uni.hideLoading()
  624 +
  625 + if (res.code === 200) {
  626 + uni.showToast({
  627 + title: '密码修改成功',
  628 + icon: 'success'
  629 + })
  630 + this.showPasswordDialog = false
  631 + this.passwordForm = {
  632 + oldPassword: '',
  633 + newPassword: '',
  634 + confirmPassword: ''
517 635 }
518   - } catch (error) {
519   - uni.hideLoading()
520   - console.error('修改密码失败:', error)
  636 + } else {
521 637 uni.showToast({
522   - title: '修改密码失败,请稍后重试',
  638 + title: res.msg || '密码修改失败',
523 639 icon: 'none'
524 640 })
525 641 }
526   - },
527   -
528   - // 退出登录
529   - handleLogout() {
530   - uni.showModal({
531   - title: '提示',
532   - content: '确定要退出登录吗?',
533   - success: (res) => {
534   - if (res.confirm) {
535   - this.API.logout().then(res => {
536   - if (res.code == 200) {
537   - // 清除本地存储
538   - uni.clearStorageSync()
539   - // 跳转到登录页
540   - uni.reLaunch({
541   - url: '/pages/login/login'
542   - })
543   - }
544   - })
545   - }
546   - }
  642 + } catch (error) {
  643 + uni.hideLoading()
  644 + console.error('修改密码失败:', error)
  645 + uni.showToast({
  646 + title: '修改密码失败,请稍后重试',
  647 + icon: 'none'
547 648 })
548 649 }
  650 + },
  651 +
  652 + // 退出登录
  653 + handleLogout() {
  654 + uni.showModal({
  655 + title: '提示',
  656 + content: '确定要退出登录吗?',
  657 + success: (res) => {
  658 + if (res.confirm) {
  659 + this.API.logout().then(res => {
  660 + if (res.code == 200) {
  661 + uni.clearStorageSync()
  662 + uni.reLaunch({
  663 + url: '/pages/login/login'
  664 + })
  665 + }
  666 + })
  667 + }
  668 + }
  669 + })
549 670 }
550 671 }
  672 +}
551 673 </script>
552 674  
553 675 <style lang="scss" scoped>
554   - .page {
555   - position: absolute;
556   - left: 0;
557   - top: 0;
558   - width: 100%;
559   - height: 100%;
560   - background-color: #f5f7fa;
561   - }
562   -
563   -
564   - .main {
565   - position: relative;
566   - z-index: 111;
567   - padding: 0 40rpx;
568   - top: 90rpx;
569   - /* #ifdef MP-WEIXIN */
570   - top: 120rpx;
571   - /* #endif */
572   -
573   - }
574   -
575   - /* 用户信息卡片 - 结合my.vue和me copy.vue的设计 */
576   - .user-card {
577   - position: relative;
578   - margin: 24rpx 0;
579   - border-radius: 20rpx;
580   - overflow: hidden;
581   - animation: slideDown 0.4s ease-out;
582   - box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.08);
583   - padding: 30rpx 0;
584   - margin-bottom: 24rpx;
  676 +.page {
  677 + position: relative;
  678 + width: 100%;
  679 + min-height: 100vh;
  680 + background: linear-gradient(135deg, #e8f5e9 0%, #b2dfdb 100%);
  681 + background-repeat: no-repeat;
  682 + background-size: 100% 100%;
  683 + font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", "SF Pro Display", "Helvetica Neue", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif;
  684 + -webkit-overflow-scrolling: touch;
  685 + overscroll-behavior-y: auto;
  686 +}
  687 +
  688 +.warpbox {
  689 + padding: 0 30rpx;
  690 + padding-bottom: 40rpx;
  691 +}
  692 +
  693 +.warpboxss {
  694 + background-color: rgba(255, 255, 255, 0.4);
  695 + backdrop-filter: blur(16px) saturate(180%);
  696 + -webkit-backdrop-filter: blur(16px) saturate(180%);
  697 + padding: 30rpx;
  698 + border-radius: 24rpx;
  699 + box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.08);
  700 + border: 1px solid rgba(255, 255, 255, 0.125);
  701 + margin-bottom: 24rpx;
  702 +}
  703 +
  704 +.warpboxs-small-title {
  705 + display: flex;
  706 + justify-content: space-between;
  707 + align-items: center;
  708 + font-size: 30rpx;
  709 + font-weight: 600;
  710 + color: #1f2937;
  711 + margin-bottom: 24rpx;
  712 +
  713 + view {
  714 + display: flex;
  715 + align-items: center;
585 716 }
586 717  
587   - .user-card-bg {
588   - position: absolute;
589   - top: 0;
590   - left: 0;
591   - right: 0;
592   - bottom: 0;
593   - // background: linear-gradient(135deg, #e8f4f8 0%, #f0e8f5 50%, #f5f0e8 100%);
594   - background: #fff;
  718 + .warpboxs-small-title-line {
  719 + display: inline-block;
  720 + width: 6rpx;
  721 + height: 28rpx;
  722 + background: linear-gradient(180deg, #43a047 0%, #66bb6a 100%);
  723 + border-radius: 3rpx;
  724 + margin-right: 12rpx;
595 725 }
  726 +}
596 727  
  728 +/* 用户信息卡片 */
  729 +.user-card {
597 730 .user-card-content {
598   - position: relative;
599   - padding: 24rpx;
600   - background: rgba(255, 255, 255, 0.6);
601   - backdrop-filter: blur(10rpx);
602   - -webkit-backdrop-filter: blur(10rpx);
  731 + padding: 0;
603 732 }
604 733  
605 734 .user-main {
... ... @@ -608,30 +737,46 @@
608 737 }
609 738  
610 739 .avatar-container {
611   - position: relative;
612   - margin-right: 20rpx;
  740 + margin-right: 24rpx;
613 741 flex-shrink: 0;
  742 + position: relative;
  743 +
  744 + .avatar {
  745 + width: 120rpx;
  746 + height: 120rpx;
  747 + border-radius: 60rpx;
  748 + border: 4rpx solid rgba(67, 160, 71, 0.2);
  749 + box-shadow: 0 4rpx 16rpx rgba(67, 160, 71, 0.2);
  750 + position: relative;
  751 + z-index: 1;
  752 + }
  753 +
  754 + &::after {
  755 + content: '';
  756 + position: absolute;
  757 + top: -4rpx;
  758 + left: -4rpx;
  759 + right: -4rpx;
  760 + bottom: -4rpx;
  761 + border-radius: 50%;
  762 + background: linear-gradient(135deg, rgba(67, 160, 71, 0.3) 0%, rgba(102, 187, 106, 0.3) 100%);
  763 + z-index: 0;
  764 + animation: pulse 2s ease-in-out infinite;
  765 + }
614 766 }
615 767  
616   - .avatar-ring {
617   - position: absolute;
618   - top: -3rpx;
619   - left: -3rpx;
620   - width: 100rpx;
621   - height: 100rpx;
622   - border-radius: 50rpx;
623   - border: 2rpx solid rgba(67, 160, 71, 0.3);
624   - animation: rotate 3s linear infinite;
625   - }
626   -
627   - .avatar {
628   - width: 94rpx;
629   - height: 94rpx;
630   - border-radius: 47rpx;
631   - border: 2rpx solid rgba(255, 255, 255, 0.9);
632   - position: relative;
633   - z-index: 1;
634   - box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
  768 + @keyframes pulse {
  769 +
  770 + 0%,
  771 + 100% {
  772 + opacity: 0.6;
  773 + transform: scale(1);
  774 + }
  775 +
  776 + 50% {
  777 + opacity: 0.8;
  778 + transform: scale(1.05);
  779 + }
635 780 }
636 781  
637 782 .user-info-wrapper {
... ... @@ -640,351 +785,327 @@
640 785 }
641 786  
642 787 .user-name {
643   - font-size: 32rpx;
  788 + font-size: 36rpx;
644 789 font-weight: 600;
645 790 color: #303133;
646   - margin-bottom: 8rpx;
647   - overflow: hidden;
648   - text-overflow: ellipsis;
649   - white-space: nowrap;
  791 + margin-bottom: 20rpx;
650 792 }
651 793  
652 794 .user-meta {
653 795 display: flex;
654   - align-items: center;
655 796 flex-wrap: wrap;
656   - gap: 8rpx;
657   - margin-top: 8rpx;
  797 + gap: 12rpx;
658 798 }
659 799  
660   - .role-badge {
  800 + .user-badge {
661 801 display: inline-flex;
662 802 align-items: center;
663   - background: rgba(67, 160, 71, 0.1);
664   - border-radius: 12rpx;
665   - padding: 6rpx 12rpx;
666   - border: 1rpx solid rgba(67, 160, 71, 0.2);
667   - font-size: 24rpx;
668   - color: #43a047;
  803 + padding: 6rpx 16rpx;
  804 + border-radius: 16rpx;
  805 + font-size: 22rpx;
669 806 font-weight: 500;
670   - }
  807 + backdrop-filter: blur(10rpx);
  808 + -webkit-backdrop-filter: blur(10rpx);
  809 + box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.08);
  810 + transition: all 0.3s ease;
  811 + margin-left: 10rpx;
  812 +
  813 + .user-badge-text {
  814 + margin-left: 6rpx;
  815 + max-width: 180rpx;
  816 + overflow: hidden;
  817 + text-overflow: ellipsis;
  818 + white-space: nowrap;
  819 + }
671 820  
672   - .role-badge text {
673   - margin-left: 6rpx;
674   - }
  821 + &.user-badge-store {
  822 + background: linear-gradient(135deg, rgba(64, 158, 255, 0.15) 0%, rgba(64, 158, 255, 0.25) 100%);
  823 + border: 1rpx solid rgba(64, 158, 255, 0.3);
  824 + color: #409EFF;
  825 + }
675 826  
676   - .store-badge {
677   - display: inline-flex;
678   - align-items: center;
679   - background: rgba(64, 158, 255, 0.1);
680   - border-radius: 12rpx;
681   - padding: 6rpx 12rpx;
682   - border: 1rpx solid rgba(64, 158, 255, 0.2);
683   - font-size: 24rpx;
684   - color: #409EFF;
685   - font-weight: 500;
686   - gap: 6rpx;
687   - }
  827 + &.user-badge-role {
  828 + background: linear-gradient(135deg, rgba(67, 160, 71, 0.15) 0%, rgba(67, 160, 71, 0.25) 100%);
  829 + border: 1rpx solid rgba(67, 160, 71, 0.3);
  830 + color: #43a047;
  831 + }
688 832  
689   - .store-badge.jsj-badge {
690   - background: rgba(255, 152, 0, 0.1);
691   - border: 1rpx solid rgba(255, 152, 0, 0.2);
692   - color: #ff9800;
  833 + &.user-badge-jsj {
  834 + background: linear-gradient(135deg, rgba(255, 152, 0, 0.15) 0%, rgba(255, 152, 0, 0.25) 100%);
  835 + border: 1rpx solid rgba(255, 152, 0, 0.3);
  836 + color: #ff9800;
  837 + }
  838 + }
  839 +}
  840 +
  841 +/* KPI卡片区域 */
  842 +.kpi-section {
  843 + display: grid;
  844 + grid-template-columns: repeat(2, 1fr);
  845 + gap: 30rpx;
  846 + margin-bottom: 24rpx;
  847 +}
  848 +
  849 +.kpi-card {
  850 + background: linear-gradient(135deg, #4caf50 0%, #66bb6a 100%);
  851 + border-radius: 24rpx;
  852 + padding: 40rpx 30rpx;
  853 + box-shadow: 0 8rpx 24rpx rgba(76, 175, 80, 0.3);
  854 + position: relative;
  855 + overflow: hidden;
  856 +
  857 + &::before {
  858 + content: '';
  859 + position: absolute;
  860 + top: -50%;
  861 + right: -50%;
  862 + width: 200%;
  863 + height: 200%;
  864 + background: radial-gradient(circle, rgba(255, 255, 255, 0.1) 0%, transparent 70%);
693 865 }
694 866  
695   - .store-badge text {
696   - overflow: hidden;
697   - text-overflow: ellipsis;
698   - white-space: nowrap;
699   - max-width: 120rpx;
  867 + .kpi-title {
  868 + font-size: 26rpx;
  869 + color: rgba(255, 255, 255, 0.9);
  870 + margin-bottom: 16rpx;
700 871 }
701 872  
702   - /* 统计数据区域 */
703   - .stats-section {
704   - margin: 24rpx 0;
705   - animation: slideDown 0.5s ease-out;
  873 + .kpi-value {
  874 + font-size: 48rpx;
  875 + font-weight: 700;
  876 + color: #ffffff;
  877 + line-height: 1.2;
706 878 }
  879 +}
  880 +
  881 +.kpi-card-2 {
  882 + background: linear-gradient(135deg, #43a047 0%, #66bb6a 100%);
  883 +}
707 884  
708   - .stats-container {
709   - background: #ffffff;
710   - border-radius: 20rpx;
711   - padding: 18rpx;
712   - border: 1rpx solid rgba(0, 0, 0, 0.06);
713   - box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.08);
  885 +/* 四个小数据卡片 */
  886 +.small-stats-section {
  887 + .small-stats-container {
714 888 display: grid;
715   - grid-template-columns: repeat(3, 1fr);
716   - gap: 14rpx;
  889 + grid-template-columns: repeat(4, 1fr);
  890 + gap: 20rpx;
717 891 }
718 892  
719   - .stat-item {
720   - background: #fff;
721   - border-radius: 16rpx;
722   - padding: 18rpx 14rpx;
  893 + .small-stat-item {
723 894 display: flex;
  895 + flex-direction: column;
724 896 align-items: center;
725   - // border: 1rpx solid #f0f2f5;
726   - box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
727   - transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
728   - cursor: pointer;
729   - }
730   -
731   - .stat-item:active {
732   - transform: translateY(-2rpx) scale(0.98);
733   - box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
  897 + text-align: center;
734 898 }
735 899  
736   - .stat-icon {
737   - width: 56rpx;
738   - height: 56rpx;
739   - border-radius: 90%;
  900 + .small-stat-icon {
  901 + width: 80rpx;
  902 + height: 80rpx;
  903 + border-radius: 16rpx;
740 904 display: flex;
741 905 align-items: center;
742 906 justify-content: center;
743   - margin-right: 12rpx;
744   - flex-shrink: 0;
745   -
  907 + margin-bottom: 12rpx;
  908 + box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.08);
  909 +
746 910 image {
747   - height: 32rpx;
748   - margin: 0 auto;
749   - vertical-align: middle;
750   - }
751   -
752   - &.icon-circle-bg-1 {
753   - background: linear-gradient(135deg, #E3F2FD 0%, #2196F3 100%); // 蓝色渐变
754   - }
755   -
756   - &.icon-circle-bg-2 {
757   - background: linear-gradient(135deg, #F3E5F5 0%, #9C27B0 100%); // 紫色渐变
758   - }
759   -
760   - &.icon-circle-bg-3 {
761   - background: linear-gradient(135deg, #E8F5E9 0%, #4CAF50 100%); // 绿色渐变
762   - }
763   -
764   - &.icon-circle-bg-4 {
765   - background: linear-gradient(135deg, #FFF3E0 0%, #FF9800 100%); // 橙色渐变
766   - }
767   -
768   - &.icon-circle-bg-5 {
769   - background: linear-gradient(135deg, #E1F5FE 0%, #03A9F4 100%); // 青色渐变
770   - }
771   -
772   - &.icon-circle-bg-6 {
773   - background: linear-gradient(135deg, #FFEBEE 0%, #F44336 100%); // 红色渐变
  911 + width: 40rpx;
  912 + height: 40rpx;
774 913 }
775 914 }
776 915  
777   - .stat-info {
778   - flex: 1;
779   - min-width: 0;
780   - }
781   -
782   - .stat-num {
783   - font-size: 28rpx;
  916 + .small-stat-num {
  917 + font-size: 32rpx;
784 918 font-weight: 600;
785 919 color: #303133;
786   - line-height: 1.2;
787   - margin-bottom: 4rpx;
  920 + margin-bottom: 6rpx;
788 921 }
789 922  
790   - .stat-name {
  923 + .small-stat-name {
791 924 font-size: 24rpx;
792 925 color: #909399;
793 926 }
794 927  
795   - /* 账户设置区域 */
796   - .settings-section {
797   - margin: 24rpx 0;
798   - animation: slideDown 0.6s ease-out;
  928 + .icon-circle-bg-1 {
  929 + background-color: #43a047;
799 930 }
800 931  
801   - .settings-card {
802   - background: #ffffff;
803   - border-radius: 20rpx;
804   - overflow: hidden;
805   - border: 1rpx solid rgba(0, 0, 0, 0.06);
806   - box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.08);
  932 + .icon-circle-bg-2 {
  933 + background-color: #2196f3;
  934 + }
  935 +
  936 + .icon-circle-bg-3 {
  937 + background-color: #ff9800;
  938 + }
  939 +
  940 + .icon-circle-bg-4 {
  941 + background-color: #f44336;
  942 + }
  943 +}
  944 +
  945 +/* 数据卡片区域 */
  946 +.data-section {
  947 + display: grid;
  948 + grid-template-columns: repeat(2, 1fr);
  949 + gap: 30rpx;
  950 + margin-bottom: 24rpx;
  951 +}
  952 +
  953 +.data-card {
  954 + background-color: rgba(255, 255, 255, 0.4);
  955 + backdrop-filter: blur(16px) saturate(180%);
  956 + -webkit-backdrop-filter: blur(16px) saturate(180%);
  957 + border-radius: 24rpx;
  958 + padding: 30rpx;
  959 + box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.08);
  960 + border: 1px solid rgba(255, 255, 255, 0.125);
  961 +}
  962 +
  963 +.data-card-title {
  964 + font-size: 28rpx;
  965 + font-weight: 600;
  966 + color: #303133;
  967 + margin-bottom: 20rpx;
  968 +}
  969 +
  970 +.data-card-content {
  971 + display: flex;
  972 + flex-direction: column;
  973 + gap: 12rpx;
  974 +}
  975 +
  976 +.data-item {
  977 + display: flex;
  978 + justify-content: space-between;
  979 + align-items: center;
  980 +}
  981 +
  982 +.data-label {
  983 + font-size: 26rpx;
  984 + color: #909399;
  985 +}
  986 +
  987 +.data-value {
  988 + font-size: 32rpx;
  989 + font-weight: 600;
  990 + color: #303133;
  991 +}
  992 +
  993 +/* 设置区域 */
  994 +.settings-section {
  995 + .settings-list {
  996 + background: transparent;
807 997 }
808 998  
809 999 .settings-item {
810 1000 display: flex;
811 1001 align-items: center;
812 1002 justify-content: space-between;
813   - padding: 28rpx 32rpx;
814   - border-bottom: 1rpx solid #f0f2f5;
  1003 + padding: 20rpx 0;
  1004 + border-bottom: 1rpx solid rgba(0, 0, 0, 0.06);
815 1005 cursor: pointer;
816 1006 transition: all 0.3s ease;
817   - background-color: #ffffff;
818   - }
819 1007  
820   - .settings-item:last-child {
821   - border-bottom: none;
822   - }
  1008 + &:last-child {
  1009 + border-bottom: none;
  1010 + }
823 1011  
824   - .settings-item:active {
825   - background-color: #f8f9fa;
826   - transform: translateX(4rpx);
  1012 + &:active {
  1013 + opacity: 0.7;
  1014 + }
827 1015 }
828 1016  
829 1017 .settings-left {
830 1018 display: flex;
831   - // align-items: center;
  1019 + align-items: center;
832 1020 flex: 1;
833 1021 }
834 1022  
835 1023 .settings-icon-wrapper {
836   - // width: 72rpx;
837   - // height: 72rpx;
838   - // border-radius: 16rpx;
839   - // display: flex;
840   - // align-items: center;
841   - // justify-content: center;
  1024 + display: flex;
  1025 + align-items: center;
  1026 + justify-content: center;
842 1027 margin-right: 16rpx;
  1028 + flex-shrink: 0;
  1029 +
843 1030 image {
844   - width: 48rpx;
845   - height: 48rpx;
  1031 + width: 40rpx;
  1032 + height: 40rpx;
846 1033 }
847 1034 }
848 1035  
849 1036 .settings-text {
850 1037 font-size: 28rpx;
851 1038 color: #303133;
852   - font-weight: 500;
853   - }
854   -
855   - /* 动画效果 */
856   - @keyframes slideDown {
857   - from {
858   - opacity: 0;
859   - transform: translateY(-20rpx);
860   - }
861   - to {
862   - opacity: 1;
863   - transform: translateY(0);
864   - }
865   - }
866   -
867   - @keyframes rotate {
868   - from {
869   - transform: rotate(0deg);
870   - }
871   - to {
872   - transform: rotate(360deg);
873   - }
874   - }
875   -
876   - /* 修改密码弹窗样式 */
877   - .password-dialog {
878   - padding: 40rpx;
879   - background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%);
880   - border-radius: 20rpx;
881   - box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.12);
882   - min-width: 600rpx;
883   - }
884   -
885   - .dialog-title {
886   - font-size: 32rpx;
887   - font-weight: 600;
888   - color: #303133;
889   - text-align: center;
890   - margin-bottom: 40rpx;
891   - position: relative;
892   - padding-bottom: 20rpx;
893   - }
894   -
895   - .dialog-title::after {
896   - content: '';
897   - position: absolute;
898   - bottom: 0;
899   - left: 50%;
900   - transform: translateX(-50%);
901   - width: 60rpx;
902   - height: 4rpx;
903   - background: linear-gradient(90deg, #43a047 0%, #66bb6a 100%);
904   - border-radius: 2rpx;
905   - }
906   -
907   - .dialog-content {
908   - margin-bottom: 40rpx;
909   - }
910   -
911   - .form-item {
912   - margin-bottom: 28rpx;
913   - }
914   -
915   - .form-item:last-child {
916   - margin-bottom: 0;
  1039 + line-height: 1.5;
917 1040 }
  1041 +}
  1042 +
  1043 +/* 修改密码弹窗 */
  1044 +.password-dialog {
  1045 + width: 600rpx;
  1046 + background: #ffffff;
  1047 + border-radius: 24rpx;
  1048 + overflow: hidden;
  1049 +}
  1050 +
  1051 +.dialog-title {
  1052 + font-size: 36rpx;
  1053 + font-weight: 600;
  1054 + color: #303133;
  1055 + text-align: center;
  1056 + padding: 40rpx 40rpx 30rpx;
  1057 +}
  1058 +
  1059 +.dialog-content {
  1060 + padding: 0 40rpx;
  1061 +}
  1062 +
  1063 +.form-item {
  1064 + margin-bottom: 32rpx;
918 1065  
919 1066 .form-label {
920 1067 display: block;
921 1068 font-size: 28rpx;
922 1069 color: #606266;
923 1070 margin-bottom: 12rpx;
924   - font-weight: 500;
925 1071 }
926 1072  
927 1073 .form-input {
928 1074 width: 100%;
929   - height: 80rpx;
930   - padding: 0 24rpx;
931   - border: 2rpx solid #e4e7ed;
  1075 + height: 88rpx;
  1076 + background: #f5f7fa;
932 1077 border-radius: 12rpx;
  1078 + padding: 0 24rpx;
933 1079 font-size: 28rpx;
934 1080 color: #303133;
935 1081 box-sizing: border-box;
936   - background-color: #ffffff;
937   - transition: all 0.3s ease;
938   - box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
939   - }
940   -
941   - .form-input:focus {
942   - border-color: #43a047;
943   - background-color: #fff;
944   - box-shadow: 0 2rpx 12rpx rgba(67, 160, 71, 0.15);
945   - }
946   -
947   - .dialog-footer {
948   - display: flex;
949   - justify-content: space-between;
950   - gap: 20rpx;
951   - margin-top: 40rpx;
952   - }
953   -
954   - .dialog-btn {
955   - flex: 1;
956   - height: 80rpx;
957   - line-height: 80rpx;
958   - text-align: center;
959   - border-radius: 12rpx;
960   - font-size: 28rpx;
961   - font-weight: 500;
962   - cursor: pointer;
963   - transition: all 0.3s ease;
964   - box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.08);
965 1082 }
966   -
967   - .cancel-btn {
968   - background-color: #f5f7fa;
  1083 +}
  1084 +
  1085 +.dialog-footer {
  1086 + display: flex;
  1087 + border-top: 1rpx solid #ebeef5;
  1088 + padding: 24rpx 40rpx;
  1089 + gap: 20rpx;
  1090 +}
  1091 +
  1092 +.dialog-btn {
  1093 + flex: 1;
  1094 + height: 80rpx;
  1095 + line-height: 80rpx;
  1096 + text-align: center;
  1097 + border-radius: 12rpx;
  1098 + font-size: 30rpx;
  1099 + font-weight: 500;
  1100 +
  1101 + &.cancel-btn {
  1102 + background: #f5f7fa;
969 1103 color: #606266;
970   - border: 1rpx solid #e4e7ed;
971   - }
972   -
973   - .cancel-btn:active {
974   - background-color: #e4e7ed;
975   - transform: scale(0.98);
976   - box-shadow: 0 1rpx 4rpx rgba(0, 0, 0, 0.1);
977 1104 }
978 1105  
979   - .confirm-btn {
  1106 + &.confirm-btn {
980 1107 background: linear-gradient(135deg, #43a047 0%, #66bb6a 100%);
981   - color: #fff;
982   - border: none;
983   - }
984   -
985   - .confirm-btn:active {
986   - background: linear-gradient(135deg, #388e3c 0%, #43a047 100%);
987   - transform: scale(0.98);
988   - box-shadow: 0 1rpx 4rpx rgba(67, 160, 71, 0.3);
  1108 + color: #ffffff;
989 1109 }
  1110 +}
990 1111 </style>
... ...