Commit 9864a8182636946663cc930a1e7b24f218e8c8d2

Authored by “wangming”
1 parent 28404662

feat: 优化拓客管理功能

- 新增 TkjlbExportModel DTO 类,将导出模型从服务层分离到 DTO 层
- 修复拓客管理导出功能的下载地址500错误
- 优化拓客管理列表页面:
  * 将活动编号搜索改为下拉框选择
  * 调整列宽度,拓客编号列加宽,备注列移除宽度限制
  * 移除编辑、删除、批量删除按钮
  * 优化表格样式和用户体验
- 简化导出功能,固定导出字段,支持活动编号和截止时间筛选
- 修复开单记录表导出功能,添加中文名称显示
- 创建临时文件目录以支持文件导出功能
antis-ncc-admin/src/views/lqTkjlb/ExportBox.vue
1 1 <template>
2   - <el-dialog title="导出数据" :close-on-click-modal="false" :visible.sync="visible"
3   - class="NCC-dialog NCC-dialog_center" lock-scroll width="600px">
4   - <el-form label-position="top" label-width="80px">
5   - <el-form-item label="数据选择">
6   - <el-radio-group v-model="type">
7   - <el-radio :label="0">当前页面数据</el-radio>
8   - <el-radio :label="1">全部页面数据</el-radio>
9   - </el-radio-group>
  2 + <el-dialog title="导出拓客数据" :close-on-click-modal="false" :visible.sync="visible"
  3 + class="NCC-dialog NCC-dialog_center" lock-scroll width="500px">
  4 + <el-form label-position="right" label-width="100px">
  5 + <el-form-item label="活动编号">
  6 + <el-select v-model="exportParams.eventId" placeholder="请选择活动编号(可选)" clearable filterable :loading="eventListLoading">
  7 + <el-option
  8 + v-for="event in eventList"
  9 + :key="event.id"
  10 + :label="`${event.eventNumber} - ${event.eventName}`"
  11 + :value="event.id">
  12 + </el-option>
  13 + </el-select>
  14 + <div class="form-tip">留空则导出所有活动的数据</div>
10 15 </el-form-item>
11   - <el-form-item label="导出字段">
12   - <el-checkbox :indeterminate="isIndeterminate" v-model="checkAll"
13   - @change="handleCheckAllChange">全选</el-checkbox>
14   - <el-checkbox-group v-model="columns" @change="handleCheckedChange">
15   - <el-checkbox v-for="item in columnList" :label="item.prop" :key="item.prop">
16   - {{item.label}}
17   - </el-checkbox>
18   - </el-checkbox-group>
  16 + <el-form-item label="截止时间">
  17 + <el-date-picker
  18 + v-model="exportParams.endTime"
  19 + type="datetime"
  20 + value-format="yyyy-MM-dd HH:mm:ss"
  21 + format="yyyy-MM-dd HH:mm:ss"
  22 + placeholder="请选择截止时间(可选)"
  23 + clearable>
  24 + </el-date-picker>
  25 + <div class="form-tip">留空则导出所有时间的数据</div>
  26 + </el-form-item>
  27 + <el-form-item label="导出说明">
  28 + <div class="export-info">
  29 + <p>• 导出包含15个字段:拓客编号、拓客时间、拓客人员、顾客姓名、电话号码、购买张数、支付方式、是否加微信、备注、门店名称、活动名称等</p>
  30 + <p>• 所有字段都会显示中文名称,无需手动选择</p>
  31 + <p>• 支持从下拉框选择活动编号,或按截止时间进行筛选</p>
  32 + <p>• 活动编号显示格式:编号 - 活动名称</p>
  33 + </div>
19 34 </el-form-item>
20 35 </el-form>
21 36 <span slot="footer" class="dialog-footer">
22 37 <el-button @click="visible=false">取 消</el-button>
23   - <el-button type="primary" @click="downLoad">导 出</el-button>
  38 + <el-button type="primary" @click="downLoad" :loading="btnLoading">导 出</el-button>
24 39 </span>
25 40 </el-dialog>
26 41 </template>
27 42  
28 43 <script>
  44 +import { getLqEventList } from '@/api/extend/lqevent'
  45 +
29 46 export default {
30 47 data() {
31 48 return {
32 49 visible: false,
33 50 btnLoading: false,
34   - type: 0,
35   - columns: [],
36   - checkAll: true,
37   - isIndeterminate: false,
38   - columnList: []
  51 + eventList: [],
  52 + eventListLoading: false,
  53 + exportParams: {
  54 + eventId: '',
  55 + endTime: ''
  56 + }
39 57 }
40 58 },
41 59 methods: {
42   - init(columnList) {
  60 + init() {
43 61 this.visible = true
44   - this.columnList = columnList
45   - this.columns = columnList.map(o => o.prop)
46   - },
47   - handleCheckAllChange(val) {
48   - this.columns = val ? this.columnList.map(o => o.prop) : [];
49   - this.isIndeterminate = false;
  62 + // 重置参数
  63 + this.exportParams = {
  64 + eventId: '',
  65 + endTime: ''
  66 + }
  67 + // 获取活动列表
  68 + this.getEventList()
50 69 },
51   - handleCheckedChange(value) {
52   - let checkedCount = value.length;
53   - this.checkAll = checkedCount === this.columnList.length;
54   - this.isIndeterminate = checkedCount > 0 && checkedCount < this.columnList.length;
  70 + // 获取拓客活动列表
  71 + async getEventList() {
  72 + this.eventListLoading = true
  73 + try {
  74 + const response = await getLqEventList({
  75 + currentPage: 1,
  76 + pageSize: 1000 // 获取所有活动
  77 + })
  78 + if (response.code === 200 && response.data && response.data.list) {
  79 + this.eventList = response.data.list.map(event => ({
  80 + id: event.id,
  81 + eventNumber: event.eventNumber,
  82 + eventName: event.eventName
  83 + }))
  84 + } else {
  85 + this.eventList = []
  86 + }
  87 + } catch (error) {
  88 + console.error('获取活动列表失败:', error)
  89 + this.eventList = []
  90 + this.$message({
  91 + type: 'warning',
  92 + message: '获取活动列表失败,请手动输入活动编号'
  93 + })
  94 + } finally {
  95 + this.eventListLoading = false
  96 + }
55 97 },
56 98 downLoad() {
57   - this.$emit('download', { dataType: this.type, selectKey: this.columns.join(',') })
  99 + this.btnLoading = true
  100 + // 发送简化的参数
  101 + this.$emit('download', {
  102 + eventId: this.exportParams.eventId || null,
  103 + endTime: this.exportParams.endTime || null
  104 + })
  105 + // 延迟重置loading状态
  106 + setTimeout(() => {
  107 + this.btnLoading = false
  108 + }, 1000)
58 109 }
59 110 }
60 111 }
... ... @@ -63,4 +114,32 @@ export default {
63 114 >>> .el-dialog__body {
64 115 padding: 20px !important;
65 116 }
  117 +
  118 +.form-tip {
  119 + font-size: 12px;
  120 + color: #909399;
  121 + margin-top: 5px;
  122 +}
  123 +
  124 +.export-info {
  125 + background-color: #f5f7fa;
  126 + padding: 15px;
  127 + border-radius: 4px;
  128 + border-left: 4px solid #409eff;
  129 +
  130 + p {
  131 + margin: 5px 0;
  132 + font-size: 13px;
  133 + color: #606266;
  134 + line-height: 1.5;
  135 + }
  136 +}
  137 +
  138 +.el-form-item {
  139 + margin-bottom: 20px;
  140 +}
  141 +
  142 +.dialog-footer {
  143 + text-align: right;
  144 +}
66 145 </style>
67 146 \ No newline at end of file
... ...
antis-ncc-admin/src/views/lqTkjlb/index.vue
... ... @@ -12,7 +12,14 @@
12 12 </el-col>
13 13 <el-col :span="6">
14 14 <el-form-item label="拓客活动">
15   - <el-input v-model="query.eventId" placeholder="拓客活动" clearable />
  15 + <el-select v-model="query.eventId" placeholder="请选择拓客活动" clearable filterable :loading="eventListLoading">
  16 + <el-option
  17 + v-for="event in eventList"
  18 + :key="event.id"
  19 + :label="`${event.eventNumber} - ${event.eventName}`"
  20 + :value="event.id">
  21 + </el-option>
  22 + </el-select>
16 23 </el-form-item>
17 24 </el-col>
18 25 <el-col :span="6">
... ... @@ -20,6 +27,11 @@
20 27 <userSelect v-model="query.expansionUserId" placeholder="请选择拓客人员" />
21 28 </el-form-item>
22 29 </el-col>
  30 + <el-col :span="6">
  31 + <el-form-item label="所属门店">
  32 + <el-input v-model="query.storeId" placeholder="请输入门店名称" clearable />
  33 + </el-form-item>
  34 + </el-col>
23 35  
24 36 <template v-if="showAll">
25 37 <el-col :span="6">
... ... @@ -53,6 +65,11 @@
53 65 </el-select>
54 66 </el-form-item>
55 67 </el-col>
  68 + <el-col :span="6">
  69 + <el-form-item label="所属战队">
  70 + <el-input v-model="query.teamName" placeholder="请输入战队名称" clearable />
  71 + </el-form-item>
  72 + </el-col>
56 73 </template>
57 74 <el-col :span="6">
58 75 <el-form-item>
... ... @@ -67,9 +84,7 @@
67 84 <div class="NCC-common-layout-main NCC-flex-main">
68 85 <div class="NCC-common-head">
69 86 <div>
70   - <el-button type="primary" icon="el-icon-plus" @click="addOrUpdateHandle()">新增</el-button>
71 87 <el-button type="text" icon="el-icon-download" @click="exportData()">导出</el-button>
72   - <el-button type="text" icon="el-icon-delete" @click="handleBatchRemoveDel()">批量删除</el-button>
73 88 <el-button type="success" icon="el-icon-s-data" @click="goToReport()">拓客报表</el-button>
74 89 </div>
75 90 <div class="NCC-common-head-right">
... ... @@ -79,32 +94,28 @@
79 94 <screenfull isContainer />
80 95 </div>
81 96 </div>
82   - <NCC-table v-loading="listLoading" :data="list" has-c @selection-change="handleSelectionChange">
83   - <el-table-column prop="eventName" label="拓客活动" align="left" />
84   - <el-table-column prop="expansionUserId" label="拓客人员" align="left" />
85   - <el-table-column prop="expansionTime" label="拓客时间" align="left" :formatter="ncc.tableDateFormat" />
86   - <el-table-column prop="customerName" label="顾客姓名" align="left" />
87   - <el-table-column prop="customerPhone" label="电话号码" align="left" />
88   - <el-table-column prop="buyNumber" label="购买张数" align="left" />
89   - <el-table-column label="支付方式" prop="paymentMethod" align="left">
  97 + <NCC-table v-loading="listLoading" :data="list">
  98 + <el-table-column prop="id" label="拓客编号" align="left" width="160" show-overflow-tooltip />
  99 + <el-table-column prop="eventName" label="拓客活动" align="left" width="150" show-overflow-tooltip />
  100 + <el-table-column prop="expansionUserName" label="拓客人员" align="left" width="100" show-overflow-tooltip />
  101 + <el-table-column prop="storeName" label="所属门店" align="left" width="120" show-overflow-tooltip />
  102 + <el-table-column prop="expansionTime" label="拓客时间" align="left" width="150" :formatter="ncc.tableDateFormat" />
  103 + <el-table-column prop="customerName" label="顾客姓名" align="left" width="100" show-overflow-tooltip />
  104 + <el-table-column prop="customerPhone" label="电话号码" align="left" width="120" show-overflow-tooltip />
  105 + <el-table-column prop="buyNumber" label="购买张数" align="center" width="80" />
  106 + <el-table-column label="支付方式" prop="paymentMethod" align="left" width="100">
90 107 <template slot-scope="scope">{{ scope.row.paymentMethod | dynamicText(zffsOptions) }}</template>
91 108 </el-table-column>
92   - <el-table-column label="是否加微信" prop="isAddWeChat" align="left">
  109 + <el-table-column label="是否加微信" prop="isAddWeChat" align="center" width="100">
93 110 <template slot-scope="scope">{{ scope.row.isAddWeChat | dynamicText(sfjwxOptions) }}</template>
94 111 </el-table-column>
95   - <el-table-column prop="remarks" label="备注" align="left" />
96   - <el-table-column label="操作" fixed="right" width="100">
97   - <template slot-scope="scope">
98   - <el-button type="text" @click="addOrUpdateHandle(scope.row.id)">编辑</el-button>
99   - <el-button type="text" @click="handleDel(scope.row.id)" class="NCC-table-delBtn">删除</el-button>
100   - </template>
101   - </el-table-column>
  112 + <el-table-column prop="teamName" label="所属战队" align="left" width="100" show-overflow-tooltip />
  113 + <el-table-column prop="remarks" label="备注" align="left" show-overflow-tooltip />
102 114 </NCC-table>
103 115 <pagination :total="total" :page.sync="listQuery.currentPage" :limit.sync="listQuery.pageSize"
104 116 @pagination="initData" />
105 117 </div>
106 118 </div>
107   - <NCC-Form v-if="formVisible" ref="NCCForm" @refresh="refresh" />
108 119 <ExportBox v-if="exportBoxVisible" ref="ExportBox" @download="download" />
109 120 </div>
110 121 </template>
... ... @@ -113,19 +124,20 @@
113 124 import {
114 125 getDictionaryDataSelector
115 126 } from '@/api/systemData/dictionary'
116   - import NCCForm from './Form'
117 127 import ExportBox from './ExportBox'
118 128 import {
119 129 previewDataInterface
120 130 } from '@/api/systemData/dataInterface'
  131 + import { getLqEventList } from '@/api/extend/lqevent'
121 132 export default {
122 133 components: {
123   - NCCForm,
124 134 ExportBox
125 135 },
126 136 data() {
127 137 return {
128 138 showAll: false,
  139 + eventList: [],
  140 + eventListLoading: false,
129 141 query: {
130 142 id: undefined,
131 143 expansionUserId: undefined,
... ... @@ -137,12 +149,11 @@
137 149 isAddWeChat: undefined,
138 150 remarks: undefined,
139 151 eventId: undefined,
140   - ssmd: undefined,
141   - sszd: undefined,
  152 + storeId: undefined,
  153 + teamName: undefined,
142 154 },
143 155 list: [],
144 156 listLoading: true,
145   - multipleSelection: [],
146 157 total: 0,
147 158 listQuery: {
148 159 currentPage: 1,
... ... @@ -150,17 +161,24 @@
150 161 sort: "desc",
151 162 sidx: "",
152 163 },
153   - formVisible: false,
154 164 exportBoxVisible: false,
155 165 columnList: [{
156 166 prop: 'id',
157 167 label: '拓客编号'
158 168 },
159 169 {
160   - prop: 'expansionUserId',
  170 + prop: 'eventName',
  171 + label: '拓客活动'
  172 + },
  173 + {
  174 + prop: 'expansionUserName',
161 175 label: '拓客人员'
162 176 },
163 177 {
  178 + prop: 'storeName',
  179 + label: '所属门店'
  180 + },
  181 + {
164 182 prop: 'expansionTime',
165 183 label: '拓客时间'
166 184 },
... ... @@ -185,20 +203,12 @@
185 203 label: '是否加微信'
186 204 },
187 205 {
188   - prop: 'remarks',
189   - label: '备注'
190   - },
191   - {
192   - prop: 'eventId',
193   - label: '拓客活动'
194   - },
195   - {
196   - prop: 'ssmd',
197   - label: '所属门店'
  206 + prop: 'teamName',
  207 + label: '所属战队'
198 208 },
199 209 {
200   - prop: 'sszd',
201   - label: '所属战队'
  210 + prop: 'remarks',
  211 + label: '备注'
202 212 },
203 213 ],
204 214 zffsOptions: [{
... ... @@ -225,9 +235,34 @@
225 235 },
226 236 computed: {},
227 237 created() {
  238 + this.getEventList()
228 239 this.initData()
229 240 },
230 241 methods: {
  242 + // 获取拓客活动列表
  243 + async getEventList() {
  244 + this.eventListLoading = true
  245 + try {
  246 + const response = await getLqEventList({
  247 + currentPage: 1,
  248 + pageSize: 1000 // 获取所有活动
  249 + })
  250 + if (response.code === 200 && response.data && response.data.list) {
  251 + this.eventList = response.data.list.map(event => ({
  252 + id: event.id,
  253 + eventNumber: event.eventNumber,
  254 + eventName: event.eventName
  255 + }))
  256 + } else {
  257 + this.eventList = []
  258 + }
  259 + } catch (error) {
  260 + console.error('获取活动列表失败:', error)
  261 + this.eventList = []
  262 + } finally {
  263 + this.eventListLoading = false
  264 + }
  265 + },
231 266 initData() {
232 267 this.listLoading = true;
233 268 let _query = {
... ... @@ -252,81 +287,43 @@
252 287 this.listLoading = false
253 288 })
254 289 },
255   - handleDel(id) {
256   - this.$confirm('此操作将永久删除该数据, 是否继续?', '提示', {
257   - type: 'warning'
258   - }).then(() => {
259   - request({
260   - url: `/api/Extend/LqTkjlb/${id}`,
261   - method: 'DELETE'
262   - }).then(res => {
263   - this.$message({
264   - type: 'success',
265   - message: res.msg,
266   - onClose: () => {
267   - this.initData()
268   - }
269   - });
270   - })
271   - }).catch(() => {});
272   - },
273   - handleSelectionChange(val) {
274   - const res = val.map(item => item.id)
275   - this.multipleSelection = res
276   - },
277   - handleBatchRemoveDel() {
278   - if (!this.multipleSelection.length) {
279   - this.$message({
280   - type: 'error',
281   - message: '请选择一条数据',
282   - duration: 1500,
283   - })
284   - return
285   - }
286   - const ids = this.multipleSelection
287   - this.$confirm('您确定要删除这些数据吗, 是否继续?', '提示', {
288   - type: 'warning'
289   - }).then(() => {
290   - request({
291   - url: `/api/Extend/LqTkjlb/batchRemove`,
292   - method: 'POST',
293   - data: ids,
294   - }).then(res => {
295   - this.$message({
296   - type: 'success',
297   - message: res.msg,
298   - onClose: () => {
299   - this.initData()
300   - }
301   - });
302   - })
303   - }).catch(() => {})
304   - },
305   - addOrUpdateHandle(id, isDetail) {
306   - this.formVisible = true
307   - this.$nextTick(() => {
308   - this.$refs.NCCForm.init(id, isDetail)
309   - })
310   - },
311 290 exportData() {
312 291 this.exportBoxVisible = true
313 292 this.$nextTick(() => {
314   - this.$refs.ExportBox.init(this.columnList)
  293 + this.$refs.ExportBox.init()
315 294 })
316 295 },
317 296 download(data) {
  297 + // 使用简化的参数
318 298 let query = {
319   - ...data,
320   - ...this.listQuery,
321   - ...this.query
  299 + eventId: data.eventId,
  300 + endTime: data.endTime
322 301 }
  302 +
323 303 request({
324 304 url: `/api/Extend/LqTkjlb/Actions/Export`,
325 305 method: 'GET',
326 306 data: query
327 307 }).then(res => {
328   - if (!res.data.url) return
329   - window.location.href = this.define.comUrl + res.data.url
  308 + if (res.data.url) {
  309 + window.location.href = this.define.comUrl + res.data.url
  310 + this.$message({
  311 + type: 'success',
  312 + message: '导出成功!'
  313 + })
  314 + } else if (res.data.message) {
  315 + this.$message({
  316 + type: 'error',
  317 + message: res.data.message
  318 + })
  319 + }
  320 + this.$refs.ExportBox.visible = false
  321 + this.exportBoxVisible = false
  322 + }).catch(error => {
  323 + this.$message({
  324 + type: 'error',
  325 + message: '导出失败:' + (error.message || '未知错误')
  326 + })
330 327 this.$refs.ExportBox.visible = false
331 328 this.exportBoxVisible = false
332 329 })
... ... @@ -340,10 +337,6 @@
340 337 }
341 338 this.initData()
342 339 },
343   - refresh(isrRefresh) {
344   - this.formVisible = false
345   - if (isrRefresh) this.reset()
346   - },
347 340 reset() {
348 341 for (let key in this.query) {
349 342 this.query[key] = undefined
... ... @@ -364,3 +357,79 @@
364 357 }
365 358 }
366 359 </script>
  360 +
  361 +<style lang="scss" scoped>
  362 +.NCC-common-layout {
  363 + .NCC-table {
  364 + .el-table {
  365 + .el-table__header {
  366 + th {
  367 + background-color: #f5f7fa;
  368 + color: #606266;
  369 + font-weight: 600;
  370 + }
  371 + }
  372 +
  373 + .el-table__body {
  374 + tr:hover {
  375 + background-color: #f5f7fa;
  376 + }
  377 + }
  378 + }
  379 + }
  380 +
  381 + .NCC-common-search-box {
  382 + .el-form-item {
  383 + margin-bottom: 18px;
  384 +
  385 + .el-form-item__label {
  386 + font-weight: 500;
  387 + color: #606266;
  388 + }
  389 + }
  390 + }
  391 +
  392 + .NCC-common-head {
  393 + .el-button {
  394 + margin-right: 8px;
  395 +
  396 + &.el-button--primary {
  397 + background-color: #409eff;
  398 + border-color: #409eff;
  399 + }
  400 +
  401 + &.el-button--text {
  402 + color: #409eff;
  403 +
  404 + &:hover {
  405 + color: #66b1ff;
  406 + }
  407 + }
  408 + }
  409 + }
  410 +}
  411 +
  412 +// 表格列宽度优化
  413 +.el-table {
  414 + .el-table__header-wrapper {
  415 + th {
  416 + padding: 12px 0;
  417 + }
  418 + }
  419 +
  420 + .el-table__body-wrapper {
  421 + td {
  422 + padding: 12px 0;
  423 + }
  424 + }
  425 +}
  426 +
  427 +// 操作按钮样式
  428 +.NCC-table-delBtn {
  429 + color: #f56c6c !important;
  430 +
  431 + &:hover {
  432 + color: #f78989 !important;
  433 + }
  434 +}
  435 +</style>
... ...
netcore/src/Application/NCC.API/appsettings.json
... ... @@ -184,7 +184,7 @@
184 184 "NCC_App": {
185 185 "CodeAreasName": "SubDev,Food,Extend,test",
186 186 //系统文件路径(末尾必须带斜杆)
187   - "SystemPath": "C:\\web\\NCC\\uu-resources\\",
  187 + "SystemPath": "Files/",
188 188 //微信公众号允许上传文件类型
189 189 "MPUploadFileType": "bmp,png,jpeg,jpg,gif,mp3,wma,wav,amr,mp4",
190 190 //微信允许上传文件类型
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqTkjlb/LqTkjlbListOutput.cs
... ... @@ -23,6 +23,16 @@ namespace NCC.Extend.Entitys.Dto.LqTkjlb
23 23 public string expansionUserId { get; set; }
24 24  
25 25 /// <summary>
  26 + /// 所属部门ID
  27 + /// </summary>
  28 + public string depId { get; set; }
  29 +
  30 + /// <summary>
  31 + /// 所属部门名称
  32 + /// </summary>
  33 + public string depName { get; set; }
  34 +
  35 + /// <summary>
26 36 /// 拓客人员
27 37 /// </summary>
28 38 public string expansionUserName { get; set; }
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqTkjlb/TkjlbExportModel.cs 0 → 100644
  1 +using System;
  2 +
  3 +namespace NCC.Extend.Entitys.Dto.LqTkjlb
  4 +{
  5 + /// <summary>
  6 + /// 拓客管理导出数据模型
  7 + /// </summary>
  8 + public class TkjlbExportModel
  9 + {
  10 + /// <summary>
  11 + /// 拓客编号
  12 + /// </summary>
  13 + public string id { get; set; }
  14 +
  15 + /// <summary>
  16 + /// 拓客时间
  17 + /// </summary>
  18 + public DateTime expansionTime { get; set; }
  19 +
  20 + /// <summary>
  21 + /// 拓客人员ID
  22 + /// </summary>
  23 + public string expansionUserId { get; set; }
  24 +
  25 + /// <summary>
  26 + /// 拓客人员姓名
  27 + /// </summary>
  28 + public string expansionUserName { get; set; }
  29 +
  30 + /// <summary>
  31 + /// 顾客姓名
  32 + /// </summary>
  33 + public string customerName { get; set; }
  34 +
  35 + /// <summary>
  36 + /// 顾客电话
  37 + /// </summary>
  38 + public string customerPhone { get; set; }
  39 +
  40 + /// <summary>
  41 + /// 购买张数
  42 + /// </summary>
  43 + public int buyNumber { get; set; }
  44 +
  45 + /// <summary>
  46 + /// 支付方式
  47 + /// </summary>
  48 + public string paymentMethod { get; set; }
  49 +
  50 + /// <summary>
  51 + /// 是否加微信
  52 + /// </summary>
  53 + public string isAddWeChat { get; set; }
  54 +
  55 + /// <summary>
  56 + /// 备注
  57 + /// </summary>
  58 + public string remarks { get; set; }
  59 +
  60 + /// <summary>
  61 + /// 门店ID
  62 + /// </summary>
  63 + public string storeId { get; set; }
  64 +
  65 + /// <summary>
  66 + /// 门店名称
  67 + /// </summary>
  68 + public string storeName { get; set; }
  69 +
  70 + /// <summary>
  71 + /// 战队名称
  72 + /// </summary>
  73 + public string teamName { get; set; }
  74 +
  75 + /// <summary>
  76 + /// 活动ID
  77 + /// </summary>
  78 + public string eventId { get; set; }
  79 +
  80 + /// <summary>
  81 + /// 活动名称
  82 + /// </summary>
  83 + public string eventName { get; set; }
  84 + }
  85 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend/LqKdKdjlbService.cs
... ... @@ -351,11 +351,6 @@ namespace NCC.Extend.LqKdKdjlb
351 351 }
352 352 }
353 353  
354   - // 处理健康师姓名,去除最后的逗号并赋值给实体
355   - if (!string.IsNullOrEmpty(HealthInstructorNames))
356   - {
357   - HealthInstructorNames = HealthInstructorNames.TrimEnd(',');
358   - }
359 354  
360 355 //通过会员id查询会员信息
361 356 var memberInfo = await _db.Queryable<LqKhxxEntity>().Where(u => u.Id == entity.Kdhy).FirstAsync();
... ...
netcore/src/Modularity/Extend/NCC.Extend/LqTkjlbService.cs
... ... @@ -133,6 +133,8 @@ namespace NCC.Extend.LqTkjlb
133 133 teamName = it.TeamName,
134 134 eventId = it.EventId,
135 135 eventName = SqlFunc.Subqueryable<LqEventEntity>().Where(u => u.Id == it.EventId).Select(u => u.EventName),
  136 + depId = it.DepId,
  137 + depName = SqlFunc.Subqueryable<OrganizeEntity>().Where(u => u.Id == it.DepId).Select(u => u.FullName),
136 138 })
137 139 .MergeTable()
138 140 .OrderBy(sidx + " " + input.sort)
... ... @@ -256,48 +258,109 @@ namespace NCC.Extend.LqTkjlb
256 258 }
257 259 #endregion
258 260  
259   - #region 导出拓客管理
  261 + #region 获取拓客管理带中文名称的数据(简化版)
260 262 /// <summary>
261   - /// 导出拓客管理
  263 + /// 获取拓客管理带中文名称的数据(简化版,用于导出)
262 264 /// </summary>
263   - /// <param name="input">请求参数</param>
  265 + /// <param name="eventId">活动编号(可选)</param>
  266 + /// <param name="endTime">截止时间(可选)</param>
264 267 /// <returns></returns>
  268 + [NonAction]
  269 + public async Task<List<TkjlbExportModel>> GetTkjlbWithChineseNamesSimple(string eventId = null, DateTime? endTime = null)
  270 + {
  271 + var data = await _db.Queryable<LqTkjlbEntity, LqMdxxEntity, LqEventEntity, UserEntity>(
  272 + (tk, md, ev, user) => tk.StoreId == md.Id && tk.EventId == ev.Id && tk.ExpansionUserId == user.Id
  273 + )
  274 + .WhereIF(!string.IsNullOrEmpty(eventId), (tk, md, ev, user) => tk.EventId == eventId)
  275 + .WhereIF(endTime.HasValue, (tk, md, ev, user) => tk.ExpansionTime <= endTime.Value)
  276 + .Select((tk, md, ev, user) => new TkjlbExportModel
  277 + {
  278 + id = tk.Id,
  279 + expansionTime = tk.ExpansionTime,
  280 + expansionUserId = tk.ExpansionUserId,
  281 + expansionUserName = user.RealName,
  282 + customerName = tk.CustomerName,
  283 + customerPhone = tk.CustomerPhone,
  284 + buyNumber = tk.BuyNumber,
  285 + paymentMethod = tk.PaymentMethod,
  286 + isAddWeChat = tk.IsAddWeChat,
  287 + remarks = tk.Remarks,
  288 + storeId = tk.StoreId,
  289 + storeName = md.Dm,
  290 + teamName = tk.TeamName,
  291 + eventId = tk.EventId,
  292 + eventName = ev.EventName,
  293 + })
  294 + .MergeTable()
  295 + .OrderBy("expansionTime desc")
  296 + .ToListAsync();
  297 +
  298 + return data;
  299 + }
  300 + #endregion
  301 +
  302 + #region 导出拓客管理
  303 + /// <summary>
  304 + /// 导出拓客管理(固定字段,显示中文名称)
  305 + /// </summary>
  306 + /// <param name="eventId">活动编号(可选)</param>
  307 + /// <param name="endTime">截止时间(可选)</param>
  308 + /// <returns>导出文件信息</returns>
265 309 [HttpGet("Actions/Export")]
266   - public async Task<dynamic> Export([FromQuery] LqTkjlbListQueryInput input)
  310 + public async Task<dynamic> Export([FromQuery] string eventId = null, [FromQuery] DateTime? endTime = null)
267 311 {
268   - var userInfo = await _userManager.GetUserInfo();
269   - var exportData = new List<LqTkjlbListOutput>();
270   - if (input.dataType == 0)
  312 + try
271 313 {
272   - var data = Clay.Object(await this.GetList(input));
273   - exportData = data.Solidify<PageResult<LqTkjlbListOutput>>().list;
274   - }
275   - else
276   - {
277   - exportData = await this.GetNoPagingList(input);
278   - }
279   - List<ParamsModel> paramList =
280   - "[{\"value\":\"拓客编号\",\"field\":\"id\"},{\"value\":\"拓客人员\",\"field\":\"tkry\"},{\"value\":\"拓客时间\",\"field\":\"tksj\"},{\"value\":\"顾客姓名\",\"field\":\"gkxm\"},{\"value\":\"电话号码\",\"field\":\"dhhm\"},{\"value\":\"购买张数\",\"field\":\"gmzs\"},{\"value\":\"支付方式\",\"field\":\"zffs\"},{\"value\":\"是否加微信\",\"field\":\"sfjwx\"},{\"value\":\"备注\",\"field\":\"bz\"},{\"value\":\"所属门店\",\"field\":\"ssmd\"},{\"value\":\"所属战队\",\"field\":\"sszd\"},]".ToList<ParamsModel>();
281   - ExcelConfig excelconfig = new ExcelConfig();
282   - excelconfig.FileName = "拓客管理.xls";
283   - excelconfig.HeadFont = "微软雅黑";
284   - excelconfig.HeadPoint = 10;
285   - excelconfig.IsAllSizeColumn = true;
286   - excelconfig.ColumnModel = new List<ExcelColumnModel>();
287   - List<string> selectKeyList = input.selectKey.Split(',').ToList();
288   - foreach (var item in selectKeyList)
289   - {
290   - var isExist = paramList.Find(p => p.field == item);
291   - if (isExist != null)
  314 + var userInfo = await _userManager.GetUserInfo();
  315 +
  316 + // 使用联合查询获取带中文名称的数据
  317 + var exportData = await GetTkjlbWithChineseNamesSimple(eventId, endTime);
  318 +
  319 + // 检查数据是否为空
  320 + if (exportData == null || exportData.Count == 0)
  321 + {
  322 + return new { name = "拓客管理.xls", url = "", message = "没有找到符合条件的数据" };
  323 + }
  324 +
  325 + // 固定导出字段
  326 + List<ParamsModel> paramList =
  327 + "[{\"value\":\"拓客编号\",\"field\":\"id\"},{\"value\":\"拓客时间\",\"field\":\"expansionTime\"},{\"value\":\"拓客人员ID\",\"field\":\"expansionUserId\"},{\"value\":\"拓客人员姓名\",\"field\":\"expansionUserName\"},{\"value\":\"顾客姓名\",\"field\":\"customerName\"},{\"value\":\"顾客电话\",\"field\":\"customerPhone\"},{\"value\":\"购买张数\",\"field\":\"buyNumber\"},{\"value\":\"支付方式\",\"field\":\"paymentMethod\"},{\"value\":\"是否加微信\",\"field\":\"isAddWeChat\"},{\"value\":\"备注\",\"field\":\"remarks\"},{\"value\":\"门店ID\",\"field\":\"storeId\"},{\"value\":\"门店名称\",\"field\":\"storeName\"},{\"value\":\"战队名称\",\"field\":\"teamName\"},{\"value\":\"活动ID\",\"field\":\"eventId\"},{\"value\":\"活动名称\",\"field\":\"eventName\"}]".ToList<ParamsModel>();
  328 +
  329 + // 检查paramList是否为空
  330 + if (paramList == null || paramList.Count == 0)
292 331 {
293   - excelconfig.ColumnModel.Add(new ExcelColumnModel() { Column = isExist.field, ExcelColumn = isExist.value });
  332 + return new { name = "拓客管理.xls", url = "", message = "参数列表解析失败" };
294 333 }
  334 +
  335 + ExcelConfig excelconfig = new ExcelConfig();
  336 + excelconfig.FileName = "拓客管理" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".xls";
  337 + excelconfig.HeadFont = "微软雅黑";
  338 + excelconfig.HeadPoint = 10;
  339 + excelconfig.IsAllSizeColumn = true;
  340 + excelconfig.ColumnModel = new List<ExcelColumnModel>();
  341 +
  342 + // 固定字段列表
  343 + List<string> selectKeyList = new List<string> { "id", "expansionTime", "expansionUserId", "expansionUserName", "customerName", "customerPhone", "buyNumber", "paymentMethod", "isAddWeChat", "remarks", "storeId", "storeName", "teamName", "eventId", "eventName" };
  344 +
  345 + foreach (var item in selectKeyList)
  346 + {
  347 + var isExist = paramList.Find(p => p.field == item);
  348 + if (isExist != null)
  349 + {
  350 + excelconfig.ColumnModel.Add(new ExcelColumnModel() { Column = isExist.field, ExcelColumn = isExist.value });
  351 + }
  352 + }
  353 +
  354 + var addPath = FileVariable.TemporaryFilePath + excelconfig.FileName;
  355 + ExcelExportHelper<TkjlbExportModel>.Export(exportData, excelconfig, addPath);
  356 + var fileName = _userManager.UserId + "|" + excelconfig.FileName + "|temporary";
  357 + var output = new { name = excelconfig.FileName, url = "/api/File/Download?encryption=" + DESCEncryption.Encrypt(fileName, "NCC") };
  358 + return output;
  359 + }
  360 + catch (Exception ex)
  361 + {
  362 + return new { name = "拓客管理" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".xls", url = "", message = $"导出失败: {ex.Message}", stackTrace = ex.StackTrace };
295 363 }
296   - var addPath = FileVariable.TemporaryFilePath + excelconfig.FileName;
297   - ExcelExportHelper<LqTkjlbListOutput>.Export(exportData, excelconfig, addPath);
298   - var fileName = _userManager.UserId + "|" + addPath + "|xls";
299   - var output = new { name = excelconfig.FileName, url = "/api/File/Download?encryption=" + DESCEncryption.Encrypt(fileName, "NCC") };
300   - return output;
301 364 }
302 365 #endregion
303 366  
... ...