Commit ffd6aaca8c3edc72e935969e05e966b97e0fe262

Authored by 李宇
1 parent d64f9fbd

最新

antis-ncc-admin/src/views/statisticsList/form12.vue
... ... @@ -42,23 +42,6 @@
42 42 </el-form-item>
43 43 </el-col>
44 44 <el-col :span="6">
45   - <el-form-item label="开单门店">
46   - <el-select
47   - v-model="query.BillingStoreId"
48   - placeholder="请选择开单门店"
49   - filterable
50   - clearable
51   - :style='{"width":"100%"}'>
52   - <el-option
53   - v-for="item in storeOptions"
54   - :key="item.id"
55   - :label="item.dm"
56   - :value="item.id">
57   - </el-option>
58   - </el-select>
59   - </el-form-item>
60   - </el-col>
61   - <el-col :span="6">
62 45 <el-form-item label="开单人">
63 46 <userSelect v-model="query.BillingUserId" placeholder="请选择开单人" clearable />
64 47 </el-form-item>
... ... @@ -132,6 +115,71 @@
132 115 </el-form-item>
133 116 </el-col>
134 117 <el-col :span="6">
  118 + <el-form-item label="当前部门月份">
  119 + <el-date-picker
  120 + v-model="query.month"
  121 + type="month"
  122 + value-format="yyyyMM"
  123 + format="yyyy年MM月"
  124 + placeholder="请选择当前部门月份"
  125 + :style='{"width":"100%"}'
  126 + @change="handleMonthChange">
  127 + </el-date-picker>
  128 + </el-form-item>
  129 + </el-col>
  130 + <el-col :span="6">
  131 + <el-form-item label="组织类型">
  132 + <el-select
  133 + v-model="query.organizationType"
  134 + placeholder="请选择组织类型"
  135 + filterable
  136 + clearable
  137 + @change="handleOrganizationTypeChange"
  138 + :style='{"width":"100%"}'>
  139 + <el-option label="事业部" value="事业部"></el-option>
  140 + <el-option label="科技部" value="科技部"></el-option>
  141 + <el-option label="教育部" value="教育部"></el-option>
  142 + <el-option label="大项目部" value="大项目部"></el-option>
  143 + </el-select>
  144 + </el-form-item>
  145 + </el-col>
  146 + <el-col :span="6">
  147 + <el-form-item label="部门">
  148 + <el-select
  149 + v-model="query.departmentId"
  150 + placeholder="请选择部门"
  151 + filterable
  152 + clearable
  153 + @change="handleDepartmentChange"
  154 + :style='{"width":"100%"}'>
  155 + <el-option
  156 + v-for="dept in departmentOptions"
  157 + :key="dept.Id || dept.id"
  158 + :label="dept.FullName || dept.fullName"
  159 + :value="dept.Id || dept.id">
  160 + </el-option>
  161 + </el-select>
  162 + </el-form-item>
  163 + </el-col>
  164 + <el-col :span="12">
  165 + <el-form-item label="开单门店">
  166 + <el-select
  167 + v-model="query.BillingStoreIds"
  168 + placeholder="请选择开单门店"
  169 + multiple
  170 + filterable
  171 + clearable
  172 + :style='{"width":"100%"}'>
  173 + <el-option
  174 + v-for="item in storeOptions"
  175 + :key="item.id"
  176 + :label="item.dm"
  177 + :value="item.id">
  178 + </el-option>
  179 + </el-select>
  180 + </el-form-item>
  181 + </el-col>
  182 + <el-col :span="6">
135 183 <el-form-item>
136 184 <el-button type="primary" icon="el-icon-search" @click="search()">查询</el-button>
137 185 <el-button icon="el-icon-refresh-right" @click="reset()">重置</el-button>
... ... @@ -242,7 +290,10 @@ export default {
242 290 query: {
243 291 MemberId: undefined,
244 292 BelongStoreId: undefined,
245   - BillingStoreId: undefined,
  293 + month: undefined,
  294 + organizationType: undefined,
  295 + departmentId: undefined,
  296 + BillingStoreIds: [],
246 297 BillingUserId: undefined,
247 298 PurchaseItemId: undefined,
248 299 GiftItemId: undefined,
... ... @@ -252,6 +303,7 @@ export default {
252 303 memberOptions: [],
253 304 memberLoading: false,
254 305 storeOptions: [],
  306 + departmentOptions: [],
255 307 itemOptions: [],
256 308 memberTypeOptions: [],
257 309 list: [],
... ... @@ -266,15 +318,32 @@ export default {
266 318 }
267 319 },
268 320 created() {
269   - this.initStoreOptions()
  321 + this.setDefaultMonth()
  322 + this.loadAllStores()
270 323 this.initItemOptions()
271 324 this.initMemberOptions()
272 325 this.getMemberTypeOptions()
273 326 this.search()
274 327 },
  328 + watch: {
  329 + // 监听年月变化,重新加载门店列表
  330 + 'query.month'() {
  331 + this.$nextTick(() => {
  332 + this.initStoreOptions()
  333 + })
  334 + }
  335 + },
275 336 methods: {
276   - // 初始化门店选项
277   - initStoreOptions() {
  337 + // 设置默认年月(当前年月)
  338 + setDefaultMonth() {
  339 + const now = new Date()
  340 + const year = now.getFullYear()
  341 + const month = String(now.getMonth() + 1).padStart(2, '0')
  342 + this.query.month = `${year}${month}`
  343 + },
  344 +
  345 + // 加载全部门店(当没有选择部门时)
  346 + loadAllStores() {
278 347 request({
279 348 url: '/api/Extend/LqMdxx',
280 349 method: 'GET',
... ... @@ -291,6 +360,112 @@ export default {
291 360 })
292 361 },
293 362  
  363 + // 获取部门选项(根据组织类型)
  364 + loadDepartmentOptions() {
  365 + if (!this.query.organizationType) {
  366 + this.departmentOptions = []
  367 + return
  368 + }
  369 +
  370 + request({
  371 + url: '/api/Extend/Organize/GetByName',
  372 + method: 'GET',
  373 + data: {
  374 + organizeName: this.query.organizationType
  375 + }
  376 + }).then(res => {
  377 + this.departmentOptions = res.data || []
  378 + // 如果部门ID不在新列表中,清空部门ID
  379 + if (this.query.departmentId) {
  380 + const exists = this.departmentOptions.some(
  381 + dept => (dept.Id || dept.id) === this.query.departmentId
  382 + )
  383 + if (!exists) {
  384 + this.query.departmentId = undefined
  385 + this.query.BillingStoreIds = []
  386 + this.storeOptions = []
  387 + }
  388 + }
  389 + }).catch(() => {
  390 + this.departmentOptions = []
  391 + })
  392 + },
  393 +
  394 + // 初始化门店选项(根据组织类型、部门、年月)
  395 + initStoreOptions() {
  396 + // 如果没有选择部门,加载全部门店
  397 + if (!this.query.departmentId) {
  398 + this.loadAllStores()
  399 + return
  400 + }
  401 +
  402 + // 如果缺少必要参数,不加载门店列表
  403 + if (!this.query.organizationType || !this.query.month) {
  404 + this.storeOptions = []
  405 + return
  406 + }
  407 +
  408 + request({
  409 + url: '/api/Extend/lqmdtarget/GetManagedStores',
  410 + method: 'POST',
  411 + data: {
  412 + month: this.query.month,
  413 + organizationType: this.query.organizationType,
  414 + departmentId: this.query.departmentId
  415 + }
  416 + }).then(res => {
  417 + if (res.data && Array.isArray(res.data)) {
  418 + // 将返回的数据格式转换为 storeOptions 需要的格式
  419 + // 返回格式: [{ StoreId: "...", StoreName: "..." }]
  420 + // 需要格式: [{ id: "...", dm: "..." }]
  421 + this.storeOptions = res.data.map(store => ({
  422 + id: store.StoreId,
  423 + dm: store.StoreName
  424 + }))
  425 + // 默认选中所有获取到的门店
  426 + this.query.BillingStoreIds = this.storeOptions.map(store => store.id)
  427 + } else {
  428 + this.storeOptions = []
  429 + this.query.BillingStoreIds = []
  430 + }
  431 + }).catch(err => {
  432 + console.error('获取门店列表失败:', err)
  433 + this.$message({
  434 + type: 'error',
  435 + message: '获取门店列表失败',
  436 + duration: 1500
  437 + })
  438 + this.storeOptions = []
  439 + this.query.BillingStoreIds = []
  440 + })
  441 + },
  442 +
  443 + // 处理年月变化
  444 + handleMonthChange() {
  445 + this.$nextTick(() => {
  446 + this.initStoreOptions()
  447 + })
  448 + },
  449 +
  450 + // 处理组织类型变化
  451 + handleOrganizationTypeChange() {
  452 + // 清空部门和门店
  453 + this.query.departmentId = undefined
  454 + this.query.BillingStoreIds = []
  455 + // 重新加载部门选项
  456 + this.loadDepartmentOptions()
  457 + // 加载全部门店(因为部门已清空)
  458 + this.loadAllStores()
  459 + },
  460 +
  461 + // 处理部门变化
  462 + handleDepartmentChange() {
  463 + // 清空门店选择
  464 + this.query.BillingStoreIds = []
  465 + // 重新加载门店列表(如果有部门则加载部门管理的门店,否则加载全部门店)
  466 + this.initStoreOptions()
  467 + },
  468 +
294 469 // 初始化品项选项
295 470 initItemOptions() {
296 471 request({
... ... @@ -562,13 +737,20 @@ export default {
562 737 this.query = {
563 738 MemberId: undefined,
564 739 BelongStoreId: undefined,
565   - BillingStoreId: undefined,
  740 + month: undefined,
  741 + organizationType: undefined,
  742 + departmentId: undefined,
  743 + BillingStoreIds: [],
566 744 BillingUserId: undefined,
567 745 PurchaseItemId: undefined,
568 746 GiftItemId: undefined,
569 747 ExperienceItemId: undefined,
570 748 memberType: undefined
571 749 }
  750 + this.setDefaultMonth()
  751 + this.departmentOptions = []
  752 + // 重置后加载全部门店
  753 + this.loadAllStores()
572 754 this.listQuery.currentPage = 1
573 755 this.listQuery.pageSize = 20
574 756 this.list = []
... ...
antis-ncc-admin/src/views/statisticsList/form13.vue
... ... @@ -111,10 +111,45 @@
111 111 </el-form-item>
112 112 </el-col>
113 113 <el-col :span="6">
  114 + <el-form-item label="组织类型">
  115 + <el-select
  116 + v-model="query.organizationType"
  117 + placeholder="请选择组织类型"
  118 + filterable
  119 + clearable
  120 + @change="handleOrganizationTypeChange"
  121 + :style='{"width":"100%"}'>
  122 + <el-option label="事业部" value="事业部"></el-option>
  123 + <el-option label="科技部" value="科技部"></el-option>
  124 + <el-option label="教育部" value="教育部"></el-option>
  125 + <el-option label="大项目部" value="大项目部"></el-option>
  126 + </el-select>
  127 + </el-form-item>
  128 + </el-col>
  129 + <el-col :span="6">
  130 + <el-form-item label="部门">
  131 + <el-select
  132 + v-model="query.departmentId"
  133 + placeholder="请选择部门"
  134 + filterable
  135 + clearable
  136 + @change="handleDepartmentChange"
  137 + :style='{"width":"100%"}'>
  138 + <el-option
  139 + v-for="dept in departmentOptions"
  140 + :key="dept.Id || dept.id"
  141 + :label="dept.FullName || dept.fullName"
  142 + :value="dept.Id || dept.id">
  143 + </el-option>
  144 + </el-select>
  145 + </el-form-item>
  146 + </el-col>
  147 + <el-col :span="12">
114 148 <el-form-item label="门店">
115 149 <el-select
116   - v-model="query.storeId"
  150 + v-model="query.storeIds"
117 151 placeholder="请选择门店"
  152 + multiple
118 153 filterable
119 154 clearable
120 155 :style='{"width":"100%"}'>
... ... @@ -255,7 +290,9 @@ export default {
255 290 memberId: undefined,
256 291 itemType: undefined,
257 292 SourceType: undefined,
258   - storeId: undefined
  293 + organizationType: undefined,
  294 + departmentId: undefined,
  295 + storeIds: []
259 296 },
260 297 activityOptions: [],
261 298 itemOptions: [],
... ... @@ -263,6 +300,7 @@ export default {
263 300 memberOptions: [],
264 301 memberLoading: false,
265 302 storeOptions: [],
  303 + departmentOptions: [],
266 304 list: [],
267 305 listLoading: false,
268 306 total: 0,
... ... @@ -278,9 +316,17 @@ export default {
278 316 this.initItemOptions()
279 317 this.initItemTypeOptions()
280 318 this.initMemberOptions()
281   - this.initStoreOptions()
  319 + this.loadAllStores()
282 320 this.search()
283 321 },
  322 + watch: {
  323 + // 监听开始时间变化,重新加载门店列表
  324 + 'query.StartBillingTime'() {
  325 + this.$nextTick(() => {
  326 + this.initStoreOptions()
  327 + })
  328 + }
  329 + },
284 330 methods: {
285 331 // 设置默认时间范围(本月1号到现在)
286 332 setDefaultTimeRange() {
... ... @@ -289,6 +335,13 @@ export default {
289 335  
290 336 this.query.StartBillingTime = this.formatDate(firstDayOfMonth)
291 337 this.query.EndBillingTime = this.formatDate(now)
  338 +
  339 + // 时间设置后,如果有组织类型和部门,重新加载门店列表
  340 + if (this.query.organizationType && this.query.departmentId) {
  341 + this.$nextTick(() => {
  342 + this.initStoreOptions()
  343 + })
  344 + }
292 345 },
293 346  
294 347 // 初始化开单活动选项
... ... @@ -364,8 +417,8 @@ export default {
364 417 })
365 418 },
366 419  
367   - // 初始化门店选项
368   - initStoreOptions() {
  420 + // 加载全部门店(当没有选择部门时)
  421 + loadAllStores() {
369 422 request({
370 423 url: '/api/Extend/LqMdxx',
371 424 method: 'GET',
... ... @@ -382,6 +435,116 @@ export default {
382 435 })
383 436 },
384 437  
  438 + // 获取部门选项(根据组织类型)
  439 + loadDepartmentOptions() {
  440 + if (!this.query.organizationType) {
  441 + this.departmentOptions = []
  442 + return
  443 + }
  444 +
  445 + request({
  446 + url: '/api/Extend/Organize/GetByName',
  447 + method: 'GET',
  448 + data: {
  449 + organizeName: this.query.organizationType
  450 + }
  451 + }).then(res => {
  452 + this.departmentOptions = res.data || []
  453 + // 如果部门ID不在新列表中,清空部门ID
  454 + if (this.query.departmentId) {
  455 + const exists = this.departmentOptions.some(
  456 + dept => (dept.Id || dept.id) === this.query.departmentId
  457 + )
  458 + if (!exists) {
  459 + this.query.departmentId = undefined
  460 + this.query.storeIds = []
  461 + this.storeOptions = []
  462 + }
  463 + }
  464 + }).catch(() => {
  465 + this.departmentOptions = []
  466 + })
  467 + },
  468 +
  469 + // 初始化门店选项(根据组织类型、部门、年月)
  470 + initStoreOptions() {
  471 + // 如果没有选择部门,加载全部门店
  472 + if (!this.query.departmentId) {
  473 + this.loadAllStores()
  474 + return
  475 + }
  476 +
  477 + // 如果缺少必要参数,不加载门店列表
  478 + if (!this.query.organizationType || !this.query.StartBillingTime) {
  479 + this.storeOptions = []
  480 + return
  481 + }
  482 +
  483 + // 从开始时间提取年月(格式:YYYYMM)
  484 + // StartBillingTime 格式为 yyyy-MM-dd
  485 + const dateStr = this.query.StartBillingTime
  486 + if (!dateStr) {
  487 + this.storeOptions = []
  488 + return
  489 + }
  490 +
  491 + // 提取年月,格式:YYYYMM
  492 + const monthStr = dateStr.substring(0, 4) + dateStr.substring(5, 7)
  493 +
  494 + request({
  495 + url: '/api/Extend/lqmdtarget/GetManagedStores',
  496 + method: 'POST',
  497 + data: {
  498 + month: monthStr,
  499 + organizationType: this.query.organizationType,
  500 + departmentId: this.query.departmentId
  501 + }
  502 + }).then(res => {
  503 + if (res.data && Array.isArray(res.data)) {
  504 + // 将返回的数据格式转换为 storeOptions 需要的格式
  505 + // 返回格式: [{ StoreId: "...", StoreName: "..." }]
  506 + // 需要格式: [{ id: "...", dm: "..." }]
  507 + this.storeOptions = res.data.map(store => ({
  508 + id: store.StoreId,
  509 + dm: store.StoreName
  510 + }))
  511 + // 默认选中所有获取到的门店
  512 + this.query.storeIds = this.storeOptions.map(store => store.id)
  513 + } else {
  514 + this.storeOptions = []
  515 + this.query.storeIds = []
  516 + }
  517 + }).catch(err => {
  518 + console.error('获取门店列表失败:', err)
  519 + this.$message({
  520 + type: 'error',
  521 + message: '获取门店列表失败',
  522 + duration: 1500
  523 + })
  524 + this.storeOptions = []
  525 + this.query.storeIds = []
  526 + })
  527 + },
  528 +
  529 + // 处理组织类型变化
  530 + handleOrganizationTypeChange() {
  531 + // 清空部门和门店
  532 + this.query.departmentId = undefined
  533 + this.query.storeIds = []
  534 + // 重新加载部门选项
  535 + this.loadDepartmentOptions()
  536 + // 加载全部门店(因为部门已清空)
  537 + this.loadAllStores()
  538 + },
  539 +
  540 + // 处理部门变化
  541 + handleDepartmentChange() {
  542 + // 清空门店选择
  543 + this.query.storeIds = []
  544 + // 重新加载门店列表(如果有部门则加载部门管理的门店,否则加载全部门店)
  545 + this.initStoreOptions()
  546 + },
  547 +
385 548 // 会员远程搜索
386 549 remoteMemberMethod(query) {
387 550 if (query !== '') {
... ... @@ -445,8 +608,8 @@ export default {
445 608 if (this.query.SourceType) {
446 609 params.SourceType = this.query.SourceType
447 610 }
448   - if (this.query.storeId) {
449   - params.StoreId = this.query.storeId
  611 + if (this.query.storeIds && this.query.storeIds.length > 0) {
  612 + params.StoreIds = this.query.storeIds
450 613 }
451 614  
452 615 request({
... ... @@ -485,9 +648,14 @@ export default {
485 648 memberId: undefined,
486 649 itemType: undefined,
487 650 SourceType: undefined,
488   - storeId: undefined
  651 + organizationType: undefined,
  652 + departmentId: undefined,
  653 + storeIds: []
489 654 }
490 655 this.setDefaultTimeRange()
  656 + this.departmentOptions = []
  657 + // 重置后加载全部门店
  658 + this.loadAllStores()
491 659 this.listQuery.currentPage = 1
492 660 this.listQuery.pageSize = 20
493 661 this.list = []
... ...
antis-ncc-admin/src/views/statisticsList/form14.vue
... ... @@ -94,10 +94,45 @@
94 94 </el-form-item>
95 95 </el-col>
96 96 <el-col :span="6">
  97 + <el-form-item label="组织类型">
  98 + <el-select
  99 + v-model="query.organizationType"
  100 + placeholder="请选择组织类型"
  101 + filterable
  102 + clearable
  103 + @change="handleOrganizationTypeChange"
  104 + :style='{"width":"100%"}'>
  105 + <el-option label="事业部" value="事业部"></el-option>
  106 + <el-option label="科技部" value="科技部"></el-option>
  107 + <el-option label="教育部" value="教育部"></el-option>
  108 + <el-option label="大项目部" value="大项目部"></el-option>
  109 + </el-select>
  110 + </el-form-item>
  111 + </el-col>
  112 + <el-col :span="6">
  113 + <el-form-item label="部门">
  114 + <el-select
  115 + v-model="query.departmentId"
  116 + placeholder="请选择部门"
  117 + filterable
  118 + clearable
  119 + @change="handleDepartmentChange"
  120 + :style='{"width":"100%"}'>
  121 + <el-option
  122 + v-for="dept in departmentOptions"
  123 + :key="dept.Id || dept.id"
  124 + :label="dept.FullName || dept.fullName"
  125 + :value="dept.Id || dept.id">
  126 + </el-option>
  127 + </el-select>
  128 + </el-form-item>
  129 + </el-col>
  130 + <el-col :span="12">
97 131 <el-form-item label="门店">
98 132 <el-select
99   - v-model="query.StoreId"
  133 + v-model="query.StoreIds"
100 134 placeholder="请选择门店"
  135 + multiple
101 136 filterable
102 137 clearable
103 138 :style='{"width":"100%"}'>
... ... @@ -222,13 +257,16 @@ export default {
222 257 MemberId: undefined,
223 258 ItemType: undefined,
224 259 SourceType: undefined,
225   - StoreId: undefined
  260 + organizationType: undefined,
  261 + departmentId: undefined,
  262 + StoreIds: []
226 263 },
227 264 itemOptions: [],
228 265 itemTypeOptions: [],
229 266 memberOptions: [],
230 267 memberLoading: false,
231 268 storeOptions: [],
  269 + departmentOptions: [],
232 270 list: [],
233 271 listLoading: false,
234 272 total: 0,
... ... @@ -243,9 +281,17 @@ export default {
243 281 this.initItemOptions()
244 282 this.initItemTypeOptions()
245 283 this.initMemberOptions()
246   - this.initStoreOptions()
  284 + this.loadAllStores()
247 285 this.search()
248 286 },
  287 + watch: {
  288 + // 监听开始时间变化,重新加载门店列表
  289 + 'query.StartConsumeTime'() {
  290 + this.$nextTick(() => {
  291 + this.initStoreOptions()
  292 + })
  293 + }
  294 + },
249 295 methods: {
250 296 // 设置默认时间范围(本月1号到现在)
251 297 setDefaultTimeRange() {
... ... @@ -254,6 +300,13 @@ export default {
254 300  
255 301 this.query.StartConsumeTime = this.formatDate(firstDayOfMonth)
256 302 this.query.EndConsumeTime = this.formatDate(now)
  303 +
  304 + // 时间设置后,如果有组织类型和部门,重新加载门店列表
  305 + if (this.query.organizationType && this.query.departmentId) {
  306 + this.$nextTick(() => {
  307 + this.initStoreOptions()
  308 + })
  309 + }
257 310 },
258 311  
259 312 // 初始化品项选项
... ... @@ -311,8 +364,8 @@ export default {
311 364 })
312 365 },
313 366  
314   - // 初始化门店选项
315   - initStoreOptions() {
  367 + // 加载全部门店(当没有选择部门时)
  368 + loadAllStores() {
316 369 request({
317 370 url: '/api/Extend/LqMdxx',
318 371 method: 'GET',
... ... @@ -329,6 +382,116 @@ export default {
329 382 })
330 383 },
331 384  
  385 + // 获取部门选项(根据组织类型)
  386 + loadDepartmentOptions() {
  387 + if (!this.query.organizationType) {
  388 + this.departmentOptions = []
  389 + return
  390 + }
  391 +
  392 + request({
  393 + url: '/api/Extend/Organize/GetByName',
  394 + method: 'GET',
  395 + data: {
  396 + organizeName: this.query.organizationType
  397 + }
  398 + }).then(res => {
  399 + this.departmentOptions = res.data || []
  400 + // 如果部门ID不在新列表中,清空部门ID
  401 + if (this.query.departmentId) {
  402 + const exists = this.departmentOptions.some(
  403 + dept => (dept.Id || dept.id) === this.query.departmentId
  404 + )
  405 + if (!exists) {
  406 + this.query.departmentId = undefined
  407 + this.query.StoreIds = []
  408 + this.storeOptions = []
  409 + }
  410 + }
  411 + }).catch(() => {
  412 + this.departmentOptions = []
  413 + })
  414 + },
  415 +
  416 + // 初始化门店选项(根据组织类型、部门、年月)
  417 + initStoreOptions() {
  418 + // 如果没有选择部门,加载全部门店
  419 + if (!this.query.departmentId) {
  420 + this.loadAllStores()
  421 + return
  422 + }
  423 +
  424 + // 如果缺少必要参数,不加载门店列表
  425 + if (!this.query.organizationType || !this.query.StartConsumeTime) {
  426 + this.storeOptions = []
  427 + return
  428 + }
  429 +
  430 + // 从开始时间提取年月(格式:YYYYMM)
  431 + // StartConsumeTime 格式为 yyyy-MM-dd
  432 + const dateStr = this.query.StartConsumeTime
  433 + if (!dateStr) {
  434 + this.storeOptions = []
  435 + return
  436 + }
  437 +
  438 + // 提取年月,格式:YYYYMM
  439 + const monthStr = dateStr.substring(0, 4) + dateStr.substring(5, 7)
  440 +
  441 + request({
  442 + url: '/api/Extend/lqmdtarget/GetManagedStores',
  443 + method: 'POST',
  444 + data: {
  445 + month: monthStr,
  446 + organizationType: this.query.organizationType,
  447 + departmentId: this.query.departmentId
  448 + }
  449 + }).then(res => {
  450 + if (res.data && Array.isArray(res.data)) {
  451 + // 将返回的数据格式转换为 storeOptions 需要的格式
  452 + // 返回格式: [{ StoreId: "...", StoreName: "..." }]
  453 + // 需要格式: [{ id: "...", dm: "..." }]
  454 + this.storeOptions = res.data.map(store => ({
  455 + id: store.StoreId,
  456 + dm: store.StoreName
  457 + }))
  458 + // 默认选中所有获取到的门店
  459 + this.query.StoreIds = this.storeOptions.map(store => store.id)
  460 + } else {
  461 + this.storeOptions = []
  462 + this.query.StoreIds = []
  463 + }
  464 + }).catch(err => {
  465 + console.error('获取门店列表失败:', err)
  466 + this.$message({
  467 + type: 'error',
  468 + message: '获取门店列表失败',
  469 + duration: 1500
  470 + })
  471 + this.storeOptions = []
  472 + this.query.StoreIds = []
  473 + })
  474 + },
  475 +
  476 + // 处理组织类型变化
  477 + handleOrganizationTypeChange() {
  478 + // 清空部门和门店
  479 + this.query.departmentId = undefined
  480 + this.query.StoreIds = []
  481 + // 重新加载部门选项
  482 + this.loadDepartmentOptions()
  483 + // 加载全部门店(因为部门已清空)
  484 + this.loadAllStores()
  485 + },
  486 +
  487 + // 处理部门变化
  488 + handleDepartmentChange() {
  489 + // 清空门店选择
  490 + this.query.StoreIds = []
  491 + // 重新加载门店列表(如果有部门则加载部门管理的门店,否则加载全部门店)
  492 + this.initStoreOptions()
  493 + },
  494 +
332 495 // 会员远程搜索
333 496 remoteMemberMethod(query) {
334 497 if (query !== '') {
... ... @@ -390,8 +553,8 @@ export default {
390 553 params.SourceType = this.query.SourceType
391 554 }
392 555  
393   - if (this.query.StoreId) {
394   - params.StoreId = this.query.StoreId
  556 + if (this.query.StoreIds && this.query.StoreIds.length > 0) {
  557 + params.StoreIds = this.query.StoreIds
395 558 }
396 559  
397 560 request({
... ... @@ -429,9 +592,14 @@ export default {
429 592 MemberId: undefined,
430 593 ItemType: undefined,
431 594 SourceType: undefined,
432   - StoreId: undefined
  595 + organizationType: undefined,
  596 + departmentId: undefined,
  597 + StoreIds: []
433 598 }
434 599 this.setDefaultTimeRange()
  600 + this.departmentOptions = []
  601 + // 重置后加载全部门店
  602 + this.loadAllStores()
435 603 this.listQuery.currentPage = 1
436 604 this.listQuery.pageSize = 10
437 605 this.list = []
... ...
antis-ncc-admin/src/views/statisticsList/form17.vue
... ... @@ -4,7 +4,7 @@
4 4 <!-- 筛选条件 -->
5 5 <el-row class="NCC-common-search-box" :gutter="16">
6 6 <el-form @submit.native.prevent>
7   - <el-col :span="6">
  7 + <el-col :span="4.8">
8 8 <el-form-item label="会员">
9 9 <el-select
10 10 v-model="query.memberIds"
... ... @@ -25,7 +25,7 @@
25 25 </el-select>
26 26 </el-form-item>
27 27 </el-col>
28   - <el-col :span="6">
  28 + <el-col :span="4.8">
29 29 <el-form-item label="是否升医美">
30 30 <el-select
31 31 v-model="query.hasUpgradeMedicalBeauty"
... ... @@ -37,7 +37,7 @@
37 37 </el-select>
38 38 </el-form-item>
39 39 </el-col>
40   - <el-col :span="6">
  40 + <el-col :span="4.8">
41 41 <el-form-item label="是否升科美">
42 42 <el-select
43 43 v-model="query.hasUpgradeTechBeauty"
... ... @@ -49,7 +49,7 @@
49 49 </el-select>
50 50 </el-form-item>
51 51 </el-col>
52   - <el-col :span="6">
  52 + <el-col :span="4.8">
53 53 <el-form-item label="是否升生美">
54 54 <el-select
55 55 v-model="query.hasUpgradeLifeBeauty"
... ... @@ -61,7 +61,72 @@
61 61 </el-select>
62 62 </el-form-item>
63 63 </el-col>
64   - <el-col :span="6">
  64 + <el-col :span="4.8">
  65 + <el-form-item label="当前部门月份">
  66 + <el-date-picker
  67 + v-model="query.month"
  68 + type="month"
  69 + value-format="yyyyMM"
  70 + format="yyyy年MM月"
  71 + placeholder="请选择当前部门月份"
  72 + :style='{"width":"100%"}'
  73 + @change="handleMonthChange">
  74 + </el-date-picker>
  75 + </el-form-item>
  76 + </el-col>
  77 + <el-col :span="4.8">
  78 + <el-form-item label="组织类型">
  79 + <el-select
  80 + v-model="query.organizationType"
  81 + placeholder="请选择组织类型"
  82 + filterable
  83 + clearable
  84 + @change="handleOrganizationTypeChange"
  85 + :style='{"width":"100%"}'>
  86 + <el-option label="事业部" value="事业部"></el-option>
  87 + <el-option label="科技部" value="科技部"></el-option>
  88 + <el-option label="教育部" value="教育部"></el-option>
  89 + <el-option label="大项目部" value="大项目部"></el-option>
  90 + </el-select>
  91 + </el-form-item>
  92 + </el-col>
  93 + <el-col :span="4.8">
  94 + <el-form-item label="部门">
  95 + <el-select
  96 + v-model="query.departmentId"
  97 + placeholder="请选择部门"
  98 + filterable
  99 + clearable
  100 + @change="handleDepartmentChange"
  101 + :style='{"width":"100%"}'>
  102 + <el-option
  103 + v-for="dept in departmentOptions"
  104 + :key="dept.Id || dept.id"
  105 + :label="dept.FullName || dept.fullName"
  106 + :value="dept.Id || dept.id">
  107 + </el-option>
  108 + </el-select>
  109 + </el-form-item>
  110 + </el-col>
  111 + <el-col :span="12">
  112 + <el-form-item label="门店">
  113 + <el-select
  114 + v-model="query.storeIds"
  115 + placeholder="请选择门店"
  116 + multiple
  117 + filterable
  118 + clearable
  119 + :style='{"width":"100%"}'>
  120 + <el-option
  121 + v-for="store in storeOptions"
  122 + :key="store.id"
  123 + :label="store.dm"
  124 + :value="store.id">
  125 + </el-option>
  126 + </el-select>
  127 + </el-form-item>
  128 + </el-col>
  129 + <el-col :span="4.8">
65 130 <el-form-item>
66 131 <el-button type="primary" icon="el-icon-search" @click="search()">查询</el-button>
67 132 <el-button icon="el-icon-refresh-right" @click="reset()">重置</el-button>
... ... @@ -146,10 +211,16 @@ export default {
146 211 memberIds: [],
147 212 hasUpgradeMedicalBeauty: null,
148 213 hasUpgradeTechBeauty: null,
149   - hasUpgradeLifeBeauty: null
  214 + hasUpgradeLifeBeauty: null,
  215 + month: undefined,
  216 + organizationType: undefined,
  217 + departmentId: undefined,
  218 + storeIds: []
150 219 },
151 220 memberOptions: [],
152 221 memberLoading: false,
  222 + storeOptions: [],
  223 + departmentOptions: [],
153 224 list: [],
154 225 listLoading: false,
155 226 total: 0,
... ... @@ -160,10 +231,152 @@ export default {
160 231 }
161 232 },
162 233 created() {
  234 + this.setDefaultMonth()
  235 + this.loadAllStores()
163 236 this.initMemberOptions()
164 237 this.search()
165 238 },
  239 + watch: {
  240 + // 监听年月变化,重新加载门店列表
  241 + 'query.month'() {
  242 + this.$nextTick(() => {
  243 + this.initStoreOptions()
  244 + })
  245 + }
  246 + },
166 247 methods: {
  248 + // 设置默认年月(当前年月)
  249 + setDefaultMonth() {
  250 + const now = new Date()
  251 + const year = now.getFullYear()
  252 + const month = String(now.getMonth() + 1).padStart(2, '0')
  253 + this.query.month = `${year}${month}`
  254 + },
  255 +
  256 + // 加载全部门店(当没有选择部门时)
  257 + loadAllStores() {
  258 + request({
  259 + url: '/api/Extend/LqMdxx',
  260 + method: 'GET',
  261 + data: {
  262 + currentPage: 1,
  263 + pageSize: 1000
  264 + }
  265 + }).then(res => {
  266 + if (res.data && res.data.list) {
  267 + this.storeOptions = res.data.list
  268 + }
  269 + }).catch(() => {
  270 + this.storeOptions = []
  271 + })
  272 + },
  273 +
  274 + // 获取部门选项(根据组织类型)
  275 + loadDepartmentOptions() {
  276 + if (!this.query.organizationType) {
  277 + this.departmentOptions = []
  278 + return
  279 + }
  280 +
  281 + request({
  282 + url: '/api/Extend/Organize/GetByName',
  283 + method: 'GET',
  284 + data: {
  285 + organizeName: this.query.organizationType
  286 + }
  287 + }).then(res => {
  288 + this.departmentOptions = res.data || []
  289 + // 如果部门ID不在新列表中,清空部门ID
  290 + if (this.query.departmentId) {
  291 + const exists = this.departmentOptions.some(
  292 + dept => (dept.Id || dept.id) === this.query.departmentId
  293 + )
  294 + if (!exists) {
  295 + this.query.departmentId = undefined
  296 + this.query.storeIds = []
  297 + this.storeOptions = []
  298 + }
  299 + }
  300 + }).catch(() => {
  301 + this.departmentOptions = []
  302 + })
  303 + },
  304 +
  305 + // 初始化门店选项(根据组织类型、部门、年月)
  306 + initStoreOptions() {
  307 + // 如果没有选择部门,加载全部门店
  308 + if (!this.query.departmentId) {
  309 + this.loadAllStores()
  310 + return
  311 + }
  312 +
  313 + // 如果缺少必要参数,不加载门店列表
  314 + if (!this.query.organizationType || !this.query.month) {
  315 + this.storeOptions = []
  316 + return
  317 + }
  318 +
  319 + request({
  320 + url: '/api/Extend/lqmdtarget/GetManagedStores',
  321 + method: 'POST',
  322 + data: {
  323 + month: this.query.month,
  324 + organizationType: this.query.organizationType,
  325 + departmentId: this.query.departmentId
  326 + }
  327 + }).then(res => {
  328 + if (res.data && Array.isArray(res.data)) {
  329 + // 将返回的数据格式转换为 storeOptions 需要的格式
  330 + // 返回格式: [{ StoreId: "...", StoreName: "..." }]
  331 + // 需要格式: [{ id: "...", dm: "..." }]
  332 + this.storeOptions = res.data.map(store => ({
  333 + id: store.StoreId,
  334 + dm: store.StoreName
  335 + }))
  336 + // 默认选中所有获取到的门店
  337 + this.query.storeIds = this.storeOptions.map(store => store.id)
  338 + } else {
  339 + this.storeOptions = []
  340 + this.query.storeIds = []
  341 + }
  342 + }).catch(err => {
  343 + console.error('获取门店列表失败:', err)
  344 + this.$message({
  345 + type: 'error',
  346 + message: '获取门店列表失败',
  347 + duration: 1500
  348 + })
  349 + this.storeOptions = []
  350 + this.query.storeIds = []
  351 + })
  352 + },
  353 +
  354 + // 处理年月变化
  355 + handleMonthChange() {
  356 + this.$nextTick(() => {
  357 + this.initStoreOptions()
  358 + })
  359 + },
  360 +
  361 + // 处理组织类型变化
  362 + handleOrganizationTypeChange() {
  363 + // 清空部门和门店
  364 + this.query.departmentId = undefined
  365 + this.query.storeIds = []
  366 + // 重新加载部门选项
  367 + this.loadDepartmentOptions()
  368 + // 加载全部门店(因为部门已清空)
  369 + this.loadAllStores()
  370 + },
  371 +
  372 + // 处理部门变化
  373 + handleDepartmentChange() {
  374 + // 清空门店选择
  375 + this.query.storeIds = []
  376 + // 重新加载门店列表(如果有部门则加载部门管理的门店,否则加载全部门店)
  377 + this.initStoreOptions()
  378 + },
  379 +
167 380 // 初始化会员选项(加载前10个)
168 381 initMemberOptions() {
169 382 request({
... ... @@ -244,6 +457,10 @@ export default {
244 457 params.hasUpgradeLifeBeauty = this.query.hasUpgradeLifeBeauty
245 458 }
246 459  
  460 + if (this.query.storeIds && this.query.storeIds.length > 0) {
  461 + params.storeIds = this.query.storeIds
  462 + }
  463 +
247 464 request({
248 465 url: '/api/Extend/lqstatistics/get-member-upgrade-statistics-list',
249 466 method: 'POST',
... ... @@ -283,8 +500,16 @@ export default {
283 500 memberIds: [],
284 501 hasUpgradeMedicalBeauty: null,
285 502 hasUpgradeTechBeauty: null,
286   - hasUpgradeLifeBeauty: null
  503 + hasUpgradeLifeBeauty: null,
  504 + month: undefined,
  505 + organizationType: undefined,
  506 + departmentId: undefined,
  507 + storeIds: []
287 508 }
  509 + this.setDefaultMonth()
  510 + this.departmentOptions = []
  511 + // 重置后加载全部门店
  512 + this.loadAllStores()
288 513 this.listQuery.pageIndex = 1
289 514 this.listQuery.pageSize = 10
290 515 this.list = []
... ...
antis-ncc-admin/src/views/statisticsList/form18.vue
... ... @@ -5,23 +5,6 @@
5 5 <el-row class="NCC-common-search-box" :gutter="16">
6 6 <el-form @submit.native.prevent>
7 7 <el-col :span="6">
8   - <el-form-item label="门店">
9   - <el-select
10   - v-model="query.StoreId"
11   - placeholder="请选择门店"
12   - filterable
13   - clearable
14   - :style='{"width":"100%"}'>
15   - <el-option
16   - v-for="store in storeOptions"
17   - :key="store.id"
18   - :label="store.dm"
19   - :value="store.id">
20   - </el-option>
21   - </el-select>
22   - </el-form-item>
23   - </el-col>
24   - <el-col :span="6">
25 8 <el-form-item label="开始日期">
26 9 <el-date-picker
27 10 v-model="query.StartTime"
... ... @@ -30,6 +13,7 @@
30 13 format="yyyy-MM-dd"
31 14 placeholder="开始日期"
32 15 :style='{"width":"100%"}'
  16 + @change="handleStartTimeChange"
33 17 />
34 18 </el-form-item>
35 19 </el-col>
... ... @@ -104,6 +88,58 @@
104 88 </el-form-item>
105 89 </el-col>
106 90 <el-col :span="6">
  91 + <el-form-item label="组织类型">
  92 + <el-select
  93 + v-model="query.organizationType"
  94 + placeholder="请选择组织类型"
  95 + filterable
  96 + clearable
  97 + @change="handleOrganizationTypeChange"
  98 + :style='{"width":"100%"}'>
  99 + <el-option label="事业部" value="事业部"></el-option>
  100 + <el-option label="科技部" value="科技部"></el-option>
  101 + <el-option label="教育部" value="教育部"></el-option>
  102 + <el-option label="大项目部" value="大项目部"></el-option>
  103 + </el-select>
  104 + </el-form-item>
  105 + </el-col>
  106 + <el-col :span="6">
  107 + <el-form-item label="部门">
  108 + <el-select
  109 + v-model="query.departmentId"
  110 + placeholder="请选择部门"
  111 + filterable
  112 + clearable
  113 + @change="handleDepartmentChange"
  114 + :style='{"width":"100%"}'>
  115 + <el-option
  116 + v-for="dept in departmentOptions"
  117 + :key="dept.Id || dept.id"
  118 + :label="dept.FullName || dept.fullName"
  119 + :value="dept.Id || dept.id">
  120 + </el-option>
  121 + </el-select>
  122 + </el-form-item>
  123 + </el-col>
  124 + <el-col :span="12">
  125 + <el-form-item label="门店">
  126 + <el-select
  127 + v-model="query.StoreIds"
  128 + placeholder="请选择门店"
  129 + multiple
  130 + filterable
  131 + clearable
  132 + :style='{"width":"100%"}'>
  133 + <el-option
  134 + v-for="store in storeOptions"
  135 + :key="store.id"
  136 + :label="store.dm"
  137 + :value="store.id">
  138 + </el-option>
  139 + </el-select>
  140 + </el-form-item>
  141 + </el-col>
  142 + <el-col :span="6">
107 143 <el-form-item>
108 144 <el-button type="primary" icon="el-icon-search" @click="search()">查询</el-button>
109 145 <el-button icon="el-icon-refresh-right" @click="reset()">重置</el-button>
... ... @@ -238,7 +274,9 @@ export default {
238 274 data() {
239 275 return {
240 276 query: {
241   - StoreId: undefined,
  277 + organizationType: undefined,
  278 + departmentId: undefined,
  279 + StoreIds: [],
242 280 StartTime: undefined,
243 281 EndTime: undefined,
244 282 ItemId: undefined,
... ... @@ -247,6 +285,7 @@ export default {
247 285 MaxAmount: undefined
248 286 },
249 287 storeOptions: [],
  288 + departmentOptions: [],
250 289 itemOptions: [],
251 290 itemCategoryOptions: [],
252 291 list: [],
... ... @@ -285,11 +324,19 @@ export default {
285 324 },
286 325 created() {
287 326 this.setDefaultTimeRange()
288   - this.initStoreOptions()
  327 + this.loadAllStores()
289 328 this.initItemOptions()
290 329 this.initItemCategoryOptions()
291 330 this.search()
292 331 },
  332 + watch: {
  333 + // 监听开始时间变化,重新加载门店列表
  334 + 'query.StartTime'() {
  335 + this.$nextTick(() => {
  336 + this.initStoreOptions()
  337 + })
  338 + }
  339 + },
293 340 methods: {
294 341 // 设置默认时间范围(本月1号到现在)
295 342 setDefaultTimeRange() {
... ... @@ -297,10 +344,17 @@ export default {
297 344 const firstDayOfMonth = new Date(now.getFullYear(), now.getMonth(), 1)
298 345 this.query.StartTime = this.formatDate(firstDayOfMonth)
299 346 this.query.EndTime = this.formatDate(now)
  347 +
  348 + // 时间设置后,如果有组织类型和部门,重新加载门店列表
  349 + if (this.query.organizationType && this.query.departmentId) {
  350 + this.$nextTick(() => {
  351 + this.initStoreOptions()
  352 + })
  353 + }
300 354 },
301 355  
302   - // 初始化门店选项
303   - initStoreOptions() {
  356 + // 加载全部门店(当没有选择部门时)
  357 + loadAllStores() {
304 358 request({
305 359 url: '/api/Extend/LqMdxx',
306 360 method: 'GET',
... ... @@ -317,6 +371,123 @@ export default {
317 371 })
318 372 },
319 373  
  374 + // 获取部门选项(根据组织类型)
  375 + loadDepartmentOptions() {
  376 + if (!this.query.organizationType) {
  377 + this.departmentOptions = []
  378 + return
  379 + }
  380 +
  381 + request({
  382 + url: '/api/Extend/Organize/GetByName',
  383 + method: 'GET',
  384 + data: {
  385 + organizeName: this.query.organizationType
  386 + }
  387 + }).then(res => {
  388 + this.departmentOptions = res.data || []
  389 + // 如果部门ID不在新列表中,清空部门ID
  390 + if (this.query.departmentId) {
  391 + const exists = this.departmentOptions.some(
  392 + dept => (dept.Id || dept.id) === this.query.departmentId
  393 + )
  394 + if (!exists) {
  395 + this.query.departmentId = undefined
  396 + this.query.StoreIds = []
  397 + this.storeOptions = []
  398 + }
  399 + }
  400 + }).catch(() => {
  401 + this.departmentOptions = []
  402 + })
  403 + },
  404 +
  405 + // 初始化门店选项(根据组织类型、部门、年月)
  406 + initStoreOptions() {
  407 + // 如果没有选择部门,加载全部门店
  408 + if (!this.query.departmentId) {
  409 + this.loadAllStores()
  410 + return
  411 + }
  412 +
  413 + // 如果缺少必要参数,不加载门店列表
  414 + if (!this.query.organizationType || !this.query.StartTime) {
  415 + this.storeOptions = []
  416 + return
  417 + }
  418 +
  419 + // 从开始时间提取年月(格式:YYYYMM)
  420 + // StartTime 格式为 yyyy-MM-dd
  421 + const dateStr = this.query.StartTime
  422 + if (!dateStr) {
  423 + this.storeOptions = []
  424 + return
  425 + }
  426 +
  427 + // 提取年月,格式:YYYYMM
  428 + const monthStr = dateStr.substring(0, 4) + dateStr.substring(5, 7)
  429 +
  430 + request({
  431 + url: '/api/Extend/lqmdtarget/GetManagedStores',
  432 + method: 'POST',
  433 + data: {
  434 + month: monthStr,
  435 + organizationType: this.query.organizationType,
  436 + departmentId: this.query.departmentId
  437 + }
  438 + }).then(res => {
  439 + if (res.data && Array.isArray(res.data)) {
  440 + // 将返回的数据格式转换为 storeOptions 需要的格式
  441 + // 返回格式: [{ StoreId: "...", StoreName: "..." }]
  442 + // 需要格式: [{ id: "...", dm: "..." }]
  443 + this.storeOptions = res.data.map(store => ({
  444 + id: store.StoreId,
  445 + dm: store.StoreName
  446 + }))
  447 + // 默认选中所有获取到的门店
  448 + this.query.StoreIds = this.storeOptions.map(store => store.id)
  449 + } else {
  450 + this.storeOptions = []
  451 + this.query.StoreIds = []
  452 + }
  453 + }).catch(err => {
  454 + console.error('获取门店列表失败:', err)
  455 + this.$message({
  456 + type: 'error',
  457 + message: '获取门店列表失败',
  458 + duration: 1500
  459 + })
  460 + this.storeOptions = []
  461 + this.query.StoreIds = []
  462 + })
  463 + },
  464 +
  465 + // 处理开始时间变化
  466 + handleStartTimeChange() {
  467 + this.$nextTick(() => {
  468 + this.initStoreOptions()
  469 + })
  470 + },
  471 +
  472 + // 处理组织类型变化
  473 + handleOrganizationTypeChange() {
  474 + // 清空部门和门店
  475 + this.query.departmentId = undefined
  476 + this.query.StoreIds = []
  477 + // 重新加载部门选项
  478 + this.loadDepartmentOptions()
  479 + // 加载全部门店(因为部门已清空)
  480 + this.loadAllStores()
  481 + },
  482 +
  483 + // 处理部门变化
  484 + handleDepartmentChange() {
  485 + // 清空门店选择
  486 + this.query.StoreIds = []
  487 + // 重新加载门店列表(如果有部门则加载部门管理的门店,否则加载全部门店)
  488 + this.initStoreOptions()
  489 + },
  490 +
320 491 // 初始化品项选项
321 492 initItemOptions() {
322 493 request({
... ... @@ -367,8 +538,8 @@ export default {
367 538 params.ItemId = this.query.ItemId
368 539 }
369 540  
370   - if (this.query.StoreId) {
371   - params.StoreId = this.query.StoreId
  541 + if (this.query.StoreIds && this.query.StoreIds.length > 0) {
  542 + params.StoreIds = this.query.StoreIds
372 543 }
373 544  
374 545 if (this.query.StartTime) {
... ... @@ -427,7 +598,9 @@ export default {
427 598 // 重置查询条件
428 599 reset() {
429 600 this.query = {
430   - StoreId: undefined,
  601 + organizationType: undefined,
  602 + departmentId: undefined,
  603 + StoreIds: [],
431 604 StartTime: undefined,
432 605 EndTime: undefined,
433 606 ItemId: undefined,
... ... @@ -436,6 +609,9 @@ export default {
436 609 MaxAmount: undefined
437 610 }
438 611 this.setDefaultTimeRange()
  612 + this.departmentOptions = []
  613 + // 重置后加载全部门店
  614 + this.loadAllStores()
439 615 this.listQuery.currentPage = 1
440 616 this.listQuery.pageSize = 10
441 617 this.list = []
... ...
antis-ncc-admin/src/views/statisticsList/form20.vue
... ... @@ -3,7 +3,7 @@
3 3 <div class="NCC-common-layout-center">
4 4 <!-- 筛选条件 -->
5 5 <el-row class="NCC-common-search-box" :gutter="16">
6   - <el-form @submit.native.prevent label-width="80px">
  6 + <el-form @submit.native.prevent >
7 7 <el-col :span="6">
8 8 <el-form-item label="选择月份">
9 9 <el-date-picker
... ... @@ -17,6 +17,23 @@
17 17 </el-form-item>
18 18 </el-col>
19 19 <el-col :span="6">
  20 + <el-form-item label="部门">
  21 + <el-select
  22 + v-model="query.departmentId"
  23 + placeholder="请选择部门"
  24 + filterable
  25 + clearable
  26 + style="width: 100%;">
  27 + <el-option
  28 + v-for="dept in departmentOptions"
  29 + :key="dept.Id || dept.id"
  30 + :label="dept.FullName || dept.fullName"
  31 + :value="dept.Id || dept.id">
  32 + </el-option>
  33 + </el-select>
  34 + </el-form-item>
  35 + </el-col>
  36 + <el-col :span="6">
20 37 <el-form-item label-width="0">
21 38 <el-button type="primary" icon="el-icon-search" @click="search()">查询</el-button>
22 39 <el-button icon="el-icon-refresh-right" @click="reset()">重置</el-button>
... ... @@ -139,14 +156,16 @@ export default {
139 156 data() {
140 157 return {
141 158 query: {
142   - month: ''
  159 + month: '',
  160 + departmentId: ''
143 161 },
144 162 list: [],
145 163 originalList: [], // 保存原始数据,用于取消排序时恢复
146 164 listLoading: false,
147 165 summaryData: null,
148 166 sortProp: '',
149   - sortOrder: ''
  167 + sortOrder: '',
  168 + departmentOptions: [] // 部门选项列表
150 169 }
151 170 },
152 171 computed: {
... ... @@ -158,6 +177,7 @@ export default {
158 177 },
159 178 created() {
160 179 this.setDefaultMonth()
  180 + this.loadDepartmentOptions()
161 181 this.search()
162 182 },
163 183 methods: {
... ... @@ -190,6 +210,11 @@ export default {
190 210 Month: parseInt(month)
191 211 }
192 212  
  213 + // 如果选择了部门,添加部门筛选参数
  214 + if (this.query.departmentId) {
  215 + params.DepartmentId = this.query.departmentId
  216 + }
  217 +
193 218 request({
194 219 url: '/api/Extend/lqtechteachersalary/statistics',
195 220 method: 'GET',
... ... @@ -306,6 +331,7 @@ export default {
306 331 // 重置查询条件
307 332 reset() {
308 333 this.setDefaultMonth()
  334 + this.query.departmentId = ''
309 335 this.list = []
310 336 this.originalList = []
311 337 this.summaryData = null
... ... @@ -314,6 +340,21 @@ export default {
314 340 this.search()
315 341 },
316 342  
  343 + // 加载部门选项(科技部)
  344 + loadDepartmentOptions() {
  345 + request({
  346 + url: '/api/Extend/Organize/GetByName',
  347 + method: 'GET',
  348 + data: {
  349 + organizeName: '科技部'
  350 + }
  351 + }).then(res => {
  352 + this.departmentOptions = res.data || []
  353 + }).catch(() => {
  354 + this.departmentOptions = []
  355 + })
  356 + },
  357 +
317 358 // 格式化金额
318 359 formatMoney(amount) {
319 360 if (amount === null || amount === undefined || amount === '') {
... ...
antis-ncc-admin/src/views/statisticsList/form21.vue 0 → 100644
  1 +<template>
  2 + <div class="NCC-common-layout">
  3 + <div class="NCC-common-layout-center">
  4 + <!-- 筛选条件 -->
  5 + <el-row class="NCC-common-search-box" :gutter="16">
  6 + <el-form @submit.native.prevent>
  7 + <el-col :span="6">
  8 + <el-form-item label="会员">
  9 + <el-select
  10 + v-model="query.memberId"
  11 + placeholder="请选择会员"
  12 + filterable
  13 + remote
  14 + :remote-method="remoteMemberMethod"
  15 + :loading="memberLoading"
  16 + clearable
  17 + :style='{"width":"100%"}'>
  18 + <el-option
  19 + v-for="item in memberOptions"
  20 + :key="item.id"
  21 + :label="`${item.khmc || ''}(${item.sjh || ''})`"
  22 + :value="item.id">
  23 + </el-option>
  24 + </el-select>
  25 + </el-form-item>
  26 + </el-col>
  27 + <el-col :span="6">
  28 + <el-form-item label="开始时间">
  29 + <el-date-picker
  30 + v-model="query.startTime"
  31 + type="datetime"
  32 + value-format="yyyy-MM-dd HH:mm:ss"
  33 + format="yyyy-MM-dd HH:mm:ss"
  34 + placeholder="开始时间"
  35 + :style='{"width":"100%"}'
  36 + @change="handleStartTimeChange" />
  37 + </el-form-item>
  38 + </el-col>
  39 + <el-col :span="6">
  40 + <el-form-item label="结束时间">
  41 + <el-date-picker
  42 + v-model="query.endTime"
  43 + type="datetime"
  44 + value-format="yyyy-MM-dd HH:mm:ss"
  45 + format="yyyy-MM-dd HH:mm:ss"
  46 + placeholder="结束时间"
  47 + :style='{"width":"100%"}' />
  48 + </el-form-item>
  49 + </el-col>
  50 + <el-col :span="6">
  51 + <el-form-item label="品项">
  52 + <el-select
  53 + v-model="query.itemId"
  54 + placeholder="请选择品项"
  55 + filterable
  56 + clearable
  57 + :style='{"width":"100%"}'>
  58 + <el-option
  59 + v-for="item in itemOptions"
  60 + :key="item.id"
  61 + :label="item.xmmc"
  62 + :value="item.id">
  63 + </el-option>
  64 + </el-select>
  65 + </el-form-item>
  66 + </el-col>
  67 + <el-col :span="6">
  68 + <el-form-item label="业绩类型">
  69 + <el-select
  70 + v-model="query.performanceType"
  71 + placeholder="请选择业绩类型"
  72 + filterable
  73 + clearable
  74 + :style='{"width":"100%"}'>
  75 + <el-option
  76 + v-for="item in performanceTypeOptions"
  77 + :key="item.value"
  78 + :label="item.label"
  79 + :value="item.value">
  80 + </el-option>
  81 + </el-select>
  82 + </el-form-item>
  83 + </el-col>
  84 + <el-col :span="6">
  85 + <el-form-item label="科美类型">
  86 + <el-select
  87 + v-model="query.beautyType"
  88 + placeholder="请选择科美类型"
  89 + filterable
  90 + clearable
  91 + :style='{"width":"100%"}'>
  92 + <el-option
  93 + v-for="item in beautyTypeOptions"
  94 + :key="item.value"
  95 + :label="item.label"
  96 + :value="item.value">
  97 + </el-option>
  98 + </el-select>
  99 + </el-form-item>
  100 + </el-col>
  101 + <el-col :span="6">
  102 + <el-form-item label="来源类型">
  103 + <el-select
  104 + v-model="query.sourceType"
  105 + placeholder="请选择来源类型"
  106 + clearable
  107 + :style='{"width":"100%"}'>
  108 + <el-option label="购买" value="购买" />
  109 + <el-option label="赠送" value="赠送" />
  110 + <el-option label="体验" value="体验" />
  111 + </el-select>
  112 + </el-form-item>
  113 + </el-col>
  114 + <el-col :span="6">
  115 + <el-form-item label="品项分类">
  116 + <el-select
  117 + v-model="query.itemCategory"
  118 + placeholder="请选择品项分类"
  119 + filterable
  120 + clearable
  121 + :style='{"width":"100%"}'>
  122 + <el-option
  123 + v-for="item in itemCategoryOptions"
  124 + :key="item.value"
  125 + :label="item.label"
  126 + :value="item.value">
  127 + </el-option>
  128 + </el-select>
  129 + </el-form-item>
  130 + </el-col>
  131 + <el-col :span="6">
  132 + <el-form-item label="组织类型">
  133 + <el-select
  134 + v-model="query.organizationType"
  135 + placeholder="请选择组织类型"
  136 + filterable
  137 + clearable
  138 + @change="handleOrganizationTypeChange"
  139 + :style='{"width":"100%"}'>
  140 + <el-option label="事业部" value="事业部"></el-option>
  141 + <el-option label="科技部" value="科技部"></el-option>
  142 + <el-option label="教育部" value="教育部"></el-option>
  143 + <el-option label="大项目部" value="大项目部"></el-option>
  144 + </el-select>
  145 + </el-form-item>
  146 + </el-col>
  147 + <el-col :span="6">
  148 + <el-form-item label="部门">
  149 + <el-select
  150 + v-model="query.departmentId"
  151 + placeholder="请选择部门"
  152 + filterable
  153 + clearable
  154 + @change="handleDepartmentChange"
  155 + :style='{"width":"100%"}'>
  156 + <el-option
  157 + v-for="dept in departmentOptions"
  158 + :key="dept.Id || dept.id"
  159 + :label="dept.FullName || dept.fullName"
  160 + :value="dept.Id || dept.id">
  161 + </el-option>
  162 + </el-select>
  163 + </el-form-item>
  164 + </el-col>
  165 + <el-col :span="12">
  166 + <el-form-item label="门店">
  167 + <el-select
  168 + v-model="query.storeIds"
  169 + placeholder="请选择门店"
  170 + multiple
  171 + filterable
  172 + clearable
  173 + :style='{"width":"100%"}'>
  174 + <el-option
  175 + v-for="store in storeOptions"
  176 + :key="store.id"
  177 + :label="store.dm"
  178 + :value="store.id">
  179 + </el-option>
  180 + </el-select>
  181 + </el-form-item>
  182 + </el-col>
  183 + <el-col :span="6">
  184 + <el-form-item label-width="0">
  185 + <el-button type="primary" icon="el-icon-search" @click="search()">查询</el-button>
  186 + <el-button icon="el-icon-refresh-right" @click="reset()">重置</el-button>
  187 + <el-button icon="el-icon-download" @click="exportExcel()">导出Excel</el-button>
  188 + </el-form-item>
  189 + </el-col>
  190 + </el-form>
  191 + </el-row>
  192 +
  193 + <!-- 数据表格 -->
  194 + <div class="NCC-common-layout-main NCC-flex-main">
  195 + <NCC-table
  196 + v-loading="listLoading"
  197 + :data="list"
  198 + has-c
  199 + @sort-change="handleSortChange">
  200 + <el-table-column prop="storeName" label="门店名称" min-width="120" sortable="custom">
  201 + <template slot-scope="scope">
  202 + <i class="el-icon-shop" style="margin-right: 4px; color: #409EFF;"></i>
  203 + <span>{{ scope.row.storeName || '无' }}</span>
  204 + </template>
  205 + </el-table-column>
  206 + <el-table-column prop="memberName" label="会员名称" min-width="120" sortable="custom">
  207 + <template slot-scope="scope">
  208 + <i class="el-icon-user" style="margin-right: 4px; color: #409EFF;"></i>
  209 + <span>{{ scope.row.memberName || '无' }}</span>
  210 + </template>
  211 + </el-table-column>
  212 + <el-table-column prop="memberPhone" label="会员电话" min-width="130" sortable="custom">
  213 + <template slot-scope="scope">
  214 + <i class="el-icon-phone" style="margin-right: 4px; color: #67C23A;"></i>
  215 + <span>{{ scope.row.memberPhone || '无' }}</span>
  216 + </template>
  217 + </el-table-column>
  218 + <el-table-column prop="refundTime" label="退卡时间" min-width="160" sortable="custom">
  219 + <template slot-scope="scope">
  220 + <i class="el-icon-time" style="margin-right: 4px; color: #909399;"></i>
  221 + <span>{{ formatDateTime(scope.row.refundTime) || '无' }}</span>
  222 + </template>
  223 + </el-table-column>
  224 + <el-table-column prop="itemName" label="退卡品项名称" min-width="150" sortable="custom">
  225 + <template slot-scope="scope">
  226 + <i class="el-icon-goods" style="margin-right: 4px; color: #E6A23C;"></i>
  227 + <span>{{ scope.row.itemName || '无' }}</span>
  228 + </template>
  229 + </el-table-column>
  230 + <el-table-column prop="refundQuantity" label="退卡数量" width="100" sortable="custom">
  231 + <template slot-scope="scope">
  232 + <span>{{ scope.row.refundQuantity || 0 }}</span>
  233 + </template>
  234 + </el-table-column>
  235 + <el-table-column prop="unitPrice" label="单价" min-width="100" sortable="custom">
  236 + <template slot-scope="scope">
  237 + <span class="amount-value">¥{{ formatMoney(scope.row.unitPrice) }}</span>
  238 + </template>
  239 + </el-table-column>
  240 + <el-table-column prop="totalPrice" label="总价" min-width="120" sortable="custom">
  241 + <template slot-scope="scope">
  242 + <span class="amount-value">¥{{ formatMoney(scope.row.totalPrice) }}</span>
  243 + </template>
  244 + </el-table-column>
  245 + <el-table-column prop="performanceType" label="业绩类型" min-width="100">
  246 + <template slot-scope="scope">
  247 + <span>{{ scope.row.performanceType || '无' }}</span>
  248 + </template>
  249 + </el-table-column>
  250 + <el-table-column prop="beautyType" label="科美类型" min-width="100">
  251 + <template slot-scope="scope">
  252 + <span>{{ scope.row.beautyType || '无' }}</span>
  253 + </template>
  254 + </el-table-column>
  255 + <el-table-column prop="sourceType" label="来源类型" min-width="100">
  256 + <template slot-scope="scope">
  257 + <el-tag
  258 + :type="getSourceTypeTagType(scope.row.sourceType)"
  259 + size="small">
  260 + {{ scope.row.sourceType || '无' }}
  261 + </el-tag>
  262 + </template>
  263 + </el-table-column>
  264 + <el-table-column prop="itemCategory" label="品项分类" min-width="100">
  265 + <template slot-scope="scope">
  266 + <el-tag
  267 + :type="getItemCategoryType(scope.row.itemCategory)"
  268 + size="small">
  269 + {{ scope.row.itemCategory || '无' }}
  270 + </el-tag>
  271 + </template>
  272 + </el-table-column>
  273 + </NCC-table>
  274 + <pagination
  275 + v-show="total > 0"
  276 + :total="total"
  277 + :page.sync="listQuery.currentPage"
  278 + :limit.sync="listQuery.pageSize"
  279 + @pagination="handlePagination"
  280 + />
  281 + </div>
  282 + </div>
  283 + </div>
  284 +</template>
  285 +
  286 +<script>
  287 +import request from '@/utils/request'
  288 +import Pagination from '@/components/Pagination'
  289 +import { saveAs } from 'file-saver'
  290 +
  291 +export default {
  292 + name: 'RefundDetailList',
  293 + components: {
  294 + Pagination
  295 + },
  296 + data() {
  297 + return {
  298 + query: {
  299 + organizationType: undefined,
  300 + departmentId: undefined,
  301 + storeIds: [],
  302 + memberId: undefined,
  303 + startTime: undefined,
  304 + endTime: undefined,
  305 + itemId: undefined,
  306 + performanceType: undefined,
  307 + beautyType: undefined,
  308 + sourceType: undefined,
  309 + itemCategory: undefined
  310 + },
  311 + storeOptions: [],
  312 + departmentOptions: [],
  313 + memberOptions: [],
  314 + memberLoading: false,
  315 + itemOptions: [],
  316 + performanceTypeOptions: [],
  317 + beautyTypeOptions: [],
  318 + itemCategoryOptions: [],
  319 + list: [],
  320 + listLoading: false,
  321 + total: 0,
  322 + listQuery: {
  323 + currentPage: 1,
  324 + pageSize: 20
  325 + },
  326 + sortProp: '',
  327 + sortOrder: ''
  328 + }
  329 + },
  330 + created() {
  331 + this.setDefaultTimeRange()
  332 + this.loadAllStores()
  333 + this.initMemberOptions()
  334 + this.initItemOptions()
  335 + this.initPerformanceTypeOptions()
  336 + this.initBeautyTypeOptions()
  337 + this.initItemCategoryOptions()
  338 + this.search()
  339 + },
  340 + watch: {
  341 + // 监听开始时间变化,重新加载门店列表
  342 + 'query.startTime'() {
  343 + this.$nextTick(() => {
  344 + this.initStoreOptions()
  345 + })
  346 + }
  347 + },
  348 + methods: {
  349 + // 设置默认时间范围(本月1号到现在)
  350 + setDefaultTimeRange() {
  351 + const now = new Date()
  352 + const firstDayOfMonth = new Date(now.getFullYear(), now.getMonth(), 1)
  353 +
  354 + this.query.startTime = this.formatDateTime(firstDayOfMonth.getTime())
  355 + this.query.endTime = this.formatDateTime(now.getTime())
  356 +
  357 + // 时间设置后,如果有组织类型和部门,重新加载门店列表
  358 + if (this.query.organizationType && this.query.departmentId) {
  359 + this.$nextTick(() => {
  360 + this.initStoreOptions()
  361 + })
  362 + }
  363 + },
  364 +
  365 + // 格式化日期时间
  366 + formatDateTime(timestamp) {
  367 + if (!timestamp) return ''
  368 + const date = new Date(timestamp)
  369 + const year = date.getFullYear()
  370 + const month = String(date.getMonth() + 1).padStart(2, '0')
  371 + const day = String(date.getDate()).padStart(2, '0')
  372 + const hours = String(date.getHours()).padStart(2, '0')
  373 + const minutes = String(date.getMinutes()).padStart(2, '0')
  374 + const seconds = String(date.getSeconds()).padStart(2, '0')
  375 + return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
  376 + },
  377 +
  378 + // 加载全部门店(当没有选择部门时)
  379 + loadAllStores() {
  380 + request({
  381 + url: '/api/Extend/LqMdxx',
  382 + method: 'GET',
  383 + data: {
  384 + currentPage: 1,
  385 + pageSize: 1000
  386 + }
  387 + }).then(res => {
  388 + if (res.data && res.data.list) {
  389 + this.storeOptions = res.data.list
  390 + }
  391 + }).catch(() => {
  392 + this.storeOptions = []
  393 + })
  394 + },
  395 +
  396 + // 获取部门选项(根据组织类型)
  397 + loadDepartmentOptions() {
  398 + if (!this.query.organizationType) {
  399 + this.departmentOptions = []
  400 + return
  401 + }
  402 +
  403 + request({
  404 + url: '/api/Extend/Organize/GetByName',
  405 + method: 'GET',
  406 + data: {
  407 + organizeName: this.query.organizationType
  408 + }
  409 + }).then(res => {
  410 + this.departmentOptions = res.data || []
  411 + // 如果部门ID不在新列表中,清空部门ID
  412 + if (this.query.departmentId) {
  413 + const exists = this.departmentOptions.some(
  414 + dept => (dept.Id || dept.id) === this.query.departmentId
  415 + )
  416 + if (!exists) {
  417 + this.query.departmentId = undefined
  418 + this.query.storeIds = []
  419 + this.storeOptions = []
  420 + }
  421 + }
  422 + }).catch(() => {
  423 + this.departmentOptions = []
  424 + })
  425 + },
  426 +
  427 + // 初始化门店选项(根据组织类型、部门、年月)
  428 + initStoreOptions() {
  429 + // 如果没有选择部门,加载全部门店
  430 + if (!this.query.departmentId) {
  431 + this.loadAllStores()
  432 + return
  433 + }
  434 +
  435 + // 如果缺少必要参数,不加载门店列表
  436 + if (!this.query.organizationType || !this.query.startTime) {
  437 + this.storeOptions = []
  438 + return
  439 + }
  440 +
  441 + // 从开始时间提取年月(格式:YYYYMM)
  442 + // startTime 格式为 yyyy-MM-dd HH:mm:ss
  443 + const dateStr = this.query.startTime
  444 + if (!dateStr) {
  445 + this.storeOptions = []
  446 + return
  447 + }
  448 +
  449 + // 提取年月,格式:YYYYMM
  450 + const monthStr = dateStr.substring(0, 4) + dateStr.substring(5, 7)
  451 +
  452 + request({
  453 + url: '/api/Extend/lqmdtarget/GetManagedStores',
  454 + method: 'POST',
  455 + data: {
  456 + month: monthStr,
  457 + organizationType: this.query.organizationType,
  458 + departmentId: this.query.departmentId
  459 + }
  460 + }).then(res => {
  461 + if (res.data && Array.isArray(res.data)) {
  462 + // 将返回的数据格式转换为 storeOptions 需要的格式
  463 + // 返回格式: [{ StoreId: "...", StoreName: "..." }]
  464 + // 需要格式: [{ id: "...", dm: "..." }]
  465 + this.storeOptions = res.data.map(store => ({
  466 + id: store.StoreId,
  467 + dm: store.StoreName
  468 + }))
  469 + // 默认选中所有获取到的门店
  470 + this.query.storeIds = this.storeOptions.map(store => store.id)
  471 + } else {
  472 + this.storeOptions = []
  473 + this.query.storeIds = []
  474 + }
  475 + }).catch(err => {
  476 + console.error('获取门店列表失败:', err)
  477 + this.$message({
  478 + type: 'error',
  479 + message: '获取门店列表失败',
  480 + duration: 1500
  481 + })
  482 + this.storeOptions = []
  483 + this.query.storeIds = []
  484 + })
  485 + },
  486 +
  487 + // 处理开始时间变化
  488 + handleStartTimeChange() {
  489 + this.$nextTick(() => {
  490 + this.initStoreOptions()
  491 + })
  492 + },
  493 +
  494 + // 处理组织类型变化
  495 + handleOrganizationTypeChange() {
  496 + // 清空部门和门店
  497 + this.query.departmentId = undefined
  498 + this.query.storeIds = []
  499 + // 重新加载部门选项
  500 + this.loadDepartmentOptions()
  501 + // 加载全部门店(因为部门已清空)
  502 + this.loadAllStores()
  503 + },
  504 +
  505 + // 处理部门变化
  506 + handleDepartmentChange() {
  507 + // 清空门店选择
  508 + this.query.storeIds = []
  509 + // 重新加载门店列表(如果有部门则加载部门管理的门店,否则加载全部门店)
  510 + this.initStoreOptions()
  511 + },
  512 +
  513 + // 初始化会员选项(加载前10个)
  514 + initMemberOptions() {
  515 + request({
  516 + url: '/api/Extend/LqKhxx',
  517 + method: 'GET',
  518 + data: {
  519 + currentPage: 1,
  520 + pageSize: 10
  521 + }
  522 + }).then(res => {
  523 + if (res.code == 200 && res.data && res.data.list) {
  524 + this.memberOptions = res.data.list
  525 + } else {
  526 + this.memberOptions = []
  527 + }
  528 + }).catch(() => {
  529 + this.memberOptions = []
  530 + })
  531 + },
  532 +
  533 + // 远程搜索会员
  534 + remoteMemberMethod(query) {
  535 + if (query !== '') {
  536 + this.memberLoading = true
  537 + request({
  538 + url: '/api/Extend/LqKhxx',
  539 + method: 'GET',
  540 + data: {
  541 + currentPage: 1,
  542 + pageSize: 20,
  543 + keyword: query
  544 + }
  545 + }).then(res => {
  546 + this.memberLoading = false
  547 + if (res.code == 200 && res.data && res.data.list) {
  548 + this.memberOptions = res.data.list
  549 + } else {
  550 + this.memberOptions = []
  551 + }
  552 + }).catch(() => {
  553 + this.memberLoading = false
  554 + this.memberOptions = []
  555 + })
  556 + } else {
  557 + this.memberOptions = []
  558 + this.initMemberOptions()
  559 + }
  560 + },
  561 +
  562 + // 初始化品项选项
  563 + initItemOptions() {
  564 + request({
  565 + url: '/api/Extend/LqXmzl',
  566 + method: 'GET',
  567 + data: {
  568 + currentPage: 1,
  569 + pageSize: 1000
  570 + }
  571 + }).then(res => {
  572 + if (res.data && res.data.list) {
  573 + this.itemOptions = res.data.list
  574 + }
  575 + }).catch(() => {
  576 + this.itemOptions = []
  577 + })
  578 + },
  579 +
  580 + // 初始化业绩类型选项(从品项表的fl3字段获取)
  581 + initPerformanceTypeOptions() {
  582 + request({
  583 + url: '/api/Extend/lqxmzl/GetDistinctFieldData',
  584 + method: 'GET',
  585 + data: {
  586 + fieldName: 'fl3'
  587 + }
  588 + }).then(res => {
  589 + if (res.code == 200 && res.data && res.data.values) {
  590 + this.performanceTypeOptions = res.data.values.map(item => ({
  591 + label: item,
  592 + value: item
  593 + }))
  594 + } else {
  595 + this.performanceTypeOptions = []
  596 + }
  597 + }).catch(() => {
  598 + this.performanceTypeOptions = []
  599 + })
  600 + },
  601 +
  602 + // 初始化科美类型选项(从品项表的beautyType字段获取)
  603 + initBeautyTypeOptions() {
  604 + request({
  605 + url: '/api/Extend/lqxmzl/GetDistinctFieldData',
  606 + method: 'GET',
  607 + data: {
  608 + fieldName: 'beautyType'
  609 + }
  610 + }).then(res => {
  611 + if (res.code == 200 && res.data && res.data.values) {
  612 + this.beautyTypeOptions = res.data.values.map(item => ({
  613 + label: item,
  614 + value: item
  615 + }))
  616 + } else {
  617 + this.beautyTypeOptions = []
  618 + }
  619 + }).catch(() => {
  620 + this.beautyTypeOptions = []
  621 + })
  622 + },
  623 +
  624 + // 初始化品项分类选项(从品项表的qt2字段获取)
  625 + initItemCategoryOptions() {
  626 + request({
  627 + url: '/api/Extend/lqxmzl/GetDistinctFieldData',
  628 + method: 'GET',
  629 + data: {
  630 + fieldName: 'qt2'
  631 + }
  632 + }).then(res => {
  633 + if (res.code == 200 && res.data && res.data.values) {
  634 + this.itemCategoryOptions = res.data.values.map(item => ({
  635 + label: item,
  636 + value: item
  637 + }))
  638 + } else {
  639 + this.itemCategoryOptions = []
  640 + }
  641 + }).catch(() => {
  642 + this.itemCategoryOptions = []
  643 + })
  644 + },
  645 +
  646 + // 查询数据
  647 + search() {
  648 + this.listLoading = true
  649 +
  650 + const params = {
  651 + currentPage: this.listQuery.currentPage,
  652 + pageSize: this.listQuery.pageSize
  653 + }
  654 +
  655 + if (this.query.storeIds && this.query.storeIds.length > 0) {
  656 + params.storeIds = this.query.storeIds
  657 + }
  658 +
  659 + if (this.query.memberId) {
  660 + params.memberId = this.query.memberId
  661 + }
  662 +
  663 + if (this.query.startTime) {
  664 + params.startTime = this.query.startTime
  665 + }
  666 +
  667 + if (this.query.endTime) {
  668 + params.endTime = this.query.endTime
  669 + }
  670 +
  671 + if (this.query.itemId) {
  672 + params.itemId = this.query.itemId
  673 + }
  674 +
  675 + if (this.query.performanceType) {
  676 + params.performanceType = this.query.performanceType
  677 + }
  678 +
  679 + if (this.query.beautyType) {
  680 + params.beautyType = this.query.beautyType
  681 + }
  682 +
  683 + if (this.query.sourceType) {
  684 + params.sourceType = this.query.sourceType
  685 + }
  686 +
  687 + if (this.query.itemCategory) {
  688 + params.itemCategory = this.query.itemCategory
  689 + }
  690 +
  691 + // 排序参数
  692 + if (this.sortProp) {
  693 + params.sidx = this.sortProp
  694 + params.sort = this.sortOrder === 'ascending' ? 'asc' : 'desc'
  695 + }
  696 +
  697 + request({
  698 + url: '/api/Extend/LqHytkHytk/refund-detail-list',
  699 + method: 'POST',
  700 + data: params
  701 + }).then(res => {
  702 + if (res.data && res.data.list) {
  703 + this.list = res.data.list
  704 + this.total = (res.data.pagination && res.data.pagination.total) || res.data.list.length || 0
  705 + } else {
  706 + this.list = []
  707 + this.total = 0
  708 + }
  709 + this.listLoading = false
  710 + }).catch(err => {
  711 + console.error('查询失败:', err)
  712 + this.$message({
  713 + type: 'error',
  714 + message: '查询失败,请重试',
  715 + duration: 1500
  716 + })
  717 + this.listLoading = false
  718 + this.list = []
  719 + this.total = 0
  720 + })
  721 + },
  722 +
  723 + // 处理排序变化
  724 + handleSortChange({ column, prop, order }) {
  725 + this.sortProp = prop || ''
  726 + this.sortOrder = order || ''
  727 + this.listQuery.currentPage = 1
  728 + this.search()
  729 + },
  730 +
  731 + // 处理分页变化
  732 + handlePagination({ page, limit }) {
  733 + this.listQuery.currentPage = page
  734 + this.listQuery.pageSize = limit
  735 + this.search()
  736 + },
  737 +
  738 + // 重置查询条件
  739 + reset() {
  740 + this.query = {
  741 + organizationType: undefined,
  742 + departmentId: undefined,
  743 + storeIds: [],
  744 + memberId: undefined,
  745 + startTime: undefined,
  746 + endTime: undefined,
  747 + itemId: undefined,
  748 + performanceType: undefined,
  749 + beautyType: undefined,
  750 + sourceType: undefined,
  751 + itemCategory: undefined
  752 + }
  753 + this.setDefaultTimeRange()
  754 + this.departmentOptions = []
  755 + // 重置后加载全部门店
  756 + this.loadAllStores()
  757 + this.sortProp = ''
  758 + this.sortOrder = ''
  759 + this.listQuery.currentPage = 1
  760 + this.listQuery.pageSize = 20
  761 + this.list = []
  762 + this.total = 0
  763 + this.search()
  764 + },
  765 +
  766 + // 格式化金额
  767 + formatMoney(amount) {
  768 + if (amount === null || amount === undefined || amount === '') {
  769 + return '0.00'
  770 + }
  771 + const num = parseFloat(amount)
  772 + if (isNaN(num)) {
  773 + return '0.00'
  774 + }
  775 + return num.toFixed(2)
  776 + },
  777 +
  778 + // 获取来源类型标签类型
  779 + getSourceTypeTagType(sourceType) {
  780 + if (!sourceType) {
  781 + return 'info'
  782 + }
  783 + if (sourceType === '购买') {
  784 + return 'success'
  785 + } else if (sourceType === '赠送') {
  786 + return 'warning'
  787 + } else if (sourceType === '体验') {
  788 + return 'info'
  789 + }
  790 + return 'info'
  791 + },
  792 +
  793 + // 获取品项分类标签类型
  794 + getItemCategoryType(category) {
  795 + if (!category) {
  796 + return 'info'
  797 + }
  798 + const categoryMap = {
  799 + '科美': 'success',
  800 + '医美': 'warning',
  801 + '生美': 'info',
  802 + '产品': 'danger'
  803 + }
  804 + return categoryMap[category] || 'info'
  805 + },
  806 +
  807 + // 导出Excel
  808 + async exportExcel() {
  809 + if (!this.list || this.list.length === 0) {
  810 + this.$message({
  811 + type: 'warning',
  812 + message: '暂无数据可导出',
  813 + duration: 1500
  814 + })
  815 + return
  816 + }
  817 +
  818 + try {
  819 + // 动态导入 xlsx 库
  820 + const XLSX = await import('xlsx')
  821 +
  822 + // 构建表头
  823 + const headers = [
  824 + '门店名称',
  825 + '会员名称',
  826 + '会员电话',
  827 + '退卡时间',
  828 + '退卡品项名称',
  829 + '退卡数量',
  830 + '单价',
  831 + '总价',
  832 + '业绩类型',
  833 + '科美类型',
  834 + '来源类型',
  835 + '品项分类'
  836 + ]
  837 +
  838 + // 构建数据行
  839 + const dataRows = this.list.map(row => [
  840 + row.storeName || '无',
  841 + row.memberName || '无',
  842 + row.memberPhone || '无',
  843 + this.formatDateTime(row.refundTime) || '无',
  844 + row.itemName || '无',
  845 + row.refundQuantity || 0,
  846 + this.formatMoney(row.unitPrice),
  847 + this.formatMoney(row.totalPrice),
  848 + row.performanceType || '无',
  849 + row.beautyType || '无',
  850 + row.sourceType || '无',
  851 + row.itemCategory || '无'
  852 + ])
  853 +
  854 + // 合并表头和数据
  855 + const excelData = [headers, ...dataRows]
  856 +
  857 + // 创建工作簿
  858 + const ws = XLSX.utils.aoa_to_sheet(excelData)
  859 +
  860 + // 设置列宽
  861 + ws['!cols'] = [
  862 + { wch: 15 }, // 门店名称
  863 + { wch: 12 }, // 会员名称
  864 + { wch: 13 }, // 会员电话
  865 + { wch: 18 }, // 退卡时间
  866 + { wch: 20 }, // 退卡品项名称
  867 + { wch: 10 }, // 退卡数量
  868 + { wch: 12 }, // 单价
  869 + { wch: 12 }, // 总价
  870 + { wch: 12 }, // 业绩类型
  871 + { wch: 12 }, // 科美类型
  872 + { wch: 12 }, // 来源类型
  873 + { wch: 12 } // 品项分类
  874 + ]
  875 +
  876 + // 创建工作簿
  877 + const wb = XLSX.utils.book_new()
  878 + XLSX.utils.book_append_sheet(wb, ws, '退卡品项明细表')
  879 +
  880 + // 生成文件名
  881 + const now = new Date()
  882 + const fileName = `退卡品项明细表_${now.getFullYear()}${String(now.getMonth() + 1).padStart(2, '0')}${String(now.getDate()).padStart(2, '0')}_${now.getTime()}.xlsx`
  883 +
  884 + // 导出文件
  885 + const wbout = XLSX.write(wb, { bookType: 'xlsx', type: 'array' })
  886 + saveAs(new Blob([wbout], { type: 'application/octet-stream' }), fileName)
  887 +
  888 + this.$message({
  889 + type: 'success',
  890 + message: '导出成功',
  891 + duration: 1500
  892 + })
  893 + } catch (error) {
  894 + console.error('导出失败:', error)
  895 + if (error.message && error.message.includes('xlsx')) {
  896 + this.$message({
  897 + type: 'error',
  898 + message: '导出失败:请先安装 xlsx 库,运行命令: npm install xlsx --save',
  899 + duration: 3000
  900 + })
  901 + } else {
  902 + this.$message({
  903 + type: 'error',
  904 + message: '导出失败:' + (error.message || '未知错误'),
  905 + duration: 2000
  906 + })
  907 + }
  908 + }
  909 + }
  910 + }
  911 +}
  912 +</script>
  913 +
  914 +<style lang="scss" scoped>
  915 +.amount-value {
  916 + color: #409EFF;
  917 + font-weight: 500;
  918 +}
  919 +</style>
  920 +
... ...
antis-ncc-admin/src/views/statisticsList/form7.vue
... ... @@ -5,20 +5,6 @@
5 5 <el-row class="NCC-common-search-box" :gutter="16">
6 6 <el-form @submit.native.prevent>
7 7 <el-col :span="6">
8   - <el-form-item label="门店">
9   - <el-select v-model="query.storeId" placeholder="请选择门店" clearable filterable>
10   - <el-option v-for="store in storeOptions" :key="store.id" :label="store.dm" :value="store.id" />
11   - </el-select>
12   - </el-form-item>
13   - </el-col>
14   - <el-col :span="6">
15   - <el-form-item label="部门">
16   - <el-select v-model="query.departmentId" placeholder="请选择部门" clearable filterable>
17   - <el-option v-for="dept in departmentOptions" :key="dept.id" :label="dept.fullName" :value="dept.id" />
18   - </el-select>
19   - </el-form-item>
20   - </el-col>
21   - <el-col :span="6">
22 8 <el-form-item label="开始时间">
23 9 <el-date-picker
24 10 v-model="query.startTime"
... ... @@ -41,6 +27,58 @@
41 27 </el-form-item>
42 28 </el-col>
43 29 <el-col :span="6">
  30 + <el-form-item label="组织类型">
  31 + <el-select
  32 + v-model="query.organizationType"
  33 + placeholder="请选择组织类型"
  34 + filterable
  35 + clearable
  36 + @change="handleOrganizationTypeChange"
  37 + :style='{"width":"100%"}'>
  38 + <el-option label="事业部" value="事业部"></el-option>
  39 + <el-option label="科技部" value="科技部"></el-option>
  40 + <el-option label="教育部" value="教育部"></el-option>
  41 + <el-option label="大项目部" value="大项目部"></el-option>
  42 + </el-select>
  43 + </el-form-item>
  44 + </el-col>
  45 + <el-col :span="6">
  46 + <el-form-item label="部门">
  47 + <el-select
  48 + v-model="query.departmentId"
  49 + placeholder="请选择部门"
  50 + filterable
  51 + clearable
  52 + @change="handleDepartmentChange"
  53 + :style='{"width":"100%"}'>
  54 + <el-option
  55 + v-for="dept in departmentOptions"
  56 + :key="dept.Id || dept.id"
  57 + :label="dept.FullName || dept.fullName"
  58 + :value="dept.Id || dept.id">
  59 + </el-option>
  60 + </el-select>
  61 + </el-form-item>
  62 + </el-col>
  63 + <el-col :span="12">
  64 + <el-form-item label="门店">
  65 + <el-select
  66 + v-model="query.storeIds"
  67 + placeholder="请选择门店"
  68 + multiple
  69 + filterable
  70 + clearable
  71 + :style='{"width":"100%"}'>
  72 + <el-option
  73 + v-for="store in storeOptions"
  74 + :key="store.id"
  75 + :label="store.dm"
  76 + :value="store.id">
  77 + </el-option>
  78 + </el-select>
  79 + </el-form-item>
  80 + </el-col>
  81 + <el-col :span="6">
44 82 <el-form-item>
45 83 <el-button type="primary" icon="el-icon-search" @click="search()">查询</el-button>
46 84 <el-button icon="el-icon-refresh-right" @click="reset()">重置</el-button>
... ... @@ -151,7 +189,7 @@
151 189 </div>
152 190 <div class="card-content">
153 191 <div class="card-title">总人头数</div>
154   - <div class="card-value">{{ summaryData.totalHeadCount || 0 }}</div>
  192 + <div class="card-value">{{ formatNumber(summaryData.totalHeadCount) }}</div>
155 193 </div>
156 194 </div>
157 195 </el-col>
... ... @@ -162,7 +200,7 @@
162 200 </div>
163 201 <div class="card-content">
164 202 <div class="card-title">总人次</div>
165   - <div class="card-value">{{ summaryData.totalPersonCount || 0 }}</div>
  203 + <div class="card-value">{{ formatNumber(summaryData.totalPersonCount) }}</div>
166 204 </div>
167 205 </div>
168 206 </el-col>
... ... @@ -312,8 +350,9 @@ export default {
312 350 data() {
313 351 return {
314 352 query: {
315   - storeId: undefined,
  353 + organizationType: undefined,
316 354 departmentId: undefined,
  355 + storeIds: [],
317 356 startTime: undefined,
318 357 endTime: undefined,
319 358 currentPage: 1,
... ... @@ -334,17 +373,25 @@ export default {
334 373 } else{
335 374 this.restoreQueryParams()
336 375 }
337   - this.initStoreOptions()
338   - this.initDepartmentOptions()
  376 + this.loadAllStores()
339 377 this.search()
340 378 },
  379 + watch: {
  380 + // 监听开始时间变化,重新加载门店列表
  381 + 'query.startTime'() {
  382 + this.$nextTick(() => {
  383 + this.initStoreOptions()
  384 + })
  385 + }
  386 + },
341 387 methods: {
342 388 // 保存筛选条件到 sessionStorage
343 389 saveQueryParams() {
344 390 try {
345 391 const paramsToSave = {
346   - storeId: this.query.storeId,
  392 + organizationType: this.query.organizationType,
347 393 departmentId: this.query.departmentId,
  394 + storeIds: this.query.storeIds,
348 395 startTime: this.query.startTime,
349 396 endTime: this.query.endTime,
350 397 currentPage: this.query.currentPage,
... ... @@ -364,8 +411,9 @@ export default {
364 411 if (savedParams) {
365 412 const params = JSON.parse(savedParams)
366 413 // 恢复筛选条件
367   - this.query.storeId = params.storeId || undefined
  414 + this.query.organizationType = params.organizationType || undefined
368 415 this.query.departmentId = params.departmentId || undefined
  416 + this.query.storeIds = params.storeIds || []
369 417 this.query.startTime = params.startTime || undefined
370 418 this.query.endTime = params.endTime || undefined
371 419 this.query.currentPage = params.currentPage || 1
... ... @@ -375,6 +423,19 @@ export default {
375 423 if (!this.query.startTime || !this.query.endTime) {
376 424 this.setDefaultTimeRange()
377 425 }
  426 +
  427 + // 恢复部门选项和门店列表
  428 + if (this.query.organizationType) {
  429 + this.loadDepartmentOptions()
  430 + }
  431 + if (this.query.departmentId && this.query.organizationType && this.query.startTime) {
  432 + this.$nextTick(() => {
  433 + this.initStoreOptions()
  434 + })
  435 + } else {
  436 + this.loadAllStores()
  437 + }
  438 +
378 439 sessionStorage.setItem('isshaixuan', false)
379 440 } else {
380 441 // 没有保存的条件,设置默认时间范围
... ... @@ -394,10 +455,17 @@ export default {
394 455  
395 456 this.query.startTime = this.formatDateTime(firstDayOfMonth.getTime())
396 457 this.query.endTime = this.formatDateTime(now.getTime())
  458 +
  459 + // 时间设置后,如果有组织类型和部门,重新加载门店列表
  460 + if (this.query.organizationType && this.query.departmentId) {
  461 + this.$nextTick(() => {
  462 + this.initStoreOptions()
  463 + })
  464 + }
397 465 },
398 466  
399   - // 初始化门店选项
400   - initStoreOptions() {
  467 + // 加载全部门店(当没有选择部门时)
  468 + loadAllStores() {
401 469 request({
402 470 url: '/api/Extend/LqMdxx',
403 471 method: 'GET',
... ... @@ -409,25 +477,120 @@ export default {
409 477 this.storeOptions = res.data.list || []
410 478 }).catch(err => {
411 479 console.error('获取门店列表失败:', err)
  480 + this.storeOptions = []
412 481 })
413 482 },
414 483  
415   - // 初始化部门选项
416   - initDepartmentOptions() {
  484 + // 获取部门选项(根据组织类型)
  485 + loadDepartmentOptions() {
  486 + if (!this.query.organizationType) {
  487 + this.departmentOptions = []
  488 + return
  489 + }
  490 +
417 491 request({
418   - url: '/api/permission/Organize/96240625-934F-490B-8AA6-0BC775B18468/Department',
419   - method: 'GET'
  492 + url: '/api/Extend/Organize/GetByName',
  493 + method: 'GET',
  494 + data: {
  495 + organizeName: this.query.organizationType
  496 + }
  497 + }).then(res => {
  498 + this.departmentOptions = res.data || []
  499 + // 如果部门ID不在新列表中,清空部门ID
  500 + if (this.query.departmentId) {
  501 + const exists = this.departmentOptions.some(
  502 + dept => (dept.Id || dept.id) === this.query.departmentId
  503 + )
  504 + if (!exists) {
  505 + this.query.departmentId = undefined
  506 + this.query.storeIds = []
  507 + this.storeOptions = []
  508 + }
  509 + }
  510 + }).catch(() => {
  511 + this.departmentOptions = []
  512 + })
  513 + },
  514 +
  515 + // 初始化门店选项(根据组织类型、部门、年月)
  516 + initStoreOptions() {
  517 + // 如果没有选择部门,加载全部门店
  518 + if (!this.query.departmentId) {
  519 + this.loadAllStores()
  520 + return
  521 + }
  522 +
  523 + // 如果缺少必要参数,不加载门店列表
  524 + if (!this.query.organizationType || !this.query.startTime) {
  525 + this.storeOptions = []
  526 + return
  527 + }
  528 +
  529 + // 从开始时间提取年月(格式:YYYYMM)
  530 + // startTime 格式为 yyyy-MM-dd HH:mm:ss
  531 + const dateStr = this.query.startTime
  532 + if (!dateStr) {
  533 + this.storeOptions = []
  534 + return
  535 + }
  536 +
  537 + // 提取年月,格式:YYYYMM
  538 + const monthStr = dateStr.substring(0, 4) + dateStr.substring(5, 7)
  539 +
  540 + request({
  541 + url: '/api/Extend/lqmdtarget/GetManagedStores',
  542 + method: 'POST',
  543 + data: {
  544 + month: monthStr,
  545 + organizationType: this.query.organizationType,
  546 + departmentId: this.query.departmentId
  547 + }
420 548 }).then(res => {
421   - // 将树形结构扁平化
422   - this.departmentOptions = res.data.list.map(item => ({
423   - id: item.id,
424   - fullName: item.fullName
425   - }))
  549 + if (res.data && Array.isArray(res.data)) {
  550 + // 将返回的数据格式转换为 storeOptions 需要的格式
  551 + // 返回格式: [{ StoreId: "...", StoreName: "..." }]
  552 + // 需要格式: [{ id: "...", dm: "..." }]
  553 + this.storeOptions = res.data.map(store => ({
  554 + id: store.StoreId,
  555 + dm: store.StoreName
  556 + }))
  557 + // 默认选中所有获取到的门店
  558 + this.query.storeIds = this.storeOptions.map(store => store.id)
  559 + } else {
  560 + this.storeOptions = []
  561 + this.query.storeIds = []
  562 + }
426 563 }).catch(err => {
427   - console.error('获取部门列表失败:', err)
  564 + console.error('获取门店列表失败:', err)
  565 + this.$message({
  566 + type: 'error',
  567 + message: '获取门店列表失败',
  568 + duration: 1500
  569 + })
  570 + this.storeOptions = []
  571 + this.query.storeIds = []
428 572 })
429 573 },
430 574  
  575 + // 处理组织类型变化
  576 + handleOrganizationTypeChange() {
  577 + // 清空部门和门店
  578 + this.query.departmentId = undefined
  579 + this.query.storeIds = []
  580 + // 重新加载部门选项
  581 + this.loadDepartmentOptions()
  582 + // 加载全部门店(因为部门已清空)
  583 + this.loadAllStores()
  584 + },
  585 +
  586 + // 处理部门变化
  587 + handleDepartmentChange() {
  588 + // 清空门店选择
  589 + this.query.storeIds = []
  590 + // 重新加载门店列表(如果有部门则加载部门管理的门店,否则加载全部门店)
  591 + this.initStoreOptions()
  592 + },
  593 +
431 594  
432 595  
433 596 // 查询数据
... ... @@ -441,8 +604,8 @@ export default {
441 604 pageSize: this.query.pageSize
442 605 }
443 606  
444   - if (this.query.storeId) {
445   - params.StoreId = this.query.storeId
  607 + if (this.query.storeIds && this.query.storeIds.length > 0) {
  608 + params.StoreIds = this.query.storeIds
446 609 }
447 610  
448 611 if (this.query.departmentId) {
... ... @@ -530,14 +693,18 @@ export default {
530 693 // 重置查询条件
531 694 reset() {
532 695 this.query = {
533   - storeId: undefined,
  696 + organizationType: undefined,
534 697 departmentId: undefined,
  698 + storeIds: [],
535 699 startTime: undefined,
536 700 endTime: undefined,
537 701 currentPage: 1,
538 702 pageSize: 20
539 703 }
540 704 this.setDefaultTimeRange()
  705 + this.departmentOptions = []
  706 + // 重置后加载全部门店
  707 + this.loadAllStores()
541 708 // 清除保存的筛选条件
542 709 try {
543 710 sessionStorage.removeItem('form7_query_params')
... ... @@ -556,6 +723,14 @@ export default {
556 723 return Number(amount).toFixed(2)
557 724 },
558 725  
  726 + // 格式化数字,保留两位小数
  727 + formatNumber(num) {
  728 + if (num === null || num === undefined || num === '') return '0.00'
  729 + const value = Number(num)
  730 + if (isNaN(value)) return '0.00'
  731 + return value.toFixed(2)
  732 + },
  733 +
559 734 // 格式化百分比
560 735 formatPercentage(ratio) {
561 736 if (ratio === null || ratio === undefined) return '0.00%'
... ...
绿纤uni-app/apis/modules/store.js 0 → 100644
  1 +import request from '@/service/request.js'
  2 +import config from '@/common/config.js'
  3 +
  4 +export default {
  5 + // 获取门店列表
  6 + getStoreList(params) {
  7 + return request.get(`${config.getApiBaseUrl()}/api/Extend/LqMdxx`, params);
  8 + },
  9 +
  10 + // 获取门店详情
  11 + getStoreDetail(id) {
  12 + return request.get(`${config.getApiBaseUrl()}/api/Extend/LqMdxx/${id}`);
  13 + },
  14 +
  15 + // 更新门店信息
  16 + updateStore(id, data) {
  17 + return request.put(`${config.getApiBaseUrl()}/api/Extend/LqMdxx/${id}`, data);
  18 + }
  19 +}
  20 +
... ...
绿纤uni-app/common/config.js
... ... @@ -10,8 +10,8 @@ const ENV_CONFIG = {
10 10 // 正式环境
11 11 production: {
12 12 name: '正式环境',
13   - // apiBaseUrl: 'http://erp_test.lvqianmeiye.com',
14   - apiBaseUrl: 'https://erp.lvqianmeiye.com',
  13 + apiBaseUrl: 'http://erp_test.lvqianmeiye.com',
  14 + // apiBaseUrl: 'https://erp.lvqianmeiye.com',
15 15 description: '生产环境服务器'
16 16 }
17 17 };
... ...
绿纤uni-app/pages.json
... ... @@ -314,6 +314,13 @@
314 314 {
315 315 "navigationBarTitleText" : "报销审核详情"
316 316 }
  317 + },
  318 + {
  319 + "path" : "pages/store-list/store-list",
  320 + "style" :
  321 + {
  322 + "navigationBarTitleText" : "门店管理"
  323 + }
317 324 }
318 325 ],
319 326 "globalStyle": {
... ...
绿纤uni-app/pages/index/index.vue
... ... @@ -152,6 +152,12 @@
152 152 </view>
153 153 <view class="icon-label">毛巾记录</view>
154 154 </view>
  155 + <view class="icon-btn" @click="goToPage('/pages/store-list/store-list')">
  156 + <view class="icon">
  157 + <u-icon name="star" size="32" color="#43a047"></u-icon>
  158 + </view>
  159 + <view class="icon-label">门店管理</view>
  160 + </view>
155 161 <view class="icon-btn" @click="goToPage('/pages/web/web')">
156 162 <view class="icon">
157 163 <u-icon name="kefu-ermai" size="32" color="#43a047"></u-icon>
... ...
绿纤uni-app/pages/store-list/store-list.vue 0 → 100644
  1 +<template>
  2 + <view class="store-list-container">
  3 + <!-- 搜索卡片 -->
  4 + <view class="search-card">
  5 + <u-search
  6 + v-model="searchKeyword"
  7 + placeholder="搜索门店名称"
  8 + @search="onSearchInput"
  9 + @clear="onSearchInput"
  10 + @custom="onSearchInput"
  11 + class="search-input">
  12 + </u-search>
  13 + </view>
  14 +
  15 + <!-- 门店列表 -->
  16 + <view class="store-list" v-if="storeList.length > 0">
  17 + <view
  18 + v-for="(store, index) in storeList"
  19 + :key="store.id"
  20 + class="store-card"
  21 + >
  22 + <view class="store-header">
  23 + <view class="store-name">{{ store.dm || '无' }}</view>
  24 + <view class="store-status" :class="store.zxzt === '开店' ? 'status-open' : store.zxzt === '闭店' ? 'status-closed' : ''">
  25 + {{ store.zxzt || '无' }}
  26 + </view>
  27 + </view>
  28 + <view class="store-row">
  29 + <view class="store-item">
  30 + <text class="store-label">单据门店</text>
  31 + <text class="store-value">{{ store.djmd || '无' }}</text>
  32 + </view>
  33 + <view class="store-item">
  34 + <text class="store-label">城市</text>
  35 + <text class="store-value">{{ store.cs || '无' }}</text>
  36 + </view>
  37 + </view>
  38 + <view class="store-row">
  39 + <view class="store-item">
  40 + <text class="store-label">联系人</text>
  41 + <text class="store-value">{{ store.xm || '无' }}</text>
  42 + </view>
  43 + <view class="store-item">
  44 + <text class="store-label">联系电话</text>
  45 + <text class="store-value">{{ store.dhhm || '无' }}</text>
  46 + </view>
  47 + </view>
  48 + <view class="store-row">
  49 + <view class="store-item">
  50 + <text class="store-label">座机</text>
  51 + <text class="store-value">{{ store.zj || '无' }}</text>
  52 + </view>
  53 + <view class="store-item">
  54 + <text class="store-label">在职人数</text>
  55 + <text class="store-value">{{ store.zzrs || 0 }}人</text>
  56 + </view>
  57 + </view>
  58 + <view class="store-row" v-if="store.kysj">
  59 + <view class="store-item full-width">
  60 + <text class="store-label">开业时间</text>
  61 + <text class="store-value">{{ formatDate(store.kysj) }}</text>
  62 + </view>
  63 + </view>
  64 + <view class="store-row" v-if="store.dz">
  65 + <view class="store-item full-width">
  66 + <text class="store-label">地址</text>
  67 + <text class="store-value">{{ store.dz || '无' }}</text>
  68 + </view>
  69 + </view>
  70 + <view class="store-actions">
  71 + <button class="edit-btn" @click.stop="openEditDialog(store)">修改在职人数</button>
  72 + </view>
  73 + </view>
  74 + </view>
  75 +
  76 + <!-- 加载状态 -->
  77 + <view v-if="isLoading" class="loading">
  78 + <u-loading-icon mode="circle" color="#43a047"></u-loading-icon>
  79 + <text class="loading-text">正在加载门店数据...</text>
  80 + </view>
  81 +
  82 + <!-- 加载更多 -->
  83 + <view v-if="isLoadingMore" class="loading-more">
  84 + <u-loading-icon mode="circle" color="#43a047" size="16"></u-loading-icon>
  85 + <text class="loading-more-text">正在加载更多...</text>
  86 + </view>
  87 +
  88 + <!-- 无更多数据 -->
  89 + <view v-if="!hasMoreData && storeList.length > 0" class="no-more-data">
  90 + 已加载全部数据
  91 + </view>
  92 +
  93 + <!-- 空状态 -->
  94 + <view v-if="!isLoading && storeList.length === 0" class="empty-state">
  95 + <view class="empty-state-icon">🏪</view>
  96 + <view class="empty-state-text">暂无门店数据</view>
  97 + <view class="empty-state-subtext">请稍后再试或联系管理员</view>
  98 + </view>
  99 +
  100 + <!-- 搜索空状态 -->
  101 + <view v-if="!isLoading && storeList.length === 0 && isSearching" class="empty-state">
  102 + <view class="empty-state-icon">🔍</view>
  103 + <view class="empty-state-text">未找到匹配的门店</view>
  104 + <view class="empty-state-subtext">请尝试其他搜索关键词</view>
  105 + </view>
  106 +
  107 + <!-- 编辑在职人数弹窗 -->
  108 + <view v-if="showEditDialog" class="dialog-overlay" @click="closeEditDialog">
  109 + <view class="edit-dialog" @click.stop>
  110 + <view class="dialog-header">
  111 + <text class="dialog-title">修改在职人数</text>
  112 + </view>
  113 + <view class="dialog-content">
  114 + <view class="form-item">
  115 + <text class="form-label">门店名称</text>
  116 + <text class="form-value">{{ currentStore.dm || '无' }}</text>
  117 + </view>
  118 + <view class="form-item">
  119 + <text class="form-label">在职人数</text>
  120 + <u-input
  121 + v-model="editZzrs"
  122 + type="number"
  123 + placeholder="请输入在职人数"
  124 + :clearable="true"
  125 + />
  126 + </view>
  127 + </view>
  128 + <view class="dialog-buttons">
  129 + <button class="dialog-btn cancel-dialog-btn" @click="closeEditDialog">取消</button>
  130 + <button
  131 + class="dialog-btn confirm-dialog-btn"
  132 + @click="submitEdit"
  133 + :loading="submitLoading"
  134 + >
  135 + 确定
  136 + </button>
  137 + </view>
  138 + </view>
  139 + </view>
  140 + </view>
  141 +</template>
  142 +
  143 +<script>
  144 + import storeApi from '@/apis/modules/store.js'
  145 +
  146 + export default {
  147 + data() {
  148 + return {
  149 + // 搜索相关
  150 + searchKeyword: '',
  151 + searchTimeout: null,
  152 + isSearching: false,
  153 +
  154 + // 列表相关
  155 + storeList: [],
  156 + currentPage: 1,
  157 + pageSize: 10,
  158 + isLoading: false,
  159 + isLoadingMore: false,
  160 + hasMoreData: true,
  161 +
  162 + // 用户信息
  163 + userInfo: null,
  164 +
  165 + // 编辑相关
  166 + showEditDialog: false,
  167 + currentStore: {},
  168 + editZzrs: '',
  169 + submitLoading: false
  170 + }
  171 + },
  172 + onLoad() {
  173 + this.initializePage();
  174 + },
  175 + onReachBottom() {
  176 + this.loadMoreData();
  177 + },
  178 + methods: {
  179 + // 初始化页面
  180 + async initializePage() {
  181 + try {
  182 + // 获取用户信息
  183 + this.userInfo = uni.getStorageSync('userInfo');
  184 + if (!this.userInfo || Object.keys(this.userInfo).length === 0) {
  185 + uni.showToast({
  186 + title: '请先登录',
  187 + icon: 'none'
  188 + });
  189 + setTimeout(() => {
  190 + uni.reLaunch({
  191 + url: '/pages/login/login'
  192 + });
  193 + }, 1500);
  194 + return;
  195 + }
  196 +
  197 + await this.loadStoreData(true);
  198 + } catch (error) {
  199 + console.error('页面初始化失败:', error);
  200 + uni.showToast({
  201 + title: '数据加载失败',
  202 + icon: 'none'
  203 + });
  204 + }
  205 + },
  206 +
  207 + // 搜索输入处理
  208 + onSearchInput() {
  209 + // 清除之前的定时器
  210 + if (this.searchTimeout) {
  211 + clearTimeout(this.searchTimeout);
  212 + }
  213 +
  214 + // 设置防抖,500ms后执行搜索
  215 + this.searchTimeout = setTimeout(() => {
  216 + if (this.searchKeyword.trim()) {
  217 + this.isSearching = true;
  218 + } else {
  219 + this.isSearching = false;
  220 + }
  221 +
  222 + // 重置分页状态
  223 + this.currentPage = 1;
  224 + this.hasMoreData = true;
  225 + this.loadStoreData(true);
  226 + }, 500);
  227 + },
  228 +
  229 + // 加载门店数据
  230 + async loadStoreData(isFirstLoad = false) {
  231 + if (this.isLoading) return;
  232 +
  233 + try {
  234 + this.isLoading = true;
  235 +
  236 + if (isFirstLoad) {
  237 + this.isLoadingMore = false;
  238 + } else {
  239 + this.isLoadingMore = true;
  240 + }
  241 +
  242 + const params = {
  243 + currentPage: this.currentPage,
  244 + pageSize: this.pageSize
  245 + };
  246 +
  247 + // 添加搜索参数
  248 + if (this.searchKeyword.trim()) {
  249 + // 只按门店名称搜索
  250 + params.dm = this.searchKeyword.trim();
  251 + }
  252 +
  253 + const result = await storeApi.getStoreList(params);
  254 +
  255 + if (result.code === 200 && result.data && result.data.list) {
  256 + const stores = result.data.list.map(item => ({
  257 + id: item.id,
  258 + mdbm: item.mdbm || '',
  259 + djmdbh: item.djmdbh || '',
  260 + djmd: item.djmd || '无',
  261 + dm: item.dm || '无',
  262 + cs: item.cs || '无',
  263 + dz: item.dz || '',
  264 + xm: item.xm || '无',
  265 + dhhm: item.dhhm || '无',
  266 + zj: item.zj || '',
  267 + kysj: item.kysj,
  268 + zxzt: item.zxzt || '',
  269 + gsmc: item.gsmc || '',
  270 + fr: item.fr || '',
  271 + ywsb: item.ywsb || '',
  272 + zzrs: item.zzrs || 0,
  273 + storeCategory: item.storeCategory || '',
  274 + storeType: item.storeType || ''
  275 + }));
  276 +
  277 + if (isFirstLoad) {
  278 + this.storeList = [...stores];
  279 + } else {
  280 + this.storeList = [...this.storeList, ...stores];
  281 + }
  282 +
  283 + // 检查是否还有更多数据
  284 + this.hasMoreData = stores.length === this.pageSize;
  285 + } else {
  286 + if (isFirstLoad) {
  287 + this.storeList = [];
  288 + }
  289 + this.hasMoreData = false;
  290 + }
  291 +
  292 + this.currentPage++;
  293 + } catch (error) {
  294 + console.error('加载门店数据失败:', error);
  295 + uni.showToast({
  296 + title: '加载失败,请重试',
  297 + icon: 'none'
  298 + });
  299 + if (isFirstLoad) {
  300 + this.storeList = [];
  301 + }
  302 + this.hasMoreData = false;
  303 + } finally {
  304 + this.isLoading = false;
  305 + this.isLoadingMore = false;
  306 + }
  307 + },
  308 +
  309 + // 加载更多数据
  310 + async loadMoreData() {
  311 + if (this.isLoading || !this.hasMoreData) return;
  312 + await this.loadStoreData(false);
  313 + },
  314 +
  315 + // 格式化日期
  316 + formatDate(date) {
  317 + if (!date) return '无';
  318 + if (typeof date === 'string') {
  319 + return date;
  320 + }
  321 + if (date instanceof Date) {
  322 + return date.toLocaleDateString('zh-CN');
  323 + }
  324 + // 处理时间戳格式
  325 + if (typeof date === 'number') {
  326 + const dateObj = new Date(date);
  327 + return dateObj.toLocaleDateString('zh-CN');
  328 + }
  329 + return '未知日期';
  330 + },
  331 +
  332 +
  333 + // 打开编辑弹窗
  334 + openEditDialog(store) {
  335 + this.currentStore = store;
  336 + this.editZzrs = store.zzrs || '';
  337 + this.showEditDialog = true;
  338 + },
  339 +
  340 + // 关闭编辑弹窗
  341 + closeEditDialog() {
  342 + this.showEditDialog = false;
  343 + this.currentStore = {};
  344 + this.editZzrs = '';
  345 + },
  346 +
  347 + // 提交编辑
  348 + async submitEdit() {
  349 + if (this.submitLoading) return;
  350 +
  351 + // 验证输入
  352 + if (!this.editZzrs && this.editZzrs !== 0) {
  353 + uni.showToast({
  354 + title: '请输入在职人数',
  355 + icon: 'none'
  356 + });
  357 + return;
  358 + }
  359 +
  360 + const zzrs = parseInt(this.editZzrs);
  361 + if (isNaN(zzrs) || zzrs < 0) {
  362 + uni.showToast({
  363 + title: '请输入有效的数字',
  364 + icon: 'none'
  365 + });
  366 + return;
  367 + }
  368 +
  369 + this.submitLoading = true;
  370 + try {
  371 + // 先获取门店完整信息
  372 + const detailRes = await storeApi.getStoreDetail(this.currentStore.id);
  373 + if (detailRes.code !== 200) {
  374 + throw new Error(detailRes.msg || '获取门店信息失败');
  375 + }
  376 +
  377 + // 更新在职人数
  378 + const updateData = {
  379 + ...detailRes.data,
  380 + zzrs: zzrs
  381 + };
  382 +
  383 + const result = await storeApi.updateStore(this.currentStore.id, updateData);
  384 +
  385 + if (result.code === 200) {
  386 + uni.showToast({
  387 + title: '修改成功',
  388 + icon: 'success'
  389 + });
  390 +
  391 + // 更新列表中的数据
  392 + const index = this.storeList.findIndex(item => item.id === this.currentStore.id);
  393 + if (index !== -1) {
  394 + this.storeList[index].zzrs = zzrs;
  395 + }
  396 +
  397 + this.closeEditDialog();
  398 + } else {
  399 + uni.showToast({
  400 + title: result.msg || '修改失败',
  401 + icon: 'none'
  402 + });
  403 + }
  404 + } catch (error) {
  405 + console.error('修改在职人数失败:', error);
  406 + uni.showToast({
  407 + title: '修改失败,请重试',
  408 + icon: 'none'
  409 + });
  410 + } finally {
  411 + this.submitLoading = false;
  412 + }
  413 + }
  414 + }
  415 + }
  416 +</script>
  417 +
  418 +<style lang="scss" scoped>
  419 + .store-list-container {
  420 + min-height: 100vh;
  421 + background: linear-gradient(135deg, #e8f5e9 0%, #b2dfdb 100%);
  422 + padding: 20rpx;
  423 + }
  424 +
  425 + .search-card {
  426 + background: #fff;
  427 + border-radius: 32rpx;
  428 + box-shadow: 0 8rpx 32rpx rgba(76, 175, 80, 0.1);
  429 + padding: 40rpx;
  430 + margin-bottom: 40rpx;
  431 + }
  432 +
  433 + .store-list {
  434 + margin-bottom: 40rpx;
  435 + }
  436 +
  437 + .store-card {
  438 + background: #fff;
  439 + border-radius: 32rpx;
  440 + box-shadow: 0 8rpx 40rpx 0 rgba(76, 175, 80, 0.12);
  441 + border: 2rpx solid #e8f5e9;
  442 + padding: 40rpx;
  443 + margin-bottom: 32rpx;
  444 + transition: all 0.2s ease;
  445 + }
  446 +
  447 + .store-card:hover {
  448 + transform: translateY(-4rpx);
  449 + box-shadow: 0 12rpx 48rpx 0 rgba(76, 175, 80, 0.18);
  450 + }
  451 +
  452 + .store-header {
  453 + display: flex;
  454 + justify-content: space-between;
  455 + align-items: center;
  456 + margin-bottom: 24rpx;
  457 + padding-bottom: 24rpx;
  458 + border-bottom: 2rpx solid #e8f5e9;
  459 + }
  460 +
  461 + .store-name {
  462 + font-size: 36rpx;
  463 + font-weight: bold;
  464 + color: #2e7d32;
  465 + flex: 1;
  466 + }
  467 +
  468 + .store-status {
  469 + padding: 8rpx 20rpx;
  470 + border-radius: 16rpx;
  471 + font-size: 24rpx;
  472 + font-weight: 500;
  473 + }
  474 +
  475 + .status-open {
  476 + background: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%);
  477 + color: #fff;
  478 + }
  479 +
  480 + .status-closed {
  481 + background: #f5f5f5;
  482 + color: #999;
  483 + }
  484 +
  485 + .store-row {
  486 + display: flex;
  487 + flex-wrap: wrap;
  488 + margin-bottom: 24rpx;
  489 + gap: 16rpx;
  490 + }
  491 +
  492 + .store-row:last-child {
  493 + margin-bottom: 0;
  494 + }
  495 +
  496 + .store-item {
  497 + flex: 1 1 calc(50% - 8rpx);
  498 + min-width: 0;
  499 + display: flex;
  500 + align-items: center;
  501 + gap: 12rpx;
  502 + padding: 16rpx 24rpx;
  503 + background: #f8fdf8;
  504 + border-radius: 16rpx;
  505 + border: 2rpx solid #e8f5e9;
  506 + }
  507 +
  508 + .store-item.full-width {
  509 + flex: 1 1 100%;
  510 + }
  511 +
  512 + .store-label {
  513 + color: #388e3c;
  514 + font-weight: 600;
  515 + font-size: 28rpx;
  516 + white-space: nowrap;
  517 + margin-right: 30rpx;
  518 + text-align: center;
  519 + }
  520 +
  521 + .store-value {
  522 + color: #2e7d32;
  523 + font-size: 30rpx;
  524 + font-weight: 500;
  525 + word-break: break-all;
  526 + flex: 1;
  527 + }
  528 +
  529 + .loading {
  530 + text-align: center;
  531 + padding: 80rpx 40rpx;
  532 + color: #6a9c6a;
  533 + font-size: 28rpx;
  534 + display: flex;
  535 + flex-direction: column;
  536 + align-items: center;
  537 + gap: 20rpx;
  538 + }
  539 +
  540 + .loading-text {
  541 + font-size: 28rpx;
  542 + }
  543 +
  544 + .loading-more {
  545 + text-align: center;
  546 + padding: 40rpx;
  547 + color: #6a9c6a;
  548 + font-size: 28rpx;
  549 + display: flex;
  550 + align-items: center;
  551 + justify-content: center;
  552 + gap: 16rpx;
  553 + }
  554 +
  555 + .loading-more-text {
  556 + font-size: 28rpx;
  557 + }
  558 +
  559 + .no-more-data {
  560 + text-align: center;
  561 + padding: 40rpx;
  562 + color: #6a9c6a;
  563 + font-size: 28rpx;
  564 + opacity: 0.8;
  565 + }
  566 +
  567 + .empty-state {
  568 + text-align: center;
  569 + padding: 120rpx 40rpx;
  570 + color: #6a9c6a;
  571 + }
  572 +
  573 + .empty-state-icon {
  574 + font-size: 120rpx;
  575 + margin-bottom: 32rpx;
  576 + opacity: 0.6;
  577 + }
  578 +
  579 + .empty-state-text {
  580 + font-size: 32rpx;
  581 + margin-bottom: 16rpx;
  582 + }
  583 +
  584 + .empty-state-subtext {
  585 + font-size: 28rpx;
  586 + opacity: 0.8;
  587 + }
  588 +
  589 + .store-actions {
  590 + margin-top: 24rpx;
  591 + padding-top: 24rpx;
  592 + border-top: 2rpx solid #e8f5e9;
  593 + }
  594 +
  595 + .edit-btn {
  596 + width: 100%;
  597 + height: 72rpx;
  598 + background: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%);
  599 + color: #fff;
  600 + border: none;
  601 + border-radius: 16rpx;
  602 + font-size: 28rpx;
  603 + font-weight: 600;
  604 + box-shadow: 0 4rpx 16rpx rgba(67, 233, 123, 0.3);
  605 + transition: all 0.2s ease;
  606 + }
  607 +
  608 + .edit-btn:active {
  609 + transform: translateY(-2rpx);
  610 + box-shadow: 0 6rpx 20rpx rgba(67, 233, 123, 0.4);
  611 + }
  612 +
  613 + /* 编辑弹窗样式 */
  614 + .dialog-overlay {
  615 + position: fixed;
  616 + top: 0;
  617 + left: 0;
  618 + right: 0;
  619 + bottom: 0;
  620 + background: rgba(0, 0, 0, 0.5);
  621 + display: flex;
  622 + align-items: center;
  623 + justify-content: center;
  624 + z-index: 9999;
  625 + }
  626 +
  627 + .edit-dialog {
  628 + background: #fff;
  629 + border-radius: 20rpx;
  630 + overflow: hidden;
  631 + width: 600rpx;
  632 + max-width: 90%;
  633 + }
  634 +
  635 + .dialog-header {
  636 + background: linear-gradient(120deg, #43e97b 0%, #38f9d7 100%);
  637 + padding: 32rpx 40rpx;
  638 + text-align: center;
  639 + }
  640 +
  641 + .dialog-title {
  642 + color: #fff;
  643 + font-size: 32rpx;
  644 + font-weight: 600;
  645 + letter-spacing: 2rpx;
  646 + }
  647 +
  648 + .dialog-content {
  649 + padding: 40rpx;
  650 + }
  651 +
  652 + .form-item {
  653 + margin-bottom: 32rpx;
  654 + }
  655 +
  656 + .form-item:last-child {
  657 + margin-bottom: 0;
  658 + }
  659 +
  660 + .form-label {
  661 + font-size: 28rpx;
  662 + color: #388e3c;
  663 + font-weight: 600;
  664 + margin-bottom: 16rpx;
  665 + display: block;
  666 + }
  667 +
  668 + .form-value {
  669 + font-size: 30rpx;
  670 + color: #2e7d32;
  671 + font-weight: 500;
  672 + display: block;
  673 + padding: 16rpx 20rpx;
  674 + background: #f8fdf8;
  675 + border-radius: 12rpx;
  676 + border: 2rpx solid #e8f5e9;
  677 + }
  678 +
  679 + .form-item /deep/ .u-input {
  680 + border: 2rpx solid #e8f5e9;
  681 + border-radius: 12rpx;
  682 + background: #f8fff8;
  683 + }
  684 +
  685 + .form-item /deep/ .u-input__content {
  686 + padding: 20rpx;
  687 + }
  688 +
  689 + .form-item /deep/ .u-input__content__field-wrapper__field {
  690 + font-size: 28rpx;
  691 + color: #2e7d32;
  692 + }
  693 +
  694 + .dialog-buttons {
  695 + display: flex;
  696 + gap: 24rpx;
  697 + padding: 0 40rpx 40rpx;
  698 + }
  699 +
  700 + .dialog-btn {
  701 + flex: 1;
  702 + height: 80rpx;
  703 + border-radius: 20rpx;
  704 + font-size: 28rpx;
  705 + font-weight: 600;
  706 + letter-spacing: 2rpx;
  707 + transition: all 0.3s ease;
  708 + }
  709 +
  710 + .cancel-dialog-btn {
  711 + background: #f5f5f5;
  712 + color: #666;
  713 + border: 2rpx solid #e0e0e0;
  714 + }
  715 +
  716 + .cancel-dialog-btn:active {
  717 + background: #eeeeee;
  718 + }
  719 +
  720 + .confirm-dialog-btn {
  721 + background: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%);
  722 + color: #fff;
  723 + border: none;
  724 + box-shadow: 0 4rpx 16rpx rgba(67, 233, 123, 0.3);
  725 + }
  726 +
  727 + .confirm-dialog-btn:active {
  728 + transform: translateY(-2rpx);
  729 + box-shadow: 0 6rpx 20rpx rgba(67, 233, 123, 0.4);
  730 + }
  731 +</style>
  732 +
... ...