Commit ffd6aaca8c3edc72e935969e05e966b97e0fe262
1 parent
d64f9fbd
最新
Showing
13 changed files
with
2930 additions
and
110 deletions
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
绿纤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 | + | ... | ... |