Commit 81aab8ac9056a097b3050fbb600706d59d1b55dd
1 parent
2ef28d30
123
Showing
30 changed files
with
5149 additions
and
1466 deletions
Antis.Erp.Plat/antis-ncc-admin/src/utils/wtRejectApproval.js
| ... | ... | @@ -67,3 +67,39 @@ export function postApprovePurchaseInbound(id, remark) { |
| 67 | 67 | data: { remark: remark || '' } |
| 68 | 68 | }) |
| 69 | 69 | } |
| 70 | + | |
| 71 | +/** 应收款增加减少(wt_yskzjjs):提交审核 */ | |
| 72 | +export function postYskzjjsSubmitForAudit(id) { | |
| 73 | + return request({ | |
| 74 | + url: `/api/Extend/WtYskzjjs/Actions/SubmitForAudit/${id}`, | |
| 75 | + method: 'POST', | |
| 76 | + data: {} | |
| 77 | + }) | |
| 78 | +} | |
| 79 | + | |
| 80 | +/** 应收款增加减少:撤回审核(回草稿) */ | |
| 81 | +export function postYskzjjsWithdrawAudit(id) { | |
| 82 | + return request({ | |
| 83 | + url: `/api/Extend/WtYskzjjs/Actions/WithdrawAudit/${id}`, | |
| 84 | + method: 'POST', | |
| 85 | + data: {} | |
| 86 | + }) | |
| 87 | +} | |
| 88 | + | |
| 89 | +/** 应收款增加减少:审核通过 */ | |
| 90 | +export function postYskzjjsApprove(id, remark) { | |
| 91 | + return request({ | |
| 92 | + url: `/api/Extend/WtYskzjjs/Actions/Approve/${id}`, | |
| 93 | + method: 'POST', | |
| 94 | + data: { remark: remark || '' } | |
| 95 | + }) | |
| 96 | +} | |
| 97 | + | |
| 98 | +/** 应收款增加减少:审核不通过 */ | |
| 99 | +export function postYskzjjsReject(id, remark) { | |
| 100 | + return request({ | |
| 101 | + url: `/api/Extend/WtYskzjjs/Actions/Reject/${id}`, | |
| 102 | + method: 'POST', | |
| 103 | + data: { remark: remark || '' } | |
| 104 | + }) | |
| 105 | +} | ... | ... |
Antis.Erp.Plat/antis-ncc-admin/src/views/basic/todoCenter/index.vue
| ... | ... | @@ -4,34 +4,72 @@ |
| 4 | 4 | <div class="NCC-common-head"> |
| 5 | 5 | <div> |
| 6 | 6 | <span class="page-title"> |
| 7 | - <i class="icon-ym icon-ym-generator-todo" style="color:#409EFF;margin-right:8px" /> | |
| 7 | + <i | |
| 8 | + class="icon-ym icon-ym-generator-todo" | |
| 9 | + style="color:#409EFF;margin-right:8px" | |
| 10 | + /> | |
| 8 | 11 | 待办中心 |
| 9 | 12 | </span> |
| 10 | - <span class="page-desc">同价调拨单、销售/预售出库、销售/预售退货、采购入库单、委托代销发/退/结算、商品调价单等待办(与首页待办数据源一致)</span> | |
| 13 | + <span class="page-desc" | |
| 14 | + >同价调拨单、销售/预售出库、销售/预售退货、采购入库单、委托代销发/退/结算、商品调价单等待办(与首页待办数据源一致)</span | |
| 15 | + > | |
| 11 | 16 | </div> |
| 12 | 17 | <div class="NCC-common-head-right"> |
| 13 | 18 | <el-tooltip effect="dark" content="刷新" placement="top"> |
| 14 | - <el-link icon="icon-ym icon-ym-Refresh NCC-common-head-icon" :underline="false" @click="loadData" /> | |
| 19 | + <el-link | |
| 20 | + icon="icon-ym icon-ym-Refresh NCC-common-head-icon" | |
| 21 | + :underline="false" | |
| 22 | + @click="loadData" | |
| 23 | + /> | |
| 15 | 24 | </el-tooltip> |
| 16 | 25 | </div> |
| 17 | 26 | </div> |
| 18 | 27 | <div class="NCC-common-layout-main NCC-flex-main"> |
| 19 | - <el-table v-loading="loading" :data="list" border stripe empty-text="暂无待办"> | |
| 20 | - <el-table-column type="index" width="50" label="#" align="center" :index="tableIndexMethod" /> | |
| 21 | - <el-table-column prop="fullName" label="待办事项" min-width="280" show-overflow-tooltip> | |
| 28 | + <el-table | |
| 29 | + v-loading="loading" | |
| 30 | + :data="list" | |
| 31 | + border | |
| 32 | + stripe | |
| 33 | + empty-text="暂无待办" | |
| 34 | + > | |
| 35 | + <el-table-column | |
| 36 | + type="index" | |
| 37 | + width="50" | |
| 38 | + label="#" | |
| 39 | + align="center" | |
| 40 | + :index="tableIndexMethod" | |
| 41 | + /> | |
| 42 | + <el-table-column | |
| 43 | + prop="fullName" | |
| 44 | + label="待办事项" | |
| 45 | + min-width="280" | |
| 46 | + show-overflow-tooltip | |
| 47 | + > | |
| 22 | 48 | <template slot-scope="scope"> |
| 23 | 49 | <span class="cell-nowrap"> |
| 24 | - <i class="el-icon-document" style="color:#409EFF;margin-right:6px" /> | |
| 50 | + <i | |
| 51 | + class="el-icon-document" | |
| 52 | + style="color:#409EFF;margin-right:6px" | |
| 53 | + /> | |
| 25 | 54 | {{ cellText(scope.row.fullName) }} |
| 26 | 55 | </span> |
| 27 | 56 | </template> |
| 28 | 57 | </el-table-column> |
| 29 | - <el-table-column prop="creatorTime" label="日期" width="130" align="center"> | |
| 30 | - <template slot-scope="scope">{{ formatTime(scope.row.creatorTime) }}</template> | |
| 58 | + <el-table-column | |
| 59 | + prop="creatorTime" | |
| 60 | + label="日期" | |
| 61 | + width="130" | |
| 62 | + align="center" | |
| 63 | + > | |
| 64 | + <template slot-scope="scope">{{ | |
| 65 | + formatTime(scope.row.creatorTime) | |
| 66 | + }}</template> | |
| 31 | 67 | </el-table-column> |
| 32 | 68 | <el-table-column label="操作" width="200" align="left" fixed="right"> |
| 33 | 69 | <template slot-scope="scope"> |
| 34 | - <el-button type="text" @click="openProcess(scope.row)">处理</el-button> | |
| 70 | + <el-button type="text" @click="openProcess(scope.row)" | |
| 71 | + >处理</el-button | |
| 72 | + > | |
| 35 | 73 | </template> |
| 36 | 74 | </el-table-column> |
| 37 | 75 | </el-table> |
| ... | ... | @@ -53,9 +91,25 @@ |
| 53 | 91 | > |
| 54 | 92 | <template slot="footer"> |
| 55 | 93 | <el-button @click="closeProcessDialog">关闭</el-button> |
| 56 | - <el-button v-if="canLevel1Approve" type="warning" @click="handleLevel1Approve">一级审核</el-button> | |
| 57 | - <el-button v-if="canLevel2Approve" type="success" @click="handleLevel2Approve">二级审核</el-button> | |
| 58 | - <el-button v-if="canAuditReject" type="danger" plain @click="handleReject">审核不通过</el-button> | |
| 94 | + <el-button | |
| 95 | + v-if="canLevel1Approve" | |
| 96 | + type="warning" | |
| 97 | + @click="handleLevel1Approve" | |
| 98 | + >一级审核</el-button | |
| 99 | + > | |
| 100 | + <el-button | |
| 101 | + v-if="canLevel2Approve" | |
| 102 | + type="success" | |
| 103 | + @click="handleLevel2Approve" | |
| 104 | + >二级审核</el-button | |
| 105 | + > | |
| 106 | + <el-button | |
| 107 | + v-if="canAuditReject" | |
| 108 | + type="danger" | |
| 109 | + plain | |
| 110 | + @click="handleReject" | |
| 111 | + >审核不通过</el-button | |
| 112 | + > | |
| 59 | 113 | </template> |
| 60 | 114 | </WtTjdbdDetailView> |
| 61 | 115 | |
| ... | ... | @@ -67,9 +121,25 @@ |
| 67 | 121 | > |
| 68 | 122 | <template slot="footer"> |
| 69 | 123 | <el-button @click="closeProcessDialog">关闭</el-button> |
| 70 | - <el-button v-if="canLevel1Approve" type="warning" @click="handleLevel1Approve">一级审核</el-button> | |
| 71 | - <el-button v-if="canLevel2Approve" type="success" @click="handleLevel2Approve">二级审核</el-button> | |
| 72 | - <el-button v-if="canAuditReject" type="danger" plain @click="handleReject">审核不通过</el-button> | |
| 124 | + <el-button | |
| 125 | + v-if="canLevel1Approve" | |
| 126 | + type="warning" | |
| 127 | + @click="handleLevel1Approve" | |
| 128 | + >一级审核</el-button | |
| 129 | + > | |
| 130 | + <el-button | |
| 131 | + v-if="canLevel2Approve" | |
| 132 | + type="success" | |
| 133 | + @click="handleLevel2Approve" | |
| 134 | + >二级审核</el-button | |
| 135 | + > | |
| 136 | + <el-button | |
| 137 | + v-if="canAuditReject" | |
| 138 | + type="danger" | |
| 139 | + plain | |
| 140 | + @click="handleReject" | |
| 141 | + >审核不通过</el-button | |
| 142 | + > | |
| 73 | 143 | </template> |
| 74 | 144 | </WtXsckdDetailView> |
| 75 | 145 | |
| ... | ... | @@ -81,9 +151,25 @@ |
| 81 | 151 | > |
| 82 | 152 | <template slot="footer"> |
| 83 | 153 | <el-button @click="closeProcessDialog">关闭</el-button> |
| 84 | - <el-button v-if="canLevel1Approve" type="warning" @click="handleLevel1Approve">一级审核</el-button> | |
| 85 | - <el-button v-if="canLevel2Approve" type="success" @click="handleLevel2Approve">二级审核</el-button> | |
| 86 | - <el-button v-if="canAuditReject" type="danger" plain @click="handleReject">审核不通过</el-button> | |
| 154 | + <el-button | |
| 155 | + v-if="canLevel1Approve" | |
| 156 | + type="warning" | |
| 157 | + @click="handleLevel1Approve" | |
| 158 | + >一级审核</el-button | |
| 159 | + > | |
| 160 | + <el-button | |
| 161 | + v-if="canLevel2Approve" | |
| 162 | + type="success" | |
| 163 | + @click="handleLevel2Approve" | |
| 164 | + >二级审核</el-button | |
| 165 | + > | |
| 166 | + <el-button | |
| 167 | + v-if="canAuditReject" | |
| 168 | + type="danger" | |
| 169 | + plain | |
| 170 | + @click="handleReject" | |
| 171 | + >审核不通过</el-button | |
| 172 | + > | |
| 87 | 173 | </template> |
| 88 | 174 | </WtXsthdDetailView> |
| 89 | 175 | |
| ... | ... | @@ -95,9 +181,25 @@ |
| 95 | 181 | > |
| 96 | 182 | <template slot="footer"> |
| 97 | 183 | <el-button @click="closeProcessDialog">关闭</el-button> |
| 98 | - <el-button v-if="canLevel1Approve" type="warning" @click="handleLevel1Approve">一级审核</el-button> | |
| 99 | - <el-button v-if="canLevel2Approve" type="success" @click="handleLevel2Approve">二级审核</el-button> | |
| 100 | - <el-button v-if="canAuditReject" type="danger" plain @click="handleReject">审核不通过</el-button> | |
| 184 | + <el-button | |
| 185 | + v-if="canLevel1Approve" | |
| 186 | + type="warning" | |
| 187 | + @click="handleLevel1Approve" | |
| 188 | + >一级审核</el-button | |
| 189 | + > | |
| 190 | + <el-button | |
| 191 | + v-if="canLevel2Approve" | |
| 192 | + type="success" | |
| 193 | + @click="handleLevel2Approve" | |
| 194 | + >二级审核</el-button | |
| 195 | + > | |
| 196 | + <el-button | |
| 197 | + v-if="canAuditReject" | |
| 198 | + type="danger" | |
| 199 | + plain | |
| 200 | + @click="handleReject" | |
| 201 | + >审核不通过</el-button | |
| 202 | + > | |
| 101 | 203 | </template> |
| 102 | 204 | </WtYsckdDetailView> |
| 103 | 205 | |
| ... | ... | @@ -109,9 +211,25 @@ |
| 109 | 211 | > |
| 110 | 212 | <template slot="footer"> |
| 111 | 213 | <el-button @click="closeProcessDialog">关闭</el-button> |
| 112 | - <el-button v-if="canLevel1Approve" type="warning" @click="handleLevel1Approve">一级审核</el-button> | |
| 113 | - <el-button v-if="canLevel2Approve" type="success" @click="handleLevel2Approve">二级审核</el-button> | |
| 114 | - <el-button v-if="canAuditReject" type="danger" plain @click="handleReject">审核不通过</el-button> | |
| 214 | + <el-button | |
| 215 | + v-if="canLevel1Approve" | |
| 216 | + type="warning" | |
| 217 | + @click="handleLevel1Approve" | |
| 218 | + >一级审核</el-button | |
| 219 | + > | |
| 220 | + <el-button | |
| 221 | + v-if="canLevel2Approve" | |
| 222 | + type="success" | |
| 223 | + @click="handleLevel2Approve" | |
| 224 | + >二级审核</el-button | |
| 225 | + > | |
| 226 | + <el-button | |
| 227 | + v-if="canAuditReject" | |
| 228 | + type="danger" | |
| 229 | + plain | |
| 230 | + @click="handleReject" | |
| 231 | + >审核不通过</el-button | |
| 232 | + > | |
| 115 | 233 | </template> |
| 116 | 234 | </WtYsthdDetailView> |
| 117 | 235 | |
| ... | ... | @@ -123,9 +241,25 @@ |
| 123 | 241 | > |
| 124 | 242 | <template slot="footer"> |
| 125 | 243 | <el-button @click="closeProcessDialog">关闭</el-button> |
| 126 | - <el-button v-if="canLevel1Approve" type="warning" @click="handleLevel1Approve">一级审核</el-button> | |
| 127 | - <el-button v-if="canLevel2Approve" type="success" @click="handleLevel2Approve">二级审核</el-button> | |
| 128 | - <el-button v-if="canAuditReject" type="danger" plain @click="handleReject">审核不通过</el-button> | |
| 244 | + <el-button | |
| 245 | + v-if="canLevel1Approve" | |
| 246 | + type="warning" | |
| 247 | + @click="handleLevel1Approve" | |
| 248 | + >一级审核</el-button | |
| 249 | + > | |
| 250 | + <el-button | |
| 251 | + v-if="canLevel2Approve" | |
| 252 | + type="success" | |
| 253 | + @click="handleLevel2Approve" | |
| 254 | + >二级审核</el-button | |
| 255 | + > | |
| 256 | + <el-button | |
| 257 | + v-if="canAuditReject" | |
| 258 | + type="danger" | |
| 259 | + plain | |
| 260 | + @click="handleReject" | |
| 261 | + >审核不通过</el-button | |
| 262 | + > | |
| 129 | 263 | </template> |
| 130 | 264 | </WtCgrkdDetailView> |
| 131 | 265 | |
| ... | ... | @@ -137,9 +271,25 @@ |
| 137 | 271 | > |
| 138 | 272 | <template slot="footer"> |
| 139 | 273 | <el-button @click="closeProcessDialog">关闭</el-button> |
| 140 | - <el-button v-if="canLevel1Approve" type="warning" @click="handleLevel1Approve">一级审核</el-button> | |
| 141 | - <el-button v-if="canLevel2Approve" type="success" @click="handleLevel2Approve">二级审核</el-button> | |
| 142 | - <el-button v-if="canAuditReject" type="danger" plain @click="handleReject">审核不通过</el-button> | |
| 274 | + <el-button | |
| 275 | + v-if="canLevel1Approve" | |
| 276 | + type="warning" | |
| 277 | + @click="handleLevel1Approve" | |
| 278 | + >一级审核</el-button | |
| 279 | + > | |
| 280 | + <el-button | |
| 281 | + v-if="canLevel2Approve" | |
| 282 | + type="success" | |
| 283 | + @click="handleLevel2Approve" | |
| 284 | + >二级审核</el-button | |
| 285 | + > | |
| 286 | + <el-button | |
| 287 | + v-if="canAuditReject" | |
| 288 | + type="danger" | |
| 289 | + plain | |
| 290 | + @click="handleReject" | |
| 291 | + >审核不通过</el-button | |
| 292 | + > | |
| 143 | 293 | </template> |
| 144 | 294 | </WtPriceAdjustDetailView> |
| 145 | 295 | |
| ... | ... | @@ -151,9 +301,25 @@ |
| 151 | 301 | > |
| 152 | 302 | <template slot="footer"> |
| 153 | 303 | <el-button @click="closeProcessDialog">关闭</el-button> |
| 154 | - <el-button v-if="canLevel1Approve" type="warning" @click="handleLevel1Approve">一级审核</el-button> | |
| 155 | - <el-button v-if="canLevel2Approve" type="success" @click="handleLevel2Approve">二级审核</el-button> | |
| 156 | - <el-button v-if="canAuditReject" type="danger" plain @click="handleReject">审核不通过</el-button> | |
| 304 | + <el-button | |
| 305 | + v-if="canLevel1Approve" | |
| 306 | + type="warning" | |
| 307 | + @click="handleLevel1Approve" | |
| 308 | + >一级审核</el-button | |
| 309 | + > | |
| 310 | + <el-button | |
| 311 | + v-if="canLevel2Approve" | |
| 312 | + type="success" | |
| 313 | + @click="handleLevel2Approve" | |
| 314 | + >二级审核</el-button | |
| 315 | + > | |
| 316 | + <el-button | |
| 317 | + v-if="canAuditReject" | |
| 318 | + type="danger" | |
| 319 | + plain | |
| 320 | + @click="handleReject" | |
| 321 | + >审核不通过</el-button | |
| 322 | + > | |
| 157 | 323 | </template> |
| 158 | 324 | </WtXswtdxfhdDetailView> |
| 159 | 325 | |
| ... | ... | @@ -165,9 +331,25 @@ |
| 165 | 331 | > |
| 166 | 332 | <template slot="footer"> |
| 167 | 333 | <el-button @click="closeProcessDialog">关闭</el-button> |
| 168 | - <el-button v-if="canLevel1Approve" type="warning" @click="handleLevel1Approve">一级审核</el-button> | |
| 169 | - <el-button v-if="canLevel2Approve" type="success" @click="handleLevel2Approve">二级审核</el-button> | |
| 170 | - <el-button v-if="canAuditReject" type="danger" plain @click="handleReject">审核不通过</el-button> | |
| 334 | + <el-button | |
| 335 | + v-if="canLevel1Approve" | |
| 336 | + type="warning" | |
| 337 | + @click="handleLevel1Approve" | |
| 338 | + >一级审核</el-button | |
| 339 | + > | |
| 340 | + <el-button | |
| 341 | + v-if="canLevel2Approve" | |
| 342 | + type="success" | |
| 343 | + @click="handleLevel2Approve" | |
| 344 | + >二级审核</el-button | |
| 345 | + > | |
| 346 | + <el-button | |
| 347 | + v-if="canAuditReject" | |
| 348 | + type="danger" | |
| 349 | + plain | |
| 350 | + @click="handleReject" | |
| 351 | + >审核不通过</el-button | |
| 352 | + > | |
| 171 | 353 | </template> |
| 172 | 354 | </WtXswtdxthdDetailView> |
| 173 | 355 | |
| ... | ... | @@ -179,44 +361,98 @@ |
| 179 | 361 | > |
| 180 | 362 | <template slot="footer"> |
| 181 | 363 | <el-button @click="closeProcessDialog">关闭</el-button> |
| 182 | - <el-button v-if="canLevel1Approve" type="warning" @click="handleLevel1Approve">一级审核</el-button> | |
| 183 | - <el-button v-if="canLevel2Approve" type="success" @click="handleLevel2Approve">二级审核</el-button> | |
| 184 | - <el-button v-if="canAuditReject" type="danger" plain @click="handleReject">审核不通过</el-button> | |
| 364 | + <el-button | |
| 365 | + v-if="canLevel1Approve" | |
| 366 | + type="warning" | |
| 367 | + @click="handleLevel1Approve" | |
| 368 | + >一级审核</el-button | |
| 369 | + > | |
| 370 | + <el-button | |
| 371 | + v-if="canLevel2Approve" | |
| 372 | + type="success" | |
| 373 | + @click="handleLevel2Approve" | |
| 374 | + >二级审核</el-button | |
| 375 | + > | |
| 376 | + <el-button | |
| 377 | + v-if="canAuditReject" | |
| 378 | + type="danger" | |
| 379 | + plain | |
| 380 | + @click="handleReject" | |
| 381 | + >审核不通过</el-button | |
| 382 | + > | |
| 185 | 383 | </template> |
| 186 | 384 | </WtXswtdxjsdDetailView> |
| 385 | + | |
| 386 | + <WtYskzjjsQtDetailView | |
| 387 | + v-if="processVisible && processBillType === '其他应收单'" | |
| 388 | + ref="processDlg" | |
| 389 | + @close="onProcessDialogClose" | |
| 390 | + @loaded="onProcessLoaded" | |
| 391 | + > | |
| 392 | + <template slot="footer"> | |
| 393 | + <el-button @click="closeProcessDialog">关闭</el-button> | |
| 394 | + <el-button | |
| 395 | + v-if="canLevel1Approve" | |
| 396 | + type="warning" | |
| 397 | + @click="handleLevel1Approve" | |
| 398 | + >一级审核</el-button | |
| 399 | + > | |
| 400 | + <el-button | |
| 401 | + v-if="canLevel2Approve" | |
| 402 | + type="success" | |
| 403 | + @click="handleLevel2Approve" | |
| 404 | + >二级审核</el-button | |
| 405 | + > | |
| 406 | + <el-button | |
| 407 | + v-if="canAuditReject" | |
| 408 | + type="danger" | |
| 409 | + plain | |
| 410 | + @click="handleReject" | |
| 411 | + >审核不通过</el-button | |
| 412 | + > | |
| 413 | + </template> | |
| 414 | + </WtYskzjjsQtDetailView> | |
| 187 | 415 | </div> |
| 188 | 416 | </template> |
| 189 | 417 | |
| 190 | 418 | <script> |
| 191 | -import { getMyFlowTodo } from '@/api/home' | |
| 192 | -import WtTjdbdDetailView from '@/views/wtTjdbd/detail-view.vue' | |
| 193 | -import WtXsckdDetailView from '@/views/wtXsckd/detail-view.vue' | |
| 194 | -import WtXsthdDetailView from '@/views/wtXsthd/detail-view.vue' | |
| 195 | -import WtYsckdDetailView from '@/views/wtYsckd/detail-view.vue' | |
| 196 | -import WtYsthdDetailView from '@/views/wtYsthd/detail-view.vue' | |
| 197 | -import WtCgrkdDetailView from '@/views/wtCgrkd/detail-view.vue' | |
| 198 | -import WtPriceAdjustDetailView from '@/views/wtPriceAdjust/detail-view.vue' | |
| 199 | -import WtXswtdxfhdDetailView from '@/views/wtXswtdxfhd/detail-view.vue' | |
| 200 | -import WtXswtdxthdDetailView from '@/views/wtXswtdxthd/detail-view.vue' | |
| 201 | -import WtXswtdxjsdDetailView from '@/views/wtXswtdxjsd/detail-view.vue' | |
| 202 | -import { promptApprovalRemark, postApproveGeneric, postRejectGeneric } from '@/utils/wtRejectApproval' | |
| 419 | +import { getMyFlowTodo } from "@/api/home"; | |
| 420 | +import WtTjdbdDetailView from "@/views/wtTjdbd/detail-view.vue"; | |
| 421 | +import WtXsckdDetailView from "@/views/wtXsckd/detail-view.vue"; | |
| 422 | +import WtXsthdDetailView from "@/views/wtXsthd/detail-view.vue"; | |
| 423 | +import WtYsckdDetailView from "@/views/wtYsckd/detail-view.vue"; | |
| 424 | +import WtYsthdDetailView from "@/views/wtYsthd/detail-view.vue"; | |
| 425 | +import WtCgrkdDetailView from "@/views/wtCgrkd/detail-view.vue"; | |
| 426 | +import WtPriceAdjustDetailView from "@/views/wtPriceAdjust/detail-view.vue"; | |
| 427 | +import WtXswtdxfhdDetailView from "@/views/wtXswtdxfhd/detail-view.vue"; | |
| 428 | +import WtXswtdxthdDetailView from "@/views/wtXswtdxthd/detail-view.vue"; | |
| 429 | +import WtXswtdxjsdDetailView from "@/views/wtXswtdxjsd/detail-view.vue"; | |
| 430 | +import WtYskzjjsQtDetailView from "@/views/wtYskzjjs_qt/detail-view.vue"; | |
| 431 | +import { | |
| 432 | + promptApprovalRemark, | |
| 433 | + postApproveGeneric, | |
| 434 | + postRejectGeneric, | |
| 435 | + postYskzjjsApprove, | |
| 436 | + postYskzjjsReject | |
| 437 | +} from "@/utils/wtRejectApproval"; | |
| 203 | 438 | |
| 204 | 439 | // 较长/易混淆的单据名称靠前,便于 fullName 解析 |
| 205 | 440 | const BILL_TYPES = [ |
| 206 | - '委托代销退货单', | |
| 207 | - '委托代销发货单', | |
| 208 | - '委托代销结算单', | |
| 209 | - '同价调拨单', | |
| 210 | - '预售出库单', | |
| 211 | - '预售退货单', | |
| 212 | - '销售出库单', | |
| 213 | - '销售退货单', | |
| 214 | - '采购入库单', | |
| 215 | - '商品调价单' | |
| 216 | -] | |
| 441 | + "委托代销退货单", | |
| 442 | + "委托代销发货单", | |
| 443 | + "委托代销结算单", | |
| 444 | + "同价调拨单", | |
| 445 | + "预售出库单", | |
| 446 | + "预售退货单", | |
| 447 | + "销售出库单", | |
| 448 | + "销售退货单", | |
| 449 | + "采购入库单", | |
| 450 | + "商品调价单", | |
| 451 | + "其他应收单" | |
| 452 | +]; | |
| 217 | 453 | |
| 218 | 454 | export default { |
| 219 | - name: 'todoCenter', | |
| 455 | + name: "todoCenter", | |
| 220 | 456 | components: { |
| 221 | 457 | WtTjdbdDetailView, |
| 222 | 458 | WtXsckdDetailView, |
| ... | ... | @@ -227,7 +463,8 @@ export default { |
| 227 | 463 | WtPriceAdjustDetailView, |
| 228 | 464 | WtXswtdxfhdDetailView, |
| 229 | 465 | WtXswtdxthdDetailView, |
| 230 | - WtXswtdxjsdDetailView | |
| 466 | + WtXswtdxjsdDetailView, | |
| 467 | + WtYskzjjsQtDetailView | |
| 231 | 468 | }, |
| 232 | 469 | data() { |
| 233 | 470 | return { |
| ... | ... | @@ -239,291 +476,335 @@ export default { |
| 239 | 476 | pageSize: 20 |
| 240 | 477 | }, |
| 241 | 478 | processVisible: false, |
| 242 | - processBillId: '', | |
| 243 | - processBillType: '', | |
| 479 | + processBillId: "", | |
| 480 | + processBillType: "", | |
| 244 | 481 | processDetail: null, |
| 245 | 482 | /** 审核成功后刷新详情,若已为「已审核」则关闭弹窗(含单级审核一次通过) */ |
| 246 | 483 | pendingCloseWhenApproved: false, |
| 247 | 484 | /** 审核不通过后刷新详情,若为「审核不通过」则关闭弹窗 */ |
| 248 | 485 | pendingCloseAfterReject: false |
| 249 | - } | |
| 486 | + }; | |
| 250 | 487 | }, |
| 251 | 488 | computed: { |
| 252 | 489 | canLevel1Approve() { |
| 253 | - const s = this.getAuditStatus(this.processDetail) | |
| 254 | - return !s || s === '待审核' | |
| 490 | + const s = this.getAuditStatus(this.processDetail); | |
| 491 | + return !s || s === "待审核"; | |
| 255 | 492 | }, |
| 256 | 493 | canLevel2Approve() { |
| 257 | - const s = this.getAuditStatus(this.processDetail) | |
| 258 | - return s === '一级已审' || s === '待二级' || s === '一级已审/待二级' | |
| 494 | + const s = this.getAuditStatus(this.processDetail); | |
| 495 | + return s === "一级已审" || s === "待二级" || s === "一级已审/待二级"; | |
| 259 | 496 | }, |
| 260 | 497 | canAuditReject() { |
| 261 | - return this.canLevel1Approve || this.canLevel2Approve | |
| 498 | + return this.canLevel1Approve || this.canLevel2Approve; | |
| 262 | 499 | } |
| 263 | 500 | }, |
| 264 | 501 | created() { |
| 265 | - this.loadData() | |
| 502 | + this.loadData(); | |
| 266 | 503 | }, |
| 267 | 504 | methods: { |
| 268 | 505 | cellText(v) { |
| 269 | - if (v === null || v === undefined || v === '') return '无' | |
| 270 | - return v | |
| 506 | + if (v === null || v === undefined || v === "") return "无"; | |
| 507 | + return v; | |
| 271 | 508 | }, |
| 272 | 509 | getAuditStatus(row) { |
| 273 | - if (!row) return '' | |
| 274 | - const z = row.djzt != null && row.djzt !== '' ? row.djzt : row.Djzt | |
| 275 | - const sh = row.shzt != null && row.shzt !== '' ? row.shzt : row.Shzt | |
| 276 | - return String(z || sh || '').trim() | |
| 510 | + if (!row) return ""; | |
| 511 | + const z = row.djzt != null && row.djzt !== "" ? row.djzt : row.Djzt; | |
| 512 | + const sh = row.shzt != null && row.shzt !== "" ? row.shzt : row.Shzt; | |
| 513 | + return String(z || sh || "").trim(); | |
| 277 | 514 | }, |
| 278 | 515 | resolveBillType(row) { |
| 279 | - const raw = row && row.billType != null ? String(row.billType).trim() : '' | |
| 280 | - if (raw && BILL_TYPES.includes(raw)) return raw | |
| 281 | - const name = row && row.fullName ? String(row.fullName) : '' | |
| 516 | + const raw = | |
| 517 | + row && row.billType != null ? String(row.billType).trim() : ""; | |
| 518 | + if (raw && BILL_TYPES.includes(raw)) return raw; | |
| 519 | + const name = row && row.fullName ? String(row.fullName) : ""; | |
| 282 | 520 | for (let i = 0; i < BILL_TYPES.length; i++) { |
| 283 | - if (name.includes(BILL_TYPES[i])) return BILL_TYPES[i] | |
| 521 | + if (name.includes(BILL_TYPES[i])) return BILL_TYPES[i]; | |
| 284 | 522 | } |
| 285 | - if (name.includes('TJD')) return '商品调价单' | |
| 286 | - return '同价调拨单' | |
| 523 | + if (name.includes("TJD")) return "商品调价单"; | |
| 524 | + return "同价调拨单"; | |
| 287 | 525 | }, |
| 288 | 526 | formatTime(v) { |
| 289 | - if (!v) return '无' | |
| 290 | - const d = new Date(v) | |
| 291 | - if (isNaN(d.getTime())) return '无' | |
| 292 | - const y = d.getFullYear() | |
| 293 | - const m = String(d.getMonth() + 1).padStart(2, '0') | |
| 294 | - const day = String(d.getDate()).padStart(2, '0') | |
| 295 | - return `${y}-${m}-${day}` | |
| 527 | + if (!v) return "无"; | |
| 528 | + const d = new Date(v); | |
| 529 | + if (isNaN(d.getTime())) return "无"; | |
| 530 | + const y = d.getFullYear(); | |
| 531 | + const m = String(d.getMonth() + 1).padStart(2, "0"); | |
| 532 | + const day = String(d.getDate()).padStart(2, "0"); | |
| 533 | + return `${y}-${m}-${day}`; | |
| 296 | 534 | }, |
| 297 | 535 | tableIndexMethod(index) { |
| 298 | - return (this.listQuery.currentPage - 1) * this.listQuery.pageSize + index + 1 | |
| 536 | + return ( | |
| 537 | + (this.listQuery.currentPage - 1) * this.listQuery.pageSize + index + 1 | |
| 538 | + ); | |
| 299 | 539 | }, |
| 300 | 540 | loadData() { |
| 301 | - this.loading = true | |
| 541 | + this.loading = true; | |
| 302 | 542 | return getMyFlowTodo({ |
| 303 | 543 | currentPage: this.listQuery.currentPage, |
| 304 | 544 | pageSize: this.listQuery.pageSize |
| 305 | 545 | }) |
| 306 | 546 | .then(res => { |
| 307 | - const raw = (res.data && res.data.list) || [] | |
| 308 | - this.list = Array.isArray(raw) ? raw : [] | |
| 309 | - const pg = res.data && res.data.pagination | |
| 310 | - this.total = (pg && typeof pg.total === 'number' ? pg.total : this.list.length) || 0 | |
| 311 | - if (this.list.length === 0 && this.total > 0 && this.listQuery.currentPage > 1) { | |
| 312 | - const lastPage = Math.max(1, Math.ceil(this.total / this.listQuery.pageSize)) | |
| 547 | + const raw = (res.data && res.data.list) || []; | |
| 548 | + this.list = Array.isArray(raw) ? raw : []; | |
| 549 | + const pg = res.data && res.data.pagination; | |
| 550 | + this.total = | |
| 551 | + (pg && typeof pg.total === "number" | |
| 552 | + ? pg.total | |
| 553 | + : this.list.length) || 0; | |
| 554 | + if ( | |
| 555 | + this.list.length === 0 && | |
| 556 | + this.total > 0 && | |
| 557 | + this.listQuery.currentPage > 1 | |
| 558 | + ) { | |
| 559 | + const lastPage = Math.max( | |
| 560 | + 1, | |
| 561 | + Math.ceil(this.total / this.listQuery.pageSize) | |
| 562 | + ); | |
| 313 | 563 | if (this.listQuery.currentPage > lastPage) { |
| 314 | - this.listQuery.currentPage = lastPage | |
| 315 | - return this.loadData() | |
| 564 | + this.listQuery.currentPage = lastPage; | |
| 565 | + return this.loadData(); | |
| 316 | 566 | } |
| 317 | 567 | } |
| 318 | 568 | }) |
| 319 | 569 | .catch(() => { |
| 320 | - this.$message.error('加载待办失败') | |
| 321 | - this.list = [] | |
| 322 | - this.total = 0 | |
| 570 | + this.$message.error("加载待办失败"); | |
| 571 | + this.list = []; | |
| 572 | + this.total = 0; | |
| 323 | 573 | }) |
| 324 | 574 | .finally(() => { |
| 325 | - this.loading = false | |
| 326 | - }) | |
| 575 | + this.loading = false; | |
| 576 | + }); | |
| 327 | 577 | }, |
| 328 | 578 | openProcess(row) { |
| 329 | - const id = row && row.id | |
| 579 | + const id = row && row.id; | |
| 330 | 580 | if (!id) { |
| 331 | - this.$message.warning('无单据编号') | |
| 332 | - return | |
| 581 | + this.$message.warning("无单据编号"); | |
| 582 | + return; | |
| 333 | 583 | } |
| 334 | - const billType = this.resolveBillType(row) | |
| 335 | - this.processBillId = String(id) | |
| 336 | - this.processBillType = billType | |
| 337 | - this.processDetail = null | |
| 338 | - this.pendingCloseWhenApproved = false | |
| 339 | - this.pendingCloseAfterReject = false | |
| 340 | - this.processVisible = true | |
| 584 | + const billType = this.resolveBillType(row); | |
| 585 | + this.processBillId = String(id); | |
| 586 | + this.processBillType = billType; | |
| 587 | + this.processDetail = null; | |
| 588 | + this.pendingCloseWhenApproved = false; | |
| 589 | + this.pendingCloseAfterReject = false; | |
| 590 | + this.processVisible = true; | |
| 341 | 591 | this.$nextTick(() => { |
| 342 | - if (this.$refs.processDlg) this.$refs.processDlg.init(this.processBillId) | |
| 343 | - }) | |
| 592 | + if (this.$refs.processDlg) | |
| 593 | + this.$refs.processDlg.init(this.processBillId); | |
| 594 | + }); | |
| 344 | 595 | }, |
| 345 | 596 | onProcessDialogClose() { |
| 346 | - this.processVisible = false | |
| 347 | - this.processBillId = '' | |
| 348 | - this.processBillType = '' | |
| 349 | - this.processDetail = null | |
| 350 | - this.pendingCloseWhenApproved = false | |
| 351 | - this.pendingCloseAfterReject = false | |
| 597 | + this.processVisible = false; | |
| 598 | + this.processBillId = ""; | |
| 599 | + this.processBillType = ""; | |
| 600 | + this.processDetail = null; | |
| 601 | + this.pendingCloseWhenApproved = false; | |
| 602 | + this.pendingCloseAfterReject = false; | |
| 352 | 603 | }, |
| 353 | 604 | closeProcessDialog() { |
| 354 | - if (this.$refs.processDlg) this.$refs.processDlg.close() | |
| 605 | + if (this.$refs.processDlg) this.$refs.processDlg.close(); | |
| 355 | 606 | }, |
| 356 | 607 | onProcessLoaded(detail) { |
| 357 | - this.processDetail = detail || null | |
| 608 | + this.processDetail = detail || null; | |
| 358 | 609 | if (this.pendingCloseWhenApproved) { |
| 359 | - this.pendingCloseWhenApproved = false | |
| 360 | - if (this.getAuditStatus(detail) === '已审核') { | |
| 610 | + this.pendingCloseWhenApproved = false; | |
| 611 | + if (this.getAuditStatus(detail) === "已审核") { | |
| 361 | 612 | this.$nextTick(() => { |
| 362 | - if (this.$refs.processDlg) this.$refs.processDlg.close() | |
| 363 | - }) | |
| 613 | + if (this.$refs.processDlg) this.$refs.processDlg.close(); | |
| 614 | + }); | |
| 364 | 615 | } |
| 365 | 616 | } |
| 366 | 617 | if (this.pendingCloseAfterReject) { |
| 367 | - this.pendingCloseAfterReject = false | |
| 368 | - if (this.getAuditStatus(detail) === '审核不通过') { | |
| 618 | + this.pendingCloseAfterReject = false; | |
| 619 | + if (this.getAuditStatus(detail) === "审核不通过") { | |
| 369 | 620 | this.$nextTick(() => { |
| 370 | - if (this.$refs.processDlg) this.$refs.processDlg.close() | |
| 371 | - }) | |
| 621 | + if (this.$refs.processDlg) this.$refs.processDlg.close(); | |
| 622 | + }); | |
| 372 | 623 | } |
| 373 | 624 | } |
| 374 | 625 | }, |
| 375 | 626 | level1Confirm() { |
| 376 | - const t = this.processBillType | |
| 377 | - if (t === '同价调拨单') { | |
| 378 | - return { msg: '确认执行一级审核(调出仓确认发货)?', title: '一级审核确认' } | |
| 627 | + const t = this.processBillType; | |
| 628 | + if (t === "其他应收单") { | |
| 629 | + return { msg: "确认执行一级审核该其他应收单?", title: "审核确认" }; | |
| 379 | 630 | } |
| 380 | - if (t === '销售出库单') { | |
| 381 | - return { msg: '确认审核该销售出库单?', title: '审核确认' } | |
| 631 | + if (t === "同价调拨单") { | |
| 632 | + return { | |
| 633 | + msg: "确认执行一级审核(调出仓确认发货)?", | |
| 634 | + title: "一级审核确认" | |
| 635 | + }; | |
| 636 | + } | |
| 637 | + if (t === "销售出库单") { | |
| 638 | + return { msg: "确认审核该销售出库单?", title: "审核确认" }; | |
| 382 | 639 | } |
| 383 | - if (t === '销售退货单') { | |
| 384 | - return { msg: '确认审核该销售退货单?', title: '审核确认' } | |
| 640 | + if (t === "销售退货单") { | |
| 641 | + return { msg: "确认审核该销售退货单?", title: "审核确认" }; | |
| 385 | 642 | } |
| 386 | - if (t === '预售出库单') { | |
| 387 | - return { msg: '确认审核该预售出库单?', title: '审核确认' } | |
| 643 | + if (t === "预售出库单") { | |
| 644 | + return { msg: "确认审核该预售出库单?", title: "审核确认" }; | |
| 388 | 645 | } |
| 389 | - if (t === '预售退货单') { | |
| 390 | - return { msg: '确认审核该预售退货单?', title: '审核确认' } | |
| 646 | + if (t === "预售退货单") { | |
| 647 | + return { msg: "确认审核该预售退货单?", title: "审核确认" }; | |
| 391 | 648 | } |
| 392 | - if (t === '采购入库单') { | |
| 649 | + if (t === "采购入库单") { | |
| 393 | 650 | return { |
| 394 | - msg: '确认审核该采购入库单?最终审核通过后将生成序列号并更新库存。', | |
| 395 | - title: '审核确认' | |
| 396 | - } | |
| 651 | + msg: "确认审核该采购入库单?最终审核通过后将生成序列号并更新库存。", | |
| 652 | + title: "审核确认" | |
| 653 | + }; | |
| 397 | 654 | } |
| 398 | - if (t === '商品调价单') { | |
| 655 | + if (t === "商品调价单") { | |
| 399 | 656 | return { |
| 400 | - msg: '确认审核该商品调价单?通过后调后售价将写入商品档案零售价。', | |
| 401 | - title: '审核确认' | |
| 402 | - } | |
| 657 | + msg: "确认审核该商品调价单?通过后调后售价将写入商品档案零售价。", | |
| 658 | + title: "审核确认" | |
| 659 | + }; | |
| 403 | 660 | } |
| 404 | - if (t === '委托代销发货单') { | |
| 405 | - return { msg: '确认审核该委托代销发货单?', title: '审核确认' } | |
| 661 | + if (t === "委托代销发货单") { | |
| 662 | + return { msg: "确认审核该委托代销发货单?", title: "审核确认" }; | |
| 406 | 663 | } |
| 407 | - if (t === '委托代销退货单') { | |
| 408 | - return { msg: '确认审核该委托代销退货单?', title: '审核确认' } | |
| 664 | + if (t === "委托代销退货单") { | |
| 665 | + return { msg: "确认审核该委托代销退货单?", title: "审核确认" }; | |
| 409 | 666 | } |
| 410 | - if (t === '委托代销结算单') { | |
| 411 | - return { msg: '确认审核该委托代销结算单?', title: '审核确认' } | |
| 667 | + if (t === "委托代销结算单") { | |
| 668 | + return { msg: "确认审核该委托代销结算单?", title: "审核确认" }; | |
| 412 | 669 | } |
| 413 | - return { msg: '确认执行一级审核?', title: '审核确认' } | |
| 670 | + return { msg: "确认执行一级审核?", title: "审核确认" }; | |
| 414 | 671 | }, |
| 415 | 672 | level2Confirm() { |
| 416 | - const t = this.processBillType | |
| 417 | - if (t === '同价调拨单') { | |
| 418 | - return { msg: '确认执行二级审核(确认收货并入库出库)?', title: '二级审核确认' } | |
| 673 | + const t = this.processBillType; | |
| 674 | + if (t === "同价调拨单") { | |
| 675 | + return { | |
| 676 | + msg: "确认执行二级审核(确认收货并入库出库)?", | |
| 677 | + title: "二级审核确认" | |
| 678 | + }; | |
| 419 | 679 | } |
| 420 | - if (t === '销售出库单') { | |
| 421 | - return { msg: '确认审核该销售出库单?', title: '审核确认' } | |
| 680 | + if (t === "销售出库单") { | |
| 681 | + return { msg: "确认审核该销售出库单?", title: "审核确认" }; | |
| 422 | 682 | } |
| 423 | - if (t === '销售退货单') { | |
| 424 | - return { msg: '确认审核该销售退货单?', title: '审核确认' } | |
| 683 | + if (t === "销售退货单") { | |
| 684 | + return { msg: "确认审核该销售退货单?", title: "审核确认" }; | |
| 425 | 685 | } |
| 426 | - if (t === '预售出库单') { | |
| 427 | - return { msg: '确认审核该预售出库单?', title: '审核确认' } | |
| 686 | + if (t === "预售出库单") { | |
| 687 | + return { msg: "确认审核该预售出库单?", title: "审核确认" }; | |
| 428 | 688 | } |
| 429 | - if (t === '预售退货单') { | |
| 430 | - return { msg: '确认审核该预售退货单?', title: '审核确认' } | |
| 689 | + if (t === "预售退货单") { | |
| 690 | + return { msg: "确认审核该预售退货单?", title: "审核确认" }; | |
| 431 | 691 | } |
| 432 | - if (t === '采购入库单') { | |
| 692 | + if (t === "采购入库单") { | |
| 433 | 693 | return { |
| 434 | - msg: '确认审核该采购入库单?最终审核通过后将生成序列号并更新库存。', | |
| 435 | - title: '审核确认' | |
| 436 | - } | |
| 694 | + msg: "确认审核该采购入库单?最终审核通过后将生成序列号并更新库存。", | |
| 695 | + title: "审核确认" | |
| 696 | + }; | |
| 437 | 697 | } |
| 438 | - if (t === '商品调价单') { | |
| 698 | + if (t === "商品调价单") { | |
| 439 | 699 | return { |
| 440 | - msg: '确认二级审核该商品调价单?通过后调后售价将写入商品档案零售价。', | |
| 441 | - title: '二级审核确认' | |
| 442 | - } | |
| 700 | + msg: "确认二级审核该商品调价单?通过后调后售价将写入商品档案零售价。", | |
| 701 | + title: "二级审核确认" | |
| 702 | + }; | |
| 443 | 703 | } |
| 444 | - if (t === '委托代销发货单') { | |
| 445 | - return { msg: '确认审核该委托代销发货单?', title: '审核确认' } | |
| 704 | + if (t === "委托代销发货单") { | |
| 705 | + return { msg: "确认审核该委托代销发货单?", title: "审核确认" }; | |
| 446 | 706 | } |
| 447 | - if (t === '委托代销退货单') { | |
| 448 | - return { msg: '确认审核该委托代销退货单?', title: '审核确认' } | |
| 707 | + if (t === "委托代销退货单") { | |
| 708 | + return { msg: "确认审核该委托代销退货单?", title: "审核确认" }; | |
| 449 | 709 | } |
| 450 | - if (t === '委托代销结算单') { | |
| 451 | - return { msg: '确认审核该委托代销结算单?', title: '审核确认' } | |
| 710 | + if (t === "委托代销结算单") { | |
| 711 | + return { msg: "确认审核该委托代销结算单?", title: "审核确认" }; | |
| 452 | 712 | } |
| 453 | - return { msg: '确认执行二级审核?', title: '审核确认' } | |
| 713 | + return { msg: "确认执行二级审核?", title: "审核确认" }; | |
| 454 | 714 | }, |
| 455 | 715 | handleLevel1Approve() { |
| 456 | - const id = this.processBillId | |
| 457 | - if (!id) return | |
| 458 | - const { msg, title } = this.level1Confirm() | |
| 459 | - this.$confirm(msg, title, { type: 'warning' }) | |
| 460 | - .then(() => promptApprovalRemark(this, '审批备注')) | |
| 461 | - .then(remark => postApproveGeneric(id, remark)) | |
| 716 | + const id = this.processBillId; | |
| 717 | + if (!id) return; | |
| 718 | + const { msg, title } = this.level1Confirm(); | |
| 719 | + this.$confirm(msg, title, { type: "warning" }) | |
| 720 | + .then(() => promptApprovalRemark(this, "审批备注")) | |
| 721 | + .then(remark => | |
| 722 | + this.processBillType === "其他应收单" | |
| 723 | + ? postYskzjjsApprove(id, remark) | |
| 724 | + : postApproveGeneric(id, remark) | |
| 725 | + ) | |
| 462 | 726 | .then(res => { |
| 463 | 727 | if (res.data && res.data.success) { |
| 464 | - this.$message({ type: 'success', message: res.data.message || '操作成功' }) | |
| 465 | - this.pendingCloseWhenApproved = true | |
| 466 | - this.loadData() | |
| 728 | + this.$message({ | |
| 729 | + type: "success", | |
| 730 | + message: res.data.message || "操作成功" | |
| 731 | + }); | |
| 732 | + this.pendingCloseWhenApproved = true; | |
| 733 | + this.loadData(); | |
| 467 | 734 | this.$nextTick(() => { |
| 468 | - if (this.$refs.processDlg) this.$refs.processDlg.init(id) | |
| 469 | - }) | |
| 735 | + if (this.$refs.processDlg) this.$refs.processDlg.init(id); | |
| 736 | + }); | |
| 470 | 737 | } else { |
| 471 | 738 | this.$message({ |
| 472 | - type: 'error', | |
| 473 | - message: (res.data && res.data.message) || '审核失败' | |
| 474 | - }) | |
| 739 | + type: "error", | |
| 740 | + message: (res.data && res.data.message) || "审核失败" | |
| 741 | + }); | |
| 475 | 742 | } |
| 476 | 743 | }) |
| 477 | - .catch(() => {}) | |
| 744 | + .catch(() => {}); | |
| 478 | 745 | }, |
| 479 | 746 | handleLevel2Approve() { |
| 480 | - const id = this.processBillId | |
| 481 | - if (!id) return | |
| 482 | - const { msg, title } = this.level2Confirm() | |
| 483 | - this.$confirm(msg, title, { type: 'warning' }) | |
| 484 | - .then(() => promptApprovalRemark(this, '审批备注')) | |
| 485 | - .then(remark => postApproveGeneric(id, remark)) | |
| 747 | + const id = this.processBillId; | |
| 748 | + if (!id) return; | |
| 749 | + const { msg, title } = this.level2Confirm(); | |
| 750 | + this.$confirm(msg, title, { type: "warning" }) | |
| 751 | + .then(() => promptApprovalRemark(this, "审批备注")) | |
| 752 | + .then(remark => | |
| 753 | + this.processBillType === "其他应收单" | |
| 754 | + ? postYskzjjsApprove(id, remark) | |
| 755 | + : postApproveGeneric(id, remark) | |
| 756 | + ) | |
| 486 | 757 | .then(res => { |
| 487 | 758 | if (res.data && res.data.success) { |
| 488 | - this.$message({ type: 'success', message: res.data.message || '操作成功' }) | |
| 489 | - this.pendingCloseWhenApproved = true | |
| 490 | - this.loadData() | |
| 759 | + this.$message({ | |
| 760 | + type: "success", | |
| 761 | + message: res.data.message || "操作成功" | |
| 762 | + }); | |
| 763 | + this.pendingCloseWhenApproved = true; | |
| 764 | + this.loadData(); | |
| 491 | 765 | this.$nextTick(() => { |
| 492 | - if (this.$refs.processDlg) this.$refs.processDlg.init(id) | |
| 493 | - }) | |
| 766 | + if (this.$refs.processDlg) this.$refs.processDlg.init(id); | |
| 767 | + }); | |
| 494 | 768 | } else { |
| 495 | 769 | this.$message({ |
| 496 | - type: 'error', | |
| 497 | - message: (res.data && res.data.message) || '审核失败' | |
| 498 | - }) | |
| 770 | + type: "error", | |
| 771 | + message: (res.data && res.data.message) || "审核失败" | |
| 772 | + }); | |
| 499 | 773 | } |
| 500 | 774 | }) |
| 501 | - .catch(() => {}) | |
| 775 | + .catch(() => {}); | |
| 502 | 776 | }, |
| 503 | 777 | handleReject() { |
| 504 | - const id = this.processBillId | |
| 505 | - if (!id) return | |
| 506 | - promptApprovalRemark(this, '审核不通过') | |
| 507 | - .then(reason => postRejectGeneric(id, reason)) | |
| 778 | + const id = this.processBillId; | |
| 779 | + if (!id) return; | |
| 780 | + promptApprovalRemark(this, "审核不通过") | |
| 781 | + .then(reason => | |
| 782 | + this.processBillType === "其他应收单" | |
| 783 | + ? postYskzjjsReject(id, reason) | |
| 784 | + : postRejectGeneric(id, reason) | |
| 785 | + ) | |
| 508 | 786 | .then(res => { |
| 509 | 787 | if (res.data && res.data.success) { |
| 510 | - this.$message({ type: 'success', message: res.data.message || '已标记审核不通过' }) | |
| 511 | - this.pendingCloseAfterReject = true | |
| 512 | - this.loadData() | |
| 788 | + this.$message({ | |
| 789 | + type: "success", | |
| 790 | + message: res.data.message || "已标记审核不通过" | |
| 791 | + }); | |
| 792 | + this.pendingCloseAfterReject = true; | |
| 793 | + this.loadData(); | |
| 513 | 794 | this.$nextTick(() => { |
| 514 | - if (this.$refs.processDlg) this.$refs.processDlg.init(id) | |
| 515 | - }) | |
| 795 | + if (this.$refs.processDlg) this.$refs.processDlg.init(id); | |
| 796 | + }); | |
| 516 | 797 | } else { |
| 517 | 798 | this.$message({ |
| 518 | - type: 'error', | |
| 519 | - message: (res.data && res.data.message) || '操作失败' | |
| 520 | - }) | |
| 799 | + type: "error", | |
| 800 | + message: (res.data && res.data.message) || "操作失败" | |
| 801 | + }); | |
| 521 | 802 | } |
| 522 | 803 | }) |
| 523 | - .catch(() => {}) | |
| 804 | + .catch(() => {}); | |
| 524 | 805 | } |
| 525 | 806 | } |
| 526 | -} | |
| 807 | +}; | |
| 527 | 808 | </script> |
| 528 | 809 | |
| 529 | 810 | <style scoped lang="scss"> | ... | ... |
Antis.Erp.Plat/antis-ncc-admin/src/views/permission/user/Form.vue
| ... | ... | @@ -21,6 +21,18 @@ |
| 21 | 21 | <el-input v-model="dataForm.account" placeholder="账户名称" /> |
| 22 | 22 | </el-form-item> |
| 23 | 23 | </el-col> |
| 24 | + <el-col v-if="!dataForm.id" :sm="12" :xs="24"> | |
| 25 | + <el-form-item label="密码" prop="password"> | |
| 26 | + <el-input v-model="dataForm.password" type="password" autocomplete="new-password" | |
| 27 | + placeholder="6-18 位字符" show-password /> | |
| 28 | + </el-form-item> | |
| 29 | + </el-col> | |
| 30 | + <el-col v-if="!dataForm.id" :sm="12" :xs="24"> | |
| 31 | + <el-form-item label="确认密码" prop="confirmPassword"> | |
| 32 | + <el-input v-model="dataForm.confirmPassword" type="password" autocomplete="new-password" | |
| 33 | + placeholder="再次输入密码" show-password /> | |
| 34 | + </el-form-item> | |
| 35 | + </el-col> | |
| 24 | 36 | <el-col :sm="12" :xs="24"> |
| 25 | 37 | <el-form-item label="姓名" prop="realName"> |
| 26 | 38 | <el-input v-model="dataForm.realName" placeholder="真实姓名" /> |
| ... | ... | @@ -215,6 +227,8 @@ export default { |
| 215 | 227 | sortCode: 0, |
| 216 | 228 | enabledMark: 1, |
| 217 | 229 | account: '', |
| 230 | + password: '', | |
| 231 | + confirmPassword: '', | |
| 218 | 232 | realName: '', |
| 219 | 233 | organizeId: '', |
| 220 | 234 | managerId: '', |
| ... | ... | @@ -269,6 +283,50 @@ export default { |
| 269 | 283 | ], |
| 270 | 284 | organizeId: [ |
| 271 | 285 | { required: true, message: '请选择组织', trigger: 'change' } |
| 286 | + ], | |
| 287 | + password: [ | |
| 288 | + { | |
| 289 | + validator: (rule, value, callback) => { | |
| 290 | + if (this.dataForm.id) { | |
| 291 | + callback() | |
| 292 | + return | |
| 293 | + } | |
| 294 | + if (!value) { | |
| 295 | + callback(new Error('请输入密码')) | |
| 296 | + return | |
| 297 | + } | |
| 298 | + const s = value.toString() | |
| 299 | + if (s.length < 6 || s.length > 18) { | |
| 300 | + callback(new Error('密码长度为6 - 18个字符')) | |
| 301 | + return | |
| 302 | + } | |
| 303 | + if (this.dataForm.confirmPassword !== '') { | |
| 304 | + this.$refs.dataForm.validateField('confirmPassword') | |
| 305 | + } | |
| 306 | + callback() | |
| 307 | + }, | |
| 308 | + trigger: 'blur' | |
| 309 | + } | |
| 310 | + ], | |
| 311 | + confirmPassword: [ | |
| 312 | + { | |
| 313 | + validator: (rule, value, callback) => { | |
| 314 | + if (this.dataForm.id) { | |
| 315 | + callback() | |
| 316 | + return | |
| 317 | + } | |
| 318 | + if (!value) { | |
| 319 | + callback(new Error('请再次输入密码')) | |
| 320 | + return | |
| 321 | + } | |
| 322 | + if (value !== this.dataForm.password) { | |
| 323 | + callback(new Error('两次输入密码不一致')) | |
| 324 | + return | |
| 325 | + } | |
| 326 | + callback() | |
| 327 | + }, | |
| 328 | + trigger: 'blur' | |
| 329 | + } | |
| 272 | 330 | ] |
| 273 | 331 | } |
| 274 | 332 | } |
| ... | ... | @@ -328,6 +386,8 @@ export default { |
| 328 | 386 | this.formLoading = true |
| 329 | 387 | getUserInfo(this.dataForm.id).then(res => { |
| 330 | 388 | this.dataForm = res.data |
| 389 | + this.$set(this.dataForm, 'password', '') | |
| 390 | + this.$set(this.dataForm, 'confirmPassword', '') | |
| 331 | 391 | if (this.dataForm.roleId) this.roleId = this.dataForm.roleId.split(',') |
| 332 | 392 | this.formLoading = false |
| 333 | 393 | }).catch(() => this.formLoading = false) |
| ... | ... | @@ -354,7 +414,12 @@ export default { |
| 354 | 414 | if (valid) { |
| 355 | 415 | this.btnLoading = true |
| 356 | 416 | const formMethod = this.dataForm.id ? updateUser : createUser |
| 357 | - formMethod(this.dataForm).then(res => { | |
| 417 | + const payload = { ...this.dataForm } | |
| 418 | + delete payload.confirmPassword | |
| 419 | + if (payload.id) { | |
| 420 | + delete payload.password | |
| 421 | + } | |
| 422 | + formMethod(payload).then(res => { | |
| 358 | 423 | this.$message({ |
| 359 | 424 | message: res.msg, |
| 360 | 425 | type: 'success', | ... | ... |
Antis.Erp.Plat/antis-ncc-admin/src/views/wtPurchaseSummary/index.vue
| ... | ... | @@ -67,20 +67,33 @@ |
| 67 | 67 | reserve-keyword |
| 68 | 68 | popper-class="wt-purchase-sum-product-dropdown" |
| 69 | 69 | :remote-method="handleProductSearch" |
| 70 | - :loading="productLoading" | |
| 70 | + :loading="productRemoteLoading" | |
| 71 | 71 | placeholder="输入商品编码或名称搜索" |
| 72 | 72 | style="width: 100%" |
| 73 | 73 | > |
| 74 | 74 | <el-option |
| 75 | 75 | v-for="item in productOptions" |
| 76 | - :key="item.F_Id || item.id" | |
| 76 | + :key="productOptionValue(item) + '-' + (item.spbm || '')" | |
| 77 | 77 | :label="formatProductLabel(item)" |
| 78 | - :value="item.F_Id || item.id" | |
| 78 | + :value="productOptionValue(item)" | |
| 79 | 79 | > |
| 80 | - <div class="product-opt-row cell-nowrap" :title="formatProductLabel(item)"> | |
| 81 | - <span v-if="productCodeRaw(item)" class="product-opt-code">{{ productCodeRaw(item) }}</span> | |
| 82 | - <span v-if="productCodeRaw(item) && productNameRaw(item)" class="product-opt-sep">|</span> | |
| 83 | - <span class="product-opt-name">{{ productNameRaw(item) || '无' }}</span> | |
| 80 | + <div | |
| 81 | + class="product-opt-row cell-nowrap" | |
| 82 | + :title="formatProductLabel(item)" | |
| 83 | + > | |
| 84 | + <span | |
| 85 | + v-if="productCodeRaw(item)" | |
| 86 | + class="product-opt-code" | |
| 87 | + >{{ productCodeRaw(item) }}</span | |
| 88 | + > | |
| 89 | + <span | |
| 90 | + v-if="productCodeRaw(item) && productNameRaw(item)" | |
| 91 | + class="product-opt-sep" | |
| 92 | + >|</span | |
| 93 | + > | |
| 94 | + <span class="product-opt-name">{{ | |
| 95 | + productNameRaw(item) || "无" | |
| 96 | + }}</span> | |
| 84 | 97 | </div> |
| 85 | 98 | </el-option> |
| 86 | 99 | </el-select> |
| ... | ... | @@ -127,8 +140,15 @@ |
| 127 | 140 | </el-col> |
| 128 | 141 | <el-col :span="6"> |
| 129 | 142 | <el-form-item> |
| 130 | - <el-button type="primary" icon="el-icon-search" @click="handleSearch">查询</el-button> | |
| 131 | - <el-button icon="el-icon-refresh-right" @click="handleReset">重置</el-button> | |
| 143 | + <el-button | |
| 144 | + type="primary" | |
| 145 | + icon="el-icon-search" | |
| 146 | + @click="handleSearch" | |
| 147 | + >查询</el-button | |
| 148 | + > | |
| 149 | + <el-button icon="el-icon-refresh-right" @click="handleReset" | |
| 150 | + >重置</el-button | |
| 151 | + > | |
| 132 | 152 | </el-form-item> |
| 133 | 153 | </el-col> |
| 134 | 154 | </el-form> |
| ... | ... | @@ -138,11 +158,27 @@ |
| 138 | 158 | <div class="NCC-common-head purchase-sum-head"> |
| 139 | 159 | <div> |
| 140 | 160 | <span class="purchase-sum-head__title"> |
| 141 | - <i class="el-icon-s-data purchase-sum-head__icon" aria-hidden="true" /> | |
| 142 | - 商品采购汇总(分类 → 品牌 → 商品明细分类 → 采购明细) | |
| 161 | + <i | |
| 162 | + class="el-icon-s-data purchase-sum-head__icon" | |
| 163 | + aria-hidden="true" | |
| 164 | + /> | |
| 165 | + 商品采购汇总(分类 → 品牌 → 商品 → 采购明细) | |
| 143 | 166 | </span> |
| 144 | 167 | </div> |
| 145 | - <div class="NCC-common-head-right"> | |
| 168 | + <div class="NCC-common-head-right purchase-sum-head__tools"> | |
| 169 | + <span class="linear-mode-label"> | |
| 170 | + <i | |
| 171 | + class="el-icon-s-operation row-ico--primary" | |
| 172 | + aria-hidden="true" | |
| 173 | + /> | |
| 174 | + 线性列表 | |
| 175 | + </span> | |
| 176 | + <el-switch | |
| 177 | + v-model="linearInlineMode" | |
| 178 | + active-color="#409EFF" | |
| 179 | + inactive-color="#dcdfe6" | |
| 180 | + @change="onLinearInlineModeChange" | |
| 181 | + /> | |
| 146 | 182 | <el-tooltip effect="dark" content="刷新" placement="top"> |
| 147 | 183 | <el-link |
| 148 | 184 | icon="icon-ym icon-ym-Refresh NCC-common-head-icon" |
| ... | ... | @@ -155,145 +191,581 @@ |
| 155 | 191 | </div> |
| 156 | 192 | |
| 157 | 193 | <el-table |
| 194 | + ref="categoryTable" | |
| 158 | 195 | v-loading="categoryLoading" |
| 159 | 196 | :data="categoryList" |
| 160 | 197 | border |
| 161 | 198 | class="purchase-tree-table" |
| 162 | - :row-key="r => String(r['分类Id'])" | |
| 199 | + :row-key="categoryRowKey" | |
| 163 | 200 | @expand-change="onCategoryExpand" |
| 201 | + @sort-change="onCategorySort" | |
| 164 | 202 | > |
| 165 | 203 | <el-table-column type="expand" width="48"> |
| 166 | 204 | <template slot-scope="catScope"> |
| 167 | - <div v-loading="brandLoading[categoryRowKey(catScope.row)]" class="nested-wrap"> | |
| 168 | - <el-table | |
| 169 | - :data="brandMap[categoryRowKey(catScope.row)] || []" | |
| 170 | - border | |
| 171 | - size="small" | |
| 172 | - class="nested-table" | |
| 173 | - :row-key="r => brandRowKey(catScope.row, r)" | |
| 174 | - @expand-change="(r, er) => onBrandExpand(catScope.row, r, er)" | |
| 175 | - > | |
| 176 | - <el-table-column type="expand" width="44"> | |
| 177 | - <template slot-scope="brandScope"> | |
| 178 | - <div v-loading="productLoading[brandRowKey(catScope.row, brandScope.row)]" class="nested-wrap"> | |
| 179 | - <el-table | |
| 180 | - :data="productMap[brandRowKey(catScope.row, brandScope.row)] || []" | |
| 181 | - border | |
| 182 | - size="small" | |
| 183 | - class="nested-table nested-table--deep" | |
| 184 | - :row-key="r => productRowKey(catScope.row, brandScope.row, r)" | |
| 185 | - @expand-change="(r, er) => onProductExpand(catScope.row, brandScope.row, r, er)" | |
| 205 | + <div | |
| 206 | + v-if="linearInlineMode" | |
| 207 | + v-loading="linearInlineLoading[categoryRowKey(catScope.row)]" | |
| 208 | + class="nested-wrap nested-wrap--linear" | |
| 209 | + > | |
| 210 | + <div class="nested-table-host"> | |
| 211 | + <el-table | |
| 212 | + :data=" | |
| 213 | + (linearInlineMap[categoryRowKey(catScope.row)] || {}) | |
| 214 | + .list || [] | |
| 215 | + " | |
| 216 | + border | |
| 217 | + size="small" | |
| 218 | + class="nested-table nested-table--scroll" | |
| 219 | + :row-key=" | |
| 220 | + (r, idx) => | |
| 221 | + lineDetailRowKey( | |
| 222 | + 'lin', | |
| 223 | + catScope.row, | |
| 224 | + null, | |
| 225 | + null, | |
| 226 | + r, | |
| 227 | + idx | |
| 228 | + ) | |
| 229 | + " | |
| 230 | + > | |
| 231 | + <el-table-column | |
| 232 | + type="index" | |
| 233 | + label="行号" | |
| 234 | + width="52" | |
| 235 | + align="center" | |
| 236 | + /> | |
| 237 | + <el-table-column | |
| 238 | + prop="单据日期" | |
| 239 | + label="单据日期" | |
| 240 | + width="108" | |
| 241 | + show-overflow-tooltip | |
| 242 | + /> | |
| 243 | + <el-table-column | |
| 244 | + prop="单据编号" | |
| 245 | + label="单据编号" | |
| 246 | + min-width="140" | |
| 247 | + show-overflow-tooltip | |
| 248 | + /> | |
| 249 | + <el-table-column | |
| 250 | + prop="单据类型" | |
| 251 | + label="单据类型" | |
| 252 | + width="108" | |
| 253 | + show-overflow-tooltip | |
| 254 | + /> | |
| 255 | + <el-table-column | |
| 256 | + prop="往来单位" | |
| 257 | + label="往来单位" | |
| 258 | + min-width="120" | |
| 259 | + show-overflow-tooltip | |
| 260 | + /> | |
| 261 | + <el-table-column | |
| 262 | + prop="经手人" | |
| 263 | + label="经手人" | |
| 264 | + width="88" | |
| 265 | + show-overflow-tooltip | |
| 266 | + /> | |
| 267 | + <el-table-column | |
| 268 | + prop="仓库名称" | |
| 269 | + label="仓库名称" | |
| 270 | + min-width="100" | |
| 271 | + show-overflow-tooltip | |
| 272 | + /> | |
| 273 | + <el-table-column | |
| 274 | + prop="商品名称" | |
| 275 | + label="商品名称" | |
| 276 | + min-width="140" | |
| 277 | + show-overflow-tooltip | |
| 278 | + /> | |
| 279 | + <el-table-column | |
| 280 | + prop="数量" | |
| 281 | + label="数量" | |
| 282 | + width="88" | |
| 283 | + align="right" | |
| 284 | + > | |
| 285 | + <template slot-scope="s">{{ | |
| 286 | + formatQty(s.row["数量"]) | |
| 287 | + }}</template> | |
| 288 | + </el-table-column> | |
| 289 | + <el-table-column | |
| 290 | + prop="入库单价" | |
| 291 | + label="入库单价" | |
| 292 | + width="100" | |
| 293 | + align="right" | |
| 294 | + > | |
| 295 | + <template slot-scope="s">{{ | |
| 296 | + formatMoney(s.row["入库单价"]) | |
| 297 | + }}</template> | |
| 298 | + </el-table-column> | |
| 299 | + <el-table-column | |
| 300 | + prop="采购金额" | |
| 301 | + label="采购金额" | |
| 302 | + width="108" | |
| 303 | + align="right" | |
| 304 | + > | |
| 305 | + <template slot-scope="s">{{ | |
| 306 | + formatMoney(s.row["采购金额"]) | |
| 307 | + }}</template> | |
| 308 | + </el-table-column> | |
| 309 | + </el-table> | |
| 310 | + </div> | |
| 311 | + </div> | |
| 312 | + <div | |
| 313 | + v-else | |
| 314 | + v-loading="brandLoading[categoryRowKey(catScope.row)]" | |
| 315 | + class="nested-wrap" | |
| 316 | + > | |
| 317 | + <div class="nested-table-host"> | |
| 318 | + <el-table | |
| 319 | + :data="brandMap[categoryRowKey(catScope.row)] || []" | |
| 320 | + border | |
| 321 | + size="small" | |
| 322 | + class="nested-table nested-table--scroll" | |
| 323 | + :row-key="r => brandRowKey(catScope.row, r)" | |
| 324 | + @expand-change=" | |
| 325 | + (r, er) => onBrandExpand(catScope.row, r, er) | |
| 326 | + " | |
| 327 | + @sort-change="ev => onBrandSort(catScope.row, ev)" | |
| 328 | + > | |
| 329 | + <el-table-column type="expand" width="44"> | |
| 330 | + <template slot-scope="brandScope"> | |
| 331 | + <div | |
| 332 | + v-loading=" | |
| 333 | + aggProductLoading[ | |
| 334 | + brandRowKey(catScope.row, brandScope.row) | |
| 335 | + ] | |
| 336 | + " | |
| 337 | + class="nested-wrap" | |
| 186 | 338 | > |
| 187 | - <el-table-column type="expand" width="42"> | |
| 188 | - <template slot-scope="prodScope"> | |
| 189 | - <div v-loading="lineLoading[lineKey(catScope.row, brandScope.row, prodScope.row)]" class="nested-wrap detail-wrap"> | |
| 190 | - <el-table | |
| 191 | - :data="(lineMap[lineKey(catScope.row, brandScope.row, prodScope.row)] || {}).list || []" | |
| 192 | - border | |
| 193 | - size="mini" | |
| 194 | - class="nested-table" | |
| 195 | - > | |
| 196 | - <el-table-column type="index" label="行号" width="52" align="center" /> | |
| 197 | - <el-table-column prop="单据日期" label="单据日期" width="108" show-overflow-tooltip sortable :sort-method="sortTextCol('单据日期')" /> | |
| 198 | - <el-table-column prop="单据编号" label="单据编号" min-width="140" show-overflow-tooltip sortable :sort-method="sortTextCol('单据编号')" /> | |
| 199 | - <el-table-column prop="单据类型" label="单据类型" width="108" show-overflow-tooltip sortable :sort-method="sortTextCol('单据类型')" /> | |
| 200 | - <el-table-column prop="往来单位" label="往来单位" min-width="120" show-overflow-tooltip sortable :sort-method="sortTextCol('往来单位')" /> | |
| 201 | - <el-table-column prop="经手人" label="经手人" width="88" show-overflow-tooltip sortable :sort-method="sortTextCol('经手人')" /> | |
| 202 | - <el-table-column prop="仓库名称" label="仓库名称" min-width="100" show-overflow-tooltip sortable :sort-method="sortTextCol('仓库名称')" /> | |
| 203 | - <el-table-column prop="商品名称" label="商品名称" min-width="140" show-overflow-tooltip sortable :sort-method="sortTextCol('商品名称')" /> | |
| 204 | - <el-table-column prop="数量" label="数量" width="88" align="right" sortable :sort-method="sortNumCol('数量')"> | |
| 205 | - <template slot-scope="s">{{ formatQty(s.row['数量']) }}</template> | |
| 206 | - </el-table-column> | |
| 207 | - <el-table-column prop="入库单价" label="入库单价" width="100" align="right" sortable :sort-method="sortNumCol('入库单价')"> | |
| 208 | - <template slot-scope="s">{{ formatMoney(s.row['入库单价']) }}</template> | |
| 209 | - </el-table-column> | |
| 210 | - <el-table-column prop="采购金额" label="采购金额" width="108" align="right" sortable :sort-method="sortNumCol('采购金额')"> | |
| 211 | - <template slot-scope="s">{{ formatMoney(s.row['采购金额']) }}</template> | |
| 212 | - </el-table-column> | |
| 213 | - </el-table> | |
| 214 | - <div v-if="linePager[lineKey(catScope.row, brandScope.row, prodScope.row)]" class="mini-pager"> | |
| 215 | - <el-pagination | |
| 216 | - small | |
| 217 | - layout="prev, pager, next, total" | |
| 218 | - :total="linePager[lineKey(catScope.row, brandScope.row, prodScope.row)].total" | |
| 219 | - :page-size="linePager[lineKey(catScope.row, brandScope.row, prodScope.row)].pageSize" | |
| 220 | - :current-page="linePager[lineKey(catScope.row, brandScope.row, prodScope.row)].currentPage" | |
| 221 | - @current-change="p => fetchLines(catScope.row, brandScope.row, prodScope.row, p)" | |
| 339 | + <div class="nested-table-host"> | |
| 340 | + <el-table | |
| 341 | + :data=" | |
| 342 | + productMap[ | |
| 343 | + brandRowKey(catScope.row, brandScope.row) | |
| 344 | + ] || [] | |
| 345 | + " | |
| 346 | + border | |
| 347 | + size="small" | |
| 348 | + class="nested-table nested-table--deep nested-table--scroll" | |
| 349 | + :row-key=" | |
| 350 | + r => | |
| 351 | + productRowKey(catScope.row, brandScope.row, r) | |
| 352 | + " | |
| 353 | + @expand-change=" | |
| 354 | + (r, er) => | |
| 355 | + onProductExpand( | |
| 356 | + catScope.row, | |
| 357 | + brandScope.row, | |
| 358 | + r, | |
| 359 | + er | |
| 360 | + ) | |
| 361 | + " | |
| 362 | + @sort-change=" | |
| 363 | + ev => | |
| 364 | + onProductSort( | |
| 365 | + catScope.row, | |
| 366 | + brandScope.row, | |
| 367 | + ev | |
| 368 | + ) | |
| 369 | + " | |
| 370 | + > | |
| 371 | + <el-table-column type="expand" width="42"> | |
| 372 | + <template slot-scope="prodScope"> | |
| 373 | + <div | |
| 374 | + v-loading=" | |
| 375 | + lineLoading[ | |
| 376 | + lineKey( | |
| 377 | + catScope.row, | |
| 378 | + brandScope.row, | |
| 379 | + prodScope.row | |
| 380 | + ) | |
| 381 | + ] | |
| 382 | + " | |
| 383 | + class="nested-wrap detail-wrap" | |
| 384 | + > | |
| 385 | + <div | |
| 386 | + class="nested-table-host nested-table-host--detail" | |
| 387 | + > | |
| 388 | + <el-table | |
| 389 | + :data=" | |
| 390 | + ( | |
| 391 | + lineMap[ | |
| 392 | + lineKey( | |
| 393 | + catScope.row, | |
| 394 | + brandScope.row, | |
| 395 | + prodScope.row | |
| 396 | + ) | |
| 397 | + ] || {} | |
| 398 | + ).list || [] | |
| 399 | + " | |
| 400 | + border | |
| 401 | + size="mini" | |
| 402 | + class="nested-table nested-table--scroll" | |
| 403 | + :row-key=" | |
| 404 | + (r, idx) => | |
| 405 | + lineDetailRowKey( | |
| 406 | + 'mx', | |
| 407 | + catScope.row, | |
| 408 | + brandScope.row, | |
| 409 | + prodScope.row, | |
| 410 | + r, | |
| 411 | + idx | |
| 412 | + ) | |
| 413 | + " | |
| 414 | + @sort-change=" | |
| 415 | + ev => | |
| 416 | + onLineSort( | |
| 417 | + catScope.row, | |
| 418 | + brandScope.row, | |
| 419 | + prodScope.row, | |
| 420 | + ev | |
| 421 | + ) | |
| 422 | + " | |
| 423 | + > | |
| 424 | + <el-table-column | |
| 425 | + type="index" | |
| 426 | + label="行号" | |
| 427 | + width="52" | |
| 428 | + align="center" | |
| 429 | + /> | |
| 430 | + <el-table-column | |
| 431 | + prop="单据日期" | |
| 432 | + label="单据日期" | |
| 433 | + width="108" | |
| 434 | + show-overflow-tooltip | |
| 435 | + sortable="custom" | |
| 436 | + /> | |
| 437 | + <el-table-column | |
| 438 | + prop="单据编号" | |
| 439 | + label="单据编号" | |
| 440 | + min-width="140" | |
| 441 | + show-overflow-tooltip | |
| 442 | + sortable="custom" | |
| 443 | + /> | |
| 444 | + <el-table-column | |
| 445 | + prop="单据类型" | |
| 446 | + label="单据类型" | |
| 447 | + width="108" | |
| 448 | + show-overflow-tooltip | |
| 449 | + sortable="custom" | |
| 450 | + /> | |
| 451 | + <el-table-column | |
| 452 | + prop="往来单位" | |
| 453 | + label="往来单位" | |
| 454 | + min-width="120" | |
| 455 | + show-overflow-tooltip | |
| 456 | + sortable="custom" | |
| 457 | + /> | |
| 458 | + <el-table-column | |
| 459 | + prop="经手人" | |
| 460 | + label="经手人" | |
| 461 | + width="88" | |
| 462 | + show-overflow-tooltip | |
| 463 | + sortable="custom" | |
| 464 | + /> | |
| 465 | + <el-table-column | |
| 466 | + prop="仓库名称" | |
| 467 | + label="仓库名称" | |
| 468 | + min-width="100" | |
| 469 | + show-overflow-tooltip | |
| 470 | + sortable="custom" | |
| 471 | + /> | |
| 472 | + <el-table-column | |
| 473 | + prop="商品名称" | |
| 474 | + label="商品名称" | |
| 475 | + min-width="140" | |
| 476 | + show-overflow-tooltip | |
| 477 | + sortable="custom" | |
| 478 | + /> | |
| 479 | + <el-table-column | |
| 480 | + prop="数量" | |
| 481 | + label="数量" | |
| 482 | + width="88" | |
| 483 | + align="right" | |
| 484 | + sortable="custom" | |
| 485 | + > | |
| 486 | + <template slot-scope="s">{{ | |
| 487 | + formatQty(s.row["数量"]) | |
| 488 | + }}</template> | |
| 489 | + </el-table-column> | |
| 490 | + <el-table-column | |
| 491 | + prop="入库单价" | |
| 492 | + label="入库单价" | |
| 493 | + width="100" | |
| 494 | + align="right" | |
| 495 | + sortable="custom" | |
| 496 | + > | |
| 497 | + <template slot-scope="s">{{ | |
| 498 | + formatMoney(s.row["入库单价"]) | |
| 499 | + }}</template> | |
| 500 | + </el-table-column> | |
| 501 | + <el-table-column | |
| 502 | + prop="采购金额" | |
| 503 | + label="采购金额" | |
| 504 | + width="108" | |
| 505 | + align="right" | |
| 506 | + sortable="custom" | |
| 507 | + > | |
| 508 | + <template slot-scope="s">{{ | |
| 509 | + formatMoney(s.row["采购金额"]) | |
| 510 | + }}</template> | |
| 511 | + </el-table-column> | |
| 512 | + </el-table> | |
| 513 | + </div> | |
| 514 | + <div | |
| 515 | + v-if=" | |
| 516 | + linePager[ | |
| 517 | + lineKey( | |
| 518 | + catScope.row, | |
| 519 | + brandScope.row, | |
| 520 | + prodScope.row | |
| 521 | + ) | |
| 522 | + ] | |
| 523 | + " | |
| 524 | + class="mini-pager" | |
| 525 | + > | |
| 526 | + <el-pagination | |
| 527 | + small | |
| 528 | + layout="prev, pager, next, total" | |
| 529 | + :total=" | |
| 530 | + linePager[ | |
| 531 | + lineKey( | |
| 532 | + catScope.row, | |
| 533 | + brandScope.row, | |
| 534 | + prodScope.row | |
| 535 | + ) | |
| 536 | + ].total | |
| 537 | + " | |
| 538 | + :page-size=" | |
| 539 | + linePager[ | |
| 540 | + lineKey( | |
| 541 | + catScope.row, | |
| 542 | + brandScope.row, | |
| 543 | + prodScope.row | |
| 544 | + ) | |
| 545 | + ].pageSize | |
| 546 | + " | |
| 547 | + :current-page=" | |
| 548 | + linePager[ | |
| 549 | + lineKey( | |
| 550 | + catScope.row, | |
| 551 | + brandScope.row, | |
| 552 | + prodScope.row | |
| 553 | + ) | |
| 554 | + ].currentPage | |
| 555 | + " | |
| 556 | + @current-change=" | |
| 557 | + p => | |
| 558 | + fetchLines( | |
| 559 | + catScope.row, | |
| 560 | + brandScope.row, | |
| 561 | + prodScope.row, | |
| 562 | + p | |
| 563 | + ) | |
| 564 | + " | |
| 565 | + /> | |
| 566 | + </div> | |
| 567 | + </div> | |
| 568 | + </template> | |
| 569 | + </el-table-column> | |
| 570 | + <el-table-column | |
| 571 | + prop="商品编号" | |
| 572 | + label="商品编号" | |
| 573 | + min-width="100" | |
| 574 | + show-overflow-tooltip | |
| 575 | + sortable="custom" | |
| 576 | + > | |
| 577 | + <template slot-scope="s"> | |
| 578 | + <i | |
| 579 | + class="el-icon-postcard row-ico row-ico--primary" | |
| 222 | 580 | /> |
| 223 | - </div> | |
| 224 | - </div> | |
| 225 | - </template> | |
| 226 | - </el-table-column> | |
| 227 | - <el-table-column label="商品编号" min-width="100" show-overflow-tooltip sortable :sort-method="sortTextCol('商品编号')"> | |
| 228 | - <template slot-scope="s"> | |
| 229 | - <i class="el-icon-postcard row-ico row-ico--primary" /> | |
| 230 | - {{ cellText(s.row['商品编号']) }} | |
| 231 | - </template> | |
| 232 | - </el-table-column> | |
| 233 | - <el-table-column label="明细分类" min-width="120" show-overflow-tooltip sortable :sort-method="sortTextCol('明细分类')"> | |
| 234 | - <template slot-scope="s"> | |
| 235 | - <i class="el-icon-collection-tag row-ico row-ico--info" /> | |
| 236 | - {{ cellText(s.row['明细分类']) }} | |
| 237 | - </template> | |
| 238 | - </el-table-column> | |
| 239 | - <el-table-column label="商品名称" min-width="140" show-overflow-tooltip sortable :sort-method="sortTextCol('商品名称')"> | |
| 240 | - <template slot-scope="s"> | |
| 241 | - <i class="el-icon-goods row-ico row-ico--muted" /> | |
| 242 | - {{ cellText(s.row['商品名称']) }} | |
| 243 | - </template> | |
| 244 | - </el-table-column> | |
| 245 | - <el-table-column label="数量" width="88" align="right" sortable :sort-method="sortNumCol('数量')"> | |
| 246 | - <template slot-scope="s">{{ formatQty(s.row['数量']) }}</template> | |
| 247 | - </el-table-column> | |
| 248 | - <el-table-column label="入库单价" width="100" align="right" sortable :sort-method="sortNumCol('入库单价')"> | |
| 249 | - <template slot-scope="s">{{ formatMoney(s.row['入库单价']) }}</template> | |
| 250 | - </el-table-column> | |
| 251 | - <el-table-column label="采购金额" width="108" align="right" sortable :sort-method="sortNumCol('采购金额')"> | |
| 252 | - <template slot-scope="s">{{ formatMoney(s.row['采购金额']) }}</template> | |
| 253 | - </el-table-column> | |
| 254 | - </el-table> | |
| 255 | - </div> | |
| 256 | - </template> | |
| 257 | - </el-table-column> | |
| 258 | - <el-table-column label="品牌" min-width="140" show-overflow-tooltip sortable :sort-method="sortTextCol('品牌名称')"> | |
| 259 | - <template slot-scope="s"> | |
| 260 | - <i class="el-icon-medal row-ico row-ico--primary" /> | |
| 261 | - {{ cellText(s.row['品牌名称'] || s.row['商品名称']) }} | |
| 262 | - </template> | |
| 263 | - </el-table-column> | |
| 264 | - <el-table-column label="数量" width="88" align="right" sortable :sort-method="sortNumCol('数量')"> | |
| 265 | - <template slot-scope="s">{{ formatQty(s.row['数量']) }}</template> | |
| 266 | - </el-table-column> | |
| 267 | - <el-table-column label="入库单价" width="100" align="right" sortable :sort-method="sortNumCol('入库单价')"> | |
| 268 | - <template slot-scope="s">{{ formatMoney(s.row['入库单价']) }}</template> | |
| 269 | - </el-table-column> | |
| 270 | - <el-table-column label="采购金额" width="108" align="right" sortable :sort-method="sortNumCol('采购金额')"> | |
| 271 | - <template slot-scope="s">{{ formatMoney(s.row['采购金额']) }}</template> | |
| 272 | - </el-table-column> | |
| 273 | - </el-table> | |
| 274 | - <div v-if="!(brandMap[categoryRowKey(catScope.row)] || []).length && !brandLoading[categoryRowKey(catScope.row)]" class="nested-empty">暂无品牌数据</div> | |
| 581 | + {{ cellText(s.row["商品编号"]) }} | |
| 582 | + </template> | |
| 583 | + </el-table-column> | |
| 584 | + <el-table-column | |
| 585 | + prop="明细分类" | |
| 586 | + label="明细分类" | |
| 587 | + min-width="120" | |
| 588 | + show-overflow-tooltip | |
| 589 | + sortable="custom" | |
| 590 | + > | |
| 591 | + <template slot-scope="s"> | |
| 592 | + <i | |
| 593 | + class="el-icon-collection-tag row-ico row-ico--info" | |
| 594 | + /> | |
| 595 | + {{ cellText(s.row["明细分类"]) }} | |
| 596 | + </template> | |
| 597 | + </el-table-column> | |
| 598 | + <el-table-column | |
| 599 | + prop="商品名称" | |
| 600 | + label="商品名称" | |
| 601 | + min-width="140" | |
| 602 | + show-overflow-tooltip | |
| 603 | + sortable="custom" | |
| 604 | + > | |
| 605 | + <template slot-scope="s"> | |
| 606 | + <i | |
| 607 | + class="el-icon-goods row-ico row-ico--muted" | |
| 608 | + /> | |
| 609 | + {{ cellText(s.row["商品名称"]) }} | |
| 610 | + </template> | |
| 611 | + </el-table-column> | |
| 612 | + <el-table-column | |
| 613 | + prop="数量" | |
| 614 | + label="数量" | |
| 615 | + width="88" | |
| 616 | + align="right" | |
| 617 | + sortable="custom" | |
| 618 | + > | |
| 619 | + <template slot-scope="s">{{ | |
| 620 | + formatQty(s.row["数量"]) | |
| 621 | + }}</template> | |
| 622 | + </el-table-column> | |
| 623 | + <el-table-column | |
| 624 | + prop="入库单价" | |
| 625 | + label="入库单价" | |
| 626 | + width="100" | |
| 627 | + align="right" | |
| 628 | + sortable="custom" | |
| 629 | + > | |
| 630 | + <template slot-scope="s">{{ | |
| 631 | + formatMoney(s.row["入库单价"]) | |
| 632 | + }}</template> | |
| 633 | + </el-table-column> | |
| 634 | + <el-table-column | |
| 635 | + prop="采购金额" | |
| 636 | + label="采购金额" | |
| 637 | + width="108" | |
| 638 | + align="right" | |
| 639 | + sortable="custom" | |
| 640 | + > | |
| 641 | + <template slot-scope="s">{{ | |
| 642 | + formatMoney(s.row["采购金额"]) | |
| 643 | + }}</template> | |
| 644 | + </el-table-column> | |
| 645 | + </el-table> | |
| 646 | + </div> | |
| 647 | + </div> | |
| 648 | + </template> | |
| 649 | + </el-table-column> | |
| 650 | + <el-table-column | |
| 651 | + prop="品牌名称" | |
| 652 | + label="品牌" | |
| 653 | + min-width="140" | |
| 654 | + show-overflow-tooltip | |
| 655 | + sortable="custom" | |
| 656 | + > | |
| 657 | + <template slot-scope="s"> | |
| 658 | + <i class="el-icon-medal row-ico row-ico--primary" /> | |
| 659 | + {{ cellText(s.row["品牌名称"] || s.row["商品名称"]) }} | |
| 660 | + </template> | |
| 661 | + </el-table-column> | |
| 662 | + <el-table-column | |
| 663 | + prop="数量" | |
| 664 | + label="数量" | |
| 665 | + width="88" | |
| 666 | + align="right" | |
| 667 | + sortable="custom" | |
| 668 | + > | |
| 669 | + <template slot-scope="s">{{ | |
| 670 | + formatQty(s.row["数量"]) | |
| 671 | + }}</template> | |
| 672 | + </el-table-column> | |
| 673 | + <el-table-column | |
| 674 | + prop="入库单价" | |
| 675 | + label="入库单价" | |
| 676 | + width="100" | |
| 677 | + align="right" | |
| 678 | + sortable="custom" | |
| 679 | + > | |
| 680 | + <template slot-scope="s">{{ | |
| 681 | + formatMoney(s.row["入库单价"]) | |
| 682 | + }}</template> | |
| 683 | + </el-table-column> | |
| 684 | + <el-table-column | |
| 685 | + prop="采购金额" | |
| 686 | + label="采购金额" | |
| 687 | + width="108" | |
| 688 | + align="right" | |
| 689 | + sortable="custom" | |
| 690 | + > | |
| 691 | + <template slot-scope="s">{{ | |
| 692 | + formatMoney(s.row["采购金额"]) | |
| 693 | + }}</template> | |
| 694 | + </el-table-column> | |
| 695 | + </el-table> | |
| 696 | + </div> | |
| 697 | + <div | |
| 698 | + v-if=" | |
| 699 | + !(brandMap[categoryRowKey(catScope.row)] || []).length && | |
| 700 | + !brandLoading[categoryRowKey(catScope.row)] | |
| 701 | + " | |
| 702 | + class="nested-empty" | |
| 703 | + > | |
| 704 | + 暂无品牌数据 | |
| 705 | + </div> | |
| 275 | 706 | </div> |
| 276 | 707 | </template> |
| 277 | 708 | </el-table-column> |
| 278 | - <el-table-column type="index" label="行号" width="56" align="center" /> | |
| 279 | - <el-table-column label="分类名称" min-width="160" show-overflow-tooltip sortable :sort-method="sortTextCol('分类名称')"> | |
| 709 | + <el-table-column | |
| 710 | + type="index" | |
| 711 | + label="行号" | |
| 712 | + width="56" | |
| 713 | + align="center" | |
| 714 | + /> | |
| 715 | + <el-table-column | |
| 716 | + prop="分类名称" | |
| 717 | + label="分类名称" | |
| 718 | + min-width="160" | |
| 719 | + show-overflow-tooltip | |
| 720 | + sortable="custom" | |
| 721 | + > | |
| 280 | 722 | <template slot-scope="scope"> |
| 281 | 723 | <i class="el-icon-folder-opened row-ico row-ico--primary" /> |
| 282 | - {{ cellText(scope.row['分类名称']) }} | |
| 724 | + {{ cellText(scope.row["分类名称"]) }} | |
| 283 | 725 | </template> |
| 284 | 726 | </el-table-column> |
| 285 | - <el-table-column label="数量" width="96" align="right" sortable :sort-method="sortNumCol('数量')"> | |
| 286 | - <template slot-scope="scope">{{ formatQty(scope.row['数量']) }}</template> | |
| 727 | + <el-table-column | |
| 728 | + prop="数量" | |
| 729 | + label="数量" | |
| 730 | + width="96" | |
| 731 | + align="right" | |
| 732 | + sortable="custom" | |
| 733 | + > | |
| 734 | + <template slot-scope="scope">{{ | |
| 735 | + formatQty(scope.row["数量"]) | |
| 736 | + }}</template> | |
| 287 | 737 | </el-table-column> |
| 288 | - <el-table-column label="入库单价" width="104" align="right" sortable :sort-method="sortNumCol('入库单价')"> | |
| 289 | - <template slot-scope="scope">{{ formatMoney(scope.row['入库单价']) }}</template> | |
| 738 | + <el-table-column | |
| 739 | + prop="入库单价" | |
| 740 | + label="入库单价" | |
| 741 | + width="104" | |
| 742 | + align="right" | |
| 743 | + sortable="custom" | |
| 744 | + > | |
| 745 | + <template slot-scope="scope">{{ | |
| 746 | + formatMoney(scope.row["入库单价"]) | |
| 747 | + }}</template> | |
| 290 | 748 | </el-table-column> |
| 291 | - <el-table-column label="采购金额" width="112" align="right" sortable :sort-method="sortNumCol('采购金额')"> | |
| 292 | - <template slot-scope="scope">{{ formatMoney(scope.row['采购金额']) }}</template> | |
| 749 | + <el-table-column | |
| 750 | + prop="采购金额" | |
| 751 | + label="采购金额" | |
| 752 | + width="112" | |
| 753 | + align="right" | |
| 754 | + sortable="custom" | |
| 755 | + > | |
| 756 | + <template slot-scope="scope">{{ | |
| 757 | + formatMoney(scope.row["采购金额"]) | |
| 758 | + }}</template> | |
| 293 | 759 | </el-table-column> |
| 294 | 760 | <el-table-column label="操作" width="120" align="left" fixed="right"> |
| 295 | 761 | <template slot-scope="scope"> |
| 296 | - <el-button type="text" size="mini" icon="el-icon-tickets" @click.stop="openLinearDialog(scope.row)">线性列表</el-button> | |
| 762 | + <el-button | |
| 763 | + type="text" | |
| 764 | + size="mini" | |
| 765 | + icon="el-icon-tickets" | |
| 766 | + @click.stop="openLinearDialog(scope.row)" | |
| 767 | + >线性列表</el-button | |
| 768 | + > | |
| 297 | 769 | </template> |
| 298 | 770 | </el-table-column> |
| 299 | 771 | </el-table> |
| ... | ... | @@ -302,7 +774,9 @@ |
| 302 | 774 | <i class="el-icon-s-data row-ico--primary" /> |
| 303 | 775 | <span>合计(当前分类列表)</span> |
| 304 | 776 | <span class="sum-item">数量:{{ formatQty(sumCategoryQty) }}</span> |
| 305 | - <span class="sum-item">采购金额:{{ formatMoney(sumCategoryAmt) }}</span> | |
| 777 | + <span class="sum-item" | |
| 778 | + >采购金额:{{ formatMoney(sumCategoryAmt) }}</span | |
| 779 | + > | |
| 306 | 780 | </div> |
| 307 | 781 | </div> |
| 308 | 782 | </div> |
| ... | ... | @@ -318,23 +792,91 @@ |
| 318 | 792 | > |
| 319 | 793 | <div v-loading="linearLoading" class="linear-dialog-body"> |
| 320 | 794 | <p class="linear-hint">{{ linearHint }}</p> |
| 321 | - <el-table :data="linearRows" border size="small" max-height="520" class="linear-table"> | |
| 795 | + <el-table | |
| 796 | + :data="linearRows" | |
| 797 | + border | |
| 798 | + size="small" | |
| 799 | + max-height="520" | |
| 800 | + class="linear-table" | |
| 801 | + > | |
| 322 | 802 | <el-table-column type="index" label="行号" width="52" /> |
| 323 | - <el-table-column prop="单据日期" label="单据日期" width="100" show-overflow-tooltip sortable :sort-method="sortTextCol('单据日期')" /> | |
| 324 | - <el-table-column prop="单据编号" label="单据编号" min-width="130" show-overflow-tooltip sortable :sort-method="sortTextCol('单据编号')" /> | |
| 325 | - <el-table-column prop="单据类型" label="单据类型" width="100" show-overflow-tooltip /> | |
| 326 | - <el-table-column prop="往来单位" label="往来单位" min-width="110" show-overflow-tooltip /> | |
| 327 | - <el-table-column prop="经手人" label="经手人" width="80" show-overflow-tooltip /> | |
| 328 | - <el-table-column prop="仓库名称" label="仓库名称" min-width="96" show-overflow-tooltip /> | |
| 329 | - <el-table-column prop="商品名称" label="商品名称" min-width="120" show-overflow-tooltip /> | |
| 330 | - <el-table-column prop="数量" label="数量" width="80" align="right" sortable :sort-method="sortNumCol('数量')"> | |
| 331 | - <template slot-scope="s">{{ formatQty(s.row['数量']) }}</template> | |
| 803 | + <el-table-column | |
| 804 | + prop="单据日期" | |
| 805 | + label="单据日期" | |
| 806 | + width="100" | |
| 807 | + show-overflow-tooltip | |
| 808 | + sortable | |
| 809 | + :sort-method="sortTextCol('单据日期')" | |
| 810 | + /> | |
| 811 | + <el-table-column | |
| 812 | + prop="单据编号" | |
| 813 | + label="单据编号" | |
| 814 | + min-width="130" | |
| 815 | + show-overflow-tooltip | |
| 816 | + sortable | |
| 817 | + :sort-method="sortTextCol('单据编号')" | |
| 818 | + /> | |
| 819 | + <el-table-column | |
| 820 | + prop="单据类型" | |
| 821 | + label="单据类型" | |
| 822 | + width="100" | |
| 823 | + show-overflow-tooltip | |
| 824 | + /> | |
| 825 | + <el-table-column | |
| 826 | + prop="往来单位" | |
| 827 | + label="往来单位" | |
| 828 | + min-width="110" | |
| 829 | + show-overflow-tooltip | |
| 830 | + /> | |
| 831 | + <el-table-column | |
| 832 | + prop="经手人" | |
| 833 | + label="经手人" | |
| 834 | + width="80" | |
| 835 | + show-overflow-tooltip | |
| 836 | + /> | |
| 837 | + <el-table-column | |
| 838 | + prop="仓库名称" | |
| 839 | + label="仓库名称" | |
| 840 | + min-width="96" | |
| 841 | + show-overflow-tooltip | |
| 842 | + /> | |
| 843 | + <el-table-column | |
| 844 | + prop="商品名称" | |
| 845 | + label="商品名称" | |
| 846 | + min-width="120" | |
| 847 | + show-overflow-tooltip | |
| 848 | + /> | |
| 849 | + <el-table-column | |
| 850 | + prop="数量" | |
| 851 | + label="数量" | |
| 852 | + width="80" | |
| 853 | + align="right" | |
| 854 | + sortable | |
| 855 | + :sort-method="sortNumCol('数量')" | |
| 856 | + > | |
| 857 | + <template slot-scope="s">{{ formatQty(s.row["数量"]) }}</template> | |
| 332 | 858 | </el-table-column> |
| 333 | - <el-table-column prop="入库单价" label="入库单价" width="92" align="right"> | |
| 334 | - <template slot-scope="s">{{ formatMoney(s.row['入库单价']) }}</template> | |
| 859 | + <el-table-column | |
| 860 | + prop="入库单价" | |
| 861 | + label="入库单价" | |
| 862 | + width="92" | |
| 863 | + align="right" | |
| 864 | + > | |
| 865 | + <template slot-scope="s">{{ | |
| 866 | + formatMoney(s.row["入库单价"]) | |
| 867 | + }}</template> | |
| 335 | 868 | </el-table-column> |
| 336 | - <el-table-column prop="采购金额" label="采购金额" width="100" align="right" sortable :sort-method="sortNumCol('采购金额')"> | |
| 337 | - <template slot-scope="s">{{ formatMoney(s.row['采购金额']) }}</template> | |
| 869 | + <el-table-column | |
| 870 | + prop="采购金额" | |
| 871 | + label="采购金额" | |
| 872 | + width="100" | |
| 873 | + align="right" | |
| 874 | + sortable | |
| 875 | + :sort-method="sortNumCol('采购金额')" | |
| 876 | + > | |
| 877 | + <template slot-scope="s">{{ | |
| 878 | + formatMoney(s.row["采购金额"]) | |
| 879 | + }}</template> | |
| 338 | 880 | </el-table-column> |
| 339 | 881 | </el-table> |
| 340 | 882 | </div> |
| ... | ... | @@ -343,13 +885,23 @@ |
| 343 | 885 | </template> |
| 344 | 886 | |
| 345 | 887 | <script> |
| 346 | -import request from '@/utils/request' | |
| 347 | -import { previewDataInterface } from '@/api/systemData/dataInterface' | |
| 888 | +import request from "@/utils/request"; | |
| 889 | +import { previewDataInterface } from "@/api/systemData/dataInterface"; | |
| 348 | 890 | |
| 349 | -const DEFAULT_BILL_TYPES = ['采购入库单', '采购退货单'] | |
| 891 | +const BILL_TYPE_SUGGEST = [ | |
| 892 | + "采购入库单", | |
| 893 | + "采购退货单", | |
| 894 | + "销售出库单", | |
| 895 | + "销售退货单", | |
| 896 | + "预售出库单", | |
| 897 | + "预售退货单", | |
| 898 | + "委托代销发货单", | |
| 899 | + "委托代销退货单", | |
| 900 | + "委托代销结算单" | |
| 901 | +]; | |
| 350 | 902 | |
| 351 | 903 | export default { |
| 352 | - name: 'PurchaseSummary', | |
| 904 | + name: "PurchaseSummary", | |
| 353 | 905 | data() { |
| 354 | 906 | return { |
| 355 | 907 | categoryList: [], |
| ... | ... | @@ -357,102 +909,127 @@ export default { |
| 357 | 909 | brandMap: {}, |
| 358 | 910 | brandLoading: {}, |
| 359 | 911 | productMap: {}, |
| 360 | - productLoading: {}, | |
| 912 | + aggProductLoading: {}, | |
| 361 | 913 | lineMap: {}, |
| 362 | 914 | linePager: {}, |
| 363 | 915 | lineLoading: {}, |
| 364 | - billTypeOptions: [...DEFAULT_BILL_TYPES], | |
| 916 | + lineSort: {}, | |
| 917 | + billTypeOptions: [...BILL_TYPE_SUGGEST], | |
| 918 | + linearInlineMode: false, | |
| 919 | + linearInlineMap: {}, | |
| 920 | + linearInlineLoading: {}, | |
| 365 | 921 | filters: { |
| 366 | 922 | dateRange: [], |
| 367 | 923 | contactUnit: [], |
| 368 | 924 | agent: [], |
| 369 | - productSpId: '', | |
| 925 | + productSpId: "", | |
| 370 | 926 | warehouse: [], |
| 371 | - billType: [...DEFAULT_BILL_TYPES] | |
| 927 | + billType: [] | |
| 372 | 928 | }, |
| 373 | 929 | contactUnitOptions: [], |
| 374 | 930 | agentOptions: [], |
| 375 | 931 | warehouseOptions: [], |
| 376 | 932 | productOptions: [], |
| 377 | - productLoading: false, | |
| 933 | + productRemoteLoading: false, | |
| 378 | 934 | linearVisible: false, |
| 379 | 935 | linearLoading: false, |
| 380 | 936 | linearRows: [], |
| 381 | - linearHint: '' | |
| 382 | - } | |
| 937 | + linearHint: "" | |
| 938 | + }; | |
| 383 | 939 | }, |
| 384 | 940 | computed: { |
| 385 | 941 | sumCategoryQty() { |
| 386 | - return this.categoryList.reduce((s, r) => s + this.parseNum(r['数量']), 0) | |
| 942 | + return this.categoryList.reduce( | |
| 943 | + (s, r) => s + this.parseNum(r["数量"]), | |
| 944 | + 0 | |
| 945 | + ); | |
| 387 | 946 | }, |
| 388 | 947 | sumCategoryAmt() { |
| 389 | - return this.categoryList.reduce((s, r) => s + this.parseNum(r['采购金额']), 0) | |
| 948 | + return this.categoryList.reduce( | |
| 949 | + (s, r) => s + this.parseNum(r["采购金额"]), | |
| 950 | + 0 | |
| 951 | + ); | |
| 390 | 952 | } |
| 391 | 953 | }, |
| 392 | 954 | created() { |
| 393 | - this.loadFilterOptions() | |
| 394 | - this.fetchCategories() | |
| 955 | + this.loadFilterOptions(); | |
| 956 | + this.fetchCategories(); | |
| 395 | 957 | }, |
| 396 | 958 | methods: { |
| 959 | + /** 表格 row-key(带前缀,避免嵌套表展开后 key 冲突) */ | |
| 397 | 960 | categoryRowKey(row) { |
| 398 | - return String(row['分类Id'] != null ? row['分类Id'] : '') | |
| 961 | + return `ps-cat:${String(row["分类Id"] != null ? row["分类Id"] : "")}`; | |
| 399 | 962 | }, |
| 400 | 963 | brandRowKey(catRow, brandRow) { |
| 401 | - return `${this.categoryRowKey(catRow)}|${String(brandRow['品牌Id'] != null ? brandRow['品牌Id'] : '')}` | |
| 964 | + return `${this.categoryRowKey(catRow)}|br:${String( | |
| 965 | + brandRow["品牌Id"] != null ? brandRow["品牌Id"] : "_" | |
| 966 | + )}`; | |
| 402 | 967 | }, |
| 403 | 968 | productRowKey(catRow, brandRow, prodRow) { |
| 404 | - return `${this.brandRowKey(catRow, brandRow)}|${String(prodRow['商品Id'] != null ? prodRow['商品Id'] : '')}` | |
| 969 | + return `${this.brandRowKey(catRow, brandRow)}|sp:${String( | |
| 970 | + prodRow["商品Id"] != null ? prodRow["商品Id"] : "" | |
| 971 | + )}`; | |
| 405 | 972 | }, |
| 406 | 973 | lineKey(catRow, brandRow, prodRow) { |
| 407 | - return this.productRowKey(catRow, brandRow, prodRow) | |
| 974 | + return this.productRowKey(catRow, brandRow, prodRow); | |
| 408 | 975 | }, |
| 409 | 976 | parseNum(val) { |
| 410 | - if (val == null || val === '') return 0 | |
| 411 | - const n = Number(String(val).replace(/,/g, '').trim()) | |
| 412 | - return Number.isFinite(n) ? n : 0 | |
| 977 | + if (val == null || val === "") return 0; | |
| 978 | + const n = Number( | |
| 979 | + String(val) | |
| 980 | + .replace(/,/g, "") | |
| 981 | + .trim() | |
| 982 | + ); | |
| 983 | + return Number.isFinite(n) ? n : 0; | |
| 413 | 984 | }, |
| 414 | 985 | sortNumCol(prop) { |
| 415 | - return (a, b) => this.parseNum(a[prop]) - this.parseNum(b[prop]) | |
| 986 | + return (a, b) => this.parseNum(a[prop]) - this.parseNum(b[prop]); | |
| 416 | 987 | }, |
| 417 | 988 | sortTextCol(prop) { |
| 418 | 989 | return (a, b) => { |
| 419 | - const sa = String(a[prop] != null ? a[prop] : '').trim() | |
| 420 | - const sb = String(b[prop] != null ? b[prop] : '').trim() | |
| 421 | - return sa.localeCompare(sb, 'zh-CN') | |
| 422 | - } | |
| 990 | + const sa = String(a[prop] != null ? a[prop] : "").trim(); | |
| 991 | + const sb = String(b[prop] != null ? b[prop] : "").trim(); | |
| 992 | + return sa.localeCompare(sb, "zh-CN"); | |
| 993 | + }; | |
| 423 | 994 | }, |
| 424 | 995 | cellText(v) { |
| 425 | - if (v == null || String(v).trim() === '') return '无' | |
| 426 | - return String(v) | |
| 996 | + if (v == null || String(v).trim() === "") return "无"; | |
| 997 | + return String(v); | |
| 427 | 998 | }, |
| 428 | 999 | formatQty(val) { |
| 429 | - if (val === null || val === undefined || val === '') return '无' | |
| 430 | - const n = Number(val) | |
| 431 | - if (Number.isNaN(n)) return String(val) | |
| 432 | - return n.toLocaleString('zh-CN', { minimumFractionDigits: 0, maximumFractionDigits: 4 }) | |
| 1000 | + if (val === null || val === undefined || val === "") return "无"; | |
| 1001 | + const n = Number(val); | |
| 1002 | + if (Number.isNaN(n)) return String(val); | |
| 1003 | + return n.toLocaleString("zh-CN", { | |
| 1004 | + minimumFractionDigits: 0, | |
| 1005 | + maximumFractionDigits: 4 | |
| 1006 | + }); | |
| 433 | 1007 | }, |
| 434 | 1008 | formatMoney(val) { |
| 435 | - if (val === null || val === undefined || val === '') return '无' | |
| 436 | - const n = Number(val) | |
| 437 | - if (Number.isNaN(n)) return String(val) | |
| 438 | - return n.toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 4 }) | |
| 1009 | + if (val === null || val === undefined || val === "") return "无"; | |
| 1010 | + const n = Number(val); | |
| 1011 | + if (Number.isNaN(n)) return String(val); | |
| 1012 | + return n.toLocaleString("zh-CN", { | |
| 1013 | + minimumFractionDigits: 2, | |
| 1014 | + maximumFractionDigits: 4 | |
| 1015 | + }); | |
| 439 | 1016 | }, |
| 440 | 1017 | /** 商品编码(空则返回空串,便于单行展示) */ |
| 441 | 1018 | productCodeRaw(item) { |
| 442 | - if (!item) return '' | |
| 1019 | + if (!item) return ""; | |
| 443 | 1020 | const c = |
| 444 | 1021 | item.F_Spbm || |
| 445 | 1022 | item.spbm || |
| 446 | 1023 | item.Spbm || |
| 447 | 1024 | item.商品编号 || |
| 448 | 1025 | item.code || |
| 449 | - '' | |
| 450 | - const t = c != null && String(c).trim() !== '' ? String(c).trim() : '' | |
| 451 | - return t | |
| 1026 | + ""; | |
| 1027 | + const t = c != null && String(c).trim() !== "" ? String(c).trim() : ""; | |
| 1028 | + return t; | |
| 452 | 1029 | }, |
| 453 | 1030 | /** 商品名称 */ |
| 454 | 1031 | productNameRaw(item) { |
| 455 | - if (!item) return '' | |
| 1032 | + if (!item) return ""; | |
| 456 | 1033 | const n = |
| 457 | 1034 | item.F_Spmc || |
| 458 | 1035 | item.spmc || |
| ... | ... | @@ -460,271 +1037,454 @@ export default { |
| 460 | 1037 | item.productName || |
| 461 | 1038 | item.商品名称 || |
| 462 | 1039 | item.name || |
| 463 | - '' | |
| 464 | - const t = n != null && String(n).trim() !== '' ? String(n).trim() : '' | |
| 465 | - return t | |
| 1040 | + ""; | |
| 1041 | + const t = n != null && String(n).trim() !== "" ? String(n).trim() : ""; | |
| 1042 | + return t; | |
| 466 | 1043 | }, |
| 467 | 1044 | /** 选中后在输入框内显示的完整文案(编码 + 名称) */ |
| 468 | 1045 | formatProductLabel(item) { |
| 469 | - if (!item) return '' | |
| 470 | - const code = this.productCodeRaw(item) | |
| 471 | - const name = this.productNameRaw(item) | |
| 472 | - if (code && name) return `${code} | ${name}` | |
| 473 | - if (name) return name | |
| 474 | - if (code) return code | |
| 475 | - const id = item.F_Id || item.id | |
| 476 | - return id ? String(id) : '无' | |
| 1046 | + if (!item) return ""; | |
| 1047 | + const code = this.productCodeRaw(item); | |
| 1048 | + const name = this.productNameRaw(item); | |
| 1049 | + if (code && name) return `${code} | ${name}`; | |
| 1050 | + if (name) return name; | |
| 1051 | + if (code) return code; | |
| 1052 | + const id = this.productOptionValue(item); | |
| 1053 | + return id ? String(id) : "无"; | |
| 1054 | + }, | |
| 1055 | + productOptionValue(item) { | |
| 1056 | + if (!item) return ""; | |
| 1057 | + const v = item.id || item.F_Id || item.f_Id; | |
| 1058 | + return v != null && String(v).trim() !== "" ? String(v).trim() : ""; | |
| 1059 | + }, | |
| 1060 | + normalizeArrayPayload(data) { | |
| 1061 | + if (Array.isArray(data)) return data; | |
| 1062 | + if (data && Array.isArray(data.list)) return data.list; | |
| 1063 | + // 兼容:{ code, msg, data: { list: [...] } } | |
| 1064 | + if (data && data.data && Array.isArray(data.data.list)) | |
| 1065 | + return data.data.list; | |
| 1066 | + if (data && Array.isArray(data.data)) return data.data; | |
| 1067 | + if (data && Array.isArray(data.records)) return data.records; | |
| 1068 | + return []; | |
| 1069 | + }, | |
| 1070 | + lineDetailRowKey(prefix, catRow, brandRow, prodRow, lineRow, idx) { | |
| 1071 | + const pk = prodRow | |
| 1072 | + ? this.lineKey(catRow, brandRow, prodRow) | |
| 1073 | + : this.categoryRowKey(catRow); | |
| 1074 | + const doc = | |
| 1075 | + lineRow && lineRow["单据编号"] != null | |
| 1076 | + ? String(lineRow["单据编号"]) | |
| 1077 | + : ""; | |
| 1078 | + const nm = | |
| 1079 | + lineRow && lineRow["商品名称"] != null | |
| 1080 | + ? String(lineRow["商品名称"]).slice(0, 48) | |
| 1081 | + : ""; | |
| 1082 | + return `${prefix}|${pk}|i${idx}|${doc}|${nm}`; | |
| 477 | 1083 | }, |
| 478 | 1084 | buildBasePayload() { |
| 479 | - const payload = {} | |
| 1085 | + const payload = {}; | |
| 480 | 1086 | if (this.filters.dateRange && this.filters.dateRange.length === 2) { |
| 481 | - payload.startDate = this.filters.dateRange[0] | |
| 482 | - payload.endDate = this.filters.dateRange[1] | |
| 1087 | + payload.startDate = this.filters.dateRange[0]; | |
| 1088 | + payload.endDate = this.filters.dateRange[1]; | |
| 483 | 1089 | } |
| 484 | - if (this.filters.contactUnit.length) payload.contactUnit = this.filters.contactUnit.join(',') | |
| 485 | - if (this.filters.agent.length) payload.agent = this.filters.agent.join(',') | |
| 486 | - if (this.filters.warehouse.length) payload.warehouse = this.filters.warehouse.join(',') | |
| 487 | - if (this.filters.productSpId) payload.productSpId = this.filters.productSpId | |
| 488 | - const bt = this.filters.billType || [] | |
| 489 | - if (bt.length > 0 && bt.length < this.billTypeOptions.length) { | |
| 490 | - payload.billType = bt.join(',') | |
| 491 | - } else { | |
| 492 | - payload.billType = '' | |
| 1090 | + if (this.filters.contactUnit.length) | |
| 1091 | + payload.contactUnit = this.filters.contactUnit.join(","); | |
| 1092 | + if (this.filters.agent.length) { | |
| 1093 | + const a = this.filters.agent | |
| 1094 | + .map(x => String(x).trim()) | |
| 1095 | + .filter(Boolean) | |
| 1096 | + .join(","); | |
| 1097 | + if (a) payload.agent = a; | |
| 493 | 1098 | } |
| 494 | - return payload | |
| 1099 | + if (this.filters.warehouse.length) | |
| 1100 | + payload.warehouse = this.filters.warehouse.join(","); | |
| 1101 | + if (this.filters.productSpId) | |
| 1102 | + payload.productSpId = this.filters.productSpId; | |
| 1103 | + const bt = this.filters.billType || []; | |
| 1104 | + if (bt.length) | |
| 1105 | + payload.billType = bt | |
| 1106 | + .map(x => String(x).trim()) | |
| 1107 | + .filter(Boolean) | |
| 1108 | + .join(","); | |
| 1109 | + return payload; | |
| 495 | 1110 | }, |
| 496 | 1111 | async loadFilterOptions() { |
| 497 | 1112 | try { |
| 498 | 1113 | const companyRes = await request({ |
| 499 | - url: '/api/Extend/WtWldw', | |
| 500 | - method: 'GET', | |
| 1114 | + url: "/api/Extend/WtWldw", | |
| 1115 | + method: "GET", | |
| 501 | 1116 | data: { pageSize: 1000, currentPage: 1 } |
| 502 | - }) | |
| 503 | - const companyList = companyRes.data.list || companyRes.data || [] | |
| 1117 | + }); | |
| 1118 | + const companyList = companyRes.data.list || companyRes.data || []; | |
| 504 | 1119 | this.contactUnitOptions = companyList |
| 505 | 1120 | .map(x => ({ |
| 506 | 1121 | label: x.dwmc || x.F_dwmc || x.id, |
| 507 | 1122 | value: x.id || x.F_Id |
| 508 | 1123 | })) |
| 509 | - .filter(x => x.value) | |
| 1124 | + .filter(x => x.value); | |
| 510 | 1125 | |
| 511 | 1126 | const warehouseRes = await request({ |
| 512 | - url: '/api/Extend/WtCk', | |
| 513 | - method: 'GET', | |
| 1127 | + url: "/api/Extend/WtCk", | |
| 1128 | + method: "GET", | |
| 514 | 1129 | data: { pageSize: 1000, currentPage: 1 } |
| 515 | - }) | |
| 516 | - const warehouseList = warehouseRes.data.list || warehouseRes.data || [] | |
| 1130 | + }); | |
| 1131 | + const warehouseList = warehouseRes.data.list || warehouseRes.data || []; | |
| 517 | 1132 | this.warehouseOptions = warehouseList.map(x => ({ |
| 518 | 1133 | label: x.mdmc || x.F_mdmc || x.id, |
| 519 | 1134 | value: x.id || x.F_Id |
| 520 | - })) | |
| 1135 | + })); | |
| 521 | 1136 | |
| 522 | - const userRes = await previewDataInterface('675937572047815941') | |
| 523 | - const userList = userRes.data || [] | |
| 524 | - this.agentOptions = (userList || []) | |
| 1137 | + const userRes = await previewDataInterface("675937572047815941"); | |
| 1138 | + const userList = this.normalizeArrayPayload(userRes.data); | |
| 1139 | + this.agentOptions = userList | |
| 525 | 1140 | .map(x => ({ |
| 526 | - label: x.realName || x.F_RealName || x.fullName || x.name || x.F_Account || x.account || '', | |
| 527 | - value: x.id || x.F_Id || x.userId | |
| 1141 | + label: String( | |
| 1142 | + x.realName || | |
| 1143 | + x.F_RealName || | |
| 1144 | + x.fullName || | |
| 1145 | + x.name || | |
| 1146 | + x.F_Account || | |
| 1147 | + x.account || | |
| 1148 | + x.f_RealName || | |
| 1149 | + "" | |
| 1150 | + ).trim(), | |
| 1151 | + value: String(x.id || x.F_Id || x.userId || x.f_Id || "").trim() | |
| 528 | 1152 | })) |
| 529 | - .filter(x => x.value && x.label) | |
| 1153 | + .filter(x => x.value && x.label); | |
| 530 | 1154 | } catch (e) { |
| 531 | - console.error('采购汇总筛选下拉加载失败', e) | |
| 1155 | + console.error("采购汇总筛选下拉加载失败", e); | |
| 532 | 1156 | } |
| 533 | 1157 | }, |
| 534 | 1158 | async handleProductSearch(query) { |
| 535 | 1159 | if (!query) { |
| 536 | - this.productOptions = [] | |
| 537 | - return | |
| 1160 | + this.productOptions = []; | |
| 1161 | + return; | |
| 538 | 1162 | } |
| 539 | - this.productLoading = true | |
| 1163 | + this.productRemoteLoading = true; | |
| 540 | 1164 | try { |
| 541 | 1165 | const res = await request({ |
| 542 | - url: '/api/Extend/WtSp/GetListByKeyword', | |
| 543 | - method: 'GET', | |
| 544 | - data: { pageSize: 200, currentPage: 1, keyword: query } | |
| 545 | - }) | |
| 546 | - this.productOptions = res.data.list || res.data || [] | |
| 1166 | + url: "/api/Extend/WtSp/GetListByKeyword", | |
| 1167 | + method: "GET", | |
| 1168 | + data: { pageSize: 200, currentPage: 1, keyword: String(query).trim() } | |
| 1169 | + }); | |
| 1170 | + this.productOptions = this.normalizeArrayPayload(res.data); | |
| 547 | 1171 | } catch (e) { |
| 548 | - console.error('采购汇总商品搜索失败', e) | |
| 1172 | + console.error("采购汇总商品搜索失败", e); | |
| 549 | 1173 | } finally { |
| 550 | - this.productLoading = false | |
| 1174 | + this.productRemoteLoading = false; | |
| 551 | 1175 | } |
| 552 | 1176 | }, |
| 553 | 1177 | clearTreeCaches() { |
| 554 | - this.brandMap = {} | |
| 555 | - this.brandLoading = {} | |
| 556 | - this.productMap = {} | |
| 557 | - this.productLoading = {} | |
| 558 | - this.lineMap = {} | |
| 559 | - this.linePager = {} | |
| 560 | - this.lineLoading = {} | |
| 1178 | + this.brandMap = {}; | |
| 1179 | + this.brandLoading = {}; | |
| 1180 | + this.productMap = {}; | |
| 1181 | + this.aggProductLoading = {}; | |
| 1182 | + this.lineMap = {}; | |
| 1183 | + this.linePager = {}; | |
| 1184 | + this.lineLoading = {}; | |
| 1185 | + this.lineSort = {}; | |
| 1186 | + this.linearInlineMap = {}; | |
| 1187 | + this.linearInlineLoading = {}; | |
| 561 | 1188 | }, |
| 562 | 1189 | fetchCategories() { |
| 563 | - this.categoryLoading = true | |
| 564 | - this.clearTreeCaches() | |
| 1190 | + this.categoryLoading = true; | |
| 1191 | + this.clearTreeCaches(); | |
| 565 | 1192 | request({ |
| 566 | - url: '/api/Extend/WtXsckd/Actions/GetPurchaseSummaryByCategory', | |
| 567 | - method: 'GET', | |
| 1193 | + url: "/api/Extend/WtXsckd/Actions/GetPurchaseSummaryByCategory", | |
| 1194 | + method: "GET", | |
| 568 | 1195 | data: this.buildBasePayload() |
| 569 | 1196 | }) |
| 570 | 1197 | .then(res => { |
| 571 | - const rows = Array.isArray(res.data) ? res.data : (res.data && res.data.list) || [] | |
| 572 | - this.categoryList = rows | |
| 1198 | + // 兼容后端返回:{ code, msg, data: [...] } / { data: { list: [...] } } / [...] | |
| 1199 | + this.categoryList = this.normalizeArrayPayload(res.data); | |
| 573 | 1200 | }) |
| 574 | 1201 | .catch(() => { |
| 575 | - this.categoryList = [] | |
| 1202 | + this.categoryList = []; | |
| 576 | 1203 | }) |
| 577 | 1204 | .finally(() => { |
| 578 | - this.categoryLoading = false | |
| 579 | - }) | |
| 1205 | + this.categoryLoading = false; | |
| 1206 | + }); | |
| 1207 | + }, | |
| 1208 | + onLinearInlineModeChange() { | |
| 1209 | + this.clearTreeCaches(); | |
| 1210 | + this.fetchCategories(); | |
| 1211 | + this.$nextTick(() => { | |
| 1212 | + const t = this.$refs.categoryTable; | |
| 1213 | + if (t && this.categoryList && this.categoryList.length) { | |
| 1214 | + this.categoryList.forEach(r => { | |
| 1215 | + try { | |
| 1216 | + t.toggleRowExpansion(r, false); | |
| 1217 | + } catch (e) { | |
| 1218 | + /* ignore */ | |
| 1219 | + } | |
| 1220 | + }); | |
| 1221 | + } | |
| 1222 | + }); | |
| 580 | 1223 | }, |
| 581 | 1224 | onCategoryExpand(row, expandedRows) { |
| 582 | - const id = String(row['分类Id']) | |
| 583 | - if (expandedRows.some(r => String(r['分类Id']) === id)) { | |
| 584 | - this.loadBrands(row) | |
| 1225 | + const id = String(row["分类Id"]); | |
| 1226 | + const isOpen = expandedRows.some(r => String(r["分类Id"]) === id); | |
| 1227 | + const ck = this.categoryRowKey(row); | |
| 1228 | + if (!isOpen) { | |
| 1229 | + this.$delete(this.linearInlineMap, ck); | |
| 1230 | + this.$delete(this.brandMap, ck); | |
| 1231 | + this.$delete(this.brandLoading, ck); | |
| 1232 | + return; | |
| 1233 | + } | |
| 1234 | + if (this.linearInlineMode) { | |
| 1235 | + this.loadLinearInline(row); | |
| 1236 | + } else { | |
| 1237 | + this.loadBrands(row); | |
| 585 | 1238 | } |
| 586 | 1239 | }, |
| 587 | - loadBrands(catRow) { | |
| 588 | - const k = this.categoryRowKey(catRow) | |
| 589 | - if (this.brandMap[k] !== undefined || this.brandLoading[k]) return | |
| 590 | - this.$set(this.brandLoading, k, true) | |
| 591 | - const cid = String(catRow['分类Id'] != null ? catRow['分类Id'] : '') | |
| 1240 | + loadLinearInline(catRow) { | |
| 1241 | + const k = this.categoryRowKey(catRow); | |
| 1242 | + this.$set(this.linearInlineLoading, k, true); | |
| 1243 | + const cid = String(catRow["分类Id"] != null ? catRow["分类Id"] : ""); | |
| 592 | 1244 | request({ |
| 593 | - url: '/api/Extend/WtXsckd/Actions/GetPurchaseSummaryByBrand', | |
| 594 | - method: 'GET', | |
| 1245 | + url: "/api/Extend/WtXsckd/Actions/GetPurchaseSummaryLinear", | |
| 1246 | + method: "GET", | |
| 595 | 1247 | data: { ...this.buildBasePayload(), categoryId: cid } |
| 596 | 1248 | }) |
| 597 | 1249 | .then(res => { |
| 598 | - const rows = Array.isArray(res.data) ? res.data : (res.data && res.data.list) || [] | |
| 599 | - this.$set(this.brandMap, k, rows) | |
| 1250 | + const rows = this.normalizeArrayPayload(res.data); | |
| 1251 | + this.$set(this.linearInlineMap, k, { list: rows, loaded: true }); | |
| 600 | 1252 | }) |
| 601 | 1253 | .catch(() => { |
| 602 | - this.$set(this.brandMap, k, []) | |
| 1254 | + this.$set(this.linearInlineMap, k, { list: [], loaded: true }); | |
| 603 | 1255 | }) |
| 604 | 1256 | .finally(() => { |
| 605 | - this.$set(this.brandLoading, k, false) | |
| 1257 | + this.$set(this.linearInlineLoading, k, false); | |
| 1258 | + }); | |
| 1259 | + }, | |
| 1260 | + loadBrands(catRow) { | |
| 1261 | + const k = this.categoryRowKey(catRow); | |
| 1262 | + if (this.brandMap[k] !== undefined || this.brandLoading[k]) return; | |
| 1263 | + this.$set(this.brandLoading, k, true); | |
| 1264 | + const cid = String(catRow["分类Id"] != null ? catRow["分类Id"] : ""); | |
| 1265 | + request({ | |
| 1266 | + url: "/api/Extend/WtXsckd/Actions/GetPurchaseSummaryByBrand", | |
| 1267 | + method: "GET", | |
| 1268 | + data: { ...this.buildBasePayload(), categoryId: cid } | |
| 1269 | + }) | |
| 1270 | + .then(res => { | |
| 1271 | + this.$set(this.brandMap, k, this.normalizeArrayPayload(res.data)); | |
| 1272 | + }) | |
| 1273 | + .catch(() => { | |
| 1274 | + this.$set(this.brandMap, k, []); | |
| 606 | 1275 | }) |
| 1276 | + .finally(() => { | |
| 1277 | + this.$set(this.brandLoading, k, false); | |
| 1278 | + }); | |
| 607 | 1279 | }, |
| 608 | 1280 | onBrandExpand(catRow, brandRow, expandedRows) { |
| 609 | - if (expandedRows.some(r => this.brandRowKey(catRow, r) === this.brandRowKey(catRow, brandRow))) { | |
| 610 | - this.loadProducts(catRow, brandRow) | |
| 1281 | + if ( | |
| 1282 | + expandedRows.some( | |
| 1283 | + r => | |
| 1284 | + this.brandRowKey(catRow, r) === this.brandRowKey(catRow, brandRow) | |
| 1285 | + ) | |
| 1286 | + ) { | |
| 1287 | + this.loadProducts(catRow, brandRow); | |
| 611 | 1288 | } |
| 612 | 1289 | }, |
| 613 | 1290 | loadProducts(catRow, brandRow) { |
| 614 | - const k = this.brandRowKey(catRow, brandRow) | |
| 615 | - if (this.productMap[k] !== undefined || this.productLoading[k]) return | |
| 616 | - this.$set(this.productLoading, k, true) | |
| 617 | - const cid = String(catRow['分类Id'] != null ? catRow['分类Id'] : '') | |
| 618 | - const bid = String(brandRow['品牌Id'] != null ? brandRow['品牌Id'] : '') | |
| 1291 | + const k = this.brandRowKey(catRow, brandRow); | |
| 1292 | + if (this.productMap[k] !== undefined || this.aggProductLoading[k]) return; | |
| 1293 | + this.$set(this.aggProductLoading, k, true); | |
| 1294 | + const cid = String(catRow["分类Id"] != null ? catRow["分类Id"] : ""); | |
| 1295 | + const bid = String(brandRow["品牌Id"] != null ? brandRow["品牌Id"] : ""); | |
| 619 | 1296 | request({ |
| 620 | - url: '/api/Extend/WtXsckd/Actions/GetPurchaseSummaryByProductAgg', | |
| 621 | - method: 'GET', | |
| 1297 | + url: "/api/Extend/WtXsckd/Actions/GetPurchaseSummaryByProductAgg", | |
| 1298 | + method: "GET", | |
| 622 | 1299 | data: { ...this.buildBasePayload(), categoryId: cid, brandId: bid } |
| 623 | 1300 | }) |
| 624 | 1301 | .then(res => { |
| 625 | - const rows = Array.isArray(res.data) ? res.data : (res.data && res.data.list) || [] | |
| 626 | - this.$set(this.productMap, k, rows) | |
| 1302 | + this.$set(this.productMap, k, this.normalizeArrayPayload(res.data)); | |
| 627 | 1303 | }) |
| 628 | 1304 | .catch(() => { |
| 629 | - this.$set(this.productMap, k, []) | |
| 1305 | + this.$set(this.productMap, k, []); | |
| 630 | 1306 | }) |
| 631 | 1307 | .finally(() => { |
| 632 | - this.$set(this.productLoading, k, false) | |
| 633 | - }) | |
| 1308 | + this.$set(this.aggProductLoading, k, false); | |
| 1309 | + }); | |
| 634 | 1310 | }, |
| 635 | 1311 | onProductExpand(catRow, brandRow, prodRow, expandedRows) { |
| 636 | - if (expandedRows.some(r => this.productRowKey(catRow, brandRow, r) === this.productRowKey(catRow, brandRow, prodRow))) { | |
| 637 | - this.initLinePager(catRow, brandRow, prodRow) | |
| 638 | - this.fetchLines(catRow, brandRow, prodRow, 1) | |
| 1312 | + if ( | |
| 1313 | + expandedRows.some( | |
| 1314 | + r => | |
| 1315 | + this.productRowKey(catRow, brandRow, r) === | |
| 1316 | + this.productRowKey(catRow, brandRow, prodRow) | |
| 1317 | + ) | |
| 1318 | + ) { | |
| 1319 | + this.initLinePager(catRow, brandRow, prodRow); | |
| 1320 | + this.fetchLines(catRow, brandRow, prodRow, 1); | |
| 639 | 1321 | } |
| 640 | 1322 | }, |
| 641 | 1323 | initLinePager(catRow, brandRow, prodRow) { |
| 642 | - const lk = this.lineKey(catRow, brandRow, prodRow) | |
| 1324 | + const lk = this.lineKey(catRow, brandRow, prodRow); | |
| 643 | 1325 | if (!this.linePager[lk]) { |
| 644 | - this.$set(this.linePager, lk, { currentPage: 1, pageSize: 50, total: 0 }) | |
| 1326 | + this.$set(this.linePager, lk, { | |
| 1327 | + currentPage: 1, | |
| 1328 | + pageSize: 50, | |
| 1329 | + total: 0 | |
| 1330 | + }); | |
| 645 | 1331 | } |
| 646 | 1332 | }, |
| 647 | 1333 | fetchLines(catRow, brandRow, prodRow, page) { |
| 648 | - const lk = this.lineKey(catRow, brandRow, prodRow) | |
| 649 | - this.initLinePager(catRow, brandRow, prodRow) | |
| 650 | - const pager = this.linePager[lk] | |
| 651 | - pager.currentPage = page || 1 | |
| 652 | - this.$set(this.lineLoading, lk, true) | |
| 653 | - const cid = String(catRow['分类Id'] != null ? catRow['分类Id'] : '') | |
| 654 | - const bid = String(brandRow['品牌Id'] != null ? brandRow['品牌Id'] : '') | |
| 655 | - const pid = String(prodRow['商品Id'] != null ? prodRow['商品Id'] : '') | |
| 1334 | + const lk = this.lineKey(catRow, brandRow, prodRow); | |
| 1335 | + this.initLinePager(catRow, brandRow, prodRow); | |
| 1336 | + const pager = this.linePager[lk]; | |
| 1337 | + pager.currentPage = page || 1; | |
| 1338 | + this.$set(this.lineLoading, lk, true); | |
| 1339 | + const cid = String(catRow["分类Id"] != null ? catRow["分类Id"] : ""); | |
| 1340 | + const bid = String(brandRow["品牌Id"] != null ? brandRow["品牌Id"] : ""); | |
| 1341 | + const pid = String(prodRow["商品Id"] != null ? prodRow["商品Id"] : ""); | |
| 1342 | + const sortCfg = this.lineSort[lk] || {}; | |
| 656 | 1343 | request({ |
| 657 | - url: '/api/Extend/WtXsckd/Actions/GetPurchaseSummary', | |
| 658 | - method: 'GET', | |
| 1344 | + url: "/api/Extend/WtXsckd/Actions/GetPurchaseSummary", | |
| 1345 | + method: "GET", | |
| 659 | 1346 | data: { |
| 660 | 1347 | ...this.buildBasePayload(), |
| 661 | 1348 | categoryId: cid, |
| 662 | 1349 | brandId: bid, |
| 663 | 1350 | productSpId: pid, |
| 664 | 1351 | currentPage: pager.currentPage, |
| 665 | - pageSize: pager.pageSize | |
| 1352 | + pageSize: pager.pageSize, | |
| 1353 | + ...(sortCfg.sortField | |
| 1354 | + ? { | |
| 1355 | + sortField: sortCfg.sortField, | |
| 1356 | + sortOrder: sortCfg.sortOrder || "desc" | |
| 1357 | + } | |
| 1358 | + : {}) | |
| 666 | 1359 | } |
| 667 | 1360 | }) |
| 668 | 1361 | .then(res => { |
| 669 | - const body = res.data | |
| 670 | - let list = [] | |
| 671 | - let total = 0 | |
| 672 | - if (body && typeof body === 'object' && !Array.isArray(body) && body.list !== undefined) { | |
| 673 | - list = body.list || [] | |
| 674 | - total = body.total != null ? Number(body.total) : 0 | |
| 1362 | + // 明细接口返回:{ code, msg, data: { list: [], total } } | |
| 1363 | + // 兼容历史:{ list, total } 或直接数组 | |
| 1364 | + const body = | |
| 1365 | + res.data && res.data.data != null ? res.data.data : res.data; | |
| 1366 | + let list = []; | |
| 1367 | + let total = 0; | |
| 1368 | + if ( | |
| 1369 | + body && | |
| 1370 | + typeof body === "object" && | |
| 1371 | + !Array.isArray(body) && | |
| 1372 | + body.list !== undefined | |
| 1373 | + ) { | |
| 1374 | + list = body.list || []; | |
| 1375 | + total = body.total != null ? Number(body.total) : 0; | |
| 675 | 1376 | } else if (Array.isArray(body)) { |
| 676 | - list = body | |
| 677 | - total = body.length | |
| 1377 | + list = body; | |
| 1378 | + total = body.length; | |
| 678 | 1379 | } |
| 679 | - this.$set(this.lineMap, lk, { list }) | |
| 680 | - this.$set(this.linePager[lk], 'total', total) | |
| 1380 | + this.$set(this.lineMap, lk, { list }); | |
| 1381 | + this.$set(this.linePager[lk], "total", total); | |
| 681 | 1382 | }) |
| 682 | 1383 | .catch(() => { |
| 683 | - this.$set(this.lineMap, lk, { list: [] }) | |
| 1384 | + this.$set(this.lineMap, lk, { list: [] }); | |
| 684 | 1385 | }) |
| 685 | 1386 | .finally(() => { |
| 686 | - this.$set(this.lineLoading, lk, false) | |
| 687 | - }) | |
| 1387 | + this.$set(this.lineLoading, lk, false); | |
| 1388 | + }); | |
| 688 | 1389 | }, |
| 689 | 1390 | openLinearDialog(catRow) { |
| 690 | - const cid = String(catRow['分类Id'] != null ? catRow['分类Id'] : '') | |
| 691 | - const cname = this.cellText(catRow['分类名称']) | |
| 692 | - this.linearHint = `分类:${cname}(最多展示 2000 条,与当前筛选条件一致)` | |
| 693 | - this.linearVisible = true | |
| 694 | - this.linearLoading = true | |
| 695 | - this.linearRows = [] | |
| 1391 | + const cid = String(catRow["分类Id"] != null ? catRow["分类Id"] : ""); | |
| 1392 | + const cname = this.cellText(catRow["分类名称"]); | |
| 1393 | + this.linearHint = `分类:${cname}(默认每页最多 2000 条,与当前筛选条件一致;可传 currentPage、pageSize 分页)`; | |
| 1394 | + this.linearVisible = true; | |
| 1395 | + this.linearLoading = true; | |
| 1396 | + this.linearRows = []; | |
| 696 | 1397 | request({ |
| 697 | - url: '/api/Extend/WtXsckd/Actions/GetPurchaseSummaryLinear', | |
| 698 | - method: 'GET', | |
| 1398 | + url: "/api/Extend/WtXsckd/Actions/GetPurchaseSummaryLinear", | |
| 1399 | + method: "GET", | |
| 699 | 1400 | data: { ...this.buildBasePayload(), categoryId: cid } |
| 700 | 1401 | }) |
| 701 | 1402 | .then(res => { |
| 702 | - this.linearRows = Array.isArray(res.data) ? res.data : (res.data && res.data.list) || [] | |
| 1403 | + this.linearRows = this.normalizeArrayPayload(res.data); | |
| 703 | 1404 | }) |
| 704 | 1405 | .catch(() => { |
| 705 | - this.linearRows = [] | |
| 1406 | + this.linearRows = []; | |
| 706 | 1407 | }) |
| 707 | 1408 | .finally(() => { |
| 708 | - this.linearLoading = false | |
| 709 | - }) | |
| 1409 | + this.linearLoading = false; | |
| 1410 | + }); | |
| 710 | 1411 | }, |
| 711 | 1412 | handleSearch() { |
| 712 | - this.fetchCategories() | |
| 1413 | + this.fetchCategories(); | |
| 713 | 1414 | }, |
| 714 | 1415 | handleReset() { |
| 715 | 1416 | this.filters = { |
| 716 | 1417 | dateRange: [], |
| 717 | 1418 | contactUnit: [], |
| 718 | 1419 | agent: [], |
| 719 | - productSpId: '', | |
| 1420 | + productSpId: "", | |
| 720 | 1421 | warehouse: [], |
| 721 | - billType: [...DEFAULT_BILL_TYPES] | |
| 1422 | + billType: [] | |
| 1423 | + }; | |
| 1424 | + this.productOptions = []; | |
| 1425 | + this.fetchCategories(); | |
| 1426 | + }, | |
| 1427 | + sortAggRows(rows, prop, order) { | |
| 1428 | + if (!rows || !rows.length || !prop || !order) return; | |
| 1429 | + const dir = order === "ascending" ? 1 : -1; | |
| 1430 | + const numCols = ["数量", "入库单价", "采购金额"]; | |
| 1431 | + const isNum = numCols.indexOf(prop) >= 0; | |
| 1432 | + rows.sort((a, b) => { | |
| 1433 | + if (isNum) | |
| 1434 | + return (this.parseNum(a[prop]) - this.parseNum(b[prop])) * dir; | |
| 1435 | + const sa = String(a[prop] != null ? a[prop] : "").trim(); | |
| 1436 | + const sb = String(b[prop] != null ? b[prop] : "").trim(); | |
| 1437 | + return sa.localeCompare(sb, "zh-CN") * dir; | |
| 1438 | + }); | |
| 1439 | + }, | |
| 1440 | + onCategorySort({ prop, order }) { | |
| 1441 | + if (!order) { | |
| 1442 | + this.fetchCategories(); | |
| 1443 | + return; | |
| 1444 | + } | |
| 1445 | + this.sortAggRows(this.categoryList, prop, order); | |
| 1446 | + }, | |
| 1447 | + onBrandSort(catRow, { prop, order }) { | |
| 1448 | + const k = this.categoryRowKey(catRow); | |
| 1449 | + const rows = this.brandMap[k]; | |
| 1450 | + if (!order) { | |
| 1451 | + this.loadBrandsForce(catRow); | |
| 1452 | + return; | |
| 1453 | + } | |
| 1454 | + if (rows && rows.length) this.sortAggRows(rows, prop, order); | |
| 1455 | + }, | |
| 1456 | + onProductSort(catRow, brandRow, { prop, order }) { | |
| 1457 | + const k = this.brandRowKey(catRow, brandRow); | |
| 1458 | + const rows = this.productMap[k]; | |
| 1459 | + if (!order) { | |
| 1460 | + this.loadProductsForce(catRow, brandRow); | |
| 1461 | + return; | |
| 722 | 1462 | } |
| 723 | - this.productOptions = [] | |
| 724 | - this.fetchCategories() | |
| 1463 | + if (rows && rows.length) this.sortAggRows(rows, prop, order); | |
| 1464 | + }, | |
| 1465 | + loadBrandsForce(catRow) { | |
| 1466 | + const k = this.categoryRowKey(catRow); | |
| 1467 | + this.$delete(this.brandMap, k); | |
| 1468 | + this.loadBrands(catRow); | |
| 1469 | + }, | |
| 1470 | + loadProductsForce(catRow, brandRow) { | |
| 1471 | + const k = this.brandRowKey(catRow, brandRow); | |
| 1472 | + this.$delete(this.productMap, k); | |
| 1473 | + this.loadProducts(catRow, brandRow); | |
| 1474 | + }, | |
| 1475 | + onLineSort(catRow, brandRow, prodRow, { prop, order }) { | |
| 1476 | + const lk = this.lineKey(catRow, brandRow, prodRow); | |
| 1477 | + if (!prop || !order) { | |
| 1478 | + this.$delete(this.lineSort, lk); | |
| 1479 | + this.fetchLines(catRow, brandRow, prodRow, 1); | |
| 1480 | + return; | |
| 1481 | + } | |
| 1482 | + const sortOrder = order === "ascending" ? "asc" : "desc"; | |
| 1483 | + this.$set(this.lineSort, lk, { sortField: prop, sortOrder }); | |
| 1484 | + this.fetchLines(catRow, brandRow, prodRow, 1); | |
| 725 | 1485 | } |
| 726 | 1486 | } |
| 727 | -} | |
| 1487 | +}; | |
| 728 | 1488 | </script> |
| 729 | 1489 | |
| 730 | 1490 | <style lang="scss" scoped> |
| ... | ... | @@ -747,6 +1507,21 @@ export default { |
| 747 | 1507 | font-size: 18px; |
| 748 | 1508 | } |
| 749 | 1509 | |
| 1510 | +.purchase-sum-head__tools { | |
| 1511 | + display: inline-flex; | |
| 1512 | + align-items: center; | |
| 1513 | + flex-wrap: wrap; | |
| 1514 | + gap: 10px; | |
| 1515 | +} | |
| 1516 | + | |
| 1517 | +.linear-mode-label { | |
| 1518 | + font-size: 13px; | |
| 1519 | + color: #606266; | |
| 1520 | + display: inline-flex; | |
| 1521 | + align-items: center; | |
| 1522 | + gap: 4px; | |
| 1523 | +} | |
| 1524 | + | |
| 750 | 1525 | .purchase-tree-table { |
| 751 | 1526 | ::v-deep .el-table .cell { |
| 752 | 1527 | white-space: nowrap; |
| ... | ... | @@ -758,8 +1533,28 @@ export default { |
| 758 | 1533 | background: #fafbfc; |
| 759 | 1534 | } |
| 760 | 1535 | |
| 1536 | +.nested-wrap--linear { | |
| 1537 | + padding-left: 12px; | |
| 1538 | +} | |
| 1539 | + | |
| 1540 | +.nested-table-host { | |
| 1541 | + width: 100%; | |
| 1542 | + max-width: 100%; | |
| 1543 | + overflow-x: auto; | |
| 1544 | + -webkit-overflow-scrolling: touch; | |
| 1545 | +} | |
| 1546 | + | |
| 1547 | +.nested-table-host--detail { | |
| 1548 | + min-width: 720px; | |
| 1549 | +} | |
| 1550 | + | |
| 761 | 1551 | .nested-table { |
| 762 | 1552 | width: 100%; |
| 1553 | + min-width: 100%; | |
| 1554 | +} | |
| 1555 | + | |
| 1556 | +.nested-table--scroll { | |
| 1557 | + min-width: 960px; | |
| 763 | 1558 | } |
| 764 | 1559 | |
| 765 | 1560 | .nested-table--deep ::v-deep .el-table__body-wrapper { |
| ... | ... | @@ -768,7 +1563,8 @@ export default { |
| 768 | 1563 | } |
| 769 | 1564 | |
| 770 | 1565 | .detail-wrap { |
| 771 | - min-width: 720px; | |
| 1566 | + min-width: 0; | |
| 1567 | + max-width: 100%; | |
| 772 | 1568 | } |
| 773 | 1569 | |
| 774 | 1570 | .mini-pager { | ... | ... |
Antis.Erp.Plat/antis-ncc-admin/src/views/wtShrysz/djmcOptions.js
| ... | ... | @@ -3,14 +3,16 @@ |
| 3 | 3 | * 须与 wt_xsckd.djlx、wt_shrysz.djmc、Dashboard 待办 QueryWtXsckdAuditTodosAsync 的 billDjlx、商品调价单等业务名完全一致。 |
| 4 | 4 | */ |
| 5 | 5 | export const djmcOptions = [ |
| 6 | - { fullName: '同价调拨单', id: '同价调拨单' }, | |
| 7 | - { fullName: '销售出库单', id: '销售出库单' }, | |
| 8 | - { fullName: '预售出库单', id: '预售出库单' }, | |
| 9 | - { fullName: '销售退货单', id: '销售退货单' }, | |
| 10 | - { fullName: '预售退货单', id: '预售退货单' }, | |
| 11 | - { fullName: '采购入库单', id: '采购入库单' }, | |
| 12 | - { fullName: '委托代销发货单', id: '委托代销发货单' }, | |
| 13 | - { fullName: '委托代销退货单', id: '委托代销退货单' }, | |
| 14 | - { fullName: '委托代销结算单', id: '委托代销结算单' }, | |
| 15 | - { fullName: '商品调价单', id: '商品调价单' } | |
| 16 | -] | |
| 6 | + { fullName: "同价调拨单", id: "同价调拨单" }, | |
| 7 | + { fullName: "销售出库单", id: "销售出库单" }, | |
| 8 | + { fullName: "预售出库单", id: "预售出库单" }, | |
| 9 | + { fullName: "销售退货单", id: "销售退货单" }, | |
| 10 | + { fullName: "预售退货单", id: "预售退货单" }, | |
| 11 | + { fullName: "采购入库单", id: "采购入库单" }, | |
| 12 | + { fullName: "委托代销发货单", id: "委托代销发货单" }, | |
| 13 | + { fullName: "委托代销退货单", id: "委托代销退货单" }, | |
| 14 | + { fullName: "委托代销结算单", id: "委托代销结算单" }, | |
| 15 | + { fullName: "商品调价单", id: "商品调价单" }, | |
| 16 | + // 其他收入单(独立主表 wt_yskzjjs,审核配置仍走 wt_shrysz.djmc 匹配 djlx) | |
| 17 | + { fullName: "其他应收单", id: "其他应收单" } | |
| 18 | +]; | ... | ... |
Antis.Erp.Plat/antis-ncc-admin/src/views/wtStockSummary/index.vue
| ... | ... | @@ -66,7 +66,7 @@ |
| 66 | 66 | <el-col :span="12"> |
| 67 | 67 | <el-form-item label="商品"> |
| 68 | 68 | <el-select |
| 69 | - v-model="filters.productKeyword" | |
| 69 | + v-model="filters.productSpId" | |
| 70 | 70 | filterable |
| 71 | 71 | remote |
| 72 | 72 | clearable |
| ... | ... | @@ -80,14 +80,20 @@ |
| 80 | 80 | v-for="item in productOptions" |
| 81 | 81 | :key="item.F_Id || item.id" |
| 82 | 82 | :label="formatProductLabel(item)" |
| 83 | - :value="formatProductLabel(item)" | |
| 83 | + :value="productOptionValue(item)" | |
| 84 | 84 | /> |
| 85 | 85 | </el-select> |
| 86 | 86 | </el-form-item> |
| 87 | 87 | </el-col> |
| 88 | 88 | <el-col :span="24"> |
| 89 | 89 | <div class="action-row"> |
| 90 | - <el-button type="primary" size="mini" icon="el-icon-search" @click="handleSearch">搜索</el-button> | |
| 90 | + <el-button | |
| 91 | + type="primary" | |
| 92 | + size="mini" | |
| 93 | + icon="el-icon-search" | |
| 94 | + @click="handleSearch" | |
| 95 | + >搜索</el-button | |
| 96 | + > | |
| 91 | 97 | <el-button size="mini" @click="handleReset">重置</el-button> |
| 92 | 98 | </div> |
| 93 | 99 | </el-col> |
| ... | ... | @@ -97,12 +103,68 @@ |
| 97 | 103 | |
| 98 | 104 | <div class="table-section"> |
| 99 | 105 | <div class="table-title-bar"> |
| 100 | - <i class="el-icon-data-analysis" style="font-size: 20px; margin-right: 8px; color: #409eff" /> | |
| 106 | + <i | |
| 107 | + class="el-icon-data-analysis" | |
| 108 | + style="font-size: 20px; margin-right: 8px; color: #409eff" | |
| 109 | + /> | |
| 101 | 110 | <span>商品库存汇总</span> |
| 102 | - <span class="hint-text">展开分类行可查看该分类下商品明细(品牌、编码、名称及数量成本)</span> | |
| 111 | + <span v-if="!isProductMode" class="hint-text" | |
| 112 | + >展开分类行可查看该分类下商品明细(品牌、编码、名称及数量成本)</span | |
| 113 | + > | |
| 114 | + <span v-else class="hint-text" | |
| 115 | + >已选择商品:按仓库展示数量、成本均价、总成本</span | |
| 116 | + > | |
| 103 | 117 | </div> |
| 104 | 118 | <div class="table-scroll"> |
| 119 | + <el-table v-if="isProductMode" :data="list" border class="stock-table"> | |
| 120 | + <el-table-column | |
| 121 | + label="仓库名称" | |
| 122 | + min-width="180" | |
| 123 | + show-overflow-tooltip | |
| 124 | + > | |
| 125 | + <template slot-scope="scope"> | |
| 126 | + <i class="el-icon-office-building row-icon cat" /> | |
| 127 | + <span>{{ cellText(scope.row["仓库名称"]) }}</span> | |
| 128 | + </template> | |
| 129 | + </el-table-column> | |
| 130 | + <el-table-column label="商品编码" width="140" show-overflow-tooltip> | |
| 131 | + <template slot-scope="scope"> | |
| 132 | + <i class="el-icon-postcard row-icon code" /> | |
| 133 | + {{ cellText(scope.row["商品编码"]) }} | |
| 134 | + </template> | |
| 135 | + </el-table-column> | |
| 136 | + <el-table-column | |
| 137 | + label="商品名称" | |
| 138 | + min-width="220" | |
| 139 | + show-overflow-tooltip | |
| 140 | + > | |
| 141 | + <template slot-scope="scope"> | |
| 142 | + <i class="el-icon-tickets row-icon pname" /> | |
| 143 | + {{ cellText(scope.row["商品名称"]) }} | |
| 144 | + </template> | |
| 145 | + </el-table-column> | |
| 146 | + <el-table-column label="数量" width="120" align="right"> | |
| 147 | + <template slot-scope="scope"> | |
| 148 | + <i class="el-icon-goods row-icon qty" /> | |
| 149 | + {{ formatQty(scope.row["数量"]) }} | |
| 150 | + </template> | |
| 151 | + </el-table-column> | |
| 152 | + <el-table-column label="成本均价" width="130" align="right"> | |
| 153 | + <template slot-scope="scope"> | |
| 154 | + <i class="el-icon-coin row-icon money" /> | |
| 155 | + {{ formatMoney(scope.row["成本均价"]) }} | |
| 156 | + </template> | |
| 157 | + </el-table-column> | |
| 158 | + <el-table-column label="总成本" width="140" align="right"> | |
| 159 | + <template slot-scope="scope"> | |
| 160 | + <i class="el-icon-wallet row-icon total" /> | |
| 161 | + {{ formatMoney(scope.row["总成本"]) }} | |
| 162 | + </template> | |
| 163 | + </el-table-column> | |
| 164 | + </el-table> | |
| 165 | + | |
| 105 | 166 | <el-table |
| 167 | + v-else | |
| 106 | 168 | ref="categoryTable" |
| 107 | 169 | :data="list" |
| 108 | 170 | :row-key="rowKeyResolver" |
| ... | ... | @@ -126,45 +188,60 @@ |
| 126 | 188 | size="small" |
| 127 | 189 | class="nested-product-table" |
| 128 | 190 | > |
| 129 | - <el-table-column label="品牌名称" width="120" show-overflow-tooltip> | |
| 191 | + <el-table-column | |
| 192 | + label="品牌名称" | |
| 193 | + width="120" | |
| 194 | + show-overflow-tooltip | |
| 195 | + > | |
| 130 | 196 | <template slot-scope="s"> |
| 131 | 197 | <i class="el-icon-medal row-icon brand" /> |
| 132 | - {{ cellText(s.row['品牌名称']) }} | |
| 198 | + {{ cellText(s.row["品牌名称"]) }} | |
| 133 | 199 | </template> |
| 134 | 200 | </el-table-column> |
| 135 | - <el-table-column label="商品编码" width="120" show-overflow-tooltip> | |
| 201 | + <el-table-column | |
| 202 | + label="商品编码" | |
| 203 | + width="120" | |
| 204 | + show-overflow-tooltip | |
| 205 | + > | |
| 136 | 206 | <template slot-scope="s"> |
| 137 | 207 | <i class="el-icon-postcard row-icon code" /> |
| 138 | - {{ cellText(s.row['商品编码']) }} | |
| 208 | + {{ cellText(s.row["商品编码"]) }} | |
| 139 | 209 | </template> |
| 140 | 210 | </el-table-column> |
| 141 | - <el-table-column label="商品名称" min-width="200" show-overflow-tooltip> | |
| 211 | + <el-table-column | |
| 212 | + label="商品名称" | |
| 213 | + min-width="200" | |
| 214 | + show-overflow-tooltip | |
| 215 | + > | |
| 142 | 216 | <template slot-scope="s"> |
| 143 | 217 | <i class="el-icon-tickets row-icon pname" /> |
| 144 | - {{ cellText(s.row['商品名称']) }} | |
| 218 | + {{ cellText(s.row["商品名称"]) }} | |
| 145 | 219 | </template> |
| 146 | 220 | </el-table-column> |
| 147 | 221 | <el-table-column label="数量" width="100" align="right"> |
| 148 | 222 | <template slot-scope="s"> |
| 149 | 223 | <i class="el-icon-goods row-icon qty" /> |
| 150 | - {{ formatQty(s.row['数量']) }} | |
| 224 | + {{ formatQty(s.row["数量"]) }} | |
| 151 | 225 | </template> |
| 152 | 226 | </el-table-column> |
| 153 | 227 | <el-table-column label="成本均价" width="110" align="right"> |
| 154 | 228 | <template slot-scope="s"> |
| 155 | 229 | <i class="el-icon-coin row-icon money" /> |
| 156 | - {{ formatMoney(s.row['成本均价']) }} | |
| 230 | + {{ formatMoney(s.row["成本均价"]) }} | |
| 157 | 231 | </template> |
| 158 | 232 | </el-table-column> |
| 159 | 233 | <el-table-column label="总成本" width="120" align="right"> |
| 160 | 234 | <template slot-scope="s"> |
| 161 | 235 | <i class="el-icon-wallet row-icon total" /> |
| 162 | - {{ formatMoney(s.row['总成本']) }} | |
| 236 | + {{ formatMoney(s.row["总成本"]) }} | |
| 163 | 237 | </template> |
| 164 | 238 | </el-table-column> |
| 165 | 239 | </el-table> |
| 166 | 240 | <div |
| 167 | - v-if="(productDetailMap[expandKey(props.row)] || []).length === 0 && !expandLoading[expandKey(props.row)]" | |
| 241 | + v-if=" | |
| 242 | + (productDetailMap[expandKey(props.row)] || []).length === | |
| 243 | + 0 && !expandLoading[expandKey(props.row)] | |
| 244 | + " | |
| 168 | 245 | class="expand-empty" |
| 169 | 246 | > |
| 170 | 247 | 暂无商品明细 |
| ... | ... | @@ -173,34 +250,44 @@ |
| 173 | 250 | </div> |
| 174 | 251 | </template> |
| 175 | 252 | </el-table-column> |
| 176 | - <el-table-column label="分类名称" min-width="200" show-overflow-tooltip> | |
| 253 | + <el-table-column | |
| 254 | + label="分类名称" | |
| 255 | + min-width="200" | |
| 256 | + show-overflow-tooltip | |
| 257 | + > | |
| 177 | 258 | <template slot-scope="scope"> |
| 178 | 259 | <i class="el-icon-folder-opened row-icon cat" /> |
| 179 | - <span>{{ cellText(scope.row['分类名称']) }}</span> | |
| 260 | + <span>{{ cellText(scope.row["分类名称"]) }}</span> | |
| 180 | 261 | </template> |
| 181 | 262 | </el-table-column> |
| 182 | 263 | <el-table-column label="数量" width="120" align="right"> |
| 183 | 264 | <template slot-scope="scope"> |
| 184 | 265 | <i class="el-icon-goods row-icon qty" /> |
| 185 | - {{ formatQty(scope.row['数量']) }} | |
| 266 | + {{ formatQty(scope.row["数量"]) }} | |
| 186 | 267 | </template> |
| 187 | 268 | </el-table-column> |
| 188 | 269 | <el-table-column label="成本均价" width="130" align="right"> |
| 189 | 270 | <template slot-scope="scope"> |
| 190 | 271 | <i class="el-icon-coin row-icon money" /> |
| 191 | - {{ formatMoney(scope.row['成本均价']) }} | |
| 272 | + {{ formatMoney(scope.row["成本均价"]) }} | |
| 192 | 273 | </template> |
| 193 | 274 | </el-table-column> |
| 194 | 275 | <el-table-column label="总成本" width="140" align="right"> |
| 195 | 276 | <template slot-scope="scope"> |
| 196 | 277 | <i class="el-icon-wallet row-icon total" /> |
| 197 | - {{ formatMoney(scope.row['总成本']) }} | |
| 278 | + {{ formatMoney(scope.row["总成本"]) }} | |
| 198 | 279 | </template> |
| 199 | 280 | </el-table-column> |
| 200 | 281 | </el-table> |
| 201 | 282 | |
| 202 | 283 | <div class="summary-footer"> |
| 203 | - <span><i class="el-icon-s-data" style="color: #409eff; margin-right: 6px" />合计(分类汇总)</span> | |
| 284 | + <span> | |
| 285 | + <i | |
| 286 | + class="el-icon-s-data" | |
| 287 | + style="color: #409eff; margin-right: 6px" | |
| 288 | + /> | |
| 289 | + {{ isProductMode ? "合计(按仓库)" : "合计(分类汇总)" }} | |
| 290 | + </span> | |
| 204 | 291 | <span class="sum-item">数量:{{ totalQty }}</span> |
| 205 | 292 | <span class="sum-item">总成本:{{ totalCost }}</span> |
| 206 | 293 | </div> |
| ... | ... | @@ -210,10 +297,10 @@ |
| 210 | 297 | </template> |
| 211 | 298 | |
| 212 | 299 | <script> |
| 213 | -import request from '@/utils/request' | |
| 300 | +import request from "@/utils/request"; | |
| 214 | 301 | |
| 215 | 302 | export default { |
| 216 | - name: 'StockSummary', | |
| 303 | + name: "StockSummary", | |
| 217 | 304 | data() { |
| 218 | 305 | return { |
| 219 | 306 | list: [], |
| ... | ... | @@ -224,183 +311,225 @@ export default { |
| 224 | 311 | warehouse: [], |
| 225 | 312 | brand: [], |
| 226 | 313 | category: [], |
| 227 | - productKeyword: '' | |
| 314 | + productSpId: "" | |
| 228 | 315 | }, |
| 229 | 316 | warehouseOptions: [], |
| 230 | 317 | brandOptions: [], |
| 231 | 318 | categoryOptions: [], |
| 232 | 319 | productOptions: [], |
| 233 | 320 | productLoading: false |
| 234 | - } | |
| 321 | + }; | |
| 235 | 322 | }, |
| 236 | 323 | computed: { |
| 324 | + isProductMode() { | |
| 325 | + return !!this.filters.productSpId; | |
| 326 | + }, | |
| 237 | 327 | totalQty() { |
| 238 | - return this.list.reduce((s, r) => s + Number(r['数量'] || 0), 0) | |
| 328 | + return this.list.reduce((s, r) => s + Number(r["数量"] || 0), 0); | |
| 239 | 329 | }, |
| 240 | 330 | totalCost() { |
| 241 | - const n = this.list.reduce((s, r) => s + Number(r['总成本'] || 0), 0) | |
| 242 | - return n.toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 }) | |
| 331 | + const n = this.list.reduce((s, r) => s + Number(r["总成本"] || 0), 0); | |
| 332 | + return n.toLocaleString("zh-CN", { | |
| 333 | + minimumFractionDigits: 2, | |
| 334 | + maximumFractionDigits: 2 | |
| 335 | + }); | |
| 243 | 336 | } |
| 244 | 337 | }, |
| 245 | 338 | methods: { |
| 339 | + normalizeArrayPayload(data) { | |
| 340 | + if (Array.isArray(data)) return data; | |
| 341 | + if (data && Array.isArray(data.list)) return data.list; | |
| 342 | + if (data && data.data && Array.isArray(data.data.list)) | |
| 343 | + return data.data.list; | |
| 344 | + if (data && Array.isArray(data.data)) return data.data; | |
| 345 | + return []; | |
| 346 | + }, | |
| 246 | 347 | rowKeyResolver(row) { |
| 247 | - const id = row['分类Id'] | |
| 248 | - if (id !== null && id !== undefined && id !== '') { | |
| 249 | - return `cat-${id}` | |
| 348 | + const id = row["分类Id"]; | |
| 349 | + if (id !== null && id !== undefined && id !== "") { | |
| 350 | + return `cat-${id}`; | |
| 250 | 351 | } |
| 251 | - return row._rowUid || 'cat-unknown' | |
| 352 | + return row._rowUid || "cat-unknown"; | |
| 252 | 353 | }, |
| 253 | 354 | expandKey(row) { |
| 254 | - return this.rowKeyResolver(row) | |
| 355 | + return this.rowKeyResolver(row); | |
| 255 | 356 | }, |
| 256 | 357 | categoryIdOf(row) { |
| 257 | - const id = row['分类Id'] | |
| 258 | - if (id === null || id === undefined || id === '') return null | |
| 259 | - return String(id) | |
| 358 | + const id = row["分类Id"]; | |
| 359 | + if (id === null || id === undefined || id === "") return null; | |
| 360 | + return String(id); | |
| 260 | 361 | }, |
| 261 | 362 | cellText(v) { |
| 262 | - if (v === null || v === undefined || v === '') return '无' | |
| 263 | - return String(v) | |
| 363 | + if (v === null || v === undefined || v === "") return "无"; | |
| 364 | + return String(v); | |
| 264 | 365 | }, |
| 265 | 366 | formatQty(v) { |
| 266 | - if (v === null || v === undefined || v === '') return '无' | |
| 267 | - const n = Number(v) | |
| 268 | - if (Number.isNaN(n)) return String(v) | |
| 269 | - return n.toLocaleString('zh-CN', { maximumFractionDigits: 4 }) | |
| 367 | + if (v === null || v === undefined || v === "") return "无"; | |
| 368 | + const n = Number(v); | |
| 369 | + if (Number.isNaN(n)) return String(v); | |
| 370 | + return n.toLocaleString("zh-CN", { maximumFractionDigits: 4 }); | |
| 270 | 371 | }, |
| 271 | 372 | formatMoney(v) { |
| 272 | - if (v === null || v === undefined || v === '') return '无' | |
| 273 | - const n = Number(v) | |
| 274 | - if (Number.isNaN(n)) return String(v) | |
| 275 | - return n.toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 4 }) | |
| 373 | + if (v === null || v === undefined || v === "") return "无"; | |
| 374 | + const n = Number(v); | |
| 375 | + if (Number.isNaN(n)) return String(v); | |
| 376 | + return n.toLocaleString("zh-CN", { | |
| 377 | + minimumFractionDigits: 2, | |
| 378 | + maximumFractionDigits: 4 | |
| 379 | + }); | |
| 276 | 380 | }, |
| 277 | 381 | formatProductLabel(item) { |
| 278 | - if (!item) return '' | |
| 279 | - const code = item.F_Spbm || item.spbm || item.商品编号 || '' | |
| 280 | - const name = item.F_Spmc || item.spmc || item.商品名称 || '' | |
| 281 | - return [code, name].filter(Boolean).join(' ') | |
| 382 | + if (!item) return ""; | |
| 383 | + const code = item.F_Spbm || item.spbm || item.商品编号 || ""; | |
| 384 | + const name = item.F_Spmc || item.spmc || item.商品名称 || ""; | |
| 385 | + return [code, name].filter(Boolean).join(" "); | |
| 386 | + }, | |
| 387 | + productOptionValue(item) { | |
| 388 | + if (!item) return ""; | |
| 389 | + const v = item.id || item.F_Id || item.f_Id; | |
| 390 | + return v != null && String(v).trim() !== "" ? String(v).trim() : ""; | |
| 282 | 391 | }, |
| 283 | 392 | async loadOptions() { |
| 284 | 393 | try { |
| 285 | 394 | const [ckRes, plRes, ppRes] = await Promise.all([ |
| 286 | - request({ url: '/api/Extend/WtCk', method: 'GET', data: { pageSize: 1000, currentPage: 1 } }), | |
| 287 | - request({ url: '/api/Extend/WtPl', method: 'GET', data: { pageSize: 1000, currentPage: 1 } }), | |
| 288 | - request({ url: '/api/Extend/WtPp', method: 'GET', data: { pageSize: 1000, currentPage: 1 } }) | |
| 289 | - ]) | |
| 290 | - const cks = ckRes.data.list || ckRes.data || [] | |
| 395 | + request({ | |
| 396 | + url: "/api/Extend/WtCk", | |
| 397 | + method: "GET", | |
| 398 | + data: { pageSize: 1000, currentPage: 1 } | |
| 399 | + }), | |
| 400 | + request({ | |
| 401 | + url: "/api/Extend/WtPl", | |
| 402 | + method: "GET", | |
| 403 | + data: { pageSize: 1000, currentPage: 1 } | |
| 404 | + }), | |
| 405 | + request({ | |
| 406 | + url: "/api/Extend/WtPp", | |
| 407 | + method: "GET", | |
| 408 | + data: { pageSize: 1000, currentPage: 1 } | |
| 409 | + }) | |
| 410 | + ]); | |
| 411 | + const cks = ckRes.data.list || ckRes.data || []; | |
| 291 | 412 | this.warehouseOptions = cks.map(x => ({ |
| 292 | 413 | label: x.mdmc || x.F_mdmc || x.id, |
| 293 | 414 | value: x.id || x.F_Id |
| 294 | - })) | |
| 295 | - const pls = plRes.data.list || plRes.data || [] | |
| 415 | + })); | |
| 416 | + const pls = plRes.data.list || plRes.data || []; | |
| 296 | 417 | this.categoryOptions = pls.map(x => ({ |
| 297 | 418 | label: x.plmc || x.F_Plmc || x.id, |
| 298 | 419 | value: x.id || x.F_Id |
| 299 | - })) | |
| 300 | - const pps = ppRes.data.list || ppRes.data || [] | |
| 420 | + })); | |
| 421 | + const pps = ppRes.data.list || ppRes.data || []; | |
| 301 | 422 | this.brandOptions = pps.map(x => ({ |
| 302 | 423 | label: x.ppmc || x.F_Ppmc || x.id, |
| 303 | 424 | value: x.id || x.F_Id |
| 304 | - })) | |
| 425 | + })); | |
| 305 | 426 | } catch (e) { |
| 306 | - console.error('库存汇总筛选项加载失败', e) | |
| 427 | + console.error("库存汇总筛选项加载失败", e); | |
| 307 | 428 | } |
| 308 | 429 | }, |
| 309 | 430 | async handleProductSearch(query) { |
| 310 | 431 | if (!query) { |
| 311 | - this.productOptions = [] | |
| 312 | - return | |
| 432 | + this.productOptions = []; | |
| 433 | + return; | |
| 313 | 434 | } |
| 314 | - this.productLoading = true | |
| 435 | + this.productLoading = true; | |
| 315 | 436 | try { |
| 316 | 437 | const res = await request({ |
| 317 | - url: '/api/Extend/WtSp', | |
| 318 | - method: 'GET', | |
| 319 | - data: { pageSize: 200, currentPage: 1, keyword: query } | |
| 320 | - }) | |
| 321 | - this.productOptions = res.data.list || res.data || [] | |
| 438 | + url: "/api/Extend/WtSp/GetListByKeyword", | |
| 439 | + method: "GET", | |
| 440 | + data: { pageSize: 200, currentPage: 1, keyword: String(query).trim() } | |
| 441 | + }); | |
| 442 | + this.productOptions = this.normalizeArrayPayload(res.data); | |
| 322 | 443 | } catch (e) { |
| 323 | - console.error(e) | |
| 444 | + console.error(e); | |
| 324 | 445 | } finally { |
| 325 | - this.productLoading = false | |
| 446 | + this.productLoading = false; | |
| 326 | 447 | } |
| 327 | 448 | }, |
| 328 | 449 | buildPayload() { |
| 329 | - const p = {} | |
| 330 | - if (this.filters.warehouse.length) p.warehouse = this.filters.warehouse.join(',') | |
| 331 | - if (this.filters.brand.length) p.brand = this.filters.brand.join(',') | |
| 332 | - if (this.filters.category.length) p.category = this.filters.category.join(',') | |
| 333 | - if (this.filters.productKeyword) p.product = this.filters.productKeyword | |
| 334 | - return p | |
| 450 | + const p = {}; | |
| 451 | + if (this.filters.warehouse.length) | |
| 452 | + p.warehouse = this.filters.warehouse.join(","); | |
| 453 | + if (this.filters.brand.length) p.brand = this.filters.brand.join(","); | |
| 454 | + if (this.filters.category.length) | |
| 455 | + p.category = this.filters.category.join(","); | |
| 456 | + if (this.filters.productSpId) p.productSpId = this.filters.productSpId; | |
| 457 | + return p; | |
| 335 | 458 | }, |
| 336 | 459 | normalizeCategoryRows(rows) { |
| 337 | - const arr = rows || [] | |
| 460 | + const arr = rows || []; | |
| 338 | 461 | return arr.map((r, i) => { |
| 339 | - const hasId = r['分类Id'] !== null && r['分类Id'] !== undefined && r['分类Id'] !== '' | |
| 340 | - return hasId ? { ...r } : { ...r, _rowUid: `no-pl-${i}` } | |
| 341 | - }) | |
| 462 | + const hasId = | |
| 463 | + r["分类Id"] !== null && | |
| 464 | + r["分类Id"] !== undefined && | |
| 465 | + r["分类Id"] !== ""; | |
| 466 | + return hasId ? { ...r } : { ...r, _rowUid: `no-pl-${i}` }; | |
| 467 | + }); | |
| 342 | 468 | }, |
| 343 | 469 | fetchData() { |
| 344 | - this.productDetailMap = {} | |
| 345 | - this.productDetailLoaded = {} | |
| 346 | - this.expandLoading = {} | |
| 347 | - request({ | |
| 348 | - url: '/api/Extend/WtXsckd/Actions/GetStockSummaryByCategory', | |
| 349 | - method: 'GET', | |
| 350 | - data: this.buildPayload() | |
| 351 | - }).then(res => { | |
| 352 | - this.list = this.normalizeCategoryRows(res.data || []) | |
| 353 | - }) | |
| 470 | + this.productDetailMap = {}; | |
| 471 | + this.productDetailLoaded = {}; | |
| 472 | + this.expandLoading = {}; | |
| 473 | + const payload = this.buildPayload(); | |
| 474 | + const url = this.isProductMode | |
| 475 | + ? "/api/Extend/WtXsckd/Actions/GetStockSummaryByWarehouse" | |
| 476 | + : "/api/Extend/WtXsckd/Actions/GetStockSummaryByCategory"; | |
| 477 | + request({ url, method: "GET", data: payload }).then(res => { | |
| 478 | + const rows = this.normalizeArrayPayload(res.data); | |
| 479 | + this.list = this.isProductMode | |
| 480 | + ? rows | |
| 481 | + : this.normalizeCategoryRows(rows); | |
| 482 | + }); | |
| 354 | 483 | }, |
| 355 | 484 | async loadProductDetailsForRow(row) { |
| 356 | - const cid = this.categoryIdOf(row) | |
| 357 | - const key = this.expandKey(row) | |
| 358 | - if (!cid) return | |
| 359 | - if (this.productDetailLoaded[key]) return | |
| 360 | - this.$set(this.expandLoading, key, true) | |
| 485 | + const cid = this.categoryIdOf(row); | |
| 486 | + const key = this.expandKey(row); | |
| 487 | + if (!cid) return; | |
| 488 | + if (this.productDetailLoaded[key]) return; | |
| 489 | + this.$set(this.expandLoading, key, true); | |
| 361 | 490 | try { |
| 362 | - const payload = { ...this.buildPayload(), categoryId: cid } | |
| 491 | + const payload = { ...this.buildPayload(), categoryId: cid }; | |
| 363 | 492 | const res = await request({ |
| 364 | - url: '/api/Extend/WtXsckd/Actions/GetStockSummaryByProduct', | |
| 365 | - method: 'GET', | |
| 493 | + url: "/api/Extend/WtXsckd/Actions/GetStockSummaryByProduct", | |
| 494 | + method: "GET", | |
| 366 | 495 | data: payload |
| 367 | - }) | |
| 368 | - const rows = res.data || [] | |
| 369 | - this.$set(this.productDetailMap, key, rows) | |
| 370 | - this.$set(this.productDetailLoaded, key, true) | |
| 496 | + }); | |
| 497 | + const rows = res.data || []; | |
| 498 | + this.$set(this.productDetailMap, key, rows); | |
| 499 | + this.$set(this.productDetailLoaded, key, true); | |
| 371 | 500 | } catch (e) { |
| 372 | - console.error(e) | |
| 373 | - this.$set(this.productDetailMap, key, []) | |
| 374 | - this.$set(this.productDetailLoaded, key, true) | |
| 501 | + console.error(e); | |
| 502 | + this.$set(this.productDetailMap, key, []); | |
| 503 | + this.$set(this.productDetailLoaded, key, true); | |
| 375 | 504 | } finally { |
| 376 | - this.$set(this.expandLoading, key, false) | |
| 505 | + this.$set(this.expandLoading, key, false); | |
| 377 | 506 | } |
| 378 | 507 | }, |
| 379 | 508 | onExpandChange(row, expandedRows) { |
| 380 | - const key = this.expandKey(row) | |
| 381 | - const opened = expandedRows.some(r => this.expandKey(r) === key) | |
| 382 | - if (!opened) return | |
| 383 | - if (!this.categoryIdOf(row)) return | |
| 384 | - this.loadProductDetailsForRow(row) | |
| 509 | + const key = this.expandKey(row); | |
| 510 | + const opened = expandedRows.some(r => this.expandKey(r) === key); | |
| 511 | + if (!opened) return; | |
| 512 | + if (!this.categoryIdOf(row)) return; | |
| 513 | + this.loadProductDetailsForRow(row); | |
| 385 | 514 | }, |
| 386 | 515 | handleSearch() { |
| 387 | - this.fetchData() | |
| 516 | + this.fetchData(); | |
| 388 | 517 | }, |
| 389 | 518 | handleReset() { |
| 390 | 519 | this.filters = { |
| 391 | 520 | warehouse: [], |
| 392 | 521 | brand: [], |
| 393 | 522 | category: [], |
| 394 | - productKeyword: '' | |
| 395 | - } | |
| 396 | - this.fetchData() | |
| 523 | + productSpId: "" | |
| 524 | + }; | |
| 525 | + this.fetchData(); | |
| 397 | 526 | } |
| 398 | 527 | }, |
| 399 | 528 | created() { |
| 400 | - this.loadOptions() | |
| 401 | - this.fetchData() | |
| 529 | + this.loadOptions(); | |
| 530 | + this.fetchData(); | |
| 402 | 531 | } |
| 403 | -} | |
| 532 | +}; | |
| 404 | 533 | </script> |
| 405 | 534 | |
| 406 | 535 | <style scoped> | ... | ... |
Antis.Erp.Plat/antis-ncc-admin/src/views/wtYskzjjs_qt/Form.vue
| 1 | 1 | <template> |
| 2 | - <el-dialog :title="!dataForm.id ? '新建' : isDetail ? '详情':'编辑'" :close-on-click-modal="false" :visible.sync="visible" class="NCC-dialog NCC-dialog_center" lock-scroll width="90%"> | |
| 3 | - <el-row :gutter="15" class="" > | |
| 4 | - <el-form ref="elForm" :model="dataForm" size="small" label-width="100px" label-position="right" :disabled="!!isDetail" :rules="rules"> | |
| 5 | - <el-col :span="8"> | |
| 6 | - <el-form-item label="单据编号" prop="id"> | |
| 7 | - <el-input v-model="dataForm.id" placeholder="请输入" clearable readonly :style='{"width":"100%"}' > | |
| 8 | - </el-input> | |
| 9 | - </el-form-item> | |
| 10 | - </el-col> | |
| 11 | - <el-col :span="8"> | |
| 12 | - <el-form-item label="单据日期" prop="djrq"> | |
| 13 | - <el-date-picker v-model="dataForm.djrq" placeholder="请选择" clearable :style='{"width":"100%"}' type='date' format="yyyy-MM-dd" value-format="timestamp" > | |
| 14 | - </el-date-picker> | |
| 15 | - </el-form-item> | |
| 16 | - </el-col> | |
| 17 | - <el-col :span="8"> | |
| 18 | - <el-form-item label="经手人" prop="jsr"> | |
| 19 | - <user-select v-model="dataForm.jsr" placeholder="请选择" clearable > | |
| 20 | - </user-select> | |
| 21 | - </el-form-item> | |
| 22 | - </el-col> | |
| 23 | - <el-col :span="8"> | |
| 24 | - <el-form-item label="往来单位" prop="wldw"> | |
| 25 | - <el-select v-model="dataForm.wldw" placeholder="请选择" clearable filterable :style='{"width":"100%"}'> | |
| 26 | - <el-option v-for="(item, index) in wldwOptions" :key="index" :label="item.dwmc" :value="item.id" :disabled="item.disabled"></el-option> | |
| 27 | - </el-select> | |
| 28 | - </el-form-item> | |
| 29 | - </el-col> | |
| 30 | - <el-col :span="24"> | |
| 31 | - <el-form-item label-width="0"> | |
| 32 | - <el-table :data="dataForm.wtYskzjjsMxList" size='mini'> | |
| 33 | - <el-table-column type="index" width="50" label="序号" align="center" /> | |
| 34 | - <el-table-column prop="srxmmc" label="收入项目"> | |
| 35 | - <template slot-scope="scope"> | |
| 36 | - <el-select | |
| 37 | - v-model="scope.row.srxmmc" | |
| 38 | - placeholder="请选择或输入" | |
| 39 | - clearable | |
| 40 | - filterable | |
| 41 | - allow-create | |
| 42 | - default-first-option | |
| 43 | - > | |
| 44 | - <el-option v-for="(item, index) in srxmmcOptions" :key="index" :label="item.fullName" :value="item.id" :disabled="item.disabled"></el-option> | |
| 45 | - </el-select> | |
| 46 | - </template> | |
| 47 | - </el-table-column> | |
| 48 | - <el-table-column prop="je" label="原币金额"> | |
| 49 | - <template slot-scope="scope"> | |
| 50 | - <el-input-number | |
| 51 | - v-model.number="scope.row.je" | |
| 52 | - placeholder="请输入" | |
| 53 | - :min="0" | |
| 54 | - :precision="2" | |
| 55 | - controls-position="right" | |
| 56 | - style="width: 100%" | |
| 57 | - @change="calculateTotalAmount" | |
| 58 | - /> | |
| 59 | - </template> | |
| 60 | - </el-table-column> | |
| 61 | - <el-table-column prop="bz" label="备注"> | |
| 62 | - <template slot-scope="scope"> | |
| 63 | - <el-input v-model="scope.row.bz" placeholder="请输入" clearable ></el-input> | |
| 64 | - </template> | |
| 65 | - </el-table-column> | |
| 66 | - <el-table-column label="操作" width="50"> | |
| 67 | - <template slot-scope="scope"> | |
| 68 | - <el-button size="mini" type="text" class="NCC-table-delBtn" @click="handleDelWtYskzjjsMxEntityList(scope.$index)">删除</el-button> | |
| 69 | - </template> | |
| 70 | - </el-table-column> | |
| 71 | - </el-table> | |
| 72 | - <div class="table-actions" @click="addHandleWtYskzjjsMxEntityList()"> | |
| 73 | - <el-button type="text" icon="el-icon-plus">新增</el-button> | |
| 74 | - </div> | |
| 75 | - </el-form-item> | |
| 76 | - </el-col> | |
| 77 | - <!-- 保留收款账户和收款金额,隐藏付款账户和付款金额 --> | |
| 78 | - <!-- | |
| 79 | - <el-col :span="6"> | |
| 80 | - <el-form-item label="付款账户" prop="fkzh"> | |
| 81 | - <el-select v-model="dataForm.fkzh" placeholder="请选择" clearable :style='{"width":"100%"}' > | |
| 82 | - <el-option v-for="(item, index) in fkzhOptions" :key="index" :label="item.fullName" :value="item.id" ></el-option> | |
| 83 | - </el-select> | |
| 84 | - </el-form-item> | |
| 85 | - </el-col> | |
| 86 | - <el-col :span="6"> | |
| 87 | - <el-form-item label="付款金额" prop="fkje"> | |
| 88 | - <el-input v-model="dataForm.fkje" placeholder="请输入" clearable :style='{"width":"100%"}' > | |
| 89 | - </el-input> | |
| 90 | - </el-form-item> | |
| 91 | - </el-col> | |
| 92 | - --> | |
| 93 | - <el-col :span="6"> | |
| 94 | - <el-form-item label="收款账户" prop="skzh"> | |
| 95 | - <el-select v-model="dataForm.skzh" placeholder="请选择" clearable :style='{"width":"100%"}' > | |
| 96 | - <el-option v-for="(item, index) in skzhOptions" :key="index" :label="item.fullName" :value="item.id" ></el-option> | |
| 97 | - </el-select> | |
| 98 | - </el-form-item> | |
| 99 | - </el-col> | |
| 100 | - <el-col :span="6"> | |
| 101 | - <el-form-item label="收款金额" prop="skje"> | |
| 102 | - <el-input v-model="dataForm.skje" placeholder="请输入" clearable :style='{"width":"100%"}' > | |
| 103 | - </el-input> | |
| 104 | - </el-form-item> | |
| 105 | - </el-col> | |
| 106 | - <el-col :span="24" v-if="false" > | |
| 107 | - <el-form-item label="单据类型" prop="djlx"> | |
| 108 | - <el-input v-model="dataForm.djlx" placeholder="请输入" clearable :style='{"width":"100%"}' > | |
| 109 | - </el-input> | |
| 110 | - </el-form-item> | |
| 111 | - </el-col> | |
| 112 | - </el-form> | |
| 113 | - </el-row> | |
| 114 | - <span slot="footer" class="dialog-footer"> | |
| 115 | - <el-button @click="visible = false">取 消</el-button> | |
| 116 | - <el-button type="primary" @click="dataFormSubmit()" v-if="!isDetail">确 定</el-button> | |
| 117 | - </span> | |
| 118 | - </el-dialog> | |
| 2 | + <el-dialog | |
| 3 | + :title="!dataForm.id ? '新建' : isDetail ? '详情' : '编辑'" | |
| 4 | + :close-on-click-modal="false" | |
| 5 | + :visible.sync="visible" | |
| 6 | + class="NCC-dialog NCC-dialog_center" | |
| 7 | + lock-scroll | |
| 8 | + width="90%" | |
| 9 | + > | |
| 10 | + <el-row :gutter="15" class=""> | |
| 11 | + <el-form | |
| 12 | + ref="elForm" | |
| 13 | + :model="dataForm" | |
| 14 | + size="small" | |
| 15 | + label-width="100px" | |
| 16 | + label-position="right" | |
| 17 | + :disabled="!!isDetail" | |
| 18 | + :rules="rules" | |
| 19 | + > | |
| 20 | + <el-col :span="8"> | |
| 21 | + <el-form-item label="单据编号" prop="id"> | |
| 22 | + <el-input | |
| 23 | + v-model="dataForm.id" | |
| 24 | + placeholder="请输入" | |
| 25 | + clearable | |
| 26 | + readonly | |
| 27 | + :style="{ width: '100%' }" | |
| 28 | + > | |
| 29 | + </el-input> | |
| 30 | + </el-form-item> | |
| 31 | + </el-col> | |
| 32 | + <el-col :span="8"> | |
| 33 | + <el-form-item label="单据日期" prop="djrq"> | |
| 34 | + <el-date-picker | |
| 35 | + v-model="dataForm.djrq" | |
| 36 | + placeholder="请选择" | |
| 37 | + clearable | |
| 38 | + :style="{ width: '100%' }" | |
| 39 | + type="date" | |
| 40 | + format="yyyy-MM-dd" | |
| 41 | + value-format="timestamp" | |
| 42 | + > | |
| 43 | + </el-date-picker> | |
| 44 | + </el-form-item> | |
| 45 | + </el-col> | |
| 46 | + <el-col :span="8"> | |
| 47 | + <el-form-item label="经手人" prop="jsr"> | |
| 48 | + <user-select v-model="dataForm.jsr" placeholder="请选择" clearable> | |
| 49 | + </user-select> | |
| 50 | + </el-form-item> | |
| 51 | + </el-col> | |
| 52 | + <el-col :span="8"> | |
| 53 | + <el-form-item label="往来单位" prop="wldw"> | |
| 54 | + <el-select | |
| 55 | + v-model="dataForm.wldw" | |
| 56 | + placeholder="输入关键字搜索往来单位" | |
| 57 | + clearable | |
| 58 | + filterable | |
| 59 | + remote | |
| 60 | + reserve-keyword | |
| 61 | + :remote-method="remoteWldw" | |
| 62 | + :loading="wldwLoading" | |
| 63 | + :style="{ width: '100%' }" | |
| 64 | + @change="onWldwChange" | |
| 65 | + > | |
| 66 | + <el-option | |
| 67 | + v-for="item in wldwOptions" | |
| 68 | + :key="'w' + item.id" | |
| 69 | + :label="item.dwmc" | |
| 70 | + :value="String(item.id)" | |
| 71 | + /> | |
| 72 | + </el-select> | |
| 73 | + </el-form-item> | |
| 74 | + </el-col> | |
| 75 | + <el-col :span="8" v-if="dataForm.id"> | |
| 76 | + <el-form-item label="审核状态"> | |
| 77 | + <el-input | |
| 78 | + :value="dataForm.djzt || '无'" | |
| 79 | + readonly | |
| 80 | + :style="{ width: '100%' }" | |
| 81 | + /> | |
| 82 | + </el-form-item> | |
| 83 | + </el-col> | |
| 84 | + <el-col :span="24"> | |
| 85 | + <el-form-item label-width="0" prop="wtYskzjjsMxList"> | |
| 86 | + <el-table :data="dataForm.wtYskzjjsMxList" size="mini"> | |
| 87 | + <el-table-column | |
| 88 | + type="index" | |
| 89 | + width="50" | |
| 90 | + label="序号" | |
| 91 | + align="center" | |
| 92 | + /> | |
| 93 | + <el-table-column prop="srxmmc" label="收入项目"> | |
| 94 | + <template slot-scope="scope"> | |
| 95 | + <el-select | |
| 96 | + v-model="scope.row.srxmmc" | |
| 97 | + placeholder="请选择或输入" | |
| 98 | + clearable | |
| 99 | + filterable | |
| 100 | + allow-create | |
| 101 | + default-first-option | |
| 102 | + > | |
| 103 | + <el-option | |
| 104 | + v-for="(item, index) in srxmmcOptions" | |
| 105 | + :key="index" | |
| 106 | + :label="item.fullName" | |
| 107 | + :value="item.id" | |
| 108 | + :disabled="item.disabled" | |
| 109 | + ></el-option> | |
| 110 | + </el-select> | |
| 111 | + </template> | |
| 112 | + </el-table-column> | |
| 113 | + <el-table-column prop="je" label="原币金额"> | |
| 114 | + <template slot-scope="scope"> | |
| 115 | + <el-input-number | |
| 116 | + v-model.number="scope.row.je" | |
| 117 | + placeholder="请输入" | |
| 118 | + :min="0" | |
| 119 | + :precision="2" | |
| 120 | + controls-position="right" | |
| 121 | + style="width: 100%" | |
| 122 | + @change="calculateTotalAmount" | |
| 123 | + /> | |
| 124 | + </template> | |
| 125 | + </el-table-column> | |
| 126 | + <el-table-column prop="bz" label="备注"> | |
| 127 | + <template slot-scope="scope"> | |
| 128 | + <el-input | |
| 129 | + v-model="scope.row.bz" | |
| 130 | + placeholder="请输入" | |
| 131 | + clearable | |
| 132 | + ></el-input> | |
| 133 | + </template> | |
| 134 | + </el-table-column> | |
| 135 | + <el-table-column label="操作" width="50"> | |
| 136 | + <template slot-scope="scope"> | |
| 137 | + <el-button | |
| 138 | + size="mini" | |
| 139 | + type="text" | |
| 140 | + class="NCC-table-delBtn" | |
| 141 | + @click="handleDelWtYskzjjsMxEntityList(scope.$index)" | |
| 142 | + >删除</el-button | |
| 143 | + > | |
| 144 | + </template> | |
| 145 | + </el-table-column> | |
| 146 | + </el-table> | |
| 147 | + <div | |
| 148 | + class="table-actions" | |
| 149 | + @click="addHandleWtYskzjjsMxEntityList()" | |
| 150 | + > | |
| 151 | + <el-button type="text" icon="el-icon-plus">新增</el-button> | |
| 152 | + </div> | |
| 153 | + </el-form-item> | |
| 154 | + </el-col> | |
| 155 | + <el-col :span="6"> | |
| 156 | + <el-form-item label="收款账户" prop="skzh"> | |
| 157 | + <el-select | |
| 158 | + v-model="dataForm.skzh" | |
| 159 | + placeholder="请选择" | |
| 160 | + clearable | |
| 161 | + :style="{ width: '100%' }" | |
| 162 | + > | |
| 163 | + <el-option | |
| 164 | + v-for="(item, index) in skzhOptions" | |
| 165 | + :key="index" | |
| 166 | + :label="item.fullName" | |
| 167 | + :value="item.id" | |
| 168 | + ></el-option> | |
| 169 | + </el-select> | |
| 170 | + </el-form-item> | |
| 171 | + </el-col> | |
| 172 | + <el-col :span="6"> | |
| 173 | + <el-form-item label="收款金额" prop="skje"> | |
| 174 | + <el-input | |
| 175 | + v-model="dataForm.skje" | |
| 176 | + placeholder="根据明细合计" | |
| 177 | + clearable | |
| 178 | + readonly | |
| 179 | + :style="{ width: '100%' }" | |
| 180 | + > | |
| 181 | + </el-input> | |
| 182 | + </el-form-item> | |
| 183 | + </el-col> | |
| 184 | + <el-col :span="24" v-if="false"> | |
| 185 | + <el-form-item label="单据类型" prop="djlx"> | |
| 186 | + <el-input | |
| 187 | + v-model="dataForm.djlx" | |
| 188 | + placeholder="请输入" | |
| 189 | + clearable | |
| 190 | + :style="{ width: '100%' }" | |
| 191 | + > | |
| 192 | + </el-input> | |
| 193 | + </el-form-item> | |
| 194 | + </el-col> | |
| 195 | + </el-form> | |
| 196 | + </el-row> | |
| 197 | + <span slot="footer" class="dialog-footer"> | |
| 198 | + <el-button @click="visible = false">取 消</el-button> | |
| 199 | + <el-button type="default" @click="saveDraft" v-if="!isDetail" | |
| 200 | + >保存草稿</el-button | |
| 201 | + > | |
| 202 | + <el-button type="primary" @click="dataFormSubmit()" v-if="!isDetail" | |
| 203 | + >提交审核</el-button | |
| 204 | + > | |
| 205 | + </span> | |
| 206 | + </el-dialog> | |
| 119 | 207 | </template> |
| 120 | 208 | <script> |
| 121 | - import request from '@/utils/request' | |
| 122 | - import { getDictionaryDataSelector } from '@/api/systemData/dictionary' | |
| 123 | - import { getAccountSelector } from '@/api/extend/wtAccount' | |
| 124 | - export default { | |
| 125 | - components: {}, | |
| 126 | - props: [], | |
| 127 | - data() { | |
| 128 | - return { | |
| 129 | - loading: false, | |
| 130 | - visible: false, | |
| 131 | - isDetail: false, | |
| 132 | - dataForm: { | |
| 133 | - id:'', | |
| 134 | - id:undefined, | |
| 135 | - djrq:undefined, | |
| 136 | - jsr:undefined, | |
| 137 | - wldw: undefined, // 新增 | |
| 138 | - wtYskzjjsMxList:[], | |
| 139 | - fkzh:undefined, | |
| 140 | - fkje:undefined, | |
| 141 | - skzh:undefined, | |
| 142 | - skje:undefined, | |
| 143 | - djlx:undefined, | |
| 144 | - }, | |
| 145 | - rules: { | |
| 146 | - }, | |
| 147 | - srxmmcOptions : [], | |
| 148 | - fkzhOptions : [], | |
| 149 | - skzhOptions : [], | |
| 150 | - wldwOptions : [], | |
| 151 | - } | |
| 152 | - }, | |
| 153 | - computed: {}, | |
| 154 | - watch: {}, | |
| 155 | - created() { | |
| 156 | - this.getsrxmmcOptions(); | |
| 157 | - this.getfkzhOptions(); | |
| 158 | - this.getskzhOptions(); | |
| 159 | - this.getWldwOptions(); | |
| 160 | - // 新建时设置默认值 | |
| 161 | - if (!this.dataForm.id) { | |
| 162 | - // 单据日期 | |
| 163 | - this.dataForm.djrq = Date.now(); | |
| 164 | - // 经手人 | |
| 165 | - if (this.$store && this.$store.getters && this.$store.getters.userInfo) { | |
| 166 | - this.dataForm.jsr = this.$store.getters.userInfo.userId || this.$store.getters.userInfo.id; | |
| 167 | - } | |
| 168 | - // 单据类型 | |
| 169 | - this.dataForm.djlx = '其他应收款'; | |
| 170 | - } | |
| 171 | - }, | |
| 172 | - mounted() { | |
| 173 | - }, | |
| 174 | - methods: { | |
| 175 | - getsrxmmcOptions(){ | |
| 176 | - getDictionaryDataSelector('715562947862070533').then(res => { | |
| 177 | - this.srxmmcOptions = res.data.list | |
| 178 | - }); | |
| 179 | - }, | |
| 180 | - getfkzhOptions(){ | |
| 181 | - getAccountSelector().then(res => { | |
| 182 | - this.fkzhOptions = res.data.list | |
| 183 | - }); | |
| 184 | - }, | |
| 185 | - getskzhOptions(){ | |
| 186 | - getAccountSelector().then(res => { | |
| 187 | - this.skzhOptions = res.data.list | |
| 188 | - }); | |
| 189 | - }, | |
| 190 | - getWldwOptions(){ | |
| 191 | - request({ | |
| 192 | - url: '/api/Extend/WtWldw', | |
| 193 | - method: 'GET', | |
| 194 | - data: { currentPage: 1, pageSize: 5000 } | |
| 195 | - }).then(res => { | |
| 196 | - this.wldwOptions = res.data.list || res.data || [] | |
| 197 | - }) | |
| 198 | - }, | |
| 199 | - // 计算明细表原币金额合计 | |
| 200 | - calculateTotalAmount() { | |
| 201 | - let totalAmount = 0; | |
| 202 | - if (this.dataForm.wtYskzjjsMxList && this.dataForm.wtYskzjjsMxList.length > 0) { | |
| 203 | - this.dataForm.wtYskzjjsMxList.forEach(row => { | |
| 204 | - const je = parseFloat(row.je) || 0; | |
| 205 | - totalAmount += je; | |
| 206 | - }); | |
| 207 | - } | |
| 208 | - // 更新收款金额 | |
| 209 | - this.dataForm.skje = totalAmount.toFixed(2); | |
| 210 | - }, | |
| 211 | - goBack() { | |
| 212 | - this.$emit('refresh') | |
| 213 | - }, | |
| 214 | - init(id, isDetail) { | |
| 215 | - this.dataForm.id = id || 0; | |
| 216 | - this.visible = true; | |
| 217 | - this.isDetail = isDetail || false; | |
| 218 | - this.$nextTick(() => { | |
| 219 | - this.$refs['elForm'].resetFields(); | |
| 220 | - if (this.dataForm.id) { | |
| 221 | - request({ | |
| 222 | - url: '/api/Extend/WtYskzjjs/' + this.dataForm.id, | |
| 223 | - method: 'get' | |
| 224 | - }).then(res =>{ | |
| 225 | - this.dataForm = res.data; | |
| 226 | - // 编辑时计算合计 | |
| 227 | - this.$nextTick(() => { | |
| 228 | - this.calculateTotalAmount(); | |
| 229 | - }); | |
| 230 | - }) | |
| 231 | - } else { | |
| 232 | - // resetFields后再赋值,确保djlx不会被清空 | |
| 233 | - this.dataForm.djlx = '其他应收款'; | |
| 234 | - } | |
| 235 | - }) | |
| 236 | - }, | |
| 237 | - dataFormSubmit() { | |
| 238 | - this.$refs['elForm'].validate((valid) => { | |
| 239 | - if (valid) { | |
| 240 | - if (!this.dataForm.id) { | |
| 241 | - request({ | |
| 242 | - url: `/api/Extend/WtYskzjjs`, | |
| 243 | - method: 'post', | |
| 244 | - data: this.dataForm, | |
| 245 | - }).then((res) => { | |
| 246 | - this.$message({ | |
| 247 | - message: res.msg, | |
| 248 | - type: 'success', | |
| 249 | - duration: 1000, | |
| 250 | - onClose: () => { | |
| 251 | - this.visible = false, | |
| 252 | - this.$emit('refresh', true) | |
| 253 | - } | |
| 254 | - }) | |
| 255 | - }) | |
| 256 | - } else { | |
| 257 | - request({ | |
| 258 | - url: '/api/Extend/WtYskzjjs/' + this.dataForm.id, | |
| 259 | - method: 'PUT', | |
| 260 | - data: this.dataForm | |
| 261 | - }).then((res) => { | |
| 262 | - this.$message({ | |
| 263 | - message: res.msg, | |
| 264 | - type: 'success', | |
| 265 | - duration: 1000, | |
| 266 | - onClose: () => { | |
| 267 | - this.visible = false | |
| 268 | - this.$emit('refresh', true) | |
| 269 | - } | |
| 270 | - }) | |
| 271 | - }) | |
| 272 | - } | |
| 273 | - } | |
| 274 | - }) | |
| 275 | - }, | |
| 276 | - addHandleWtYskzjjsMxEntityList() { | |
| 277 | - let item = { | |
| 278 | - srxmmc: undefined, | |
| 279 | - je: undefined, | |
| 280 | - bz: undefined, | |
| 281 | - mxlx: '其他收入单', | |
| 282 | - } | |
| 283 | - this.dataForm.wtYskzjjsMxList.push(item) | |
| 284 | - // 新增明细行后重新计算合计 | |
| 285 | - this.$nextTick(() => { | |
| 286 | - this.calculateTotalAmount(); | |
| 287 | - }); | |
| 288 | - }, | |
| 289 | - handleDelWtYskzjjsMxEntityList(index) { | |
| 290 | - this.dataForm.wtYskzjjsMxList.splice(index, 1); | |
| 291 | - // 删除明细行后重新计算合计 | |
| 292 | - this.$nextTick(() => { | |
| 293 | - this.calculateTotalAmount(); | |
| 294 | - }); | |
| 295 | - }, | |
| 296 | - } | |
| 297 | - } | |
| 209 | +import request from "@/utils/request"; | |
| 210 | +import { getDictionaryDataSelector } from "@/api/systemData/dictionary"; | |
| 211 | +import { getAccountSelector } from "@/api/extend/wtAccount"; | |
| 212 | +export default { | |
| 213 | + components: {}, | |
| 214 | + props: [], | |
| 215 | + data() { | |
| 216 | + const validateSkje = (rule, value, callback) => { | |
| 217 | + const n = parseFloat(value); | |
| 218 | + if ( | |
| 219 | + value === "" || | |
| 220 | + value === undefined || | |
| 221 | + value === null || | |
| 222 | + isNaN(n) || | |
| 223 | + n <= 0 | |
| 224 | + ) { | |
| 225 | + callback(new Error("请填写明细金额,收款金额须大于 0")); | |
| 226 | + } else { | |
| 227 | + callback(); | |
| 228 | + } | |
| 229 | + }; | |
| 230 | + const validateMxList = (rule, value, callback) => { | |
| 231 | + const list = value || []; | |
| 232 | + if (!list.length) { | |
| 233 | + callback(new Error("请至少添加一条明细")); | |
| 234 | + return; | |
| 235 | + } | |
| 236 | + for (let i = 0; i < list.length; i++) { | |
| 237 | + const row = list[i]; | |
| 238 | + if ( | |
| 239 | + row.srxmmc === undefined || | |
| 240 | + row.srxmmc === null || | |
| 241 | + row.srxmmc === "" | |
| 242 | + ) { | |
| 243 | + callback(new Error(`第 ${i + 1} 行收入项目为必填`)); | |
| 244 | + return; | |
| 245 | + } | |
| 246 | + const je = parseFloat(row.je); | |
| 247 | + if ( | |
| 248 | + row.je === undefined || | |
| 249 | + row.je === null || | |
| 250 | + row.je === "" || | |
| 251 | + isNaN(je) || | |
| 252 | + je <= 0 | |
| 253 | + ) { | |
| 254 | + callback(new Error(`第 ${i + 1} 行原币金额为必填且须大于 0`)); | |
| 255 | + return; | |
| 256 | + } | |
| 257 | + } | |
| 258 | + callback(); | |
| 259 | + }; | |
| 260 | + return { | |
| 261 | + loading: false, | |
| 262 | + visible: false, | |
| 263 | + isDetail: false, | |
| 264 | + wldwLoading: false, | |
| 265 | + dataForm: { | |
| 266 | + id: undefined, | |
| 267 | + djrq: undefined, | |
| 268 | + jsr: undefined, | |
| 269 | + wldw: undefined, | |
| 270 | + wtYskzjjsMxList: [], | |
| 271 | + fkzh: undefined, | |
| 272 | + fkje: undefined, | |
| 273 | + skzh: undefined, | |
| 274 | + skje: undefined, | |
| 275 | + djlx: undefined, | |
| 276 | + djzt: "草稿" | |
| 277 | + }, | |
| 278 | + rules: { | |
| 279 | + djrq: [ | |
| 280 | + { required: true, message: "请选择单据日期", trigger: "change" } | |
| 281 | + ], | |
| 282 | + jsr: [{ required: true, message: "请选择经手人", trigger: "change" }], | |
| 283 | + wldw: [ | |
| 284 | + { required: true, message: "请选择往来单位", trigger: "change" } | |
| 285 | + ], | |
| 286 | + skzh: [ | |
| 287 | + { required: true, message: "请选择收款账户", trigger: "change" } | |
| 288 | + ], | |
| 289 | + skje: [{ validator: validateSkje, trigger: "blur" }], | |
| 290 | + wtYskzjjsMxList: [{ validator: validateMxList, trigger: "change" }] | |
| 291 | + }, | |
| 292 | + srxmmcOptions: [], | |
| 293 | + fkzhOptions: [], | |
| 294 | + skzhOptions: [], | |
| 295 | + wldwOptions: [] | |
| 296 | + }; | |
| 297 | + }, | |
| 298 | + computed: {}, | |
| 299 | + watch: {}, | |
| 300 | + created() { | |
| 301 | + this.getsrxmmcOptions(); | |
| 302 | + this.getfkzhOptions(); | |
| 303 | + this.getskzhOptions(); | |
| 304 | + }, | |
| 305 | + mounted() {}, | |
| 306 | + methods: { | |
| 307 | + getsrxmmcOptions() { | |
| 308 | + getDictionaryDataSelector("715562947862070533").then(res => { | |
| 309 | + this.srxmmcOptions = res.data.list; | |
| 310 | + }); | |
| 311 | + }, | |
| 312 | + getfkzhOptions() { | |
| 313 | + getAccountSelector().then(res => { | |
| 314 | + this.fkzhOptions = res.data.list; | |
| 315 | + }); | |
| 316 | + }, | |
| 317 | + getskzhOptions() { | |
| 318 | + getAccountSelector().then(res => { | |
| 319 | + this.skzhOptions = res.data.list; | |
| 320 | + }); | |
| 321 | + }, | |
| 322 | + remoteWldw(query) { | |
| 323 | + this.wldwLoading = true; | |
| 324 | + request({ | |
| 325 | + url: "/api/Extend/WtWldw", | |
| 326 | + method: "GET", | |
| 327 | + data: { | |
| 328 | + currentPage: 1, | |
| 329 | + pageSize: 50, | |
| 330 | + dwmc: query && String(query).trim() ? String(query).trim() : undefined | |
| 331 | + } | |
| 332 | + }) | |
| 333 | + .then(res => { | |
| 334 | + const raw = res.data.list || res.data || []; | |
| 335 | + this.wldwOptions = raw | |
| 336 | + .map(x => { | |
| 337 | + const id = x && (x.id || x.F_Id || x.f_Id); | |
| 338 | + return { ...x, id: id != null ? String(id) : "" }; | |
| 339 | + }) | |
| 340 | + .filter(x => x.id); | |
| 341 | + }) | |
| 342 | + .finally(() => { | |
| 343 | + this.wldwLoading = false; | |
| 344 | + }); | |
| 345 | + }, | |
| 346 | + ensureWldwOption(id) { | |
| 347 | + if (!id) return Promise.resolve(); | |
| 348 | + const sid = String(id); | |
| 349 | + if (this.wldwOptions.some(x => String(x.id) === sid)) | |
| 350 | + return Promise.resolve(); | |
| 351 | + return request({ | |
| 352 | + url: "/api/Extend/WtWldw", | |
| 353 | + method: "GET", | |
| 354 | + data: { currentPage: 1, pageSize: 20, id: sid } | |
| 355 | + }).then(res => { | |
| 356 | + const raw = res.data.list || res.data || []; | |
| 357 | + const hit = raw.find(x => String(x.id || x.F_Id || x.f_Id) === sid); | |
| 358 | + if (hit) { | |
| 359 | + const row = { ...hit, id: String(hit.id || hit.F_Id || hit.f_Id) }; | |
| 360 | + this.wldwOptions = [ | |
| 361 | + row, | |
| 362 | + ...this.wldwOptions.filter(x => String(x.id) !== sid) | |
| 363 | + ]; | |
| 364 | + } | |
| 365 | + }); | |
| 366 | + }, | |
| 367 | + onWldwChange() { | |
| 368 | + this.syncKhFromWldw(); | |
| 369 | + }, | |
| 370 | + syncKhFromWldw() { | |
| 371 | + const w = this.dataForm.wldw; | |
| 372 | + if (!w || !this.dataForm.wtYskzjjsMxList) return; | |
| 373 | + this.dataForm.wtYskzjjsMxList.forEach(row => { | |
| 374 | + if (!row) return; | |
| 375 | + if (row.kh === undefined || row.kh === null || row.kh === "") { | |
| 376 | + this.$set(row, "kh", String(w)); | |
| 377 | + } | |
| 378 | + }); | |
| 379 | + }, | |
| 380 | + // 计算明细表原币金额合计 | |
| 381 | + calculateTotalAmount() { | |
| 382 | + let totalAmount = 0; | |
| 383 | + if ( | |
| 384 | + this.dataForm.wtYskzjjsMxList && | |
| 385 | + this.dataForm.wtYskzjjsMxList.length > 0 | |
| 386 | + ) { | |
| 387 | + this.dataForm.wtYskzjjsMxList.forEach(row => { | |
| 388 | + const je = parseFloat(row.je) || 0; | |
| 389 | + totalAmount += je; | |
| 390 | + }); | |
| 391 | + } | |
| 392 | + this.dataForm.skje = totalAmount > 0 ? totalAmount.toFixed(2) : ""; | |
| 393 | + this.$nextTick(() => { | |
| 394 | + this.$refs.elForm && this.$refs.elForm.validateField("skje"); | |
| 395 | + this.$refs.elForm && this.$refs.elForm.validateField("wtYskzjjsMxList"); | |
| 396 | + }); | |
| 397 | + }, | |
| 398 | + goBack() { | |
| 399 | + this.$emit("refresh"); | |
| 400 | + }, | |
| 401 | + init(id, isDetail) { | |
| 402 | + this.dataForm.id = id || 0; | |
| 403 | + this.visible = true; | |
| 404 | + this.isDetail = isDetail || false; | |
| 405 | + this.$nextTick(() => { | |
| 406 | + if (this.$refs["elForm"]) this.$refs["elForm"].resetFields(); | |
| 407 | + this.wldwOptions = []; | |
| 408 | + if (this.dataForm.id) { | |
| 409 | + request({ | |
| 410 | + url: "/api/Extend/WtYskzjjs/" + this.dataForm.id, | |
| 411 | + method: "get" | |
| 412 | + }).then(res => { | |
| 413 | + this.dataForm = Object.assign({}, this.dataForm, res.data); | |
| 414 | + if (!this.dataForm.wtYskzjjsMxList) | |
| 415 | + this.dataForm.wtYskzjjsMxList = []; | |
| 416 | + if (this.dataForm.wldw != null && this.dataForm.wldw !== "") { | |
| 417 | + this.dataForm.wldw = String(this.dataForm.wldw); | |
| 418 | + } | |
| 419 | + this.$nextTick(() => { | |
| 420 | + this.ensureWldwOption(this.dataForm.wldw).then(() => { | |
| 421 | + this.remoteWldw(""); | |
| 422 | + }); | |
| 423 | + this.calculateTotalAmount(); | |
| 424 | + }); | |
| 425 | + }); | |
| 426 | + } else { | |
| 427 | + this.dataForm.djlx = "其他应收单"; | |
| 428 | + this.dataForm.djzt = "草稿"; | |
| 429 | + this.dataForm.djrq = Date.now(); | |
| 430 | + if ( | |
| 431 | + this.$store && | |
| 432 | + this.$store.getters && | |
| 433 | + this.$store.getters.userInfo | |
| 434 | + ) { | |
| 435 | + this.dataForm.jsr = | |
| 436 | + this.$store.getters.userInfo.userId || | |
| 437 | + this.$store.getters.userInfo.id; | |
| 438 | + } | |
| 439 | + this.dataForm.wtYskzjjsMxList = []; | |
| 440 | + this.$nextTick(() => { | |
| 441 | + this.remoteWldw(""); | |
| 442 | + }); | |
| 443 | + } | |
| 444 | + }); | |
| 445 | + }, | |
| 446 | + validateSubmitMessage() { | |
| 447 | + return new Promise(resolve => { | |
| 448 | + this.$refs["elForm"].validate(valid => { | |
| 449 | + if (!valid) { | |
| 450 | + this.$message.warning("请完善必填项后再提交(备注除外)"); | |
| 451 | + resolve(false); | |
| 452 | + return; | |
| 453 | + } | |
| 454 | + const list = this.dataForm.wtYskzjjsMxList || []; | |
| 455 | + if (!list.length) { | |
| 456 | + this.$message.warning("请至少添加一条明细后再提交"); | |
| 457 | + resolve(false); | |
| 458 | + return; | |
| 459 | + } | |
| 460 | + for (let i = 0; i < list.length; i++) { | |
| 461 | + const row = list[i]; | |
| 462 | + if ( | |
| 463 | + row.srxmmc === undefined || | |
| 464 | + row.srxmmc === null || | |
| 465 | + row.srxmmc === "" | |
| 466 | + ) { | |
| 467 | + this.$message.warning(`第 ${i + 1} 行收入项目为必填`); | |
| 468 | + resolve(false); | |
| 469 | + return; | |
| 470 | + } | |
| 471 | + const je = parseFloat(row.je); | |
| 472 | + if ( | |
| 473 | + row.je === undefined || | |
| 474 | + row.je === null || | |
| 475 | + row.je === "" || | |
| 476 | + isNaN(je) || | |
| 477 | + je <= 0 | |
| 478 | + ) { | |
| 479 | + this.$message.warning(`第 ${i + 1} 行原币金额须大于 0`); | |
| 480 | + resolve(false); | |
| 481 | + return; | |
| 482 | + } | |
| 483 | + } | |
| 484 | + resolve(true); | |
| 485 | + }); | |
| 486 | + }); | |
| 487 | + }, | |
| 488 | + saveDraft() { | |
| 489 | + this.dataForm.djlx = "其他应收单"; | |
| 490 | + this.dataForm.djzt = "草稿"; | |
| 491 | + this.syncKhFromWldw(); | |
| 492 | + if (!this.dataForm.djrq) { | |
| 493 | + this.$message.warning("请选择单据日期后再保存草稿"); | |
| 494 | + return; | |
| 495 | + } | |
| 496 | + if (!this.dataForm.jsr) { | |
| 497 | + this.$message.warning("请选择经手人后再保存草稿"); | |
| 498 | + return; | |
| 499 | + } | |
| 500 | + if (!this.dataForm.wldw) { | |
| 501 | + this.$message.warning("请选择往来单位后再保存草稿"); | |
| 502 | + return; | |
| 503 | + } | |
| 504 | + this.persistBill(); | |
| 505 | + }, | |
| 506 | + async dataFormSubmit() { | |
| 507 | + this.dataForm.djlx = "其他应收单"; | |
| 508 | + this.dataForm.djzt = "待审核"; | |
| 509 | + this.syncKhFromWldw(); | |
| 510 | + const ok = await this.validateSubmitMessage(); | |
| 511 | + if (!ok) return; | |
| 512 | + this.persistBill(); | |
| 513 | + }, | |
| 514 | + persistBill() { | |
| 515 | + const payload = { ...this.dataForm }; | |
| 516 | + this.syncKhFromWldw(); | |
| 517 | + if (!payload.id) { | |
| 518 | + request({ | |
| 519 | + url: `/api/Extend/WtYskzjjs`, | |
| 520 | + method: "post", | |
| 521 | + data: payload | |
| 522 | + }).then(res => { | |
| 523 | + this.$message({ | |
| 524 | + message: res.msg, | |
| 525 | + type: "success", | |
| 526 | + duration: 1000, | |
| 527 | + onClose: () => { | |
| 528 | + this.visible = false; | |
| 529 | + this.$emit("refresh", true); | |
| 530 | + } | |
| 531 | + }); | |
| 532 | + }); | |
| 533 | + } else { | |
| 534 | + request({ | |
| 535 | + url: "/api/Extend/WtYskzjjs/" + this.dataForm.id, | |
| 536 | + method: "PUT", | |
| 537 | + data: payload | |
| 538 | + }).then(res => { | |
| 539 | + this.$message({ | |
| 540 | + message: res.msg, | |
| 541 | + type: "success", | |
| 542 | + duration: 1000, | |
| 543 | + onClose: () => { | |
| 544 | + this.visible = false; | |
| 545 | + this.$emit("refresh", true); | |
| 546 | + } | |
| 547 | + }); | |
| 548 | + }); | |
| 549 | + } | |
| 550 | + }, | |
| 551 | + addHandleWtYskzjjsMxEntityList() { | |
| 552 | + let item = { | |
| 553 | + srxmmc: undefined, | |
| 554 | + je: undefined, | |
| 555 | + bz: undefined, | |
| 556 | + mxlx: "其他收入单", | |
| 557 | + kh: undefined | |
| 558 | + }; | |
| 559 | + this.dataForm.wtYskzjjsMxList.push(item); | |
| 560 | + this.syncKhFromWldw(); | |
| 561 | + this.$nextTick(() => { | |
| 562 | + this.calculateTotalAmount(); | |
| 563 | + this.$refs.elForm && this.$refs.elForm.validateField("wtYskzjjsMxList"); | |
| 564 | + }); | |
| 565 | + }, | |
| 566 | + handleDelWtYskzjjsMxEntityList(index) { | |
| 567 | + this.dataForm.wtYskzjjsMxList.splice(index, 1); | |
| 568 | + this.$nextTick(() => { | |
| 569 | + this.calculateTotalAmount(); | |
| 570 | + this.$refs.elForm && this.$refs.elForm.validateField("wtYskzjjsMxList"); | |
| 571 | + }); | |
| 572 | + } | |
| 573 | + } | |
| 574 | +}; | |
| 298 | 575 | </script> | ... | ... |
Antis.Erp.Plat/antis-ncc-admin/src/views/wtYskzjjs_qt/detail-view.vue
| 1 | 1 | <template> |
| 2 | - <el-dialog | |
| 3 | - title="其他应收款详情" | |
| 4 | - :close-on-click-modal="false" | |
| 5 | - :visible.sync="visible" | |
| 6 | - class="NCC-dialog NCC-dialog_center qt-detail-dialog" | |
| 7 | - lock-scroll | |
| 8 | - width="960px" | |
| 9 | - top="6vh" | |
| 10 | - @close="handleClose" | |
| 11 | - > | |
| 12 | - <div v-loading="loading" class="qt-detail-body"> | |
| 13 | - <template v-if="detail"> | |
| 14 | - <el-descriptions :column="2" border size="small"> | |
| 15 | - <el-descriptions-item label="单据编号">{{ cellText(detail.id) }}</el-descriptions-item> | |
| 16 | - <el-descriptions-item label="审核状态">{{ detail.djzt || detail.shzt || '未审核' }}</el-descriptions-item> | |
| 17 | - <el-descriptions-item label="日期">{{ formatDate(detail.djrq) }}</el-descriptions-item> | |
| 18 | - <el-descriptions-item label="往来单位">{{ wldwText(detail.wldw) }}</el-descriptions-item> | |
| 19 | - <el-descriptions-item label="金额">{{ money(detail.skje) }}</el-descriptions-item> | |
| 20 | - <el-descriptions-item label="经手人">{{ cellText(detail.jsr) }}</el-descriptions-item> | |
| 21 | - <el-descriptions-item label="摘要" :span="2"> | |
| 22 | - <ncc-bill-summary :value="detail.billZy || detail.zy || detail.bz" mode="block" :show-icon="false" /> | |
| 23 | - </el-descriptions-item> | |
| 24 | - </el-descriptions> | |
| 2 | + <el-dialog | |
| 3 | + title="其他应收单详情" | |
| 4 | + :close-on-click-modal="false" | |
| 5 | + :visible.sync="visible" | |
| 6 | + class="NCC-dialog NCC-dialog_center qt-detail-dialog" | |
| 7 | + lock-scroll | |
| 8 | + width="960px" | |
| 9 | + top="6vh" | |
| 10 | + @close="handleClose" | |
| 11 | + > | |
| 12 | + <div v-loading="loading" class="qt-detail-body"> | |
| 13 | + <template v-if="detail"> | |
| 14 | + <el-descriptions :column="2" border size="small"> | |
| 15 | + <el-descriptions-item label="单据编号">{{ | |
| 16 | + cellText(detail.id) | |
| 17 | + }}</el-descriptions-item> | |
| 18 | + <el-descriptions-item label="审核状态">{{ | |
| 19 | + cellText(detail.djzt || detail.shzt || "未审核") | |
| 20 | + }}</el-descriptions-item> | |
| 21 | + <el-descriptions-item label="日期">{{ | |
| 22 | + formatDate(detail.djrq) | |
| 23 | + }}</el-descriptions-item> | |
| 24 | + <el-descriptions-item label="往来单位">{{ | |
| 25 | + cellText(detail.wldwmc || wldwText(detail.wldw)) | |
| 26 | + }}</el-descriptions-item> | |
| 27 | + <el-descriptions-item label="金额">{{ | |
| 28 | + money(detail.skje) | |
| 29 | + }}</el-descriptions-item> | |
| 30 | + <el-descriptions-item label="经手人">{{ | |
| 31 | + cellText(detail.jsr) | |
| 32 | + }}</el-descriptions-item> | |
| 33 | + <el-descriptions-item label="审批备注" :span="2">{{ | |
| 34 | + cellText(detail.spbz) | |
| 35 | + }}</el-descriptions-item> | |
| 36 | + <el-descriptions-item label="摘要" :span="2"> | |
| 37 | + <ncc-bill-summary | |
| 38 | + :value="detail.billZy || detail.zy || detail.bz" | |
| 39 | + mode="block" | |
| 40 | + :show-icon="false" | |
| 41 | + /> | |
| 42 | + </el-descriptions-item> | |
| 43 | + </el-descriptions> | |
| 25 | 44 | |
| 26 | - <div class="mx-title">明细</div> | |
| 27 | - <el-table :data="detail.wtYskzjjsMxList || []" border size="small" class="mx-table" empty-text="无"> | |
| 28 | - <el-table-column type="index" width="52" label="#" align="center" /> | |
| 29 | - <el-table-column label="往来单位" min-width="150" show-overflow-tooltip> | |
| 30 | - <template slot-scope="scope">{{ wldwText(scope.row.kh) }}</template> | |
| 31 | - </el-table-column> | |
| 32 | - <el-table-column label="收入项目" min-width="180" show-overflow-tooltip> | |
| 33 | - <template slot-scope="scope">{{ srxmText(scope.row.srxmmc) }}</template> | |
| 34 | - </el-table-column> | |
| 35 | - <el-table-column prop="je" label="金额" width="120" align="right"> | |
| 36 | - <template slot-scope="scope">{{ money(scope.row.je) }}</template> | |
| 37 | - </el-table-column> | |
| 38 | - <el-table-column label="备注" min-width="180" show-overflow-tooltip> | |
| 39 | - <template slot-scope="scope">{{ cellText(scope.row.bz) }}</template> | |
| 40 | - </el-table-column> | |
| 41 | - </el-table> | |
| 42 | - </template> | |
| 43 | - </div> | |
| 44 | - </el-dialog> | |
| 45 | + <div class="mx-title">明细</div> | |
| 46 | + <el-table | |
| 47 | + :data="detail.wtYskzjjsMxList || []" | |
| 48 | + border | |
| 49 | + size="small" | |
| 50 | + class="mx-table" | |
| 51 | + empty-text="无" | |
| 52 | + > | |
| 53 | + <el-table-column type="index" width="52" label="#" align="center" /> | |
| 54 | + <el-table-column | |
| 55 | + label="往来单位" | |
| 56 | + min-width="150" | |
| 57 | + show-overflow-tooltip | |
| 58 | + > | |
| 59 | + <template slot-scope="scope">{{ | |
| 60 | + wldwText(scope.row.kh || detail.wldw) | |
| 61 | + }}</template> | |
| 62 | + </el-table-column> | |
| 63 | + <el-table-column | |
| 64 | + label="收入项目" | |
| 65 | + min-width="180" | |
| 66 | + show-overflow-tooltip | |
| 67 | + > | |
| 68 | + <template slot-scope="scope">{{ | |
| 69 | + srxmText(scope.row.srxmmc) | |
| 70 | + }}</template> | |
| 71 | + </el-table-column> | |
| 72 | + <el-table-column prop="je" label="金额" width="120" align="right"> | |
| 73 | + <template slot-scope="scope">{{ money(scope.row.je) }}</template> | |
| 74 | + </el-table-column> | |
| 75 | + <el-table-column label="备注" min-width="180" show-overflow-tooltip> | |
| 76 | + <template slot-scope="scope">{{ cellText(scope.row.bz) }}</template> | |
| 77 | + </el-table-column> | |
| 78 | + </el-table> | |
| 79 | + </template> | |
| 80 | + </div> | |
| 81 | + | |
| 82 | + <template slot="footer"> | |
| 83 | + <slot name="footer"> | |
| 84 | + <el-button @click="close">关闭</el-button> | |
| 85 | + </slot> | |
| 86 | + </template> | |
| 87 | + </el-dialog> | |
| 45 | 88 | </template> |
| 46 | 89 | |
| 47 | 90 | <script> |
| 48 | -import request from '@/utils/request' | |
| 49 | -import { getDictionaryDataSelector } from '@/api/systemData/dictionary' | |
| 91 | +import request from "@/utils/request"; | |
| 92 | +import { getDictionaryDataSelector } from "@/api/systemData/dictionary"; | |
| 50 | 93 | |
| 51 | 94 | export default { |
| 52 | - name: 'WtYskzjjsQtDetailView', | |
| 53 | - data() { | |
| 54 | - return { | |
| 55 | - visible: false, | |
| 56 | - loading: false, | |
| 57 | - detail: null, | |
| 58 | - wldwOptions: [], | |
| 59 | - srxmmcOptions: [] | |
| 60 | - } | |
| 61 | - }, | |
| 62 | - created() { | |
| 63 | - this.loadWldw() | |
| 64 | - this.loadSrxmmc() | |
| 65 | - }, | |
| 66 | - methods: { | |
| 67 | - loadWldw() { | |
| 68 | - request({ | |
| 69 | - url: '/api/Extend/WtWldw', | |
| 70 | - method: 'GET', | |
| 71 | - data: { currentPage: 1, pageSize: 5000 } | |
| 72 | - }).then(res => { | |
| 73 | - this.wldwOptions = res.data.list || res.data || [] | |
| 74 | - }) | |
| 75 | - }, | |
| 76 | - loadSrxmmc() { | |
| 77 | - getDictionaryDataSelector('715562947862070533').then(res => { | |
| 78 | - this.srxmmcOptions = res.data.list || [] | |
| 79 | - }) | |
| 80 | - }, | |
| 81 | - cellText(v) { | |
| 82 | - return v === undefined || v === null || v === '' ? '无' : v | |
| 83 | - }, | |
| 84 | - money(v) { | |
| 85 | - const n = Number(v) | |
| 86 | - return isNaN(n) ? '0.00' : n.toFixed(2) | |
| 87 | - }, | |
| 88 | - formatDate(v) { | |
| 89 | - if (!v) return '无' | |
| 90 | - const d = new Date(v) | |
| 91 | - if (isNaN(d.getTime())) return '无' | |
| 92 | - return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}` | |
| 93 | - }, | |
| 94 | - wldwText(id) { | |
| 95 | - if (!id) return '无' | |
| 96 | - const hit = this.wldwOptions.find(item => String(item.id) === String(id)) | |
| 97 | - return hit && hit.dwmc ? hit.dwmc : id | |
| 98 | - }, | |
| 99 | - srxmText(v) { | |
| 100 | - if (!v) return '无' | |
| 101 | - const hit = this.srxmmcOptions.find(item => String(item.id) === String(v)) | |
| 102 | - return hit && hit.fullName ? hit.fullName : v | |
| 103 | - }, | |
| 104 | - handleClose() { | |
| 105 | - this.detail = null | |
| 106 | - this.$emit('close') | |
| 107 | - }, | |
| 108 | - init(id) { | |
| 109 | - if (!id) return | |
| 110 | - this.visible = true | |
| 111 | - this.loading = true | |
| 112 | - request({ | |
| 113 | - url: `/api/Extend/WtYskzjjs/${id}`, | |
| 114 | - method: 'GET' | |
| 115 | - }).then(res => { | |
| 116 | - this.detail = res.data || null | |
| 117 | - if (this.detail && !this.detail.wtYskzjjsMxList) { | |
| 118 | - this.$set(this.detail, 'wtYskzjjsMxList', []) | |
| 119 | - } | |
| 120 | - }).finally(() => { | |
| 121 | - this.loading = false | |
| 122 | - }) | |
| 123 | - } | |
| 124 | - } | |
| 125 | -} | |
| 95 | + name: "WtYskzjjsQtDetailView", | |
| 96 | + data() { | |
| 97 | + return { | |
| 98 | + visible: false, | |
| 99 | + loading: false, | |
| 100 | + detail: null, | |
| 101 | + wldwOptions: [], | |
| 102 | + srxmmcOptions: [] | |
| 103 | + }; | |
| 104 | + }, | |
| 105 | + created() { | |
| 106 | + this.loadWldw(); | |
| 107 | + this.loadSrxmmc(); | |
| 108 | + }, | |
| 109 | + methods: { | |
| 110 | + loadWldw() { | |
| 111 | + request({ | |
| 112 | + url: "/api/Extend/WtWldw", | |
| 113 | + method: "GET", | |
| 114 | + data: { currentPage: 1, pageSize: 5000 } | |
| 115 | + }).then(res => { | |
| 116 | + this.wldwOptions = res.data.list || res.data || []; | |
| 117 | + }); | |
| 118 | + }, | |
| 119 | + loadSrxmmc() { | |
| 120 | + getDictionaryDataSelector("715562947862070533").then(res => { | |
| 121 | + this.srxmmcOptions = res.data.list || []; | |
| 122 | + }); | |
| 123 | + }, | |
| 124 | + cellText(v) { | |
| 125 | + return v === undefined || v === null || v === "" ? "无" : v; | |
| 126 | + }, | |
| 127 | + money(v) { | |
| 128 | + const n = Number(v); | |
| 129 | + return isNaN(n) ? "0.00" : n.toFixed(2); | |
| 130 | + }, | |
| 131 | + formatDate(v) { | |
| 132 | + if (!v) return "无"; | |
| 133 | + const d = new Date(v); | |
| 134 | + if (isNaN(d.getTime())) return "无"; | |
| 135 | + return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart( | |
| 136 | + 2, | |
| 137 | + "0" | |
| 138 | + )}-${String(d.getDate()).padStart(2, "0")}`; | |
| 139 | + }, | |
| 140 | + wldwText(id) { | |
| 141 | + if (!id) return "无"; | |
| 142 | + const hit = this.wldwOptions.find(item => String(item.id) === String(id)); | |
| 143 | + return hit && hit.dwmc ? hit.dwmc : id; | |
| 144 | + }, | |
| 145 | + srxmText(v) { | |
| 146 | + if (!v) return "无"; | |
| 147 | + const hit = this.srxmmcOptions.find( | |
| 148 | + item => String(item.id) === String(v) | |
| 149 | + ); | |
| 150 | + return hit && hit.fullName ? hit.fullName : v; | |
| 151 | + }, | |
| 152 | + handleClose() { | |
| 153 | + this.detail = null; | |
| 154 | + this.$emit("close"); | |
| 155 | + }, | |
| 156 | + close() { | |
| 157 | + this.visible = false; | |
| 158 | + }, | |
| 159 | + init(id) { | |
| 160 | + if (!id) return; | |
| 161 | + this.visible = true; | |
| 162 | + this.loading = true; | |
| 163 | + request({ | |
| 164 | + url: `/api/Extend/WtYskzjjs/${id}`, | |
| 165 | + method: "GET" | |
| 166 | + }) | |
| 167 | + .then(res => { | |
| 168 | + this.detail = res.data || null; | |
| 169 | + if (this.detail && !this.detail.wtYskzjjsMxList) { | |
| 170 | + this.$set(this.detail, "wtYskzjjsMxList", []); | |
| 171 | + } | |
| 172 | + this.$emit("loaded", this.detail); | |
| 173 | + }) | |
| 174 | + .finally(() => { | |
| 175 | + this.loading = false; | |
| 176 | + }); | |
| 177 | + } | |
| 178 | + } | |
| 179 | +}; | |
| 126 | 180 | </script> |
| 127 | 181 | |
| 128 | 182 | <style scoped lang="scss"> |
| 129 | 183 | .mx-title { |
| 130 | - margin: 14px 0 10px; | |
| 131 | - font-weight: 600; | |
| 184 | + margin: 14px 0 10px; | |
| 185 | + font-weight: 600; | |
| 132 | 186 | } |
| 133 | 187 | .mx-table ::v-deep .cell { |
| 134 | - white-space: nowrap; | |
| 188 | + white-space: nowrap; | |
| 135 | 189 | } |
| 136 | 190 | .mx-table { |
| 137 | - margin-bottom: 12px; | |
| 191 | + margin-bottom: 12px; | |
| 138 | 192 | } |
| 139 | 193 | .qt-detail-body { |
| 140 | - padding-bottom: 8px; | |
| 194 | + padding-bottom: 8px; | |
| 141 | 195 | } |
| 142 | 196 | .qt-detail-dialog ::v-deep .el-dialog__body { |
| 143 | - padding-bottom: 20px; | |
| 197 | + padding-bottom: 20px; | |
| 144 | 198 | } |
| 145 | 199 | </style> | ... | ... |
Antis.Erp.Plat/antis-ncc-admin/src/views/wtYskzjjs_qt/index.vue
| 1 | 1 | <template> |
| 2 | - <div class="NCC-common-layout"> | |
| 3 | - <div class="NCC-common-layout-center"> | |
| 4 | - <el-row class="NCC-common-search-box" :gutter="16"> | |
| 5 | - <el-form @submit.native.prevent> | |
| 6 | - <el-col :span="6"> | |
| 7 | - <el-form-item label="单据编号"> | |
| 8 | - <el-input v-model="query.id" placeholder="单据编号" clearable /> | |
| 9 | - </el-form-item> | |
| 10 | - </el-col> | |
| 11 | - <el-col :span="6"> | |
| 12 | - <el-form-item label="单据日期"> | |
| 13 | - <el-date-picker v-model="query.djrq" type="daterange" value-format="timestamp" format="yyyy-MM-dd" start-placeholder="开始日期" end-placeholder="结束日期"> | |
| 14 | - </el-date-picker> | |
| 15 | - </el-form-item> | |
| 16 | - </el-col> | |
| 17 | - <template v-if="showAll"> | |
| 18 | - <el-col :span="6"> | |
| 19 | - <el-form-item label="往来单位"> | |
| 20 | - <el-select v-model="query.kh" placeholder="请选择往来单位" clearable filterable > | |
| 21 | - <el-option v-for="(item, index) in wldwOptions" :key="index" :label="item.dwmc" :value="item.id" /> | |
| 22 | - </el-select> | |
| 23 | - </el-form-item> | |
| 24 | - </el-col> | |
| 25 | - <el-col :span="6"> | |
| 26 | - <el-form-item label="经手人"> | |
| 27 | - <userSelect v-model="query.jsr" placeholder="请选择经手人" /> | |
| 28 | - </el-form-item> | |
| 29 | - </el-col> | |
| 30 | - </template> | |
| 31 | - <el-col :span="6"> | |
| 32 | - <el-form-item> | |
| 33 | - <el-button type="primary" icon="el-icon-search" @click="search()">查询</el-button> | |
| 34 | - <el-button icon="el-icon-refresh-right" @click="reset()">重置</el-button> | |
| 35 | - <el-button type="text" icon="el-icon-arrow-down" @click="showAll=true" v-if="!showAll">展开</el-button> | |
| 36 | - <el-button type="text" icon="el-icon-arrow-up" @click="showAll=false" v-else>收起</el-button> | |
| 37 | - </el-form-item> | |
| 38 | - </el-col> | |
| 39 | - </el-form> | |
| 40 | - </el-row> | |
| 41 | - <div class="NCC-common-layout-main NCC-flex-main"> | |
| 42 | - <div class="NCC-common-head"> | |
| 43 | - <div> | |
| 44 | - <el-button type="primary" icon="el-icon-plus" @click="addOrUpdateHandle()">新增</el-button> | |
| 45 | - <el-button type="text" icon="el-icon-download" @click="exportData()">导出</el-button> | |
| 46 | - <el-button type="text" icon="el-icon-delete" @click="handleBatchRemoveDel()">批量删除</el-button> | |
| 47 | - </div> | |
| 48 | - <div class="NCC-common-head-right"> | |
| 49 | - <el-tooltip effect="dark" content="刷新" placement="top"> | |
| 50 | - <el-link icon="icon-ym icon-ym-Refresh NCC-common-head-icon" :underline="false" @click="reset()" /> | |
| 51 | - </el-tooltip> | |
| 52 | - <screenfull isContainer /> | |
| 53 | - </div> | |
| 54 | - </div> | |
| 55 | - <NCC-table v-loading="listLoading" :data="list" has-c @selection-change="handleSelectionChange"> | |
| 56 | - <el-table-column prop="djrq" label="单据日期" align="left"> | |
| 57 | - <template slot-scope="scope"> | |
| 58 | - {{ scope.row.djrq ? (new Date(scope.row.djrq).toLocaleDateString('zh-CN', {year:'numeric',month:'2-digit',day:'2-digit'}).replace(/\//g,'-')) : '' }} | |
| 59 | - </template> | |
| 60 | - </el-table-column> | |
| 61 | - <el-table-column prop="id" label="单据编号" align="left" /> | |
| 62 | - <el-table-column label="审核状态" align="left" width="100"> | |
| 63 | - <template slot-scope="scope"> | |
| 64 | - {{ scope.row.djzt || scope.row.shzt || '未审核' }} | |
| 65 | - </template> | |
| 66 | - </el-table-column> | |
| 67 | - <el-table-column label="往来单位" align="left" min-width="160" show-overflow-tooltip> | |
| 68 | - <template slot-scope="scope"> | |
| 69 | - {{ wldwText(scope.row.wldw || scope.row.kh) }} | |
| 70 | - </template> | |
| 71 | - </el-table-column> | |
| 72 | - <el-table-column prop="skje" label="金额" align="left" /> | |
| 73 | - <el-table-column prop="jsr" label="经手人" align="left" /> | |
| 74 | - <el-table-column label="摘要" align="left" min-width="200"> | |
| 75 | - <template slot-scope="scope"> | |
| 76 | - <ncc-table-summary-cell :row="scope.row" fields="billZy,BillZy,zy,Zy,bz,Bz" /> | |
| 77 | - </template> | |
| 78 | - </el-table-column> | |
| 79 | - <el-table-column label="操作" fixed="right" width="140"> | |
| 80 | - <template slot-scope="scope"> | |
| 81 | - <el-button type="text" @click="openDetail(scope.row.id)" >查看</el-button> | |
| 82 | - <el-button type="text" @click="addOrUpdateHandle(scope.row.id)" >编辑</el-button> | |
| 83 | - <el-button type="text" @click="handleDel(scope.row.id)" class="NCC-table-delBtn" >删除</el-button> | |
| 84 | - </template> | |
| 85 | - </el-table-column> | |
| 86 | - </NCC-table> | |
| 87 | - <pagination :total="total" :page.sync="listQuery.currentPage" :limit.sync="listQuery.pageSize" @pagination="initData" /> | |
| 88 | - </div> | |
| 2 | + <div class="NCC-common-layout"> | |
| 3 | + <div class="NCC-common-layout-center"> | |
| 4 | + <el-row class="NCC-common-search-box" :gutter="16"> | |
| 5 | + <el-form @submit.native.prevent> | |
| 6 | + <el-col :span="6"> | |
| 7 | + <el-form-item label="单据编号"> | |
| 8 | + <el-input v-model="query.id" placeholder="单据编号" clearable /> | |
| 9 | + </el-form-item> | |
| 10 | + </el-col> | |
| 11 | + <el-col :span="6"> | |
| 12 | + <el-form-item label="单据日期"> | |
| 13 | + <el-date-picker | |
| 14 | + v-model="query.djrq" | |
| 15 | + type="daterange" | |
| 16 | + value-format="timestamp" | |
| 17 | + format="yyyy-MM-dd" | |
| 18 | + start-placeholder="开始日期" | |
| 19 | + end-placeholder="结束日期" | |
| 20 | + > | |
| 21 | + </el-date-picker> | |
| 22 | + </el-form-item> | |
| 23 | + </el-col> | |
| 24 | + <template v-if="showAll"> | |
| 25 | + <el-col :span="6"> | |
| 26 | + <el-form-item label="往来单位"> | |
| 27 | + <el-select | |
| 28 | + v-model="query.kh" | |
| 29 | + placeholder="请选择往来单位" | |
| 30 | + clearable | |
| 31 | + filterable | |
| 32 | + > | |
| 33 | + <el-option | |
| 34 | + v-for="(item, index) in wldwOptions" | |
| 35 | + :key="index" | |
| 36 | + :label="item.dwmc" | |
| 37 | + :value="item.id" | |
| 38 | + /> | |
| 39 | + </el-select> | |
| 40 | + </el-form-item> | |
| 41 | + </el-col> | |
| 42 | + <el-col :span="6"> | |
| 43 | + <el-form-item label="经手人"> | |
| 44 | + <userSelect v-model="query.jsr" placeholder="请选择经手人" /> | |
| 45 | + </el-form-item> | |
| 46 | + </el-col> | |
| 47 | + </template> | |
| 48 | + <el-col :span="6"> | |
| 49 | + <el-form-item> | |
| 50 | + <el-button type="primary" icon="el-icon-search" @click="search()" | |
| 51 | + >查询</el-button | |
| 52 | + > | |
| 53 | + <el-button icon="el-icon-refresh-right" @click="reset()" | |
| 54 | + >重置</el-button | |
| 55 | + > | |
| 56 | + <el-button | |
| 57 | + type="text" | |
| 58 | + icon="el-icon-arrow-down" | |
| 59 | + @click="showAll = true" | |
| 60 | + v-if="!showAll" | |
| 61 | + >展开</el-button | |
| 62 | + > | |
| 63 | + <el-button | |
| 64 | + type="text" | |
| 65 | + icon="el-icon-arrow-up" | |
| 66 | + @click="showAll = false" | |
| 67 | + v-else | |
| 68 | + >收起</el-button | |
| 69 | + > | |
| 70 | + </el-form-item> | |
| 71 | + </el-col> | |
| 72 | + </el-form> | |
| 73 | + </el-row> | |
| 74 | + <div class="NCC-common-layout-main NCC-flex-main"> | |
| 75 | + <div class="NCC-common-head"> | |
| 76 | + <div> | |
| 77 | + <el-button | |
| 78 | + type="primary" | |
| 79 | + icon="el-icon-plus" | |
| 80 | + @click="addOrUpdateHandle()" | |
| 81 | + >新增</el-button | |
| 82 | + > | |
| 83 | + <el-button type="text" icon="el-icon-download" @click="exportData()" | |
| 84 | + >导出</el-button | |
| 85 | + > | |
| 86 | + <el-button | |
| 87 | + type="text" | |
| 88 | + icon="el-icon-delete" | |
| 89 | + @click="handleBatchRemoveDel()" | |
| 90 | + >批量删除</el-button | |
| 91 | + > | |
| 92 | + </div> | |
| 93 | + <div class="NCC-common-head-right"> | |
| 94 | + <el-tooltip effect="dark" content="刷新" placement="top"> | |
| 95 | + <el-link | |
| 96 | + icon="icon-ym icon-ym-Refresh NCC-common-head-icon" | |
| 97 | + :underline="false" | |
| 98 | + @click="reset()" | |
| 99 | + /> | |
| 100 | + </el-tooltip> | |
| 101 | + <screenfull isContainer /> | |
| 102 | + </div> | |
| 89 | 103 | </div> |
| 90 | - <NCC-Form v-if="formVisible" ref="NCCForm" @refresh="refresh" /> | |
| 91 | - <DetailView v-if="detailVisible" ref="NCCDetailView" @close="detailVisible = false" /> | |
| 92 | - <ExportBox v-if="exportBoxVisible" ref="ExportBox" @download="download" /> | |
| 93 | - </div> | |
| 104 | + <NCC-table | |
| 105 | + v-loading="listLoading" | |
| 106 | + :data="list" | |
| 107 | + has-c | |
| 108 | + @selection-change="handleSelectionChange" | |
| 109 | + > | |
| 110 | + <el-table-column prop="djrq" label="单据日期" align="left"> | |
| 111 | + <template slot-scope="scope"> | |
| 112 | + {{ | |
| 113 | + scope.row.djrq | |
| 114 | + ? new Date(scope.row.djrq) | |
| 115 | + .toLocaleDateString("zh-CN", { | |
| 116 | + year: "numeric", | |
| 117 | + month: "2-digit", | |
| 118 | + day: "2-digit" | |
| 119 | + }) | |
| 120 | + .replace(/\//g, "-") | |
| 121 | + : "" | |
| 122 | + }} | |
| 123 | + </template> | |
| 124 | + </el-table-column> | |
| 125 | + <el-table-column prop="id" label="单据编号" align="left" /> | |
| 126 | + <el-table-column label="审核状态" align="left" width="130"> | |
| 127 | + <template slot-scope="scope"> | |
| 128 | + <el-tag | |
| 129 | + v-if="auditStatus(scope.row) === '草稿'" | |
| 130 | + type="info" | |
| 131 | + size="mini" | |
| 132 | + >草稿</el-tag | |
| 133 | + > | |
| 134 | + <el-tag | |
| 135 | + v-else-if="auditStatus(scope.row) === '待审核'" | |
| 136 | + type="warning" | |
| 137 | + size="mini" | |
| 138 | + >待审核</el-tag | |
| 139 | + > | |
| 140 | + <el-tag | |
| 141 | + v-else-if=" | |
| 142 | + auditStatus(scope.row) === '一级已审' || | |
| 143 | + auditStatus(scope.row) === '待二级' || | |
| 144 | + auditStatus(scope.row) === '一级已审/待二级' | |
| 145 | + " | |
| 146 | + type="warning" | |
| 147 | + size="mini" | |
| 148 | + >一级已审</el-tag | |
| 149 | + > | |
| 150 | + <el-tag | |
| 151 | + v-else-if="auditStatus(scope.row) === '已审核'" | |
| 152 | + type="success" | |
| 153 | + size="mini" | |
| 154 | + >已审核</el-tag | |
| 155 | + > | |
| 156 | + <el-tag | |
| 157 | + v-else-if="auditStatus(scope.row) === '审核不通过'" | |
| 158 | + type="danger" | |
| 159 | + size="mini" | |
| 160 | + >审核不通过</el-tag | |
| 161 | + > | |
| 162 | + <el-tag v-else type="info" size="mini">{{ | |
| 163 | + cellText(auditStatus(scope.row) || "未审核") | |
| 164 | + }}</el-tag> | |
| 165 | + </template> | |
| 166 | + </el-table-column> | |
| 167 | + <el-table-column | |
| 168 | + label="往来单位" | |
| 169 | + align="left" | |
| 170 | + min-width="160" | |
| 171 | + show-overflow-tooltip | |
| 172 | + > | |
| 173 | + <template slot-scope="scope"> | |
| 174 | + {{ showWldw(scope.row) }} | |
| 175 | + </template> | |
| 176 | + </el-table-column> | |
| 177 | + <el-table-column prop="skje" label="金额" align="left" /> | |
| 178 | + <el-table-column prop="jsr" label="经手人" align="left" /> | |
| 179 | + <el-table-column label="摘要" align="left" min-width="200"> | |
| 180 | + <template slot-scope="scope"> | |
| 181 | + <ncc-table-summary-cell | |
| 182 | + :row="scope.row" | |
| 183 | + fields="billZy,BillZy,zy,Zy,bz,Bz" | |
| 184 | + /> | |
| 185 | + </template> | |
| 186 | + </el-table-column> | |
| 187 | + <el-table-column label="操作" fixed="right" width="300"> | |
| 188 | + <template slot-scope="scope"> | |
| 189 | + <el-button type="text" @click="openDetail(scope.row.id)" | |
| 190 | + >查看</el-button | |
| 191 | + > | |
| 192 | + <el-button type="text" @click="openAuditInfo(scope.row)" | |
| 193 | + >审核信息</el-button | |
| 194 | + > | |
| 195 | + <el-button | |
| 196 | + v-if="canEditRow(scope.row)" | |
| 197 | + type="text" | |
| 198 | + @click="addOrUpdateHandle(scope.row.id)" | |
| 199 | + >编辑</el-button | |
| 200 | + > | |
| 201 | + <el-button | |
| 202 | + type="text" | |
| 203 | + style="color:#E6A23C" | |
| 204 | + v-if="canSubmitAudit(scope.row)" | |
| 205 | + @click="handleSubmitAudit(scope.row.id)" | |
| 206 | + >提交审核</el-button | |
| 207 | + > | |
| 208 | + <el-button | |
| 209 | + type="text" | |
| 210 | + v-if="canWithdrawAudit(scope.row)" | |
| 211 | + @click="handleWithdrawAudit(scope.row.id)" | |
| 212 | + >撤回</el-button | |
| 213 | + > | |
| 214 | + <el-button | |
| 215 | + type="text" | |
| 216 | + style="color:#E6A23C" | |
| 217 | + v-if="canLevel1Approve(scope.row)" | |
| 218 | + @click="handleLevel1Approve(scope.row.id)" | |
| 219 | + >一级审核</el-button | |
| 220 | + > | |
| 221 | + <el-button | |
| 222 | + type="text" | |
| 223 | + style="color:#67C23A" | |
| 224 | + v-if="canLevel2Approve(scope.row)" | |
| 225 | + @click="handleLevel2Approve(scope.row.id)" | |
| 226 | + >二级审核</el-button | |
| 227 | + > | |
| 228 | + <el-button | |
| 229 | + type="text" | |
| 230 | + style="color:#F56C6C" | |
| 231 | + v-if="canReject(scope.row)" | |
| 232 | + @click="handleReject(scope.row.id)" | |
| 233 | + >审核不通过</el-button | |
| 234 | + > | |
| 235 | + <el-button | |
| 236 | + type="text" | |
| 237 | + @click="handleDel(scope.row.id)" | |
| 238 | + class="NCC-table-delBtn" | |
| 239 | + v-if="canEditRow(scope.row)" | |
| 240 | + >删除</el-button | |
| 241 | + > | |
| 242 | + </template> | |
| 243 | + </el-table-column> | |
| 244 | + </NCC-table> | |
| 245 | + <pagination | |
| 246 | + :total="total" | |
| 247 | + :page.sync="listQuery.currentPage" | |
| 248 | + :limit.sync="listQuery.pageSize" | |
| 249 | + @pagination="initData" | |
| 250 | + /> | |
| 251 | + </div> | |
| 252 | + </div> | |
| 253 | + <NCC-Form v-if="formVisible" ref="NCCForm" @refresh="refresh" /> | |
| 254 | + <DetailView | |
| 255 | + v-if="detailVisible" | |
| 256 | + ref="NCCDetailView" | |
| 257 | + @close="detailVisible = false" | |
| 258 | + /> | |
| 259 | + <ExportBox v-if="exportBoxVisible" ref="ExportBox" @download="download" /> | |
| 260 | + </div> | |
| 94 | 261 | </template> |
| 95 | 262 | <script> |
| 96 | - import request from '@/utils/request' | |
| 97 | - import NCCForm from './Form' | |
| 98 | - import DetailView from './detail-view' | |
| 99 | - import ExportBox from './ExportBox' | |
| 100 | - export default { | |
| 101 | - components: { NCCForm, DetailView, ExportBox }, | |
| 102 | - data() { | |
| 103 | - const billType = '其他应收款' | |
| 104 | - return { | |
| 105 | - billType, | |
| 106 | - showAll: false, | |
| 107 | - query: { | |
| 108 | - id:undefined, | |
| 109 | - djrq:undefined, | |
| 110 | - kh:undefined, | |
| 111 | - jsr:undefined, | |
| 112 | - djlx: billType, | |
| 113 | - }, | |
| 114 | - list: [], | |
| 115 | - listLoading: true, | |
| 116 | - multipleSelection: [], total: 0, | |
| 117 | - listQuery: { | |
| 118 | - currentPage: 1, | |
| 119 | - pageSize: 20, | |
| 120 | - sort: "desc", | |
| 121 | - sidx: "", | |
| 122 | - }, | |
| 123 | - formVisible: false, | |
| 124 | - detailVisible: false, | |
| 125 | - exportBoxVisible: false, | |
| 126 | - columnList: [ | |
| 127 | - { prop: 'djrq', label: '单据日期' }, | |
| 128 | - { prop: 'id', label: '单据编号' }, | |
| 129 | - { prop: 'djzt', label: '审核状态' }, | |
| 130 | - { prop: 'wldw', label: '往来单位' }, | |
| 131 | - { prop: 'skje', label: '金额' }, | |
| 132 | - { prop: 'jsr', label: '经手人' }, | |
| 133 | - { prop: 'zy', label: '摘要' }, | |
| 134 | - ], | |
| 135 | - wldwOptions : [], | |
| 136 | - } | |
| 137 | - }, | |
| 138 | - computed: {}, | |
| 139 | - created() { | |
| 140 | - this.initData() | |
| 141 | - this.getWldwOptions(); | |
| 142 | - }, | |
| 143 | - methods: { | |
| 144 | - getWldwOptions() { | |
| 145 | - request({ | |
| 146 | - url: '/api/Extend/WtWldw', | |
| 147 | - method: 'GET', | |
| 148 | - data: { currentPage: 1, pageSize: 5000 } | |
| 149 | - }).then(res => { | |
| 150 | - this.wldwOptions = res.data.list || res.data || [] | |
| 151 | - }) | |
| 152 | - }, | |
| 153 | - wldwText(val) { | |
| 154 | - if (!val) return '无' | |
| 155 | - const hit = this.wldwOptions.find(item => String(item.id) === String(val)) | |
| 156 | - return hit && hit.dwmc ? hit.dwmc : val | |
| 157 | - }, | |
| 158 | - openDetail(id) { | |
| 159 | - if (!id) return | |
| 160 | - this.detailVisible = true | |
| 161 | - this.$nextTick(() => { | |
| 162 | - this.$refs.NCCDetailView && this.$refs.NCCDetailView.init(id) | |
| 163 | - }) | |
| 164 | - }, | |
| 165 | - initData() { | |
| 166 | - this.listLoading = true; | |
| 167 | - let _query = { | |
| 168 | - ...this.listQuery, | |
| 169 | - ...this.query | |
| 170 | - }; | |
| 171 | - let query = {} | |
| 172 | - for (let key in _query) { | |
| 173 | - if (Array.isArray(_query[key])) { | |
| 174 | - query[key] = _query[key].join() | |
| 175 | - } else { | |
| 176 | - query[key] = _query[key] | |
| 177 | - } | |
| 178 | - } | |
| 179 | - request({ | |
| 180 | - url: `/api/Extend/WtYskzjjs`, | |
| 181 | - method: 'GET', | |
| 182 | - data: query | |
| 183 | - }).then(res => { | |
| 184 | - this.list = res.data.list | |
| 185 | - this.total = res.data.pagination.total | |
| 186 | - this.listLoading = false | |
| 187 | - }) | |
| 188 | - }, | |
| 189 | - handleDel(id) { | |
| 190 | - this.$confirm('此操作将永久删除该数据, 是否继续?', '提示', { | |
| 191 | - type: 'warning' | |
| 192 | - }).then(() => { | |
| 193 | - request({ | |
| 194 | - url: `/api/Extend/WtYskzjjs/${id}`, | |
| 195 | - method: 'DELETE' | |
| 196 | - }).then(res => { | |
| 197 | - this.$message({ | |
| 198 | - type: 'success', | |
| 199 | - message: res.msg, | |
| 200 | - onClose: () => { | |
| 201 | - this.initData() | |
| 202 | - } | |
| 203 | - }); | |
| 204 | - }) | |
| 205 | - }).catch(() => { | |
| 206 | - }); | |
| 207 | - }, | |
| 208 | - handleSelectionChange(val) { | |
| 209 | - const res = val.map(item => item.id) | |
| 210 | - this.multipleSelection = res | |
| 211 | - }, | |
| 212 | - handleBatchRemoveDel() { | |
| 213 | - if (!this.multipleSelection.length) { | |
| 214 | - this.$message({ | |
| 215 | - type: 'error', | |
| 216 | - message: '请选择一条数据', | |
| 217 | - duration: 1500, | |
| 218 | - }) | |
| 219 | - return | |
| 220 | - } | |
| 221 | - const ids = this.multipleSelection | |
| 222 | - this.$confirm('您确定要删除这些数据吗, 是否继续?', '提示', { | |
| 223 | - type: 'warning' | |
| 224 | - }).then(() => { | |
| 225 | - request({ | |
| 226 | - url: `/api/Extend/WtYskzjjs/batchRemove`, | |
| 227 | - method: 'POST', | |
| 228 | - data: ids , | |
| 229 | - }).then(res => { | |
| 230 | - this.$message({ | |
| 231 | - type: 'success', | |
| 232 | - message: res.msg, | |
| 233 | - onClose: () => { | |
| 234 | - this.initData() | |
| 235 | - } | |
| 236 | - }); | |
| 237 | - }) | |
| 238 | - }).catch(() => { }) | |
| 239 | - }, | |
| 240 | - addOrUpdateHandle(id, isDetail) { | |
| 241 | - this.formVisible = true | |
| 242 | - this.$nextTick(() => { | |
| 243 | - this.$refs.NCCForm.init(id, isDetail) | |
| 244 | - }) | |
| 245 | - }, | |
| 246 | - exportData() { | |
| 247 | - this.exportBoxVisible = true | |
| 248 | - this.$nextTick(() => { | |
| 249 | - this.$refs.ExportBox.init(this.columnList) | |
| 250 | - }) | |
| 251 | - }, | |
| 252 | - download(data) { | |
| 253 | - let query = { ...data, ...this.listQuery, ...this.query } | |
| 254 | - request({ | |
| 255 | - url: `/api/Extend/WtYskzjjs/Actions/Export`, | |
| 256 | - method: 'GET', | |
| 257 | - data: query | |
| 258 | - }).then(res => { | |
| 259 | - if (!res.data.url) return | |
| 260 | - window.location.href = this.define.comUrl + res.data.url | |
| 261 | - this.$refs.ExportBox.visible = false | |
| 262 | - this.exportBoxVisible = false | |
| 263 | - }) | |
| 264 | - }, | |
| 265 | - search() { | |
| 266 | - this.listQuery = { | |
| 267 | - currentPage: 1, | |
| 268 | - pageSize: 20, | |
| 269 | - sort: "desc", | |
| 270 | - sidx: "", | |
| 271 | - } | |
| 272 | - this.query.djlx = this.billType | |
| 273 | - this.initData() | |
| 274 | - }, | |
| 275 | - refresh(isrRefresh) { | |
| 276 | - this.formVisible = false | |
| 277 | - if (isrRefresh) this.reset() | |
| 278 | - }, | |
| 279 | - reset() { | |
| 280 | - for (let key in this.query) { | |
| 281 | - this.query[key] = undefined | |
| 282 | - } | |
| 283 | - this.query.djlx = this.billType | |
| 284 | - this.listQuery = { | |
| 285 | - currentPage: 1, | |
| 286 | - pageSize: 20, | |
| 287 | - sort: "desc", | |
| 288 | - sidx: "", | |
| 289 | - } | |
| 290 | - this.initData() | |
| 291 | - } | |
| 292 | - } | |
| 263 | +import request from "@/utils/request"; | |
| 264 | +import NCCForm from "./Form"; | |
| 265 | +import DetailView from "./detail-view"; | |
| 266 | +import ExportBox from "./ExportBox"; | |
| 267 | +import { | |
| 268 | + promptApprovalRemark, | |
| 269 | + postYskzjjsSubmitForAudit, | |
| 270 | + postYskzjjsWithdrawAudit, | |
| 271 | + postYskzjjsApprove, | |
| 272 | + postYskzjjsReject | |
| 273 | +} from "@/utils/wtRejectApproval"; | |
| 274 | +export default { | |
| 275 | + components: { NCCForm, DetailView, ExportBox }, | |
| 276 | + data() { | |
| 277 | + const billType = "其他应收单"; | |
| 278 | + return { | |
| 279 | + billType, | |
| 280 | + showAll: false, | |
| 281 | + query: { | |
| 282 | + id: undefined, | |
| 283 | + djrq: undefined, | |
| 284 | + kh: undefined, | |
| 285 | + jsr: undefined, | |
| 286 | + djlx: billType | |
| 287 | + }, | |
| 288 | + list: [], | |
| 289 | + listLoading: true, | |
| 290 | + multipleSelection: [], | |
| 291 | + total: 0, | |
| 292 | + listQuery: { | |
| 293 | + currentPage: 1, | |
| 294 | + pageSize: 20, | |
| 295 | + sort: "desc", | |
| 296 | + sidx: "" | |
| 297 | + }, | |
| 298 | + formVisible: false, | |
| 299 | + detailVisible: false, | |
| 300 | + exportBoxVisible: false, | |
| 301 | + columnList: [ | |
| 302 | + { prop: "djrq", label: "单据日期" }, | |
| 303 | + { prop: "id", label: "单据编号" }, | |
| 304 | + { prop: "djzt", label: "审核状态" }, | |
| 305 | + { prop: "wldw", label: "往来单位" }, | |
| 306 | + { prop: "skje", label: "金额" }, | |
| 307 | + { prop: "jsr", label: "经手人" }, | |
| 308 | + { prop: "zy", label: "摘要" } | |
| 309 | + ], | |
| 310 | + wldwOptions: [] | |
| 311 | + }; | |
| 312 | + }, | |
| 313 | + computed: {}, | |
| 314 | + created() { | |
| 315 | + this.initData(); | |
| 316 | + this.getWldwOptions(); | |
| 317 | + }, | |
| 318 | + methods: { | |
| 319 | + cellText(v) { | |
| 320 | + if (v === null || v === undefined || v === "") return "无"; | |
| 321 | + return v; | |
| 322 | + }, | |
| 323 | + auditStatus(row) { | |
| 324 | + if (!row) return ""; | |
| 325 | + return (row.djzt || row.shzt || "").trim(); | |
| 326 | + }, | |
| 327 | + showWldw(row) { | |
| 328 | + if (!row) return "无"; | |
| 329 | + if (row.wldwmc && row.wldwmc !== "无") return row.wldwmc; | |
| 330 | + return this.wldwText(row.wldw || row.kh); | |
| 331 | + }, | |
| 332 | + canEditRow(row) { | |
| 333 | + const z = this.auditStatus(row); | |
| 334 | + return !z || z === "草稿" || z === "审核不通过"; | |
| 335 | + }, | |
| 336 | + canSubmitAudit(row) { | |
| 337 | + const z = this.auditStatus(row); | |
| 338 | + return z === "草稿" || z === "审核不通过"; | |
| 339 | + }, | |
| 340 | + canWithdrawAudit(row) { | |
| 341 | + const z = this.auditStatus(row); | |
| 342 | + return ( | |
| 343 | + z === "待审核" || | |
| 344 | + z === "一级已审" || | |
| 345 | + z === "待二级" || | |
| 346 | + z === "一级已审/待二级" | |
| 347 | + ); | |
| 348 | + }, | |
| 349 | + canLevel1Approve(row) { | |
| 350 | + const z = this.auditStatus(row); | |
| 351 | + return z === "待审核" || !z; | |
| 352 | + }, | |
| 353 | + canLevel2Approve(row) { | |
| 354 | + const z = this.auditStatus(row); | |
| 355 | + return z === "一级已审" || z === "待二级" || z === "一级已审/待二级"; | |
| 356 | + }, | |
| 357 | + canReject(row) { | |
| 358 | + return this.canLevel1Approve(row) || this.canLevel2Approve(row); | |
| 359 | + }, | |
| 360 | + openAuditInfo(row) { | |
| 361 | + const z = this.auditStatus(row) || "无"; | |
| 362 | + const sp = row && row.spbz ? String(row.spbz) : "无"; | |
| 363 | + this.$alert( | |
| 364 | + `审核状态:${this.cellText(z)}\n\n审批备注:\n${this.cellText(sp)}`, | |
| 365 | + "审核信息" | |
| 366 | + ); | |
| 367 | + }, | |
| 368 | + handleSubmitAudit(id) { | |
| 369 | + if (!id) return; | |
| 370 | + this.$confirm("确认提交审核?", "提示", { type: "warning" }) | |
| 371 | + .then(() => postYskzjjsSubmitForAudit(id)) | |
| 372 | + .then(res => { | |
| 373 | + const d = res.data || {}; | |
| 374 | + if (d.success) { | |
| 375 | + this.$message.success(d.message || "已提交审核"); | |
| 376 | + this.initData(); | |
| 377 | + } else { | |
| 378 | + this.$message.error(d.message || "提交失败"); | |
| 379 | + } | |
| 380 | + }) | |
| 381 | + .catch(() => {}); | |
| 382 | + }, | |
| 383 | + handleWithdrawAudit(id) { | |
| 384 | + if (!id) return; | |
| 385 | + this.$confirm("确认撤回审核(单据将变为草稿)?", "提示", { | |
| 386 | + type: "warning" | |
| 387 | + }) | |
| 388 | + .then(() => postYskzjjsWithdrawAudit(id)) | |
| 389 | + .then(res => { | |
| 390 | + const d = res.data || {}; | |
| 391 | + if (d.success) { | |
| 392 | + this.$message.success(d.message || "已撤回"); | |
| 393 | + this.initData(); | |
| 394 | + } else { | |
| 395 | + this.$message.error(d.message || "撤回失败"); | |
| 396 | + } | |
| 397 | + }) | |
| 398 | + .catch(() => {}); | |
| 399 | + }, | |
| 400 | + handleLevel1Approve(id) { | |
| 401 | + this.$confirm("确认执行一级审核?", "一级审核", { type: "warning" }) | |
| 402 | + .then(() => promptApprovalRemark(this, "审批备注")) | |
| 403 | + .then(remark => postYskzjjsApprove(id, remark)) | |
| 404 | + .then(res => { | |
| 405 | + const d = res.data || {}; | |
| 406 | + if (d.success) { | |
| 407 | + this.$message.success(d.message || "审核成功"); | |
| 408 | + this.initData(); | |
| 409 | + } else { | |
| 410 | + this.$message.error(d.message || "审核失败"); | |
| 411 | + } | |
| 412 | + }) | |
| 413 | + .catch(() => {}); | |
| 414 | + }, | |
| 415 | + handleLevel2Approve(id) { | |
| 416 | + this.$confirm("确认执行二级审核?", "二级审核", { type: "warning" }) | |
| 417 | + .then(() => promptApprovalRemark(this, "审批备注")) | |
| 418 | + .then(remark => postYskzjjsApprove(id, remark)) | |
| 419 | + .then(res => { | |
| 420 | + const d = res.data || {}; | |
| 421 | + if (d.success) { | |
| 422 | + this.$message.success(d.message || "审核成功"); | |
| 423 | + this.initData(); | |
| 424 | + } else { | |
| 425 | + this.$message.error(d.message || "审核失败"); | |
| 426 | + } | |
| 427 | + }) | |
| 428 | + .catch(() => {}); | |
| 429 | + }, | |
| 430 | + handleReject(id) { | |
| 431 | + promptApprovalRemark(this, "审核不通过") | |
| 432 | + .then(remark => postYskzjjsReject(id, remark)) | |
| 433 | + .then(res => { | |
| 434 | + const d = res.data || {}; | |
| 435 | + if (d.success) { | |
| 436 | + this.$message.success(d.message || "已标记审核不通过"); | |
| 437 | + this.initData(); | |
| 438 | + } else { | |
| 439 | + this.$message.error(d.message || "操作失败"); | |
| 440 | + } | |
| 441 | + }) | |
| 442 | + .catch(() => {}); | |
| 443 | + }, | |
| 444 | + getWldwOptions() { | |
| 445 | + request({ | |
| 446 | + url: "/api/Extend/WtWldw", | |
| 447 | + method: "GET", | |
| 448 | + data: { currentPage: 1, pageSize: 5000 } | |
| 449 | + }).then(res => { | |
| 450 | + const raw = res.data.list || res.data || []; | |
| 451 | + this.wldwOptions = raw | |
| 452 | + .map(x => ({ | |
| 453 | + ...x, | |
| 454 | + id: String(x && (x.id || x.F_Id || x.f_Id || "")) | |
| 455 | + })) | |
| 456 | + .filter(x => x.id); | |
| 457 | + }); | |
| 458 | + }, | |
| 459 | + wldwText(val) { | |
| 460 | + if (!val) return "无"; | |
| 461 | + const hit = this.wldwOptions.find( | |
| 462 | + item => String(item.id) === String(val) | |
| 463 | + ); | |
| 464 | + return hit && hit.dwmc ? hit.dwmc : val; | |
| 465 | + }, | |
| 466 | + openDetail(id) { | |
| 467 | + if (!id) return; | |
| 468 | + this.detailVisible = true; | |
| 469 | + this.$nextTick(() => { | |
| 470 | + this.$refs.NCCDetailView && this.$refs.NCCDetailView.init(id); | |
| 471 | + }); | |
| 472 | + }, | |
| 473 | + initData() { | |
| 474 | + this.listLoading = true; | |
| 475 | + let _query = { | |
| 476 | + ...this.listQuery, | |
| 477 | + ...this.query | |
| 478 | + }; | |
| 479 | + let query = {}; | |
| 480 | + for (let key in _query) { | |
| 481 | + if (Array.isArray(_query[key])) { | |
| 482 | + query[key] = _query[key].join(); | |
| 483 | + } else { | |
| 484 | + query[key] = _query[key]; | |
| 485 | + } | |
| 486 | + } | |
| 487 | + request({ | |
| 488 | + url: `/api/Extend/WtYskzjjs`, | |
| 489 | + method: "GET", | |
| 490 | + data: query | |
| 491 | + }).then(res => { | |
| 492 | + this.list = res.data.list; | |
| 493 | + this.total = res.data.pagination.total; | |
| 494 | + this.listLoading = false; | |
| 495 | + }); | |
| 496 | + }, | |
| 497 | + handleDel(id) { | |
| 498 | + this.$confirm("此操作将永久删除该数据, 是否继续?", "提示", { | |
| 499 | + type: "warning" | |
| 500 | + }) | |
| 501 | + .then(() => { | |
| 502 | + request({ | |
| 503 | + url: `/api/Extend/WtYskzjjs/${id}`, | |
| 504 | + method: "DELETE" | |
| 505 | + }).then(res => { | |
| 506 | + this.$message({ | |
| 507 | + type: "success", | |
| 508 | + message: res.msg, | |
| 509 | + onClose: () => { | |
| 510 | + this.initData(); | |
| 511 | + } | |
| 512 | + }); | |
| 513 | + }); | |
| 514 | + }) | |
| 515 | + .catch(() => {}); | |
| 516 | + }, | |
| 517 | + handleSelectionChange(val) { | |
| 518 | + const res = val.map(item => item.id); | |
| 519 | + this.multipleSelection = res; | |
| 520 | + }, | |
| 521 | + handleBatchRemoveDel() { | |
| 522 | + if (!this.multipleSelection.length) { | |
| 523 | + this.$message({ | |
| 524 | + type: "error", | |
| 525 | + message: "请选择一条数据", | |
| 526 | + duration: 1500 | |
| 527 | + }); | |
| 528 | + return; | |
| 529 | + } | |
| 530 | + const ids = this.multipleSelection; | |
| 531 | + this.$confirm("您确定要删除这些数据吗, 是否继续?", "提示", { | |
| 532 | + type: "warning" | |
| 533 | + }) | |
| 534 | + .then(() => { | |
| 535 | + request({ | |
| 536 | + url: `/api/Extend/WtYskzjjs/batchRemove`, | |
| 537 | + method: "POST", | |
| 538 | + data: ids | |
| 539 | + }).then(res => { | |
| 540 | + this.$message({ | |
| 541 | + type: "success", | |
| 542 | + message: res.msg, | |
| 543 | + onClose: () => { | |
| 544 | + this.initData(); | |
| 545 | + } | |
| 546 | + }); | |
| 547 | + }); | |
| 548 | + }) | |
| 549 | + .catch(() => {}); | |
| 550 | + }, | |
| 551 | + addOrUpdateHandle(id, isDetail) { | |
| 552 | + this.formVisible = true; | |
| 553 | + this.$nextTick(() => { | |
| 554 | + this.$refs.NCCForm.init(id, isDetail); | |
| 555 | + }); | |
| 556 | + }, | |
| 557 | + exportData() { | |
| 558 | + this.exportBoxVisible = true; | |
| 559 | + this.$nextTick(() => { | |
| 560 | + this.$refs.ExportBox.init(this.columnList); | |
| 561 | + }); | |
| 562 | + }, | |
| 563 | + download(data) { | |
| 564 | + let query = { ...data, ...this.listQuery, ...this.query }; | |
| 565 | + request({ | |
| 566 | + url: `/api/Extend/WtYskzjjs/Actions/Export`, | |
| 567 | + method: "GET", | |
| 568 | + data: query | |
| 569 | + }).then(res => { | |
| 570 | + if (!res.data.url) return; | |
| 571 | + window.location.href = this.define.comUrl + res.data.url; | |
| 572 | + this.$refs.ExportBox.visible = false; | |
| 573 | + this.exportBoxVisible = false; | |
| 574 | + }); | |
| 575 | + }, | |
| 576 | + search() { | |
| 577 | + this.listQuery = { | |
| 578 | + currentPage: 1, | |
| 579 | + pageSize: 20, | |
| 580 | + sort: "desc", | |
| 581 | + sidx: "" | |
| 582 | + }; | |
| 583 | + this.query.djlx = this.billType; | |
| 584 | + this.initData(); | |
| 585 | + }, | |
| 586 | + refresh(isrRefresh) { | |
| 587 | + this.formVisible = false; | |
| 588 | + if (isrRefresh) this.reset(); | |
| 589 | + }, | |
| 590 | + reset() { | |
| 591 | + for (let key in this.query) { | |
| 592 | + this.query[key] = undefined; | |
| 593 | + } | |
| 594 | + this.query.djlx = this.billType; | |
| 595 | + this.listQuery = { | |
| 596 | + currentPage: 1, | |
| 597 | + pageSize: 20, | |
| 598 | + sort: "desc", | |
| 599 | + sidx: "" | |
| 600 | + }; | |
| 601 | + this.initData(); | |
| 293 | 602 | } |
| 294 | -</script> | |
| 295 | 603 | \ No newline at end of file |
| 604 | + } | |
| 605 | +}; | |
| 606 | +</script> | ... | ... |
Antis.Erp.Plat/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/WtFysrdCrInput.cs
| ... | ... | @@ -77,6 +77,26 @@ namespace NCC.Extend.Entitys.Dto.WtFysrd |
| 77 | 77 | /// 付款单位 |
| 78 | 78 | /// </summary> |
| 79 | 79 | public string fkdw { get; set; } |
| 80 | + | |
| 81 | + /// <summary> | |
| 82 | + /// 往来单位(wt_wldw.F_Id);与 fkdw 同步保存 | |
| 83 | + /// </summary> | |
| 84 | + public string wldw { get; set; } | |
| 85 | + | |
| 86 | + /// <summary> | |
| 87 | + /// 兼容请求:客户主键,落库时与 wldw/fkdw 对齐 | |
| 88 | + /// </summary> | |
| 89 | + public string kh { get; set; } | |
| 90 | + | |
| 91 | + /// <summary> | |
| 92 | + /// 兼容请求:供应商主键,落库时与 wldw/fkdw 对齐 | |
| 93 | + /// </summary> | |
| 94 | + public string gys { get; set; } | |
| 95 | + | |
| 96 | + /// <summary> | |
| 97 | + /// 单据状态(一般仅查询回显;写入以服务端为准) | |
| 98 | + /// </summary> | |
| 99 | + public string djzt { get; set; } | |
| 80 | 100 | |
| 81 | 101 | /// <summary> |
| 82 | 102 | /// 费用收入单明细 | ... | ... |
Antis.Erp.Plat/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/WtFysrdInfoOutput.cs
| ... | ... | @@ -77,6 +77,36 @@ namespace NCC.Extend.Entitys.Dto.WtFysrd |
| 77 | 77 | /// 付款单位 |
| 78 | 78 | /// </summary> |
| 79 | 79 | public string fkdw { get; set; } |
| 80 | + | |
| 81 | + /// <summary> | |
| 82 | + /// 往来单位主键(与 fkdw 一致) | |
| 83 | + /// </summary> | |
| 84 | + public string wldw { get; set; } | |
| 85 | + | |
| 86 | + /// <summary> | |
| 87 | + /// 往来单位名称 | |
| 88 | + /// </summary> | |
| 89 | + public string wldwmc { get; set; } | |
| 90 | + | |
| 91 | + /// <summary> | |
| 92 | + /// 单据状态 | |
| 93 | + /// </summary> | |
| 94 | + public string djzt { get; set; } | |
| 95 | + | |
| 96 | + /// <summary> | |
| 97 | + /// 审批备注 | |
| 98 | + /// </summary> | |
| 99 | + public string spbz { get; set; } | |
| 100 | + | |
| 101 | + /// <summary> | |
| 102 | + /// 一级审核人 | |
| 103 | + /// </summary> | |
| 104 | + public string shr1 { get; set; } | |
| 105 | + | |
| 106 | + /// <summary> | |
| 107 | + /// 二级审核人 | |
| 108 | + /// </summary> | |
| 109 | + public string shr2 { get; set; } | |
| 80 | 110 | |
| 81 | 111 | /// <summary> |
| 82 | 112 | /// 费用收入单明细 | ... | ... |
Antis.Erp.Plat/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/WtFysrdListOutput.cs
| ... | ... | @@ -71,6 +71,26 @@ namespace NCC.Extend.Entitys.Dto.WtFysrd |
| 71 | 71 | /// 单据类型 |
| 72 | 72 | /// </summary> |
| 73 | 73 | public string djlx { get; set; } |
| 74 | + | |
| 75 | + /// <summary> | |
| 76 | + /// 付款单位 | |
| 77 | + /// </summary> | |
| 78 | + public string fkdw { get; set; } | |
| 79 | + | |
| 80 | + /// <summary> | |
| 81 | + /// 往来单位主键 | |
| 82 | + /// </summary> | |
| 83 | + public string wldw { get; set; } | |
| 84 | + | |
| 85 | + /// <summary> | |
| 86 | + /// 往来单位名称 | |
| 87 | + /// </summary> | |
| 88 | + public string wldwmc { get; set; } | |
| 89 | + | |
| 90 | + /// <summary> | |
| 91 | + /// 单据状态 | |
| 92 | + /// </summary> | |
| 93 | + public string djzt { get; set; } | |
| 74 | 94 | |
| 75 | 95 | } |
| 76 | 96 | } | ... | ... |
Antis.Erp.Plat/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/WtFysrdListQueryInput.cs
| ... | ... | @@ -83,6 +83,16 @@ namespace NCC.Extend.Entitys.Dto.WtFysrd |
| 83 | 83 | /// 单据类型 |
| 84 | 84 | /// </summary> |
| 85 | 85 | public string djlx { get; set; } |
| 86 | + | |
| 87 | + /// <summary> | |
| 88 | + /// 付款单位 | |
| 89 | + /// </summary> | |
| 90 | + public string fkdw { get; set; } | |
| 91 | + | |
| 92 | + /// <summary> | |
| 93 | + /// 往来单位(与 fkdw 任一匹配) | |
| 94 | + /// </summary> | |
| 95 | + public string wldw { get; set; } | |
| 86 | 96 | |
| 87 | 97 | } |
| 88 | 98 | } | ... | ... |
Antis.Erp.Plat/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/WtPurchaseSummaryQueryInput.cs
| ... | ... | @@ -36,11 +36,21 @@ namespace NCC.Extend.Entitys.Dto.WtXsckd |
| 36 | 36 | public string Warehouse { get; set; } |
| 37 | 37 | |
| 38 | 38 | /// <summary> |
| 39 | - /// 单据类型(支持逗号分隔多值) | |
| 39 | + /// 单据类型(逗号分隔,仅允许采购/销售/预售/委托代销共 9 类;空或 all 表示默认包含全部 9 类) | |
| 40 | 40 | /// </summary> |
| 41 | 41 | public string BillType { get; set; } |
| 42 | 42 | |
| 43 | 43 | /// <summary> |
| 44 | + /// 排序列键(白名单):分类/品牌/商品聚合支持「分类名称」「采购金额」等;明细/线性列表支持「单据日期」「数量」等;非法则走各接口默认排序。 | |
| 45 | + /// </summary> | |
| 46 | + public string SortField { get; set; } | |
| 47 | + | |
| 48 | + /// <summary> | |
| 49 | + /// 排序方向:asc / desc(默认 desc) | |
| 50 | + /// </summary> | |
| 51 | + public string SortOrder { get; set; } | |
| 52 | + | |
| 53 | + /// <summary> | |
| 44 | 54 | /// 下钻:商品分类主键(wt_pl.F_Id),与明细接口联用 |
| 45 | 55 | /// </summary> |
| 46 | 56 | public string CategoryId { get; set; } | ... | ... |
Antis.Erp.Plat/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/WtStockSummaryQueryInput.cs
| ... | ... | @@ -24,5 +24,10 @@ namespace NCC.Extend.Entitys.Dto.WtXsckd |
| 24 | 24 | /// 商品关键字(匹配 wt_sp 名称或编码) |
| 25 | 25 | /// </summary> |
| 26 | 26 | public string Product { get; set; } |
| 27 | + | |
| 28 | + /// <summary> | |
| 29 | + /// 商品主键(wt_sp.F_Id);非空时按精确商品筛选(优先级高于 <see cref="Product"/>) | |
| 30 | + /// </summary> | |
| 31 | + public string ProductSpId { get; set; } | |
| 27 | 32 | } |
| 28 | 33 | } | ... | ... |
Antis.Erp.Plat/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/WtYskzjjsCrInput.cs
| ... | ... | @@ -29,6 +29,11 @@ namespace NCC.Extend.Entitys.Dto.WtYskzjjs |
| 29 | 29 | public string jsr { get; set; } |
| 30 | 30 | |
| 31 | 31 | /// <summary> |
| 32 | + /// 往来单位(主表 <c>wldw</c>,与明细 <c>kh</c> 对应) | |
| 33 | + /// </summary> | |
| 34 | + public string wldw { get; set; } | |
| 35 | + | |
| 36 | + /// <summary> | |
| 32 | 37 | /// 审核状态 |
| 33 | 38 | /// </summary> |
| 34 | 39 | public string djzt { get; set; } | ... | ... |
Antis.Erp.Plat/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/WtYskzjjsInfoOutput.cs
| ... | ... | @@ -27,6 +27,11 @@ namespace NCC.Extend.Entitys.Dto.WtYskzjjs |
| 27 | 27 | /// 往来单位 |
| 28 | 28 | /// </summary> |
| 29 | 29 | public string wldw { get; set; } |
| 30 | + | |
| 31 | + /// <summary> | |
| 32 | + /// 往来单位名称(详情展示,服务端解析) | |
| 33 | + /// </summary> | |
| 34 | + public string wldwmc { get; set; } | |
| 30 | 35 | |
| 31 | 36 | /// <summary> |
| 32 | 37 | /// 经手人 |
| ... | ... | @@ -34,6 +39,26 @@ namespace NCC.Extend.Entitys.Dto.WtYskzjjs |
| 34 | 39 | public string jsr { get; set; } |
| 35 | 40 | |
| 36 | 41 | /// <summary> |
| 42 | + /// 审批备注 | |
| 43 | + /// </summary> | |
| 44 | + public string spbz { get; set; } | |
| 45 | + | |
| 46 | + /// <summary> | |
| 47 | + /// 审核人(终审) | |
| 48 | + /// </summary> | |
| 49 | + public string shr { get; set; } | |
| 50 | + | |
| 51 | + /// <summary> | |
| 52 | + /// 一级审核人 | |
| 53 | + /// </summary> | |
| 54 | + public string shr1 { get; set; } | |
| 55 | + | |
| 56 | + /// <summary> | |
| 57 | + /// 二级审核人 | |
| 58 | + /// </summary> | |
| 59 | + public string shr2 { get; set; } | |
| 60 | + | |
| 61 | + /// <summary> | |
| 37 | 62 | /// 审核状态 |
| 38 | 63 | /// </summary> |
| 39 | 64 | public string djzt { get; set; } | ... | ... |
Antis.Erp.Plat/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/WtYskzjjsListOutput.cs
| ... | ... | @@ -86,6 +86,26 @@ namespace NCC.Extend.Entitys.Dto.WtYskzjjs |
| 86 | 86 | /// 往来单位名称(按往来单位/会员/供应商自动解析) |
| 87 | 87 | /// </summary> |
| 88 | 88 | public string wldwmc { get; set; } |
| 89 | + | |
| 90 | + /// <summary> | |
| 91 | + /// 审批备注 | |
| 92 | + /// </summary> | |
| 93 | + public string spbz { get; set; } | |
| 94 | + | |
| 95 | + /// <summary> | |
| 96 | + /// 审核人(终审) | |
| 97 | + /// </summary> | |
| 98 | + public string shr { get; set; } | |
| 99 | + | |
| 100 | + /// <summary> | |
| 101 | + /// 一级审核人 | |
| 102 | + /// </summary> | |
| 103 | + public string shr1 { get; set; } | |
| 104 | + | |
| 105 | + /// <summary> | |
| 106 | + /// 二级审核人 | |
| 107 | + /// </summary> | |
| 108 | + public string shr2 { get; set; } | |
| 89 | 109 | |
| 90 | 110 | } |
| 91 | 111 | } | ... | ... |
Antis.Erp.Plat/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/WtFysrdEntity.cs
| ... | ... | @@ -94,6 +94,36 @@ namespace NCC.Extend.Entitys |
| 94 | 94 | /// </summary> |
| 95 | 95 | [SugarColumn(ColumnName = "fkdw")] |
| 96 | 96 | public string Fkdw { get; set; } |
| 97 | + | |
| 98 | + /// <summary> | |
| 99 | + /// 往来单位(与 fkdw 存同一 wt_wldw.F_Id,便于与 kh/gys/wldw 统一口径) | |
| 100 | + /// </summary> | |
| 101 | + [SugarColumn(ColumnName = "wldw", IsNullable = true)] | |
| 102 | + public string Wldw { get; set; } | |
| 103 | + | |
| 104 | + /// <summary> | |
| 105 | + /// 单据状态(草稿/待审核/一级已审/已审核/审核不通过) | |
| 106 | + /// </summary> | |
| 107 | + [SugarColumn(ColumnName = "djzt", IsNullable = true)] | |
| 108 | + public string Djzt { get; set; } | |
| 109 | + | |
| 110 | + /// <summary> | |
| 111 | + /// 审批备注(与业务备注 bz 分离) | |
| 112 | + /// </summary> | |
| 113 | + [SugarColumn(ColumnName = "spbz", IsNullable = true)] | |
| 114 | + public string Spbz { get; set; } | |
| 115 | + | |
| 116 | + /// <summary> | |
| 117 | + /// 一级审核人 | |
| 118 | + /// </summary> | |
| 119 | + [SugarColumn(ColumnName = "shr1", IsNullable = true)] | |
| 120 | + public string Shr1 { get; set; } | |
| 121 | + | |
| 122 | + /// <summary> | |
| 123 | + /// 二级审核人 | |
| 124 | + /// </summary> | |
| 125 | + [SugarColumn(ColumnName = "shr2", IsNullable = true)] | |
| 126 | + public string Shr2 { get; set; } | |
| 97 | 127 | |
| 98 | 128 | } |
| 99 | 129 | } |
| 100 | 130 | \ No newline at end of file | ... | ... |
Antis.Erp.Plat/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/WtYskzjjsEntity.cs
| ... | ... | @@ -42,6 +42,30 @@ namespace NCC.Extend.Entitys |
| 42 | 42 | public string Jsr { get; set; } |
| 43 | 43 | |
| 44 | 44 | /// <summary> |
| 45 | + /// 审批备注(与业务备注分离;库表须含列 <c>spbz</c>) | |
| 46 | + /// </summary> | |
| 47 | + [SugarColumn(ColumnName = "spbz", IsNullable = true, ColumnDataType = "text")] | |
| 48 | + public string Spbz { get; set; } | |
| 49 | + | |
| 50 | + /// <summary> | |
| 51 | + /// 审核人(终审) | |
| 52 | + /// </summary> | |
| 53 | + [SugarColumn(ColumnName = "shr", IsNullable = true)] | |
| 54 | + public string Shr { get; set; } | |
| 55 | + | |
| 56 | + /// <summary> | |
| 57 | + /// 一级审核人 | |
| 58 | + /// </summary> | |
| 59 | + [SugarColumn(ColumnName = "shr1", IsNullable = true)] | |
| 60 | + public string Shr1 { get; set; } | |
| 61 | + | |
| 62 | + /// <summary> | |
| 63 | + /// 二级审核人 | |
| 64 | + /// </summary> | |
| 65 | + [SugarColumn(ColumnName = "shr2", IsNullable = true)] | |
| 66 | + public string Shr2 { get; set; } | |
| 67 | + | |
| 68 | + /// <summary> | |
| 45 | 69 | /// 审核状态 |
| 46 | 70 | /// </summary> |
| 47 | 71 | [SugarColumn(ColumnName = "djzt")] | ... | ... |
Antis.Erp.Plat/netcore/src/Modularity/Extend/NCC.Extend/WtFysrdService.cs
| ... | ... | @@ -36,6 +36,7 @@ namespace NCC.Extend.WtFysrd |
| 36 | 36 | private readonly ISqlSugarRepository<WtFysrdMxEntity> _wtFysrdMxRepository; |
| 37 | 37 | private readonly SqlSugarScope _db; |
| 38 | 38 | private readonly IUserManager _userManager; |
| 39 | + private readonly WtFysrdWorkflowHelper _fysrdWorkflow; | |
| 39 | 40 | |
| 40 | 41 | /// <summary> |
| 41 | 42 | /// 初始化一个<see cref="WtFysrdService"/>类型的新实例 |
| ... | ... | @@ -43,12 +44,71 @@ namespace NCC.Extend.WtFysrd |
| 43 | 44 | public WtFysrdService( |
| 44 | 45 | ISqlSugarRepository<WtFysrdEntity> wtFysrdRepository, |
| 45 | 46 | ISqlSugarRepository<WtFysrdMxEntity> wtFysrdMxRepository, |
| 46 | - IUserManager userManager) | |
| 47 | + IUserManager userManager, | |
| 48 | + WtFysrdWorkflowHelper fysrdWorkflow) | |
| 47 | 49 | { |
| 48 | 50 | _wtFysrdRepository = wtFysrdRepository; |
| 49 | 51 | _db = _wtFysrdRepository.Context; |
| 50 | 52 | _wtFysrdMxRepository = wtFysrdMxRepository; |
| 51 | 53 | _userManager = userManager; |
| 54 | + _fysrdWorkflow = fysrdWorkflow; | |
| 55 | + } | |
| 56 | + | |
| 57 | + private static bool IsLockedForEdit(string djzt) | |
| 58 | + { | |
| 59 | + var s = djzt?.Trim() ?? ""; | |
| 60 | + return s == "待审核" || s == "已审核" || s == "一级已审" || s == "待二级" || s == "一级已审/待二级"; | |
| 61 | + } | |
| 62 | + | |
| 63 | + private static bool IsDeletableState(string djzt) | |
| 64 | + { | |
| 65 | + var s = djzt?.Trim() ?? ""; | |
| 66 | + return string.IsNullOrEmpty(s) || s == "草稿" || s == "审核不通过"; | |
| 67 | + } | |
| 68 | + | |
| 69 | + private void NormalizeHeaderFromInput(WtFysrdCrInput input, WtFysrdEntity entity) | |
| 70 | + { | |
| 71 | + if (input == null || entity == null) return; | |
| 72 | + if (!string.IsNullOrWhiteSpace(input.djlx)) | |
| 73 | + entity.Djlx = WtFysrdWorkflowHelper.NormalizeOtherIncomeDjlx(input.djlx) ?? input.djlx; | |
| 74 | + if (!string.IsNullOrWhiteSpace(WtFysrdWorkflowHelper.ResolveCounterpartyId(input.wldw, input.fkdw, input.kh, input.gys))) | |
| 75 | + WtFysrdWorkflowHelper.ApplyCounterpartyToEntity(entity, input.wldw, input.fkdw, input.kh, input.gys); | |
| 76 | + } | |
| 77 | + | |
| 78 | + private async Task EnrichWldwForListAsync(IEnumerable<WtFysrdListOutput> rows) | |
| 79 | + { | |
| 80 | + if (rows == null) return; | |
| 81 | + var rowList = rows as IList<WtFysrdListOutput> ?? rows.ToList(); | |
| 82 | + if (rowList.Count == 0) return; | |
| 83 | + foreach (var r in rowList) | |
| 84 | + { | |
| 85 | + if (string.IsNullOrWhiteSpace(r.wldw)) | |
| 86 | + r.wldw = r.fkdw; | |
| 87 | + if (string.IsNullOrWhiteSpace(r.fkdw)) | |
| 88 | + r.fkdw = r.wldw; | |
| 89 | + } | |
| 90 | + var ids = rowList.Select(x => x.wldw).Where(x => !string.IsNullOrWhiteSpace(x)).Distinct().ToList(); | |
| 91 | + if (ids.Count == 0) return; | |
| 92 | + var wldwRows = await _db.Queryable<WtWldwEntity>().In(w => w.Id, ids).ToListAsync(); | |
| 93 | + var map = wldwRows.ToDictionary(x => x.Id, x => x.Dwmc, StringComparer.OrdinalIgnoreCase); | |
| 94 | + foreach (var r in rowList) | |
| 95 | + { | |
| 96 | + if (!string.IsNullOrWhiteSpace(r.wldw) && map.TryGetValue(r.wldw, out var mc)) | |
| 97 | + r.wldwmc = mc; | |
| 98 | + } | |
| 99 | + } | |
| 100 | + | |
| 101 | + /// <summary> | |
| 102 | + /// 提交审核:草稿/审核不通过 → 待审核(其他收入单;除备注外必填校验) | |
| 103 | + /// </summary> | |
| 104 | + /// <param name="id">单据编号</param> | |
| 105 | + [HttpPost("Actions/SubmitForAudit/{id}")] | |
| 106 | + public async Task<dynamic> SubmitForAudit(string id) | |
| 107 | + { | |
| 108 | + dynamic r = await _fysrdWorkflow.SubmitForAuditAsync(id); | |
| 109 | + if (r.success == true) | |
| 110 | + return new { msg = (string)(r.message ?? "已提交") }; | |
| 111 | + throw NCCException.Bah((string)(r.message ?? "提交失败")); | |
| 52 | 112 | } |
| 53 | 113 | |
| 54 | 114 | /// <summary> |
| ... | ... | @@ -59,9 +119,22 @@ namespace NCC.Extend.WtFysrd |
| 59 | 119 | [HttpGet("{id}")] |
| 60 | 120 | public async Task<dynamic> GetInfo(string id) |
| 61 | 121 | { |
| 122 | + _fysrdWorkflow.EnsureFysrdAuditColumns(); | |
| 62 | 123 | var entity = await _db.Queryable<WtFysrdEntity>().FirstAsync(p => p.Id == id); |
| 63 | 124 | var output = entity.Adapt<WtFysrdInfoOutput>(); |
| 64 | - | |
| 125 | + output.djlx = WtFysrdWorkflowHelper.NormalizeOtherIncomeDjlx(entity.Djlx) ?? entity.Djlx; | |
| 126 | + output.wldw = string.IsNullOrWhiteSpace(entity.Wldw) ? entity.Fkdw : entity.Wldw; | |
| 127 | + output.fkdw = string.IsNullOrWhiteSpace(entity.Fkdw) ? entity.Wldw : entity.Fkdw; | |
| 128 | + output.djzt = entity.Djzt; | |
| 129 | + output.spbz = entity.Spbz; | |
| 130 | + output.shr1 = entity.Shr1; | |
| 131 | + output.shr2 = entity.Shr2; | |
| 132 | + var wldwId = output.wldw ?? output.fkdw; | |
| 133 | + if (!string.IsNullOrWhiteSpace(wldwId)) | |
| 134 | + { | |
| 135 | + var w = await _db.Queryable<WtWldwEntity>().FirstAsync(x => x.Id == wldwId); | |
| 136 | + output.wldwmc = w?.Dwmc; | |
| 137 | + } | |
| 65 | 138 | var wtFysrdMxList = await _db.Queryable<WtFysrdMxEntity>().Where(w => w.Djbh == entity.Id).ToListAsync(); |
| 66 | 139 | output.wtFysrdMxList = wtFysrdMxList.Adapt<List<WtFysrdMxInfoOutput>>(); |
| 67 | 140 | return output; |
| ... | ... | @@ -75,6 +148,7 @@ namespace NCC.Extend.WtFysrd |
| 75 | 148 | [HttpGet("")] |
| 76 | 149 | public async Task<dynamic> GetList([FromQuery] WtFysrdListQueryInput input) |
| 77 | 150 | { |
| 151 | + _fysrdWorkflow.EnsureFysrdAuditColumns(); | |
| 78 | 152 | var sidx = input.sidx == null ? "id" : input.sidx; |
| 79 | 153 | List<string> queryDjrq = input.djrq != null ? input.djrq.Split(',').ToObeject<List<string>>() : null; |
| 80 | 154 | DateTime? startDjrq = queryDjrq != null ? Ext.GetDateTime(queryDjrq.First()) : null; |
| ... | ... | @@ -94,6 +168,8 @@ namespace NCC.Extend.WtFysrd |
| 94 | 168 | .WhereIF(!string.IsNullOrEmpty(input.bz), p => p.Bz.Contains(input.bz)) |
| 95 | 169 | .WhereIF(!string.IsNullOrEmpty(input.zy), p => p.Zy.Contains(input.zy)) |
| 96 | 170 | .WhereIF(!string.IsNullOrEmpty(input.djlx), p => p.Djlx.Contains(input.djlx)) |
| 171 | + .WhereIF(!string.IsNullOrEmpty(input.fkdw), p => p.Fkdw == input.fkdw || p.Wldw == input.fkdw) | |
| 172 | + .WhereIF(!string.IsNullOrEmpty(input.wldw), p => p.Wldw == input.wldw || p.Fkdw == input.wldw) | |
| 97 | 173 | .Select(it=> new WtFysrdListOutput |
| 98 | 174 | { |
| 99 | 175 | id = it.Id, |
| ... | ... | @@ -109,7 +185,11 @@ namespace NCC.Extend.WtFysrd |
| 109 | 185 | bz=it.Bz, |
| 110 | 186 | zy=it.Zy, |
| 111 | 187 | djlx=it.Djlx, |
| 188 | + fkdw = it.Fkdw, | |
| 189 | + wldw = it.Wldw, | |
| 190 | + djzt = it.Djzt, | |
| 112 | 191 | }).MergeTable().OrderBy(sidx+" "+input.sort).ToPagedListAsync(input.currentPage, input.pageSize); |
| 192 | + await EnrichWldwForListAsync(data.list); | |
| 113 | 193 | return PageResult<WtFysrdListOutput>.SqlSugarPageResult(data); |
| 114 | 194 | } |
| 115 | 195 | |
| ... | ... | @@ -121,15 +201,18 @@ namespace NCC.Extend.WtFysrd |
| 121 | 201 | [HttpPost("")] |
| 122 | 202 | public async Task Create([FromBody] WtFysrdCrInput input) |
| 123 | 203 | { |
| 204 | + _fysrdWorkflow.EnsureFysrdAuditColumns(); | |
| 124 | 205 | var userInfo = await _userManager.GetUserInfo(); |
| 125 | 206 | var entity = input.Adapt<WtFysrdEntity>(); |
| 207 | + NormalizeHeaderFromInput(input, entity); | |
| 208 | + entity.Djzt = "草稿"; | |
| 126 | 209 | // 生成每日递增单号 |
| 127 | 210 | var today = DateTime.Now.ToString("yyyyMMdd"); |
| 128 | 211 | var prefix = "FY"; |
| 129 | 212 | // 根据单据类型设置前缀 |
| 130 | - if (!string.IsNullOrEmpty(input.djlx)) { | |
| 131 | - if (input.djlx.Contains("现金费用单")) prefix = "XF"; | |
| 132 | - else if (input.djlx.Contains("其他收入单")) prefix = "QT"; | |
| 213 | + if (!string.IsNullOrEmpty(entity.Djlx)) { | |
| 214 | + if (entity.Djlx.Contains("现金费用单")) prefix = "XF"; | |
| 215 | + else if (WtFysrdWorkflowHelper.IsOtherIncomeDjlx(entity.Djlx)) prefix = "QT"; | |
| 133 | 216 | else prefix = "FY"; // 默认费用单前缀 |
| 134 | 217 | } |
| 135 | 218 | var maxId = await _db.Queryable<WtFysrdEntity>() |
| ... | ... | @@ -199,6 +282,7 @@ namespace NCC.Extend.WtFysrd |
| 199 | 282 | [NonAction] |
| 200 | 283 | public async Task<dynamic> GetNoPagingList([FromQuery] WtFysrdListQueryInput input) |
| 201 | 284 | { |
| 285 | + _fysrdWorkflow.EnsureFysrdAuditColumns(); | |
| 202 | 286 | var sidx = input.sidx == null ? "id" : input.sidx; |
| 203 | 287 | List<string> queryDjrq = input.djrq != null ? input.djrq.Split(',').ToObeject<List<string>>() : null; |
| 204 | 288 | DateTime? startDjrq = queryDjrq != null ? Ext.GetDateTime(queryDjrq.First()) : null; |
| ... | ... | @@ -218,6 +302,8 @@ namespace NCC.Extend.WtFysrd |
| 218 | 302 | .WhereIF(!string.IsNullOrEmpty(input.bz), p => p.Bz.Contains(input.bz)) |
| 219 | 303 | .WhereIF(!string.IsNullOrEmpty(input.zy), p => p.Zy.Contains(input.zy)) |
| 220 | 304 | .WhereIF(!string.IsNullOrEmpty(input.djlx), p => p.Djlx.Contains(input.djlx)) |
| 305 | + .WhereIF(!string.IsNullOrEmpty(input.fkdw), p => p.Fkdw == input.fkdw || p.Wldw == input.fkdw) | |
| 306 | + .WhereIF(!string.IsNullOrEmpty(input.wldw), p => p.Wldw == input.wldw || p.Fkdw == input.wldw) | |
| 221 | 307 | .Select(it=> new WtFysrdListOutput |
| 222 | 308 | { |
| 223 | 309 | id = it.Id, |
| ... | ... | @@ -233,7 +319,11 @@ namespace NCC.Extend.WtFysrd |
| 233 | 319 | bz=it.Bz, |
| 234 | 320 | zy=it.Zy, |
| 235 | 321 | djlx=it.Djlx, |
| 322 | + fkdw = it.Fkdw, | |
| 323 | + wldw = it.Wldw, | |
| 324 | + djzt = it.Djzt, | |
| 236 | 325 | }).MergeTable().OrderBy(sidx+" "+input.sort).ToListAsync(); |
| 326 | + await EnrichWldwForListAsync(data); | |
| 237 | 327 | return data; |
| 238 | 328 | } |
| 239 | 329 | |
| ... | ... | @@ -256,7 +346,7 @@ namespace NCC.Extend.WtFysrd |
| 256 | 346 | { |
| 257 | 347 | exportData = await this.GetNoPagingList(input); |
| 258 | 348 | } |
| 259 | - List<ParamsModel> paramList = "[{\"value\":\"单据编号\",\"field\":\"id\"},{\"value\":\"单据日期\",\"field\":\"djrq\"},{\"value\":\"分支机构\",\"field\":\"fzjg\"},{\"value\":\"部门\",\"field\":\"bm\"},{\"value\":\"经手人\",\"field\":\"jsr\"},{\"value\":\"结算账户\",\"field\":\"jszh\"},{\"value\":\"金额\",\"field\":\"je\"},{\"value\":\"制单人\",\"field\":\"zdr\"},{\"value\":\"审核人\",\"field\":\"shr\"},{\"value\":\"过账人\",\"field\":\"gzr\"},{\"value\":\"备注\",\"field\":\"bz\"},{\"value\":\"摘要\",\"field\":\"zy\"},{\"value\":\"单据类型\",\"field\":\"djlx\"},]".ToList<ParamsModel>(); | |
| 349 | + List<ParamsModel> paramList = "[{\"value\":\"单据编号\",\"field\":\"id\"},{\"value\":\"单据日期\",\"field\":\"djrq\"},{\"value\":\"分支机构\",\"field\":\"fzjg\"},{\"value\":\"部门\",\"field\":\"bm\"},{\"value\":\"经手人\",\"field\":\"jsr\"},{\"value\":\"结算账户\",\"field\":\"jszh\"},{\"value\":\"金额\",\"field\":\"je\"},{\"value\":\"制单人\",\"field\":\"zdr\"},{\"value\":\"审核人\",\"field\":\"shr\"},{\"value\":\"过账人\",\"field\":\"gzr\"},{\"value\":\"备注\",\"field\":\"bz\"},{\"value\":\"摘要\",\"field\":\"zy\"},{\"value\":\"单据类型\",\"field\":\"djlx\"},{\"value\":\"往来单位\",\"field\":\"wldw\"},{\"value\":\"往来单位名称\",\"field\":\"wldwmc\"},{\"value\":\"付款单位\",\"field\":\"fkdw\"},{\"value\":\"单据状态\",\"field\":\"djzt\"},]".ToList<ParamsModel>(); | |
| 260 | 350 | ExcelConfig excelconfig = new ExcelConfig(); |
| 261 | 351 | excelconfig.FileName = "费用单.xls"; |
| 262 | 352 | excelconfig.HeadFont = "微软雅黑"; |
| ... | ... | @@ -292,6 +382,11 @@ namespace NCC.Extend.WtFysrd |
| 292 | 382 | public async Task BatchRemove([FromBody] List<string> ids) |
| 293 | 383 | { |
| 294 | 384 | var entitys = await _db.Queryable<WtFysrdEntity>().In(it => it.Id, ids).ToListAsync(); |
| 385 | + foreach (var e in entitys) | |
| 386 | + { | |
| 387 | + if (!IsDeletableState(e.Djzt)) | |
| 388 | + throw NCCException.Bah($"单据 {e.Id} 当前状态不允许删除"); | |
| 389 | + } | |
| 295 | 390 | if (entitys.Count > 0) |
| 296 | 391 | { |
| 297 | 392 | try |
| ... | ... | @@ -324,7 +419,37 @@ namespace NCC.Extend.WtFysrd |
| 324 | 419 | [HttpPut("{id}")] |
| 325 | 420 | public async Task Update(string id, [FromBody] WtFysrdUpInput input) |
| 326 | 421 | { |
| 422 | + _fysrdWorkflow.EnsureFysrdAuditColumns(); | |
| 423 | + var existing = await _db.Queryable<WtFysrdEntity>().FirstAsync(p => p.Id == id); | |
| 424 | + if (IsLockedForEdit(existing.Djzt)) | |
| 425 | + throw NCCException.Bah("当前单据状态不允许修改"); | |
| 426 | + | |
| 327 | 427 | var entity = input.Adapt<WtFysrdEntity>(); |
| 428 | + entity.Id = id; | |
| 429 | + entity.Djzt = existing.Djzt; | |
| 430 | + if (string.IsNullOrWhiteSpace(entity.Djlx)) | |
| 431 | + entity.Djlx = existing.Djlx; | |
| 432 | + NormalizeHeaderFromInput(input, entity); | |
| 433 | + if (string.IsNullOrWhiteSpace(WtFysrdWorkflowHelper.ResolveCounterpartyId(entity.Wldw, entity.Fkdw, null, null))) | |
| 434 | + { | |
| 435 | + entity.Wldw = existing.Wldw; | |
| 436 | + entity.Fkdw = existing.Fkdw; | |
| 437 | + } | |
| 438 | + | |
| 439 | + if (WtFysrdWorkflowHelper.IsOtherIncomeDjlx(entity.Djlx) | |
| 440 | + && !string.Equals(existing.Djzt?.Trim(), "草稿", StringComparison.Ordinal)) | |
| 441 | + { | |
| 442 | + var mxForVal = input.wtFysrdMxList.Adapt<List<WtFysrdMxEntity>>(); | |
| 443 | + try | |
| 444 | + { | |
| 445 | + WtFysrdWorkflowHelper.ValidateOtherIncomeForSubmit(entity, mxForVal); | |
| 446 | + } | |
| 447 | + catch (InvalidOperationException ex) | |
| 448 | + { | |
| 449 | + throw NCCException.Bah(ex.Message); | |
| 450 | + } | |
| 451 | + } | |
| 452 | + | |
| 328 | 453 | try |
| 329 | 454 | { |
| 330 | 455 | //开启事务 |
| ... | ... | @@ -367,6 +492,8 @@ namespace NCC.Extend.WtFysrd |
| 367 | 492 | { |
| 368 | 493 | var entity = await _db.Queryable<WtFysrdEntity>().FirstAsync(p => p.Id == id); |
| 369 | 494 | _ = entity ?? throw NCCException.Oh(ErrorCode.COM1005); |
| 495 | + if (!IsDeletableState(entity.Djzt)) | |
| 496 | + throw NCCException.Bah("当前单据状态不允许删除"); | |
| 370 | 497 | try |
| 371 | 498 | { |
| 372 | 499 | //开启事务 | ... | ... |
Antis.Erp.Plat/netcore/src/Modularity/Extend/NCC.Extend/WtFysrdWorkflowHelper.cs
0 → 100644
| 1 | +using System; | |
| 2 | +using System.Collections.Generic; | |
| 3 | +using System.Linq; | |
| 4 | +using System.Threading.Tasks; | |
| 5 | +using NCC.Common.Core.Manager; | |
| 6 | +using NCC.Dependency; | |
| 7 | +using NCC.Extend.Entitys; | |
| 8 | +using SqlSugar; | |
| 9 | + | |
| 10 | +namespace NCC.Extend.WtFysrd | |
| 11 | +{ | |
| 12 | + /// <summary> | |
| 13 | + /// 其他收入单(wt_fysrd)审批流:与待办中心、<c>ApproveGeneric/RejectGeneric/ReverseApproval</c> 对接。 | |
| 14 | + /// </summary> | |
| 15 | + public class WtFysrdWorkflowHelper : ITransient | |
| 16 | + { | |
| 17 | + /// <summary>与 <c>wt_shrysz.djmc</c>、待办 <c>billType</c> 一致</summary> | |
| 18 | + public const string BillName = "其他收入单"; | |
| 19 | + | |
| 20 | + private readonly SqlSugarScope _db; | |
| 21 | + private readonly IUserManager _userManager; | |
| 22 | + private static bool _auditColumnsChecked; | |
| 23 | + | |
| 24 | + public WtFysrdWorkflowHelper(ISqlSugarRepository<WtFysrdEntity> fysrdRepository, IUserManager userManager) | |
| 25 | + { | |
| 26 | + _db = fysrdRepository.Context; | |
| 27 | + _userManager = userManager; | |
| 28 | + } | |
| 29 | + | |
| 30 | + /// <summary> | |
| 31 | + /// 确保 wt_fysrd 具备审批与往来单位统一字段(djzt、spbz、shr、shr1、shr2、wldw) | |
| 32 | + /// </summary> | |
| 33 | + public void EnsureFysrdAuditColumns() | |
| 34 | + { | |
| 35 | + if (_auditColumnsChecked) return; | |
| 36 | + lock (typeof(WtFysrdWorkflowHelper)) | |
| 37 | + { | |
| 38 | + if (_auditColumnsChecked) return; | |
| 39 | + try | |
| 40 | + { | |
| 41 | + if (!_db.DbMaintenance.IsAnyTable("wt_fysrd")) { _auditColumnsChecked = true; return; } | |
| 42 | + var cols = _db.DbMaintenance.GetColumnInfosByTableName("wt_fysrd"); | |
| 43 | + var names = cols.Select(c => c.DbColumnName.ToLowerInvariant()).ToHashSet(); | |
| 44 | + if (!names.Contains("djzt")) | |
| 45 | + _db.Ado.ExecuteCommand( | |
| 46 | + "ALTER TABLE `wt_fysrd` ADD COLUMN `djzt` varchar(32) NULL COMMENT '单据状态'"); | |
| 47 | + if (!names.Contains("spbz")) | |
| 48 | + _db.Ado.ExecuteCommand( | |
| 49 | + "ALTER TABLE `wt_fysrd` ADD COLUMN `spbz` text NULL COMMENT '审批备注'"); | |
| 50 | + if (!names.Contains("shr")) | |
| 51 | + _db.Ado.ExecuteCommand( | |
| 52 | + "ALTER TABLE `wt_fysrd` ADD COLUMN `shr` varchar(64) NULL COMMENT '审核人'"); | |
| 53 | + if (!names.Contains("shr1")) | |
| 54 | + _db.Ado.ExecuteCommand( | |
| 55 | + "ALTER TABLE `wt_fysrd` ADD COLUMN `shr1` varchar(500) NULL COMMENT '一级审核人'"); | |
| 56 | + if (!names.Contains("shr2")) | |
| 57 | + _db.Ado.ExecuteCommand( | |
| 58 | + "ALTER TABLE `wt_fysrd` ADD COLUMN `shr2` varchar(500) NULL COMMENT '二级审核人'"); | |
| 59 | + if (!names.Contains("wldw")) | |
| 60 | + _db.Ado.ExecuteCommand( | |
| 61 | + "ALTER TABLE `wt_fysrd` ADD COLUMN `wldw` varchar(64) NULL COMMENT '往来单位(wt_wldw.F_Id),与 fkdw 同步'"); | |
| 62 | + | |
| 63 | + _db.Ado.ExecuteCommand( | |
| 64 | + "UPDATE `wt_fysrd` SET `djzt`='草稿' WHERE `djzt` IS NULL OR TRIM(IFNULL(`djzt`,''))=''"); | |
| 65 | + _db.Ado.ExecuteCommand( | |
| 66 | + "UPDATE `wt_fysrd` SET `wldw`=`fkdw` WHERE (`wldw` IS NULL OR TRIM(IFNULL(`wldw`,''))='') AND `fkdw` IS NOT NULL AND TRIM(`fkdw`)<>''"); | |
| 67 | + } | |
| 68 | + catch (Exception ex) { Console.WriteLine($"EnsureFysrdAuditColumns: {ex.Message}"); } | |
| 69 | + _auditColumnsChecked = true; | |
| 70 | + } | |
| 71 | + } | |
| 72 | + | |
| 73 | + /// <summary>是否按「其他收入单」口径处理的单据类型(含历史前端传值)</summary> | |
| 74 | + public static bool IsOtherIncomeDjlx(string djlx) | |
| 75 | + { | |
| 76 | + var n = NormalizeOtherIncomeDjlx(djlx); | |
| 77 | + return string.Equals(n, BillName, StringComparison.Ordinal); | |
| 78 | + } | |
| 79 | + | |
| 80 | + /// <summary>统一单据类型展示与审核配置匹配用字符串</summary> | |
| 81 | + public static string NormalizeOtherIncomeDjlx(string djlx) | |
| 82 | + { | |
| 83 | + if (string.IsNullOrWhiteSpace(djlx)) return djlx; | |
| 84 | + var t = djlx.Trim().Replace("其它", "其他"); | |
| 85 | + if (t == "其他收入" || t == "其他收入单" || t.Contains("其他收入单")) | |
| 86 | + return BillName; | |
| 87 | + if (t.Contains("其他收入")) | |
| 88 | + return BillName; | |
| 89 | + return djlx.Trim(); | |
| 90 | + } | |
| 91 | + | |
| 92 | + /// <summary>往来单位主键:优先 wldw,其次 fkdw、kh、gys(请求兼容)</summary> | |
| 93 | + public static string ResolveCounterpartyId(string wldw, string fkdw, string kh, string gys) | |
| 94 | + { | |
| 95 | + var v = !string.IsNullOrWhiteSpace(wldw) ? wldw | |
| 96 | + : !string.IsNullOrWhiteSpace(fkdw) ? fkdw | |
| 97 | + : !string.IsNullOrWhiteSpace(kh) ? kh | |
| 98 | + : gys; | |
| 99 | + return string.IsNullOrWhiteSpace(v) ? null : v.Trim(); | |
| 100 | + } | |
| 101 | + | |
| 102 | + public static void ApplyCounterpartyToEntity(WtFysrdEntity entity, string wldw, string fkdw, string kh, string gys) | |
| 103 | + { | |
| 104 | + var id = ResolveCounterpartyId(wldw, fkdw, kh, gys); | |
| 105 | + if (string.IsNullOrEmpty(id)) return; | |
| 106 | + entity.Wldw = id; | |
| 107 | + entity.Fkdw = id; | |
| 108 | + } | |
| 109 | + | |
| 110 | + private static void AppendSpbz(WtFysrdEntity entity, string actionTag, string remark) | |
| 111 | + { | |
| 112 | + var r = (remark ?? "").Trim(); | |
| 113 | + if (string.IsNullOrEmpty(r)) return; | |
| 114 | + var line = string.IsNullOrEmpty(actionTag) ? r : $"[{actionTag}] {r}"; | |
| 115 | + var existing = entity.Spbz?.TrimEnd() ?? ""; | |
| 116 | + entity.Spbz = string.IsNullOrWhiteSpace(existing) ? line : existing + "\n" + line; | |
| 117 | + } | |
| 118 | + | |
| 119 | + private static bool IsUserInAuditConfig(string configValue, string userId, string userAccount) | |
| 120 | + { | |
| 121 | + if (string.IsNullOrWhiteSpace(configValue)) return false; | |
| 122 | + if (string.IsNullOrWhiteSpace(userId) && string.IsNullOrWhiteSpace(userAccount)) return false; | |
| 123 | + var users = configValue | |
| 124 | + .Split(new[] { ',', ',', ';', ';', '|', ' ' }, StringSplitOptions.RemoveEmptyEntries) | |
| 125 | + .Select(x => x.Trim()) | |
| 126 | + .Where(x => !string.IsNullOrEmpty(x)) | |
| 127 | + .ToList(); | |
| 128 | + return users.Any(x => | |
| 129 | + (!string.IsNullOrWhiteSpace(userId) && string.Equals(x, userId.Trim(), StringComparison.OrdinalIgnoreCase)) | |
| 130 | + || (!string.IsNullOrWhiteSpace(userAccount) && string.Equals(x, userAccount.Trim(), StringComparison.OrdinalIgnoreCase))); | |
| 131 | + } | |
| 132 | + | |
| 133 | + /// <summary> | |
| 134 | + /// 提交审核前校验:除备注外主表及明细必填(仅其他收入单) | |
| 135 | + /// </summary> | |
| 136 | + public static void ValidateOtherIncomeForSubmit(WtFysrdEntity h, List<WtFysrdMxEntity> mxList) | |
| 137 | + { | |
| 138 | + if (h == null) throw new ArgumentNullException(nameof(h)); | |
| 139 | + if (!IsOtherIncomeDjlx(h.Djlx)) | |
| 140 | + return; | |
| 141 | + | |
| 142 | + if (h.Djrq == null) | |
| 143 | + throw new InvalidOperationException("单据日期不能为空"); | |
| 144 | + if (string.IsNullOrWhiteSpace(h.Fzjg)) | |
| 145 | + throw new InvalidOperationException("分支机构不能为空"); | |
| 146 | + if (string.IsNullOrWhiteSpace(h.Bm)) | |
| 147 | + throw new InvalidOperationException("部门不能为空"); | |
| 148 | + if (string.IsNullOrWhiteSpace(h.Jsr)) | |
| 149 | + throw new InvalidOperationException("经手人不能为空"); | |
| 150 | + if (string.IsNullOrWhiteSpace(h.Jszh)) | |
| 151 | + throw new InvalidOperationException("结算账户不能为空"); | |
| 152 | + if (h.Je <= 0) | |
| 153 | + throw new InvalidOperationException("金额必须大于 0"); | |
| 154 | + if (string.IsNullOrWhiteSpace(h.Zdr)) | |
| 155 | + throw new InvalidOperationException("制单人不能为空"); | |
| 156 | + if (string.IsNullOrWhiteSpace(h.Zy)) | |
| 157 | + throw new InvalidOperationException("摘要不能为空"); | |
| 158 | + var cp = ResolveCounterpartyId(h.Wldw, h.Fkdw, null, null); | |
| 159 | + if (string.IsNullOrWhiteSpace(cp)) | |
| 160 | + throw new InvalidOperationException("往来单位不能为空"); | |
| 161 | + | |
| 162 | + if (mxList == null || mxList.Count == 0) | |
| 163 | + throw new InvalidOperationException("请先维护收入明细"); | |
| 164 | + | |
| 165 | + foreach (var mx in mxList) | |
| 166 | + { | |
| 167 | + if (string.IsNullOrWhiteSpace(mx.Km)) | |
| 168 | + throw new InvalidOperationException("明细科目不能为空"); | |
| 169 | + if (mx.Je <= 0) | |
| 170 | + throw new InvalidOperationException("明细金额必须大于 0"); | |
| 171 | + if (string.IsNullOrWhiteSpace(mx.Mxlx)) | |
| 172 | + throw new InvalidOperationException("明细类型不能为空"); | |
| 173 | + } | |
| 174 | + } | |
| 175 | + | |
| 176 | + /// <summary> | |
| 177 | + /// 草稿 / 审核不通过 → 待审核 | |
| 178 | + /// </summary> | |
| 179 | + public async Task<dynamic> SubmitForAuditAsync(string id) | |
| 180 | + { | |
| 181 | + EnsureFysrdAuditColumns(); | |
| 182 | + var entity = await _db.Queryable<WtFysrdEntity>().FirstAsync(p => p.Id == id); | |
| 183 | + if (entity == null) | |
| 184 | + return new { success = false, message = "单据不存在" }; | |
| 185 | + if (!IsOtherIncomeDjlx(entity.Djlx)) | |
| 186 | + return new { success = false, message = "该接口仅支持其他收入单" }; | |
| 187 | + | |
| 188 | + var st = entity.Djzt?.Trim() ?? ""; | |
| 189 | + if (st != "草稿" && st != "审核不通过") | |
| 190 | + return new { success = false, message = "仅草稿或审核不通过状态可提交审核" }; | |
| 191 | + | |
| 192 | + var mxList = await _db.Queryable<WtFysrdMxEntity>().Where(w => w.Djbh == id).ToListAsync(); | |
| 193 | + try | |
| 194 | + { | |
| 195 | + ValidateOtherIncomeForSubmit(entity, mxList); | |
| 196 | + } | |
| 197 | + catch (InvalidOperationException ex) | |
| 198 | + { | |
| 199 | + return new { success = false, message = ex.Message }; | |
| 200 | + } | |
| 201 | + | |
| 202 | + entity.Djzt = "待审核"; | |
| 203 | + await _db.Updateable(entity).UpdateColumns(x => new { x.Djzt }).ExecuteCommandAsync(); | |
| 204 | + return new { success = true, message = "已提交审核,请在待办中心处理" }; | |
| 205 | + } | |
| 206 | + | |
| 207 | + /// <summary> | |
| 208 | + /// 与 <see cref="NCC.Extend.WtXsckd.WtXsckdService.ApproveGeneric"/> 对接 | |
| 209 | + /// </summary> | |
| 210 | + public async Task<dynamic> ApproveAsync(string id, string remark) | |
| 211 | + { | |
| 212 | + EnsureFysrdAuditColumns(); | |
| 213 | + try | |
| 214 | + { | |
| 215 | + _db.BeginTran(); | |
| 216 | + var entity = await _db.Queryable<WtFysrdEntity>().FirstAsync(p => p.Id == id); | |
| 217 | + if (entity == null) | |
| 218 | + { | |
| 219 | + _db.RollbackTran(); | |
| 220 | + return new { success = false, message = "单据不存在" }; | |
| 221 | + } | |
| 222 | + if (!IsOtherIncomeDjlx(entity.Djlx)) | |
| 223 | + { | |
| 224 | + _db.RollbackTran(); | |
| 225 | + return new { success = false, message = "该单据不是其他收入单" }; | |
| 226 | + } | |
| 227 | + | |
| 228 | + if (entity.Djzt == "已审核") | |
| 229 | + { | |
| 230 | + _db.RollbackTran(); | |
| 231 | + return new { success = false, message = "该单据已经审核,无需重复审核" }; | |
| 232 | + } | |
| 233 | + | |
| 234 | + var userInfo = await _userManager.GetUserInfo(); | |
| 235 | + var userId = userInfo?.userId ?? ""; | |
| 236 | + var userAccount = userInfo?.userAccount?.Trim(); | |
| 237 | + if (string.IsNullOrEmpty(userAccount)) | |
| 238 | + userAccount = _userManager.Account?.Trim(); | |
| 239 | + | |
| 240 | + var approvalConfig = await _db.Queryable<WtShryszEntity>() | |
| 241 | + .Where(c => c.Djmc == BillName) | |
| 242 | + .FirstAsync(); | |
| 243 | + | |
| 244 | + var configShr1 = approvalConfig?.Shr1; | |
| 245 | + var configShr2 = approvalConfig?.Shr2; | |
| 246 | + var hasTwoLevel = !string.IsNullOrWhiteSpace(configShr1) && !string.IsNullOrWhiteSpace(configShr2); | |
| 247 | + | |
| 248 | + if (string.IsNullOrWhiteSpace(configShr1)) | |
| 249 | + { | |
| 250 | + _db.RollbackTran(); | |
| 251 | + return new { success = false, message = "未配置其他收入单一级审核人员,请先在审核人员设置中维护" }; | |
| 252 | + } | |
| 253 | + | |
| 254 | + var djztTrim = entity.Djzt?.Trim() ?? ""; | |
| 255 | + if (entity.Djzt == "待审核" || string.IsNullOrEmpty(djztTrim)) | |
| 256 | + { | |
| 257 | + if (!IsUserInAuditConfig(configShr1, userId, userAccount)) | |
| 258 | + { | |
| 259 | + _db.RollbackTran(); | |
| 260 | + return new { success = false, message = "当前用户不在其他收入单一级审核人员范围内" }; | |
| 261 | + } | |
| 262 | + | |
| 263 | + if (hasTwoLevel) | |
| 264 | + { | |
| 265 | + entity.Djzt = "一级已审"; | |
| 266 | + entity.Shr1 = userId; | |
| 267 | + AppendSpbz(entity, "一级通过", remark); | |
| 268 | + await _db.Updateable(entity).UpdateColumns(x => new { x.Djzt, x.Shr1, x.Spbz }).ExecuteCommandAsync(); | |
| 269 | + _db.CommitTran(); | |
| 270 | + return new { success = true, message = "一级审核通过,等待二级审核" }; | |
| 271 | + } | |
| 272 | + | |
| 273 | + entity.Djzt = "已审核"; | |
| 274 | + entity.Shr = userId; | |
| 275 | + entity.Shr1 = userId; | |
| 276 | + AppendSpbz(entity, "审核通过", remark); | |
| 277 | + await _db.Updateable(entity).UpdateColumns(x => new { x.Djzt, x.Shr, x.Shr1, x.Spbz }).ExecuteCommandAsync(); | |
| 278 | + _db.CommitTran(); | |
| 279 | + return new { success = true, message = "审核通过" }; | |
| 280 | + } | |
| 281 | + | |
| 282 | + if (entity.Djzt == "一级已审" || entity.Djzt == "待二级" || entity.Djzt == "一级已审/待二级") | |
| 283 | + { | |
| 284 | + if (!hasTwoLevel) | |
| 285 | + { | |
| 286 | + _db.RollbackTran(); | |
| 287 | + return new { success = false, message = "当前为单级审核配置,单据状态异常" }; | |
| 288 | + } | |
| 289 | + if (string.IsNullOrWhiteSpace(configShr2)) | |
| 290 | + { | |
| 291 | + _db.RollbackTran(); | |
| 292 | + return new { success = false, message = "未配置其他收入单二级审核人员,请先在审核人员设置中维护" }; | |
| 293 | + } | |
| 294 | + if (!IsUserInAuditConfig(configShr2, userId, userAccount)) | |
| 295 | + { | |
| 296 | + _db.RollbackTran(); | |
| 297 | + return new { success = false, message = "当前用户不在其他收入单二级审核人员范围内" }; | |
| 298 | + } | |
| 299 | + | |
| 300 | + entity.Djzt = "已审核"; | |
| 301 | + entity.Shr2 = userId; | |
| 302 | + entity.Shr = userId; | |
| 303 | + AppendSpbz(entity, "二级通过", remark); | |
| 304 | + await _db.Updateable(entity).UpdateColumns(x => new { x.Djzt, x.Shr, x.Shr2, x.Spbz }).ExecuteCommandAsync(); | |
| 305 | + _db.CommitTran(); | |
| 306 | + return new { success = true, message = "二级审核通过,审核完成" }; | |
| 307 | + } | |
| 308 | + | |
| 309 | + _db.RollbackTran(); | |
| 310 | + return new { success = false, message = $"当前单据状态「{entity.Djzt}」不允许审核" }; | |
| 311 | + } | |
| 312 | + catch (Exception ex) | |
| 313 | + { | |
| 314 | + _db.RollbackTran(); | |
| 315 | + return new { success = false, message = $"审核失败: {ex.Message}" }; | |
| 316 | + } | |
| 317 | + } | |
| 318 | + | |
| 319 | + /// <summary> | |
| 320 | + /// 与 RejectGeneric 对接 | |
| 321 | + /// </summary> | |
| 322 | + public async Task<dynamic> RejectAsync(string id, string remark) | |
| 323 | + { | |
| 324 | + EnsureFysrdAuditColumns(); | |
| 325 | + var entity = await _db.Queryable<WtFysrdEntity>().FirstAsync(p => p.Id == id); | |
| 326 | + if (entity == null) | |
| 327 | + return new { success = false, message = "单据不存在" }; | |
| 328 | + if (!IsOtherIncomeDjlx(entity.Djlx)) | |
| 329 | + return new { success = false, message = "该单据不是其他收入单" }; | |
| 330 | + if (entity.Djzt == "已审核") | |
| 331 | + return new { success = false, message = "该单据已审核通过" }; | |
| 332 | + if (entity.Djzt == "审核不通过") | |
| 333 | + return new { success = false, message = "该单据已是审核不通过状态" }; | |
| 334 | + if (entity.Djzt == "草稿") | |
| 335 | + return new { success = false, message = "草稿状态请直接修改或删除单据" }; | |
| 336 | + | |
| 337 | + var userInfo = await _userManager.GetUserInfo(); | |
| 338 | + var userId = userInfo?.userId ?? ""; | |
| 339 | + var userAccount = userInfo?.userAccount?.Trim(); | |
| 340 | + if (string.IsNullOrEmpty(userAccount)) | |
| 341 | + userAccount = _userManager.Account?.Trim(); | |
| 342 | + | |
| 343 | + var approvalConfig = await _db.Queryable<WtShryszEntity>() | |
| 344 | + .Where(c => c.Djmc == BillName) | |
| 345 | + .FirstAsync(); | |
| 346 | + var configShr1 = approvalConfig?.Shr1; | |
| 347 | + var configShr2 = approvalConfig?.Shr2; | |
| 348 | + | |
| 349 | + var djztTrim = entity.Djzt?.Trim() ?? ""; | |
| 350 | + var level1 = djztTrim == "待审核" || string.IsNullOrEmpty(djztTrim); | |
| 351 | + var level2 = entity.Djzt == "一级已审" || entity.Djzt == "待二级" || entity.Djzt == "一级已审/待二级"; | |
| 352 | + | |
| 353 | + if (!level1 && !level2) | |
| 354 | + return new { success = false, message = $"当前单据状态「{entity.Djzt}」不允许审核不通过" }; | |
| 355 | + | |
| 356 | + if (level1) | |
| 357 | + { | |
| 358 | + if (string.IsNullOrWhiteSpace(configShr1)) | |
| 359 | + return new { success = false, message = "未配置其他收入单一级审核人员,请先在审核人员设置中维护" }; | |
| 360 | + if (!IsUserInAuditConfig(configShr1, userId, userAccount)) | |
| 361 | + return new { success = false, message = "当前用户不在其他收入单一级审核人员范围内" }; | |
| 362 | + } | |
| 363 | + else | |
| 364 | + { | |
| 365 | + if (string.IsNullOrWhiteSpace(configShr2)) | |
| 366 | + return new { success = false, message = "未配置其他收入单二级审核人员,请先在审核人员设置中维护" }; | |
| 367 | + if (!IsUserInAuditConfig(configShr2, userId, userAccount)) | |
| 368 | + return new { success = false, message = "当前用户不在其他收入单二级审核人员范围内" }; | |
| 369 | + } | |
| 370 | + | |
| 371 | + _db.BeginTran(); | |
| 372 | + try | |
| 373 | + { | |
| 374 | + var row = await _db.Queryable<WtFysrdEntity>().FirstAsync(p => p.Id == id); | |
| 375 | + if (row == null) | |
| 376 | + { | |
| 377 | + _db.RollbackTran(); | |
| 378 | + return new { success = false, message = "单据不存在" }; | |
| 379 | + } | |
| 380 | + AppendSpbz(row, "审核不通过", remark); | |
| 381 | + row.Djzt = "审核不通过"; | |
| 382 | + row.Shr = userId; | |
| 383 | + row.Shr1 = null; | |
| 384 | + row.Shr2 = null; | |
| 385 | + await _db.Updateable(row).UpdateColumns(x => new { x.Djzt, x.Spbz, x.Shr, x.Shr1, x.Shr2 }).ExecuteCommandAsync(); | |
| 386 | + _db.CommitTran(); | |
| 387 | + return new { success = true, message = "已标记为审核不通过" }; | |
| 388 | + } | |
| 389 | + catch (Exception ex) | |
| 390 | + { | |
| 391 | + _db.RollbackTran(); | |
| 392 | + return new { success = false, message = $"操作失败: {ex.Message}" }; | |
| 393 | + } | |
| 394 | + } | |
| 395 | + | |
| 396 | + /// <summary> | |
| 397 | + /// 与 ReverseApproval 对接:已审核或一级已审 → 待审核 | |
| 398 | + /// </summary> | |
| 399 | + public async Task<dynamic> ReverseAsync(string id) | |
| 400 | + { | |
| 401 | + EnsureFysrdAuditColumns(); | |
| 402 | + try | |
| 403 | + { | |
| 404 | + var entity = await _db.Queryable<WtFysrdEntity>().FirstAsync(p => p.Id == id); | |
| 405 | + if (entity == null) | |
| 406 | + return new { success = false, message = "单据不存在" }; | |
| 407 | + if (!IsOtherIncomeDjlx(entity.Djlx)) | |
| 408 | + return new { success = false, message = "该单据不是其他收入单" }; | |
| 409 | + | |
| 410 | + if (entity.Djzt != "已审核" && entity.Djzt != "一级已审" && entity.Djzt != "一级已审/待二级" && entity.Djzt != "待二级") | |
| 411 | + return new { success = false, message = "当前单据状态不允许反审" }; | |
| 412 | + | |
| 413 | + var userInfo = await _userManager.GetUserInfo(); | |
| 414 | + var userId = userInfo?.userId ?? ""; | |
| 415 | + var userAccount = userInfo?.userAccount?.Trim(); | |
| 416 | + if (string.IsNullOrEmpty(userAccount)) | |
| 417 | + userAccount = _userManager.Account?.Trim(); | |
| 418 | + | |
| 419 | + var approvalConfig = await _db.Queryable<WtShryszEntity>() | |
| 420 | + .Where(c => c.Djmc == BillName) | |
| 421 | + .FirstAsync(); | |
| 422 | + | |
| 423 | + var configShr1 = approvalConfig?.Shr1; | |
| 424 | + var configShr2 = approvalConfig?.Shr2; | |
| 425 | + var bothUnset = string.IsNullOrWhiteSpace(configShr1) && string.IsNullOrWhiteSpace(configShr2); | |
| 426 | + var isAuthorized = bothUnset | |
| 427 | + || IsUserInAuditConfig(configShr1 ?? "", userId, userAccount) | |
| 428 | + || IsUserInAuditConfig(configShr2 ?? "", userId, userAccount); | |
| 429 | + | |
| 430 | + if (!isAuthorized) | |
| 431 | + return new { success = false, message = "您没有反审权限,只有一级或二级审核人可以反审" }; | |
| 432 | + | |
| 433 | + entity.Djzt = "待审核"; | |
| 434 | + entity.Shr = null; | |
| 435 | + entity.Shr1 = null; | |
| 436 | + entity.Shr2 = null; | |
| 437 | + await _db.Updateable(entity).UpdateColumns(x => new { x.Djzt, x.Shr, x.Shr1, x.Shr2 }).ExecuteCommandAsync(); | |
| 438 | + return new { success = true, message = "反审成功,单据已恢复为待审核状态" }; | |
| 439 | + } | |
| 440 | + catch (Exception ex) | |
| 441 | + { | |
| 442 | + return new { success = false, message = $"反审失败: {ex.Message}" }; | |
| 443 | + } | |
| 444 | + } | |
| 445 | + } | |
| 446 | +} | ... | ... |
Antis.Erp.Plat/netcore/src/Modularity/Extend/NCC.Extend/WtXsckdService.cs
| ... | ... | @@ -50,6 +50,7 @@ namespace NCC.Extend.WtXsckd |
| 50 | 50 | private readonly WtBillSummaryService _billSummaryService; |
| 51 | 51 | private readonly WtDjzyService _wtDjzyService; |
| 52 | 52 | private readonly WtTjd.WtTjdWorkflowHelper _tjdWorkflowHelper; |
| 53 | + private readonly WtFysrd.WtFysrdWorkflowHelper _fysrdWorkflowHelper; | |
| 53 | 54 | |
| 54 | 55 | // 序列号生成信号量,确保线程安全 |
| 55 | 56 | private static readonly SemaphoreSlim _serialNumberSemaphore = new SemaphoreSlim(1, 1); |
| ... | ... | @@ -1691,7 +1692,8 @@ WHERE d.djlx IN ('销售退货单','预售退货单','委托代销退货单') |
| 1691 | 1692 | IUserManager userManager, |
| 1692 | 1693 | WtBillSummaryService billSummaryService, |
| 1693 | 1694 | WtDjzyService wtDjzyService, |
| 1694 | - WtTjd.WtTjdWorkflowHelper tjdWorkflowHelper) | |
| 1695 | + WtTjd.WtTjdWorkflowHelper tjdWorkflowHelper, | |
| 1696 | + WtFysrd.WtFysrdWorkflowHelper fysrdWorkflowHelper) | |
| 1695 | 1697 | { |
| 1696 | 1698 | _wtXsckdRepository = wtXsckdRepository; |
| 1697 | 1699 | _db = _wtXsckdRepository.Context; |
| ... | ... | @@ -1700,6 +1702,7 @@ WHERE d.djlx IN ('销售退货单','预售退货单','委托代销退货单') |
| 1700 | 1702 | _billSummaryService = billSummaryService; |
| 1701 | 1703 | _wtDjzyService = wtDjzyService; |
| 1702 | 1704 | _tjdWorkflowHelper = tjdWorkflowHelper; |
| 1705 | + _fysrdWorkflowHelper = fysrdWorkflowHelper; | |
| 1703 | 1706 | } |
| 1704 | 1707 | |
| 1705 | 1708 | /// <summary> |
| ... | ... | @@ -4453,7 +4456,12 @@ ORDER BY IFNULL(MAX(pp.F_Ppmc), ''), IFNULL(MAX(s.F_Spbm), '')"; |
| 4453 | 4456 | AddInCondition("c.ck", input.Warehouse, "stockWh"); |
| 4454 | 4457 | AddInCondition("s.F_Pp", input.Brand, "stockPp"); |
| 4455 | 4458 | |
| 4456 | - if (!string.IsNullOrWhiteSpace(input.Product)) | |
| 4459 | + if (!string.IsNullOrWhiteSpace(input.ProductSpId)) | |
| 4460 | + { | |
| 4461 | + whereList.Add("s.F_Id = @stockProdId"); | |
| 4462 | + paramList.Add(new SugarParameter("@stockProdId", input.ProductSpId.Trim())); | |
| 4463 | + } | |
| 4464 | + else if (!string.IsNullOrWhiteSpace(input.Product)) | |
| 4457 | 4465 | { |
| 4458 | 4466 | whereList.Add("(s.F_Spmc LIKE @stockProdKw OR s.F_Spbm LIKE @stockProdKw)"); |
| 4459 | 4467 | paramList.Add(new SugarParameter("@stockProdKw", $"%{input.Product.Trim()}%")); |
| ... | ... | @@ -4464,6 +4472,51 @@ ORDER BY IFNULL(MAX(pp.F_Ppmc), ''), IFNULL(MAX(s.F_Spbm), '')"; |
| 4464 | 4472 | } |
| 4465 | 4473 | |
| 4466 | 4474 | /// <summary> |
| 4475 | + /// 商品库存汇总(按仓库聚合):用于“选择某个商品后,展示该商品在各仓数量/成本”。 | |
| 4476 | + /// </summary> | |
| 4477 | + /// <param name="input">必须提供 ProductSpId;可选 Warehouse(限定仓库范围)</param> | |
| 4478 | + [HttpGet("Actions/GetStockSummaryByWarehouse")] | |
| 4479 | + public async Task<dynamic> GetStockSummaryByWarehouse([FromQuery] WtStockSummaryQueryInput input) | |
| 4480 | + { | |
| 4481 | + input ??= new WtStockSummaryQueryInput(); | |
| 4482 | + if (string.IsNullOrWhiteSpace(input.ProductSpId)) | |
| 4483 | + { | |
| 4484 | + throw NCCException.Oh("商品 productSpId 不能为空"); | |
| 4485 | + } | |
| 4486 | + | |
| 4487 | + // 仓库维度不需要分类/品牌筛选,但允许传 warehouse 限定仓库范围 | |
| 4488 | + var (whereSql, paramList) = BuildWtStockCostSummaryWhere( | |
| 4489 | + new WtStockSummaryQueryInput | |
| 4490 | + { | |
| 4491 | + Warehouse = input.Warehouse, | |
| 4492 | + ProductSpId = input.ProductSpId | |
| 4493 | + }, | |
| 4494 | + null); | |
| 4495 | + | |
| 4496 | + var sql = $@" | |
| 4497 | +SELECT | |
| 4498 | + c.ck AS `仓库Id`, | |
| 4499 | + IFNULL(NULLIF(TRIM(ck.F_mdmc), ''), CONCAT('未知仓库(', c.ck, ')')) AS `仓库名称`, | |
| 4500 | + IFNULL(NULLIF(TRIM(MAX(s.F_Spbm)), ''), '无') AS `商品编码`, | |
| 4501 | + IFNULL(NULLIF(TRIM(MAX(s.F_Spmc)), ''), '无') AS `商品名称`, | |
| 4502 | + SUM(CAST(c.sl AS DECIMAL(18,4))) AS `数量`, | |
| 4503 | + CASE WHEN SUM(CAST(c.sl AS DECIMAL(18,4))) = 0 THEN 0 | |
| 4504 | + ELSE SUM(CAST(c.sl AS DECIMAL(18,4)) * c.cbj) / SUM(CAST(c.sl AS DECIMAL(18,4))) END AS `成本均价`, | |
| 4505 | + SUM(CAST(c.sl AS DECIMAL(18,4)) * c.cbj) AS `总成本` | |
| 4506 | +FROM wt_sp_cost c | |
| 4507 | +INNER JOIN wt_sp s ON s.F_Id = c.spbh | |
| 4508 | +LEFT JOIN wt_ck ck ON ck.F_Id = c.ck | |
| 4509 | +WHERE c.sl <> 0 | |
| 4510 | + AND c.ck IS NOT NULL AND TRIM(c.ck) <> '' | |
| 4511 | + {whereSql} | |
| 4512 | +GROUP BY c.ck, ck.F_mdmc | |
| 4513 | +ORDER BY SUM(CAST(c.sl AS DECIMAL(18,4)) * c.cbj) DESC"; | |
| 4514 | + | |
| 4515 | + var list = await _db.Ado.GetDataTableAsync(sql, paramList); | |
| 4516 | + return list; | |
| 4517 | + } | |
| 4518 | + | |
| 4519 | + /// <summary> | |
| 4467 | 4520 | /// 获取指定商品在指定门店/仓库范围内的库存数量(与商品库存汇总口径一致:仅汇总 <c>wt_sp_cost.sl</c>,不按序列号条数统计;大量无序列号商品亦适用)。 |
| 4468 | 4521 | /// </summary> |
| 4469 | 4522 | /// <param name="productId">商品ID</param> |
| ... | ... | @@ -4580,11 +4633,135 @@ INNER JOIN wt_xsckd d ON d.F_Id = mx.djbh |
| 4580 | 4633 | LEFT JOIN wt_sp sp ON sp.F_Id = mx.spbh |
| 4581 | 4634 | LEFT JOIN wt_pl pl ON pl.F_Id = sp.F_Pl |
| 4582 | 4635 | LEFT JOIN wt_pp pp ON pp.F_Id = sp.F_Pp |
| 4583 | -LEFT JOIN wt_wldw w ON w.F_Id = d.gys | |
| 4584 | -LEFT JOIN BASE_USER u ON u.F_Id = d.jsr | |
| 4636 | +LEFT JOIN wt_wldw w ON w.F_Id = IFNULL(NULLIF(TRIM(d.gys), ''), d.kh) | |
| 4637 | +LEFT JOIN BASE_USER u ON u.F_Id = IFNULL(NULLIF(TRIM(d.jsr), ''), d.zdr) | |
| 4585 | 4638 | LEFT JOIN wt_ck ck ON ck.F_Id = IFNULL(NULLIF(TRIM(mx.rkck), ''), d.rkck) |
| 4586 | 4639 | WHERE 1 = 1"; |
| 4587 | 4640 | |
| 4641 | + /// <summary>采购汇总限定单据类型(默认全集)。</summary> | |
| 4642 | + private static readonly string[] PurSumAllowedDjlx = | |
| 4643 | + { | |
| 4644 | + "采购入库单", "采购退货单", "销售出库单", "销售退货单", "预售出库单", "预售退货单", | |
| 4645 | + "委托代销发货单", "委托代销退货单", "委托代销结算单" | |
| 4646 | + }; | |
| 4647 | + | |
| 4648 | + /// <summary>主表 d.djlx 加减符号(与明细 mx 解耦)。</summary> | |
| 4649 | + private const string PurSumBizSignCase = | |
| 4650 | + "CASE WHEN d.djlx IN ('采购入库单','销售退货单','预售退货单','委托代销退货单') THEN 1 " | |
| 4651 | + + "WHEN d.djlx IN ('采购退货单','销售出库单','预售出库单','委托代销发货单','委托代销结算单') THEN -1 ELSE 0 END"; | |
| 4652 | + | |
| 4653 | + // 注意:部分退货/冲销类单据明细 mx.sl/mx.je 可能已为负数;若再按单据类型乘 -1 会出现“双重取反”导致统计方向错误。 | |
| 4654 | + // 统一口径:先取 ABS,再按单据类型决定正负。 | |
| 4655 | + private static string PurSumSignedSlExpr => $"(ABS(CAST(mx.sl AS DECIMAL(18,4))) * ({PurSumBizSignCase}))"; | |
| 4656 | + | |
| 4657 | + private static string PurSumSignedJeExpr => $"(ABS(CAST(mx.je AS DECIMAL(18,4))) * ({PurSumBizSignCase}))"; | |
| 4658 | + | |
| 4659 | + // 单价保持正数展示(方向由数量/金额体现),避免出现负单价 | |
| 4660 | + private static string PurSumSignedDjExpr => "(ABS(CAST(mx.dj AS DECIMAL(18,6))))"; | |
| 4661 | + | |
| 4662 | + private static string NormalizePurSumDjlx(string raw) | |
| 4663 | + { | |
| 4664 | + if (string.IsNullOrWhiteSpace(raw)) | |
| 4665 | + { | |
| 4666 | + return raw; | |
| 4667 | + } | |
| 4668 | + | |
| 4669 | + var t = raw.Trim(); | |
| 4670 | + return t == "委托代销结算" ? "委托代销结算单" : t; | |
| 4671 | + } | |
| 4672 | + | |
| 4673 | + /// <summary> | |
| 4674 | + /// 采购汇总聚合 ORDER BY(白名单)。 | |
| 4675 | + /// </summary> | |
| 4676 | + private static string BuildPurchaseSummaryAggOrderBy(string kind, string sortField, string sortOrder) | |
| 4677 | + { | |
| 4678 | + var dir = string.Equals(sortOrder?.Trim(), "asc", StringComparison.OrdinalIgnoreCase) | |
| 4679 | + ? "ASC" | |
| 4680 | + : "DESC"; | |
| 4681 | + | |
| 4682 | + var sumJe = $"SUM({PurSumSignedJeExpr})"; | |
| 4683 | + var sumSl = $"SUM({PurSumSignedSlExpr})"; | |
| 4684 | + var avgDj = $"CASE WHEN ABS({sumSl}) < 0.00000001 THEN 0 ELSE {sumJe} / {sumSl} END"; | |
| 4685 | + | |
| 4686 | + if (string.Equals(kind, "category", StringComparison.OrdinalIgnoreCase)) | |
| 4687 | + { | |
| 4688 | + var col = (sortField?.Trim()) switch | |
| 4689 | + { | |
| 4690 | + "分类Id" or "categoryId" => "IFNULL(NULLIF(TRIM(sp.F_Pl), ''), '__NONE__')", | |
| 4691 | + "分类名称" or "categoryName" => "IFNULL(NULLIF(TRIM(MAX(pl.F_Plmc)), ''), '无')", | |
| 4692 | + "数量" or "qty" => sumSl, | |
| 4693 | + "入库单价" or "inboundPrice" or "unitPrice" => avgDj, | |
| 4694 | + "采购金额" or "purchaseAmount" => sumJe, | |
| 4695 | + _ => sumJe | |
| 4696 | + }; | |
| 4697 | + return $"{col} {dir}"; | |
| 4698 | + } | |
| 4699 | + | |
| 4700 | + if (string.Equals(kind, "brand", StringComparison.OrdinalIgnoreCase)) | |
| 4701 | + { | |
| 4702 | + var col = (sortField?.Trim()) switch | |
| 4703 | + { | |
| 4704 | + "品牌Id" or "brandId" => "IFNULL(NULLIF(TRIM(sp.F_Pp), ''), '')", | |
| 4705 | + "品牌名称" or "brandName" => "IFNULL(NULLIF(TRIM(MAX(pp.F_Ppmc)), ''), '无')", | |
| 4706 | + "数量" or "qty" => sumSl, | |
| 4707 | + "入库单价" or "inboundPrice" or "unitPrice" => avgDj, | |
| 4708 | + "采购金额" or "purchaseAmount" => sumJe, | |
| 4709 | + _ => sumJe | |
| 4710 | + }; | |
| 4711 | + return $"{col} {dir}"; | |
| 4712 | + } | |
| 4713 | + | |
| 4714 | + if (string.Equals(kind, "productAgg", StringComparison.OrdinalIgnoreCase)) | |
| 4715 | + { | |
| 4716 | + var col = (sortField?.Trim()) switch | |
| 4717 | + { | |
| 4718 | + "商品Id" or "productId" => "sp.F_Id", | |
| 4719 | + "商品编号" or "productCode" => "IFNULL(NULLIF(TRIM(MAX(sp.F_Spbm)), ''), '无')", | |
| 4720 | + "商品名称" or "productName" => "IFNULL(NULLIF(TRIM(MAX(sp.F_Spmc)), ''), '无')", | |
| 4721 | + "明细分类" or "detailCategory" => | |
| 4722 | + "IFNULL(NULLIF(TRIM(CONCAT_WS(' / ', NULLIF(TRIM(sp.F_Splx1), ''), NULLIF(TRIM(sp.F_Splx2), ''))), ''), '无')", | |
| 4723 | + "数量" or "qty" => sumSl, | |
| 4724 | + "入库单价" or "inboundPrice" or "unitPrice" => avgDj, | |
| 4725 | + "采购金额" or "purchaseAmount" => sumJe, | |
| 4726 | + _ => sumJe | |
| 4727 | + }; | |
| 4728 | + return $"{col} {dir}"; | |
| 4729 | + } | |
| 4730 | + | |
| 4731 | + return $"{sumJe} DESC"; | |
| 4732 | + } | |
| 4733 | + | |
| 4734 | + /// <summary> | |
| 4735 | + /// 采购明细 / 线性列表 ORDER BY(仅允许白名单列,防注入);数量金额单价按采购汇总符号口径排序。 | |
| 4736 | + /// </summary> | |
| 4737 | + private static string BuildPurchaseSummaryDetailOrderBy(string sortField, string sortOrder) | |
| 4738 | + { | |
| 4739 | + var dir = string.Equals(sortOrder?.Trim(), "asc", StringComparison.OrdinalIgnoreCase) | |
| 4740 | + ? "ASC" | |
| 4741 | + : "DESC"; | |
| 4742 | + | |
| 4743 | + var agentExpr = "IFNULL(NULLIF(TRIM(u.F_RealName), ''), '无')"; | |
| 4744 | + | |
| 4745 | + var col = sortField?.Trim() switch | |
| 4746 | + { | |
| 4747 | + "单据日期" or "billDate" => "d.djrq", | |
| 4748 | + "单据编号" or "billId" => "d.F_Id", | |
| 4749 | + "单据类型" or "billType" => "d.djlx", | |
| 4750 | + "往来单位" or "contactName" => "IFNULL(NULLIF(TRIM(w.dwmc), ''), '无')", | |
| 4751 | + "经手人" or "agentName" => agentExpr, | |
| 4752 | + "仓库名称" or "warehouseName" => "IFNULL(NULLIF(TRIM(ck.F_mdmc), ''), '无')", | |
| 4753 | + "商品名称" or "productName" => "IFNULL(NULLIF(TRIM(mx.spmc), ''), '无')", | |
| 4754 | + "数量" or "qty" => PurSumSignedSlExpr, | |
| 4755 | + "入库单价" or "inboundPrice" or "unitPrice" => PurSumSignedDjExpr, | |
| 4756 | + "采购金额" or "purchaseAmount" => PurSumSignedJeExpr, | |
| 4757 | + _ => null | |
| 4758 | + }; | |
| 4759 | + | |
| 4760 | + return string.IsNullOrEmpty(col) | |
| 4761 | + ? "d.djrq DESC, d.F_Id DESC, mx.F_Id" | |
| 4762 | + : $"{col} {dir}, d.F_Id DESC, mx.F_Id"; | |
| 4763 | + } | |
| 4764 | + | |
| 4588 | 4765 | /// <summary> |
| 4589 | 4766 | /// 采购汇总公共 WHERE(需配合含 sp/pl/pp 的 PurchaseSummaryJoinFromSql 使用)。 |
| 4590 | 4767 | /// </summary> |
| ... | ... | @@ -4644,22 +4821,56 @@ WHERE 1 = 1"; |
| 4644 | 4821 | paramList.Add(new SugarParameter("@purSumEndDate", endDate.Date.AddDays(1))); |
| 4645 | 4822 | } |
| 4646 | 4823 | |
| 4647 | - AddInCondition("d.gys", input.ContactUnit, "purSumContact"); | |
| 4648 | - | |
| 4649 | - // 经手人:主表 wt_xsckd.jsr 存 BASE_USER.F_Id,按用户主键 IN 筛选(与前端下拉 value 一致) | |
| 4650 | - AddInCondition("d.jsr", input.Agent, "purSumJsr"); | |
| 4824 | + whereList.Add("d.djzt = @purSumDjzt"); | |
| 4825 | + paramList.Add(new SugarParameter("@purSumDjzt", "已审核")); | |
| 4651 | 4826 | |
| 4652 | - AddInCondition("IFNULL(NULLIF(TRIM(mx.rkck), ''), d.rkck)", input.Warehouse, "purSumWh"); | |
| 4653 | - | |
| 4654 | - var billTypeValues = SplitCsv(input.BillType); | |
| 4827 | + var allowedSet = new HashSet<string>(PurSumAllowedDjlx, StringComparer.Ordinal); | |
| 4828 | + var billRaw = input.BillType?.Trim(); | |
| 4829 | + var billAll = string.IsNullOrEmpty(billRaw) || billRaw.Equals("all", StringComparison.OrdinalIgnoreCase); | |
| 4830 | + var billRequested = SplitCsv(input.BillType).Select(NormalizePurSumDjlx).Where(s => !string.IsNullOrWhiteSpace(s)).ToList(); | |
| 4831 | + var billTypeValues = billAll || billRequested.Count == 0 | |
| 4832 | + ? PurSumAllowedDjlx.ToList() | |
| 4833 | + : billRequested.Where(allowedSet.Contains).Distinct().ToList(); | |
| 4655 | 4834 | if (billTypeValues.Count == 0) |
| 4656 | 4835 | { |
| 4657 | - billTypeValues.Add("采购入库单"); | |
| 4658 | - billTypeValues.Add("采购退货单"); | |
| 4836 | + billTypeValues = PurSumAllowedDjlx.ToList(); | |
| 4659 | 4837 | } |
| 4660 | 4838 | |
| 4661 | 4839 | AddInCondition("d.djlx", string.Join(",", billTypeValues), "purSumDjlx"); |
| 4662 | 4840 | |
| 4841 | + var contactVals = SplitCsv(input.ContactUnit); | |
| 4842 | + if (contactVals.Count > 0) | |
| 4843 | + { | |
| 4844 | + var gysParts = new List<string>(); | |
| 4845 | + var khParts = new List<string>(); | |
| 4846 | + for (var i = 0; i < contactVals.Count; i++) | |
| 4847 | + { | |
| 4848 | + var pn = $"@purSumContact{i}"; | |
| 4849 | + gysParts.Add($"d.gys = {pn}"); | |
| 4850 | + khParts.Add($"d.kh = {pn}"); | |
| 4851 | + paramList.Add(new SugarParameter(pn, contactVals[i])); | |
| 4852 | + } | |
| 4853 | + | |
| 4854 | + whereList.Add($"(({string.Join(" OR ", gysParts)}) OR ({string.Join(" OR ", khParts)}))"); | |
| 4855 | + } | |
| 4856 | + | |
| 4857 | + var agentVals = SplitCsv(input.Agent); | |
| 4858 | + if (agentVals.Count > 0) | |
| 4859 | + { | |
| 4860 | + var agentParts = new List<string>(); | |
| 4861 | + for (var i = 0; i < agentVals.Count; i++) | |
| 4862 | + { | |
| 4863 | + var pn = $"@purSumJsr{i}"; | |
| 4864 | + agentParts.Add( | |
| 4865 | + $"IFNULL(NULLIF(TRIM(d.jsr), ''), IFNULL(NULLIF(TRIM(d.zdr), ''), '')) = {pn}"); | |
| 4866 | + paramList.Add(new SugarParameter(pn, agentVals[i])); | |
| 4867 | + } | |
| 4868 | + | |
| 4869 | + whereList.Add($"({string.Join(" OR ", agentParts)})"); | |
| 4870 | + } | |
| 4871 | + | |
| 4872 | + AddInCondition("IFNULL(NULLIF(TRIM(mx.rkck), ''), d.rkck)", input.Warehouse, "purSumWh"); | |
| 4873 | + | |
| 4663 | 4874 | var productValues = SplitCsv(input.Product); |
| 4664 | 4875 | if (productValues.Count > 0) |
| 4665 | 4876 | { |
| ... | ... | @@ -4668,7 +4879,8 @@ WHERE 1 = 1"; |
| 4668 | 4879 | { |
| 4669 | 4880 | var pEq = $"@purProdEq{i}"; |
| 4670 | 4881 | var pLike = $"@purProdLike{i}"; |
| 4671 | - productConditions.Add($"(mx.spbh = {pEq} OR sp.F_Spbm = {pEq} OR mx.spmc LIKE {pLike} OR IFNULL(sp.F_Spmc, '') LIKE {pLike})"); | |
| 4882 | + productConditions.Add( | |
| 4883 | + $"(mx.spbh = {pEq} OR sp.F_Id = {pEq} OR sp.F_Spbm = {pEq} OR mx.spmc LIKE {pLike} OR IFNULL(sp.F_Spmc, '') LIKE {pLike})"); | |
| 4672 | 4884 | paramList.Add(new SugarParameter(pEq, productValues[i])); |
| 4673 | 4885 | paramList.Add(new SugarParameter(pLike, $"%{productValues[i]}%")); |
| 4674 | 4886 | } |
| ... | ... | @@ -4697,7 +4909,7 @@ WHERE 1 = 1"; |
| 4697 | 4909 | var spId = !string.IsNullOrWhiteSpace(scopeProductSpId) ? scopeProductSpId.Trim() : (input.ProductSpId ?? string.Empty).Trim(); |
| 4698 | 4910 | if (!string.IsNullOrEmpty(spId)) |
| 4699 | 4911 | { |
| 4700 | - whereList.Add("mx.spbh = @purSumScopeSp"); | |
| 4912 | + whereList.Add("(mx.spbh = @purSumScopeSp OR sp.F_Id = @purSumScopeSp)"); | |
| 4701 | 4913 | paramList.Add(new SugarParameter("@purSumScopeSp", spId)); |
| 4702 | 4914 | } |
| 4703 | 4915 | |
| ... | ... | @@ -4713,20 +4925,21 @@ WHERE 1 = 1"; |
| 4713 | 4925 | { |
| 4714 | 4926 | input ??= new WtPurchaseSummaryQueryInput(); |
| 4715 | 4927 | var (whereSql, paramList) = BuildPurchaseSummaryWhere(input, null, null, null); |
| 4928 | + var orderBy = BuildPurchaseSummaryAggOrderBy("category", input.SortField, input.SortOrder); | |
| 4716 | 4929 | var sql = $@" |
| 4717 | 4930 | SELECT |
| 4718 | 4931 | IFNULL(NULLIF(TRIM(sp.F_Pl), ''), '__NONE__') AS `分类Id`, |
| 4719 | 4932 | IFNULL(NULLIF(TRIM(MAX(pl.F_Plmc)), ''), '无') AS `分类名称`, |
| 4720 | 4933 | '无' AS `商品编号`, |
| 4721 | 4934 | IFNULL(NULLIF(TRIM(MAX(pl.F_Plmc)), ''), '无') AS `商品名称`, |
| 4722 | - SUM(CAST(mx.sl AS DECIMAL(18,4))) AS `数量`, | |
| 4723 | - CASE WHEN ABS(SUM(CAST(mx.sl AS DECIMAL(18,4)))) < 0.00000001 THEN 0 | |
| 4724 | - ELSE SUM(CAST(mx.je AS DECIMAL(18,4))) / SUM(CAST(mx.sl AS DECIMAL(18,4))) END AS `入库单价`, | |
| 4725 | - SUM(CAST(mx.je AS DECIMAL(18,4))) AS `采购金额` | |
| 4935 | + SUM({PurSumSignedSlExpr}) AS `数量`, | |
| 4936 | + CASE WHEN ABS(SUM({PurSumSignedSlExpr})) < 0.00000001 THEN 0 | |
| 4937 | + ELSE SUM({PurSumSignedJeExpr}) / SUM({PurSumSignedSlExpr}) END AS `入库单价`, | |
| 4938 | + SUM({PurSumSignedJeExpr}) AS `采购金额` | |
| 4726 | 4939 | {PurchaseSummaryJoinFromSql} |
| 4727 | 4940 | {whereSql} |
| 4728 | 4941 | GROUP BY sp.F_Pl, pl.F_Plmc |
| 4729 | -ORDER BY SUM(CAST(mx.je AS DECIMAL(18,4))) DESC"; | |
| 4942 | +ORDER BY {orderBy}"; | |
| 4730 | 4943 | var list = await _db.Ado.GetDataTableAsync(sql, paramList); |
| 4731 | 4944 | return list; |
| 4732 | 4945 | } |
| ... | ... | @@ -4744,20 +4957,21 @@ ORDER BY SUM(CAST(mx.je AS DECIMAL(18,4))) DESC"; |
| 4744 | 4957 | |
| 4745 | 4958 | input ??= new WtPurchaseSummaryQueryInput(); |
| 4746 | 4959 | var (whereSql, paramList) = BuildPurchaseSummaryWhere(input, categoryId, null, null); |
| 4960 | + var orderBy = BuildPurchaseSummaryAggOrderBy("brand", input.SortField, input.SortOrder); | |
| 4747 | 4961 | var sql = $@" |
| 4748 | 4962 | SELECT |
| 4749 | 4963 | IFNULL(NULLIF(TRIM(sp.F_Pp), ''), '') AS `品牌Id`, |
| 4750 | 4964 | IFNULL(NULLIF(TRIM(MAX(pp.F_Ppmc)), ''), '无') AS `品牌名称`, |
| 4751 | 4965 | '无' AS `商品编号`, |
| 4752 | 4966 | IFNULL(NULLIF(TRIM(MAX(pp.F_Ppmc)), ''), '无') AS `商品名称`, |
| 4753 | - SUM(CAST(mx.sl AS DECIMAL(18,4))) AS `数量`, | |
| 4754 | - CASE WHEN ABS(SUM(CAST(mx.sl AS DECIMAL(18,4)))) < 0.00000001 THEN 0 | |
| 4755 | - ELSE SUM(CAST(mx.je AS DECIMAL(18,4))) / SUM(CAST(mx.sl AS DECIMAL(18,4))) END AS `入库单价`, | |
| 4756 | - SUM(CAST(mx.je AS DECIMAL(18,4))) AS `采购金额` | |
| 4967 | + SUM({PurSumSignedSlExpr}) AS `数量`, | |
| 4968 | + CASE WHEN ABS(SUM({PurSumSignedSlExpr})) < 0.00000001 THEN 0 | |
| 4969 | + ELSE SUM({PurSumSignedJeExpr}) / SUM({PurSumSignedSlExpr}) END AS `入库单价`, | |
| 4970 | + SUM({PurSumSignedJeExpr}) AS `采购金额` | |
| 4757 | 4971 | {PurchaseSummaryJoinFromSql} |
| 4758 | 4972 | {whereSql} |
| 4759 | 4973 | GROUP BY sp.F_Pp, pp.F_Ppmc |
| 4760 | -ORDER BY SUM(CAST(mx.je AS DECIMAL(18,4))) DESC"; | |
| 4974 | +ORDER BY {orderBy}"; | |
| 4761 | 4975 | var list = await _db.Ado.GetDataTableAsync(sql, paramList); |
| 4762 | 4976 | return list; |
| 4763 | 4977 | } |
| ... | ... | @@ -4780,26 +4994,27 @@ ORDER BY SUM(CAST(mx.je AS DECIMAL(18,4))) DESC"; |
| 4780 | 4994 | |
| 4781 | 4995 | input ??= new WtPurchaseSummaryQueryInput(); |
| 4782 | 4996 | var (whereSql, paramList) = BuildPurchaseSummaryWhere(input, categoryId, brandId, null); |
| 4997 | + var orderBy = BuildPurchaseSummaryAggOrderBy("productAgg", input.SortField, input.SortOrder); | |
| 4783 | 4998 | var sql = $@" |
| 4784 | 4999 | SELECT |
| 4785 | 5000 | sp.F_Id AS `商品Id`, |
| 4786 | 5001 | IFNULL(NULLIF(TRIM(MAX(sp.F_Spbm)), ''), '无') AS `商品编号`, |
| 4787 | 5002 | IFNULL(NULLIF(TRIM(MAX(sp.F_Spmc)), ''), '无') AS `商品名称`, |
| 4788 | 5003 | IFNULL(NULLIF(TRIM(CONCAT_WS(' / ', NULLIF(TRIM(sp.F_Splx1), ''), NULLIF(TRIM(sp.F_Splx2), ''))), ''), '无') AS `明细分类`, |
| 4789 | - SUM(CAST(mx.sl AS DECIMAL(18,4))) AS `数量`, | |
| 4790 | - CASE WHEN ABS(SUM(CAST(mx.sl AS DECIMAL(18,4)))) < 0.00000001 THEN 0 | |
| 4791 | - ELSE SUM(CAST(mx.je AS DECIMAL(18,4))) / SUM(CAST(mx.sl AS DECIMAL(18,4))) END AS `入库单价`, | |
| 4792 | - SUM(CAST(mx.je AS DECIMAL(18,4))) AS `采购金额` | |
| 5004 | + SUM({PurSumSignedSlExpr}) AS `数量`, | |
| 5005 | + CASE WHEN ABS(SUM({PurSumSignedSlExpr})) < 0.00000001 THEN 0 | |
| 5006 | + ELSE SUM({PurSumSignedJeExpr}) / SUM({PurSumSignedSlExpr}) END AS `入库单价`, | |
| 5007 | + SUM({PurSumSignedJeExpr}) AS `采购金额` | |
| 4793 | 5008 | {PurchaseSummaryJoinFromSql} |
| 4794 | 5009 | {whereSql} |
| 4795 | 5010 | GROUP BY sp.F_Id, sp.F_Splx1, sp.F_Splx2 |
| 4796 | -ORDER BY IFNULL(MAX(sp.F_Spbm), ''), IFNULL(MAX(sp.F_Spmc), '')"; | |
| 5011 | +ORDER BY {orderBy}"; | |
| 4797 | 5012 | var list = await _db.Ado.GetDataTableAsync(sql, paramList); |
| 4798 | 5013 | return list; |
| 4799 | 5014 | } |
| 4800 | 5015 | |
| 4801 | 5016 | /// <summary> |
| 4802 | - /// 商品采购「线性列表」:指定分类下全部采购明细行(最多 2000 条),与明细列表列一致。 | |
| 5017 | + /// 商品采购「线性列表」:指定分类下全部相关单据明细(分页,与 GetPurchaseSummary 筛选及加减口径一致)。 | |
| 4803 | 5018 | /// </summary> |
| 4804 | 5019 | [HttpGet("Actions/GetPurchaseSummaryLinear")] |
| 4805 | 5020 | public async Task<dynamic> GetPurchaseSummaryLinear([FromQuery] string categoryId, [FromQuery] WtPurchaseSummaryQueryInput input = null) |
| ... | ... | @@ -4811,25 +5026,50 @@ ORDER BY IFNULL(MAX(sp.F_Spbm), ''), IFNULL(MAX(sp.F_Spmc), '')"; |
| 4811 | 5026 | |
| 4812 | 5027 | input ??= new WtPurchaseSummaryQueryInput(); |
| 4813 | 5028 | var (whereSql, paramList) = BuildPurchaseSummaryWhere(input, categoryId, null, null); |
| 4814 | - const int maxRows = 2000; | |
| 5029 | + | |
| 5030 | + var page = input.CurrentPage.GetValueOrDefault(1); | |
| 5031 | + if (page < 1) | |
| 5032 | + { | |
| 5033 | + page = 1; | |
| 5034 | + } | |
| 5035 | + | |
| 5036 | + // 线性列表单次可拉较大窗口(默认 2000),与历史「最多 2000 条」一致;仍支持分页防一次过大。 | |
| 5037 | + var pageSize = input.PageSize.GetValueOrDefault(2000); | |
| 5038 | + if (pageSize < 1) | |
| 5039 | + { | |
| 5040 | + pageSize = 2000; | |
| 5041 | + } | |
| 5042 | + | |
| 5043 | + if (pageSize > 2000) | |
| 5044 | + { | |
| 5045 | + pageSize = 2000; | |
| 5046 | + } | |
| 5047 | + | |
| 5048 | + var offset = (page - 1) * pageSize; | |
| 5049 | + | |
| 5050 | + var countSql = "SELECT COUNT(*) " + PurchaseSummaryJoinFromSql + whereSql; | |
| 5051 | + var totalObj = await _db.Ado.GetScalarAsync(countSql, paramList); | |
| 5052 | + var total = Convert.ToInt32(totalObj ?? 0); | |
| 5053 | + | |
| 5054 | + var orderByLin = BuildPurchaseSummaryDetailOrderBy(input.SortField, input.SortOrder); | |
| 4815 | 5055 | var sql = $@" |
| 4816 | 5056 | SELECT |
| 4817 | 5057 | DATE_FORMAT(d.djrq, '%Y-%m-%d') AS `单据日期`, |
| 4818 | 5058 | d.F_Id AS `单据编号`, |
| 4819 | 5059 | d.djlx AS `单据类型`, |
| 4820 | 5060 | IFNULL(NULLIF(TRIM(w.dwmc), ''), '无') AS `往来单位`, |
| 4821 | - IFNULL(NULLIF(TRIM(u.F_RealName), ''), IFNULL(NULLIF(TRIM(d.jsr), ''), '无')) AS `经手人`, | |
| 5061 | + IFNULL(NULLIF(TRIM(u.F_RealName), ''), '无') AS `经手人`, | |
| 4822 | 5062 | IFNULL(NULLIF(TRIM(ck.F_mdmc), ''), '无') AS `仓库名称`, |
| 4823 | 5063 | IFNULL(NULLIF(TRIM(mx.spmc), ''), '无') AS `商品名称`, |
| 4824 | - CAST(mx.sl AS DECIMAL(18,4)) AS `数量`, | |
| 4825 | - mx.dj AS `入库单价`, | |
| 4826 | - mx.je AS `采购金额` | |
| 5064 | + {PurSumSignedSlExpr} AS `数量`, | |
| 5065 | + {PurSumSignedDjExpr} AS `入库单价`, | |
| 5066 | + {PurSumSignedJeExpr} AS `采购金额` | |
| 4827 | 5067 | {PurchaseSummaryJoinFromSql} |
| 4828 | 5068 | {whereSql} |
| 4829 | -ORDER BY d.djrq DESC, d.F_Id, mx.F_Id | |
| 4830 | -LIMIT {maxRows}"; | |
| 5069 | +ORDER BY {orderByLin} | |
| 5070 | +LIMIT {offset}, {pageSize}"; | |
| 4831 | 5071 | var list = await _db.Ado.GetDataTableAsync(sql, paramList); |
| 4832 | - return list; | |
| 5072 | + return new { list, total }; | |
| 4833 | 5073 | } |
| 4834 | 5074 | |
| 4835 | 5075 | /// <summary> |
| ... | ... | @@ -4866,21 +5106,22 @@ LIMIT {maxRows}"; |
| 4866 | 5106 | var totalObj = await _db.Ado.GetScalarAsync(countSql, paramList); |
| 4867 | 5107 | var total = Convert.ToInt32(totalObj ?? 0); |
| 4868 | 5108 | |
| 5109 | + var orderByDetail = BuildPurchaseSummaryDetailOrderBy(input.SortField, input.SortOrder); | |
| 4869 | 5110 | var listSql = $@" |
| 4870 | 5111 | SELECT |
| 4871 | 5112 | DATE_FORMAT(d.djrq, '%Y-%m-%d') AS `单据日期`, |
| 4872 | 5113 | d.F_Id AS `单据编号`, |
| 4873 | 5114 | d.djlx AS `单据类型`, |
| 4874 | 5115 | IFNULL(NULLIF(TRIM(w.dwmc), ''), '无') AS `往来单位`, |
| 4875 | - IFNULL(NULLIF(TRIM(u.F_RealName), ''), IFNULL(NULLIF(TRIM(d.jsr), ''), '无')) AS `经手人`, | |
| 5116 | + IFNULL(NULLIF(TRIM(u.F_RealName), ''), '无') AS `经手人`, | |
| 4876 | 5117 | IFNULL(NULLIF(TRIM(ck.F_mdmc), ''), '无') AS `仓库名称`, |
| 4877 | 5118 | IFNULL(NULLIF(TRIM(mx.spmc), ''), '无') AS `商品名称`, |
| 4878 | - CAST(mx.sl AS DECIMAL(18,4)) AS `数量`, | |
| 4879 | - mx.dj AS `入库单价`, | |
| 4880 | - mx.je AS `采购金额` | |
| 5119 | + {PurSumSignedSlExpr} AS `数量`, | |
| 5120 | + {PurSumSignedDjExpr} AS `入库单价`, | |
| 5121 | + {PurSumSignedJeExpr} AS `采购金额` | |
| 4881 | 5122 | {PurchaseSummaryJoinFromSql} |
| 4882 | 5123 | {whereSql} |
| 4883 | -ORDER BY d.djrq DESC, d.F_Id, mx.F_Id | |
| 5124 | +ORDER BY {orderByDetail} | |
| 4884 | 5125 | LIMIT {offset}, {pageSize}"; |
| 4885 | 5126 | var list = await _db.Ado.GetDataTableAsync(listSql, paramList); |
| 4886 | 5127 | return new { list, total }; |
| ... | ... | @@ -5744,11 +5985,13 @@ LIMIT {offset}, {pageSize}"; |
| 5744 | 5985 | } |
| 5745 | 5986 | |
| 5746 | 5987 | /// <summary> |
| 5747 | - /// 通用审核接口:自动根据单据的 djlx 匹配审核配置;编号以 TJD 开头时优先判断是否为 wt_xsckd 同价调拨单,否则走商品调价单审批流 | |
| 5988 | + /// 通用审核接口:自动根据单据的 djlx 匹配审核配置;编号以 TJD 开头时优先判断是否为 wt_xsckd 同价调拨单,否则走商品调价单审批流;wt_fysrd 其他收入单走费用收入单审批流 | |
| 5748 | 5989 | /// </summary> |
| 5749 | 5990 | [HttpPost("ApproveGeneric/{id}")] |
| 5750 | 5991 | public async Task<dynamic> ApproveGeneric(string id, [FromBody] WtApprovalRemarkInput input) |
| 5751 | 5992 | { |
| 5993 | + if (!string.IsNullOrEmpty(id) && await _db.Queryable<WtFysrdEntity>().AnyAsync(x => x.Id == id)) | |
| 5994 | + return await _fysrdWorkflowHelper.ApproveAsync(id, input?.remark); | |
| 5752 | 5995 | if (!string.IsNullOrEmpty(id) && id.StartsWith("TJD", StringComparison.Ordinal)) |
| 5753 | 5996 | { |
| 5754 | 5997 | var isSamePriceTransfer = await _db.Queryable<WtXsckdEntity>() |
| ... | ... | @@ -5768,6 +6011,8 @@ LIMIT {offset}, {pageSize}"; |
| 5768 | 6011 | [HttpPost("RejectGeneric/{id}")] |
| 5769 | 6012 | public async Task<dynamic> RejectGeneric(string id, [FromBody] WtApprovalRemarkInput input) |
| 5770 | 6013 | { |
| 6014 | + if (!string.IsNullOrEmpty(id) && await _db.Queryable<WtFysrdEntity>().AnyAsync(x => x.Id == id)) | |
| 6015 | + return await _fysrdWorkflowHelper.RejectAsync(id, input?.remark); | |
| 5771 | 6016 | if (!string.IsNullOrEmpty(id) && id.StartsWith("TJD", StringComparison.Ordinal)) |
| 5772 | 6017 | { |
| 5773 | 6018 | var isSamePriceTransfer = await _db.Queryable<WtXsckdEntity>() |
| ... | ... | @@ -5942,6 +6187,9 @@ LIMIT {offset}, {pageSize}"; |
| 5942 | 6187 | { |
| 5943 | 6188 | try |
| 5944 | 6189 | { |
| 6190 | + if (!string.IsNullOrEmpty(id) && await _db.Queryable<WtFysrdEntity>().AnyAsync(x => x.Id == id)) | |
| 6191 | + return await _fysrdWorkflowHelper.ReverseAsync(id); | |
| 6192 | + | |
| 5945 | 6193 | var entity = await _db.Queryable<WtXsckdEntity>().Where(x => x.Id == id).FirstAsync(); |
| 5946 | 6194 | if (entity == null) |
| 5947 | 6195 | return new { success = false, message = "单据不存在" }; | ... | ... |
Antis.Erp.Plat/netcore/src/Modularity/Extend/NCC.Extend/WtYskzjjsService.cs
| ... | ... | @@ -14,6 +14,7 @@ using System.Collections.Generic; |
| 14 | 14 | using System.Linq; |
| 15 | 15 | using System.Threading.Tasks; |
| 16 | 16 | using NCC.Extend.Entitys; |
| 17 | +using NCC.Extend.Entitys.Dto; | |
| 17 | 18 | using NCC.Extend.Entitys.Dto.WtYskzjjs; |
| 18 | 19 | using Yitter.IdGenerator; |
| 19 | 20 | using NCC.Common.Helper; |
| ... | ... | @@ -40,6 +41,7 @@ namespace NCC.Extend.WtYskzjjs |
| 40 | 41 | private readonly IUserManager _userManager; |
| 41 | 42 | private readonly WtDjzyService _wtDjzyService; |
| 42 | 43 | private readonly WtBillSummaryService _billSummaryService; |
| 44 | + private static bool _yskAuditColsEnsured; | |
| 43 | 45 | |
| 44 | 46 | /// <summary> |
| 45 | 47 | /// 初始化一个<see cref="WtYskzjjsService"/>类型的新实例 |
| ... | ... | @@ -60,6 +62,39 @@ namespace NCC.Extend.WtYskzjjs |
| 60 | 62 | } |
| 61 | 63 | |
| 62 | 64 | /// <summary> |
| 65 | + /// 确保 wt_yskzjjs 具备审批相关列(避免线上旧库缺列导致 Unknown column)。 | |
| 66 | + /// </summary> | |
| 67 | + private void EnsureYskzjjsAuditColumns() | |
| 68 | + { | |
| 69 | + if (_yskAuditColsEnsured) return; | |
| 70 | + lock (typeof(WtYskzjjsService)) | |
| 71 | + { | |
| 72 | + if (_yskAuditColsEnsured) return; | |
| 73 | + try | |
| 74 | + { | |
| 75 | + if (!_db.DbMaintenance.IsAnyTable("wt_yskzjjs")) { _yskAuditColsEnsured = true; return; } | |
| 76 | + var cols = _db.DbMaintenance.GetColumnInfosByTableName("wt_yskzjjs"); | |
| 77 | + var names = cols.Select(c => c.DbColumnName.ToLowerInvariant()).ToHashSet(); | |
| 78 | + if (!names.Contains("djzt")) | |
| 79 | + _db.Ado.ExecuteCommand("ALTER TABLE `wt_yskzjjs` ADD COLUMN `djzt` varchar(32) NULL COMMENT '单据状态'"); | |
| 80 | + if (!names.Contains("spbz")) | |
| 81 | + _db.Ado.ExecuteCommand("ALTER TABLE `wt_yskzjjs` ADD COLUMN `spbz` text NULL COMMENT '审批备注'"); | |
| 82 | + if (!names.Contains("shr")) | |
| 83 | + _db.Ado.ExecuteCommand("ALTER TABLE `wt_yskzjjs` ADD COLUMN `shr` varchar(64) NULL COMMENT '审核人'"); | |
| 84 | + if (!names.Contains("shr1")) | |
| 85 | + _db.Ado.ExecuteCommand("ALTER TABLE `wt_yskzjjs` ADD COLUMN `shr1` varchar(500) NULL COMMENT '一级审核人'"); | |
| 86 | + if (!names.Contains("shr2")) | |
| 87 | + _db.Ado.ExecuteCommand("ALTER TABLE `wt_yskzjjs` ADD COLUMN `shr2` varchar(500) NULL COMMENT '二级审核人'"); | |
| 88 | + } | |
| 89 | + catch (Exception ex) | |
| 90 | + { | |
| 91 | + Console.WriteLine($"EnsureYskzjjsAuditColumns: {ex.Message}"); | |
| 92 | + } | |
| 93 | + _yskAuditColsEnsured = true; | |
| 94 | + } | |
| 95 | + } | |
| 96 | + | |
| 97 | + /// <summary> | |
| 63 | 98 | /// 获取应收款增加减少 |
| 64 | 99 | /// </summary> |
| 65 | 100 | /// <param name="id">参数</param> |
| ... | ... | @@ -67,12 +102,14 @@ namespace NCC.Extend.WtYskzjjs |
| 67 | 102 | [HttpGet("{id}")] |
| 68 | 103 | public async Task<dynamic> GetInfo(string id) |
| 69 | 104 | { |
| 105 | + EnsureYskzjjsAuditColumns(); | |
| 70 | 106 | var entity = await _db.Queryable<WtYskzjjsEntity>().FirstAsync(p => p.Id == id); |
| 71 | 107 | var output = entity.Adapt<WtYskzjjsInfoOutput>(); |
| 72 | 108 | |
| 73 | 109 | var wtYskzjjsMxList = await _db.Queryable<WtYskzjjsMxEntity>().Where(w => w.Djbh == entity.Id).ToListAsync(); |
| 74 | 110 | output.wtYskzjjsMxList = wtYskzjjsMxList.Adapt<List<WtYskzjjsMxInfoOutput>>(); |
| 75 | 111 | output.billZy = await _billSummaryService.ComputeWtYskzjjsZyByBillIdAsync(entity.Id); |
| 112 | + output.wldwmc = await ResolveWldwMcAsync(output.wldw); | |
| 76 | 113 | return output; |
| 77 | 114 | } |
| 78 | 115 | |
| ... | ... | @@ -84,6 +121,7 @@ namespace NCC.Extend.WtYskzjjs |
| 84 | 121 | [HttpGet("")] |
| 85 | 122 | public async Task<dynamic> GetList([FromQuery] WtYskzjjsListQueryInput input) |
| 86 | 123 | { |
| 124 | + EnsureYskzjjsAuditColumns(); | |
| 87 | 125 | var sidx = input.sidx == null ? "id" : input.sidx; |
| 88 | 126 | List<string> queryDjrq = input.djrq != null ? input.djrq.Split(',').ToObeject<List<string>>() : null; |
| 89 | 127 | DateTime? startDjrq = queryDjrq != null ? Ext.GetDateTime(queryDjrq.First()) : null; |
| ... | ... | @@ -113,6 +151,10 @@ namespace NCC.Extend.WtYskzjjs |
| 113 | 151 | djrq = d.Djrq, |
| 114 | 152 | jsr = d.Jsr, |
| 115 | 153 | djzt = d.Djzt, |
| 154 | + spbz = d.Spbz, | |
| 155 | + shr = d.Shr, | |
| 156 | + shr1 = d.Shr1, | |
| 157 | + shr2 = d.Shr2, | |
| 116 | 158 | dyddh = d.Dyddh, |
| 117 | 159 | hysjh = d.Hysjh, |
| 118 | 160 | fkzh = d.Fkzh, |
| ... | ... | @@ -132,6 +174,10 @@ namespace NCC.Extend.WtYskzjjs |
| 132 | 174 | djrq = it.djrq, |
| 133 | 175 | jsr = it.jsr, |
| 134 | 176 | djzt = it.djzt, |
| 177 | + spbz = it.spbz, | |
| 178 | + shr = it.shr, | |
| 179 | + shr1 = it.shr1, | |
| 180 | + shr2 = it.shr2, | |
| 135 | 181 | dyddh = it.dyddh, |
| 136 | 182 | hysjh = it.hysjh, |
| 137 | 183 | fkzh = it.fkzh, |
| ... | ... | @@ -158,9 +204,12 @@ namespace NCC.Extend.WtYskzjjs |
| 158 | 204 | [HttpPost("")] |
| 159 | 205 | public async Task Create([FromBody] WtYskzjjsCrInput input) |
| 160 | 206 | { |
| 207 | + EnsureYskzjjsAuditColumns(); | |
| 161 | 208 | var userInfo = await _userManager.GetUserInfo(); |
| 162 | 209 | NormalizeDjlxForQt(input); |
| 163 | 210 | NormalizeDjlxForTransfer(input); |
| 211 | + SyncMxKhFromWldw(input); | |
| 212 | + ThrowIfInvalidForSubmit(input, input?.djzt); | |
| 164 | 213 | var entity = input.Adapt<WtYskzjjsEntity>(); |
| 165 | 214 | entity.Id = await BuildCreateBillId(input); |
| 166 | 215 | try |
| ... | ... | @@ -264,6 +313,10 @@ namespace NCC.Extend.WtYskzjjs |
| 264 | 313 | djrq = d.Djrq, |
| 265 | 314 | jsr = d.Jsr, |
| 266 | 315 | djzt = d.Djzt, |
| 316 | + spbz = d.Spbz, | |
| 317 | + shr = d.Shr, | |
| 318 | + shr1 = d.Shr1, | |
| 319 | + shr2 = d.Shr2, | |
| 267 | 320 | dyddh = d.Dyddh, |
| 268 | 321 | hysjh = d.Hysjh, |
| 269 | 322 | fkzh = d.Fkzh, |
| ... | ... | @@ -283,6 +336,10 @@ namespace NCC.Extend.WtYskzjjs |
| 283 | 336 | djrq = it.djrq, |
| 284 | 337 | jsr = it.jsr, |
| 285 | 338 | djzt = it.djzt, |
| 339 | + spbz = it.spbz, | |
| 340 | + shr = it.shr, | |
| 341 | + shr1 = it.shr1, | |
| 342 | + shr2 = it.shr2, | |
| 286 | 343 | dyddh = it.dyddh, |
| 287 | 344 | hysjh = it.hysjh, |
| 288 | 345 | fkzh = it.fkzh, |
| ... | ... | @@ -389,8 +446,11 @@ namespace NCC.Extend.WtYskzjjs |
| 389 | 446 | [HttpPut("{id}")] |
| 390 | 447 | public async Task Update(string id, [FromBody] WtYskzjjsUpInput input) |
| 391 | 448 | { |
| 449 | + EnsureYskzjjsAuditColumns(); | |
| 392 | 450 | NormalizeDjlxForQt(input); |
| 393 | 451 | NormalizeDjlxForTransfer(input); |
| 452 | + SyncMxKhFromWldw(input); | |
| 453 | + ThrowIfInvalidForSubmit(input, input?.djzt); | |
| 394 | 454 | var entity = input.Adapt<WtYskzjjsEntity>(); |
| 395 | 455 | try |
| 396 | 456 | { |
| ... | ... | @@ -461,7 +521,7 @@ namespace NCC.Extend.WtYskzjjs |
| 461 | 521 | } |
| 462 | 522 | |
| 463 | 523 | /// <summary> |
| 464 | - /// 兼容 qt 页面对 djlx 的历史传值:当明细为“其他收入单”时统一落库为“其他应收款”。 | |
| 524 | + /// 兼容 qt 页面对 djlx 的历史传值:当明细为“其他收入单”时统一落库为“其他应收单”。 | |
| 465 | 525 | /// 仅修正 qt 场景,不影响其它单据类型。 |
| 466 | 526 | /// </summary> |
| 467 | 527 | /// <param name="input">新增/更新入参</param> |
| ... | ... | @@ -478,9 +538,10 @@ namespace NCC.Extend.WtYskzjjs |
| 478 | 538 | |
| 479 | 539 | if (string.IsNullOrWhiteSpace(input.djlx) || |
| 480 | 540 | input.djlx.Trim().Equals("应收款减少", StringComparison.Ordinal) || |
| 481 | - input.djlx.Trim().Equals("其他收入单", StringComparison.Ordinal)) | |
| 541 | + input.djlx.Trim().Equals("其他收入单", StringComparison.Ordinal) || | |
| 542 | + input.djlx.Trim().Equals("其他应收款", StringComparison.Ordinal)) | |
| 482 | 543 | { |
| 483 | - input.djlx = "其他应收款"; | |
| 544 | + input.djlx = "其他应收单"; | |
| 484 | 545 | } |
| 485 | 546 | } |
| 486 | 547 | |
| ... | ... | @@ -598,5 +659,326 @@ namespace NCC.Extend.WtYskzjjs |
| 598 | 659 | |
| 599 | 660 | await _billSummaryService.EnrichWtYskzjjsListBillZyAsync(rowList); |
| 600 | 661 | } |
| 662 | + | |
| 663 | + /// <summary> | |
| 664 | + /// 主表往来单位写入明细客户字段,便于列表按 kh 筛选与详情列展示。 | |
| 665 | + /// </summary> | |
| 666 | + private static void SyncMxKhFromWldw(WtYskzjjsCrInput input) | |
| 667 | + { | |
| 668 | + if (input == null || string.IsNullOrWhiteSpace(input.wldw) || input.wtYskzjjsMxList == null) | |
| 669 | + return; | |
| 670 | + var w = input.wldw.Trim(); | |
| 671 | + foreach (var mx in input.wtYskzjjsMxList.Where(m => m != null)) | |
| 672 | + { | |
| 673 | + if (string.IsNullOrWhiteSpace(mx.kh)) | |
| 674 | + mx.kh = w; | |
| 675 | + } | |
| 676 | + } | |
| 677 | + | |
| 678 | + private async Task<string> ResolveWldwMcAsync(string wldwId) | |
| 679 | + { | |
| 680 | + if (string.IsNullOrWhiteSpace(wldwId)) | |
| 681 | + return "无"; | |
| 682 | + var dwmc = (await _db.Queryable<WtWldwEntity>().Where(x => x.Id == wldwId).Select(x => x.Dwmc).ToListAsync()).FirstOrDefault(); | |
| 683 | + if (!string.IsNullOrWhiteSpace(dwmc)) | |
| 684 | + return dwmc; | |
| 685 | + var xm = (await _db.Queryable<WtHyEntity>().Where(x => x.Id == wldwId).Select(x => x.Xm).ToListAsync()).FirstOrDefault(); | |
| 686 | + if (!string.IsNullOrWhiteSpace(xm)) | |
| 687 | + return xm; | |
| 688 | + var gysmc = (await _db.Queryable<WtGysEntity>().Where(x => x.Id == wldwId).Select(x => x.Gysmc).ToListAsync()).FirstOrDefault(); | |
| 689 | + if (!string.IsNullOrWhiteSpace(gysmc)) | |
| 690 | + return gysmc; | |
| 691 | + return "无"; | |
| 692 | + } | |
| 693 | + | |
| 694 | + private static void AppendApprovalSpbzLineYsk(WtYskzjjsEntity entity, string actionTag, string remark) | |
| 695 | + { | |
| 696 | + var r = (remark ?? "").Trim(); | |
| 697 | + if (string.IsNullOrEmpty(r)) return; | |
| 698 | + var line = string.IsNullOrEmpty(actionTag) ? r : $"[{actionTag}] {r}"; | |
| 699 | + var existing = entity.Spbz?.TrimEnd() ?? ""; | |
| 700 | + entity.Spbz = string.IsNullOrWhiteSpace(existing) ? line : existing + "\n" + line; | |
| 701 | + } | |
| 702 | + | |
| 703 | + private static bool IsUserInAuditConfigYsk(string configValue, string userId, string userAccount = null) | |
| 704 | + { | |
| 705 | + if (string.IsNullOrWhiteSpace(configValue)) | |
| 706 | + return false; | |
| 707 | + if (string.IsNullOrWhiteSpace(userId) && string.IsNullOrWhiteSpace(userAccount)) | |
| 708 | + return false; | |
| 709 | + | |
| 710 | + var users = configValue | |
| 711 | + .Split(new[] { ',', ',', ';', ';', '|', ' ' }, StringSplitOptions.RemoveEmptyEntries) | |
| 712 | + .Select(x => x.Trim()) | |
| 713 | + .Where(x => !string.IsNullOrEmpty(x)) | |
| 714 | + .ToList(); | |
| 715 | + | |
| 716 | + return users.Any(x => | |
| 717 | + (!string.IsNullOrWhiteSpace(userId) && string.Equals(x, userId.Trim(), StringComparison.OrdinalIgnoreCase)) | |
| 718 | + || (!string.IsNullOrWhiteSpace(userAccount) && string.Equals(x, userAccount.Trim(), StringComparison.OrdinalIgnoreCase))); | |
| 719 | + } | |
| 720 | + | |
| 721 | + /// <summary> | |
| 722 | + /// 提交审核:草稿 / 空 / 审核不通过 → 待审核 | |
| 723 | + /// </summary> | |
| 724 | + [HttpPost("Actions/SubmitForAudit/{id}")] | |
| 725 | + public async Task<dynamic> SubmitForAudit(string id) | |
| 726 | + { | |
| 727 | + EnsureYskzjjsAuditColumns(); | |
| 728 | + var entity = await _db.Queryable<WtYskzjjsEntity>().FirstAsync(p => p.Id == id); | |
| 729 | + if (entity == null) | |
| 730 | + return new { success = false, message = "单据不存在" }; | |
| 731 | + var z = entity.Djzt?.Trim() ?? ""; | |
| 732 | + if (z != "草稿" && z != "审核不通过" && !string.IsNullOrEmpty(z)) | |
| 733 | + return new { success = false, message = $"当前状态「{entity.Djzt}」不可提交审核" }; | |
| 734 | + | |
| 735 | + // 提交审核前做必填校验(备注除外) | |
| 736 | + var mxList = await _db.Queryable<WtYskzjjsMxEntity>().Where(x => x.Djbh == entity.Id).ToListAsync(); | |
| 737 | + var inputLike = new WtYskzjjsCrInput | |
| 738 | + { | |
| 739 | + id = entity.Id, | |
| 740 | + djlx = entity.Djlx, | |
| 741 | + djrq = entity.Djrq, | |
| 742 | + jsr = entity.Jsr, | |
| 743 | + wldw = entity.Wldw, | |
| 744 | + djzt = "待审核", | |
| 745 | + fkzh = entity.Fkzh, | |
| 746 | + fkje = entity.Fkje, | |
| 747 | + skzh = entity.Skzh, | |
| 748 | + skje = entity.Skje, | |
| 749 | + zy = entity.Zy, | |
| 750 | + wtYskzjjsMxList = mxList?.Select(m => new WtYskzjjsMxCrInput | |
| 751 | + { | |
| 752 | + srxmmc = m.Srxmmc, | |
| 753 | + je = m.Je, | |
| 754 | + bz = m.Bz, | |
| 755 | + mxlx = m.Mxlx, | |
| 756 | + kh = m.Kh, | |
| 757 | + zhbh = m.Zhbh | |
| 758 | + }).ToList() | |
| 759 | + }; | |
| 760 | + try | |
| 761 | + { | |
| 762 | + ThrowIfInvalidForSubmit(inputLike, "待审核"); | |
| 763 | + } | |
| 764 | + catch (Exception ex) | |
| 765 | + { | |
| 766 | + return new { success = false, message = ex.Message }; | |
| 767 | + } | |
| 768 | + | |
| 769 | + entity.Djzt = "待审核"; | |
| 770 | + await _db.Updateable(entity).UpdateColumns(x => new { x.Djzt }).ExecuteCommandAsync(); | |
| 771 | + return new { success = true, message = "已提交审核" }; | |
| 772 | + } | |
| 773 | + | |
| 774 | + /// <summary> | |
| 775 | + /// 除备注外必填:仅在提交审核/非草稿状态强制校验;草稿可放宽。 | |
| 776 | + /// </summary> | |
| 777 | + private static void ThrowIfInvalidForSubmit(WtYskzjjsCrInput input, string djzt) | |
| 778 | + { | |
| 779 | + if (input == null) throw NCCException.Oh("参数不能为空"); | |
| 780 | + var z = (djzt ?? input.djzt ?? "").Trim(); | |
| 781 | + if (string.IsNullOrEmpty(z) || z == "草稿") return; | |
| 782 | + | |
| 783 | + if (input.djrq == null) throw NCCException.Oh("请选择单据日期"); | |
| 784 | + if (string.IsNullOrWhiteSpace(input.jsr)) throw NCCException.Oh("请选择经手人"); | |
| 785 | + if (string.IsNullOrWhiteSpace(input.wldw)) throw NCCException.Oh("请选择往来单位"); | |
| 786 | + if (string.IsNullOrWhiteSpace(input.skzh)) throw NCCException.Oh("请选择收款账户"); | |
| 787 | + if (input.skje <= 0) throw NCCException.Oh("请填写明细金额,收款金额须大于 0"); | |
| 788 | + if (input.wtYskzjjsMxList == null || input.wtYskzjjsMxList.Count == 0) throw NCCException.Oh("请至少添加一条明细"); | |
| 789 | + | |
| 790 | + for (var i = 0; i < input.wtYskzjjsMxList.Count; i++) | |
| 791 | + { | |
| 792 | + var row = input.wtYskzjjsMxList[i]; | |
| 793 | + if (row == null) throw NCCException.Oh($"第 {i + 1} 行明细不能为空"); | |
| 794 | + if (string.IsNullOrWhiteSpace(row.srxmmc)) throw NCCException.Oh($"第 {i + 1} 行收入项目为必填"); | |
| 795 | + if (row.je <= 0) throw NCCException.Oh($"第 {i + 1} 行原币金额为必填且须大于 0"); | |
| 796 | + } | |
| 797 | + } | |
| 798 | + | |
| 799 | + /// <summary> | |
| 800 | + /// 撤回:待审核或一级已审 → 草稿 | |
| 801 | + /// </summary> | |
| 802 | + [HttpPost("Actions/WithdrawAudit/{id}")] | |
| 803 | + public async Task<dynamic> WithdrawAudit(string id) | |
| 804 | + { | |
| 805 | + EnsureYskzjjsAuditColumns(); | |
| 806 | + var entity = await _db.Queryable<WtYskzjjsEntity>().FirstAsync(p => p.Id == id); | |
| 807 | + if (entity == null) | |
| 808 | + return new { success = false, message = "单据不存在" }; | |
| 809 | + var z = entity.Djzt?.Trim() ?? ""; | |
| 810 | + if (z != "待审核" && z != "一级已审" && z != "待二级" && z != "一级已审/待二级") | |
| 811 | + return new { success = false, message = $"当前状态「{entity.Djzt}」不可撤回" }; | |
| 812 | + | |
| 813 | + entity.Djzt = "草稿"; | |
| 814 | + entity.Shr1 = null; | |
| 815 | + entity.Shr2 = null; | |
| 816 | + await _db.Updateable(entity).UpdateColumns(x => new { x.Djzt, x.Shr1, x.Shr2 }).ExecuteCommandAsync(); | |
| 817 | + return new { success = true, message = "已撤回为草稿" }; | |
| 818 | + } | |
| 819 | + | |
| 820 | + /// <summary> | |
| 821 | + /// 审核通过(按 <c>wt_shrysz.djmc</c> 与主表 <c>djlx</c> 匹配,支持一级/两级) | |
| 822 | + /// </summary> | |
| 823 | + [HttpPost("Actions/Approve/{id}")] | |
| 824 | + public async Task<dynamic> Approve(string id, [FromBody] WtApprovalRemarkInput input = null) | |
| 825 | + { | |
| 826 | + EnsureYskzjjsAuditColumns(); | |
| 827 | + return await ApproveYskzjjsDocumentAsync(id, input?.remark); | |
| 828 | + } | |
| 829 | + | |
| 830 | + /// <summary> | |
| 831 | + /// 审核不通过(审批备注写入 <c>spbz</c>) | |
| 832 | + /// </summary> | |
| 833 | + [HttpPost("Actions/Reject/{id}")] | |
| 834 | + public async Task<dynamic> Reject(string id, [FromBody] WtApprovalRemarkInput input = null) | |
| 835 | + { | |
| 836 | + EnsureYskzjjsAuditColumns(); | |
| 837 | + return await RejectYskzjjsDocumentAsync(id, input?.remark); | |
| 838 | + } | |
| 839 | + | |
| 840 | + private async Task<dynamic> ApproveYskzjjsDocumentAsync(string id, string approvalRemark) | |
| 841 | + { | |
| 842 | + try | |
| 843 | + { | |
| 844 | + _db.BeginTran(); | |
| 845 | + var entity = await _db.Queryable<WtYskzjjsEntity>().Where(x => x.Id == id).FirstAsync(); | |
| 846 | + if (entity == null) | |
| 847 | + { | |
| 848 | + _db.RollbackTran(); | |
| 849 | + return new { success = false, message = "单据不存在" }; | |
| 850 | + } | |
| 851 | + | |
| 852 | + if (entity.Djzt == "已审核") | |
| 853 | + { | |
| 854 | + _db.RollbackTran(); | |
| 855 | + return new { success = false, message = "该单据已经审核,无需重复审核" }; | |
| 856 | + } | |
| 857 | + | |
| 858 | + var userInfo = await _userManager.GetUserInfo(); | |
| 859 | + var userId = userInfo?.userId ?? ""; | |
| 860 | + var userAccount = userInfo?.userAccount?.Trim(); | |
| 861 | + if (string.IsNullOrEmpty(userAccount)) | |
| 862 | + userAccount = _userManager.Account?.Trim(); | |
| 863 | + | |
| 864 | + var djmc = entity.Djlx?.Trim() ?? ""; | |
| 865 | + var approvalConfig = await _db.Queryable<WtShryszEntity>() | |
| 866 | + .Where(c => c.Djmc == djmc) | |
| 867 | + .FirstAsync(); | |
| 868 | + | |
| 869 | + var configShr1 = approvalConfig?.Shr1; | |
| 870 | + var configShr2 = approvalConfig?.Shr2; | |
| 871 | + var hasTwoLevel = !string.IsNullOrEmpty(configShr1) && !string.IsNullOrEmpty(configShr2); | |
| 872 | + | |
| 873 | + if (entity.Djzt == "待审核" || string.IsNullOrEmpty(entity.Djzt)) | |
| 874 | + { | |
| 875 | + if (hasTwoLevel) | |
| 876 | + { | |
| 877 | + entity.Djzt = "一级已审"; | |
| 878 | + entity.Shr1 = userId; | |
| 879 | + AppendApprovalSpbzLineYsk(entity, "一级通过", approvalRemark); | |
| 880 | + await _db.Updateable(entity).UpdateColumns(x => new { x.Djzt, x.Shr1, x.Spbz }).ExecuteCommandAsync(); | |
| 881 | + _db.CommitTran(); | |
| 882 | + return new { success = true, message = "一级审核通过,等待二级审核" }; | |
| 883 | + } | |
| 884 | + | |
| 885 | + entity.Djzt = "已审核"; | |
| 886 | + entity.Shr = userId; | |
| 887 | + entity.Shr1 = userId; | |
| 888 | + AppendApprovalSpbzLineYsk(entity, "审核通过", approvalRemark); | |
| 889 | + await _db.Updateable(entity).UpdateColumns(x => new { x.Djzt, x.Shr, x.Shr1, x.Spbz }).ExecuteCommandAsync(); | |
| 890 | + _db.CommitTran(); | |
| 891 | + return new { success = true, message = "审核通过" }; | |
| 892 | + } | |
| 893 | + | |
| 894 | + if (entity.Djzt == "一级已审" || entity.Djzt == "一级已审/待二级" || entity.Djzt == "待二级") | |
| 895 | + { | |
| 896 | + if (!hasTwoLevel) | |
| 897 | + { | |
| 898 | + _db.RollbackTran(); | |
| 899 | + return new { success = false, message = "未配置两级审核,当前状态不允许二级操作" }; | |
| 900 | + } | |
| 901 | + if (string.IsNullOrWhiteSpace(configShr2)) | |
| 902 | + { | |
| 903 | + _db.RollbackTran(); | |
| 904 | + return new { success = false, message = "未配置二级审核人员" }; | |
| 905 | + } | |
| 906 | + if (!IsUserInAuditConfigYsk(configShr2, userId, userAccount)) | |
| 907 | + { | |
| 908 | + _db.RollbackTran(); | |
| 909 | + return new { success = false, message = "当前用户不在二级审核人员范围内" }; | |
| 910 | + } | |
| 911 | + | |
| 912 | + entity.Djzt = "已审核"; | |
| 913 | + entity.Shr2 = userId; | |
| 914 | + entity.Shr = userId; | |
| 915 | + AppendApprovalSpbzLineYsk(entity, "二级通过", approvalRemark); | |
| 916 | + await _db.Updateable(entity).UpdateColumns(x => new { x.Djzt, x.Shr, x.Shr2, x.Spbz }).ExecuteCommandAsync(); | |
| 917 | + _db.CommitTran(); | |
| 918 | + return new { success = true, message = "二级审核通过,审核完成" }; | |
| 919 | + } | |
| 920 | + | |
| 921 | + _db.RollbackTran(); | |
| 922 | + return new { success = false, message = $"当前单据状态「{entity.Djzt}」不允许审核" }; | |
| 923 | + } | |
| 924 | + catch (Exception ex) | |
| 925 | + { | |
| 926 | + _db.RollbackTran(); | |
| 927 | + return new { success = false, message = $"审核失败: {ex.Message}" }; | |
| 928 | + } | |
| 929 | + } | |
| 930 | + | |
| 931 | + private async Task<dynamic> RejectYskzjjsDocumentAsync(string id, string approvalRemark) | |
| 932 | + { | |
| 933 | + try | |
| 934 | + { | |
| 935 | + _db.BeginTran(); | |
| 936 | + var entity = await _db.Queryable<WtYskzjjsEntity>().Where(x => x.Id == id).FirstAsync(); | |
| 937 | + if (entity == null) | |
| 938 | + { | |
| 939 | + _db.RollbackTran(); | |
| 940 | + return new { success = false, message = "单据不存在" }; | |
| 941 | + } | |
| 942 | + | |
| 943 | + if (entity.Djzt == "已审核") | |
| 944 | + { | |
| 945 | + _db.RollbackTran(); | |
| 946 | + return new { success = false, message = "该单据已审核通过" }; | |
| 947 | + } | |
| 948 | + | |
| 949 | + if (entity.Djzt == "审核不通过") | |
| 950 | + { | |
| 951 | + _db.RollbackTran(); | |
| 952 | + return new { success = false, message = "该单据已是审核不通过状态" }; | |
| 953 | + } | |
| 954 | + | |
| 955 | + if (entity.Djzt == "草稿") | |
| 956 | + { | |
| 957 | + _db.RollbackTran(); | |
| 958 | + return new { success = false, message = "草稿状态请直接修改或删除单据" }; | |
| 959 | + } | |
| 960 | + | |
| 961 | + var djztTrim = entity.Djzt?.Trim() ?? ""; | |
| 962 | + var level1 = djztTrim == "待审核" || string.IsNullOrEmpty(djztTrim); | |
| 963 | + var level2 = entity.Djzt == "一级已审" || entity.Djzt == "待二级" || entity.Djzt == "一级已审/待二级"; | |
| 964 | + | |
| 965 | + if (!level1 && !level2) | |
| 966 | + { | |
| 967 | + _db.RollbackTran(); | |
| 968 | + return new { success = false, message = $"当前单据状态「{entity.Djzt}」不允许审核不通过" }; | |
| 969 | + } | |
| 970 | + | |
| 971 | + entity.Djzt = "审核不通过"; | |
| 972 | + AppendApprovalSpbzLineYsk(entity, "审核不通过", approvalRemark); | |
| 973 | + await _db.Updateable(entity).UpdateColumns(x => new { x.Djzt, x.Spbz }).ExecuteCommandAsync(); | |
| 974 | + _db.CommitTran(); | |
| 975 | + return new { success = true, message = "已标记审核不通过" }; | |
| 976 | + } | |
| 977 | + catch (Exception ex) | |
| 978 | + { | |
| 979 | + _db.RollbackTran(); | |
| 980 | + return new { success = false, message = $"操作失败: {ex.Message}" }; | |
| 981 | + } | |
| 982 | + } | |
| 601 | 983 | } |
| 602 | 984 | } | ... | ... |
Antis.Erp.Plat/netcore/src/Modularity/OAuth/NCC.OAuth/Service/OAuthService.cs
| ... | ... | @@ -148,7 +148,11 @@ namespace NCC.OAuth.Service |
| 148 | 148 | bool isMoble = false; |
| 149 | 149 | if (input.account == user.MobilePhone) isMoble = true; |
| 150 | 150 | //获取加密后的密码 |
| 151 | - var encryptPasswod = MD5Encryption.Encrypt(input.password + user.Secretkey); | |
| 151 | + var pwd = (input.password ?? "").Trim(); | |
| 152 | + // 兼容:前端既可能传 MD5(明文),也可能直接传明文(如收银台)。 | |
| 153 | + // 系统入库口径为:MD5(MD5(明文) + Secretkey) | |
| 154 | + var md5Once = NormalizePasswordToMd5Once(pwd); | |
| 155 | + var encryptPasswod = MD5Encryption.Encrypt(md5Once + user.Secretkey); | |
| 152 | 156 | |
| 153 | 157 | var userAnyPwd = await _userService.GetInfoByLogin(input.account, encryptPasswod, isMoble); |
| 154 | 158 | _ = userAnyPwd ?? throw NCCException.Oh(ErrorCode.D1000); |
| ... | ... | @@ -597,7 +601,9 @@ namespace NCC.OAuth.Service |
| 597 | 601 | var secretkey = (await _userService.GetInfoByAccount(input.account)).Secretkey; |
| 598 | 602 | |
| 599 | 603 | //获取加密后的密码 |
| 600 | - var encryptPasswod = MD5Encryption.Encrypt(input.password + secretkey); | |
| 604 | + var pwd = (input.password ?? "").Trim(); | |
| 605 | + var md5Once = NormalizePasswordToMd5Once(pwd); | |
| 606 | + var encryptPasswod = MD5Encryption.Encrypt(md5Once + secretkey); | |
| 601 | 607 | |
| 602 | 608 | bool isMoble = false; |
| 603 | 609 | if (input.account == users.MobilePhone) isMoble = true; |
| ... | ... | @@ -606,6 +612,25 @@ namespace NCC.OAuth.Service |
| 606 | 612 | _ = user ?? throw NCCException.Oh(ErrorCode.D1000); |
| 607 | 613 | } |
| 608 | 614 | |
| 615 | + private static bool LooksLikeMd5(string s) | |
| 616 | + { | |
| 617 | + if (string.IsNullOrEmpty(s) || s.Length != 32) return false; | |
| 618 | + foreach (var ch in s) | |
| 619 | + { | |
| 620 | + var isHex = (ch >= '0' && ch <= '9') | |
| 621 | + || (ch >= 'a' && ch <= 'f') | |
| 622 | + || (ch >= 'A' && ch <= 'F'); | |
| 623 | + if (!isHex) return false; | |
| 624 | + } | |
| 625 | + return true; | |
| 626 | + } | |
| 627 | + | |
| 628 | + private static string NormalizePasswordToMd5Once(string passwordOrMd5) | |
| 629 | + { | |
| 630 | + var p = (passwordOrMd5 ?? "").Trim(); | |
| 631 | + return LooksLikeMd5(p) ? p : MD5Encryption.Encrypt(p); | |
| 632 | + } | |
| 633 | + | |
| 609 | 634 | /// <summary> |
| 610 | 635 | /// 获取当前登录用户信息 |
| 611 | 636 | /// </summary> | ... | ... |
Antis.Erp.Plat/netcore/src/Modularity/System/NCC.System.Entitys/Dto/Permission/User/UserCrInput.cs
| ... | ... | @@ -133,8 +133,16 @@ namespace NCC.System.Entitys.Dto.Permission.User |
| 133 | 133 | /// 排序 |
| 134 | 134 | /// </summary> |
| 135 | 135 | public long? sortCode { get; set; } |
| 136 | - | |
| 137 | - | |
| 136 | + | |
| 137 | + /// <summary> | |
| 138 | + /// 初始密码(明文,可选)。为空或未传时仍按系统默认密码规则生成(与历史行为一致)。 | |
| 139 | + /// </summary> | |
| 140 | + /// <remarks> | |
| 141 | + /// 非空时按与登录校验一致的口径入库:MD5(MD5(明文) + 用户 Secretkey)。 | |
| 142 | + /// (登录请求中的 password 通常为 MD5(明文),服务端再拼接 Secretkey 后做最终 MD5) | |
| 143 | + /// </remarks> | |
| 144 | + public string password { get; set; } | |
| 145 | + | |
| 138 | 146 | /// <summary> |
| 139 | 147 | /// 门店信息 |
| 140 | 148 | /// </summary> | ... | ... |
Antis.Erp.Plat/netcore/src/Modularity/System/NCC.System/Service/Permission/UsersService.cs
| ... | ... | @@ -262,10 +262,31 @@ namespace NCC.System.Service.Permission |
| 262 | 262 | } |
| 263 | 263 | |
| 264 | 264 | /// <summary> |
| 265 | - /// 新建 | |
| 265 | + /// 新建用户 | |
| 266 | 266 | /// </summary> |
| 267 | - /// <param name="input">参数</param> | |
| 268 | - /// <returns></returns> | |
| 267 | + /// <remarks> | |
| 268 | + /// 可选传入 <c>password</c>(明文)。非空时按与「重置密码」相同的规则写入库,便于新建用户后直接以明文登录; | |
| 269 | + /// 未传或为空时仍使用系统默认密码哈希(兼容旧前端)。 | |
| 270 | + /// | |
| 271 | + /// 示例请求: | |
| 272 | + /// ```json | |
| 273 | + /// { | |
| 274 | + /// "account": "zhangsan", | |
| 275 | + /// "password": "PlainTextPwd", | |
| 276 | + /// "realName": "张三", | |
| 277 | + /// "organizeId": "orgId", | |
| 278 | + /// "headIcon": "/api/file/Image/userAvatar/001.png" | |
| 279 | + /// } | |
| 280 | + /// ``` | |
| 281 | + /// | |
| 282 | + /// 参数说明: | |
| 283 | + /// - password: 可选,非空时为初始明文密码 | |
| 284 | + /// </remarks> | |
| 285 | + /// <param name="input">创建用户参数</param> | |
| 286 | + /// <returns>无返回体,成功即完成创建</returns> | |
| 287 | + /// <response code="200">创建成功</response> | |
| 288 | + /// <response code="400">参数或业务校验失败</response> | |
| 289 | + /// <response code="500">服务器内部错误</response> | |
| 269 | 290 | [HttpPost("")] |
| 270 | 291 | public async Task Create([FromBody] UserCrInput input) |
| 271 | 292 | { |
| ... | ... | @@ -294,7 +315,12 @@ namespace NCC.System.Service.Permission |
| 294 | 315 | entity.Birthday = input.birthday.IsNullOrEmpty() ? DateTime.Now : Ext.GetDateTime(input.birthday.ToString()); |
| 295 | 316 | entity.QuickQuery = PinyinUtil.PinyinString(input.realName); |
| 296 | 317 | entity.Secretkey = Guid.NewGuid().ToString(); |
| 297 | - entity.Password = MD5Encryption.Encrypt(MD5Encryption.Encrypt(CommonConst.DEFAULT_PASSWORD) + entity.Secretkey); | |
| 318 | + if (string.IsNullOrWhiteSpace(input.password)) | |
| 319 | + { | |
| 320 | + throw NCCException.Oh("请输入密码"); | |
| 321 | + } | |
| 322 | + entity.Password = HashPasswordForStorage(input.password.Trim(), entity.Secretkey); | |
| 323 | + | |
| 298 | 324 | entity.Mdxx = input.mdxx; |
| 299 | 325 | var headIcon = input.headIcon.Split('/').ToList().Last(); |
| 300 | 326 | if (string.IsNullOrEmpty(headIcon)) |
| ... | ... | @@ -680,7 +706,7 @@ namespace NCC.System.Service.Permission |
| 680 | 706 | |
| 681 | 707 | _ = entity ?? throw NCCException.Oh(ErrorCode.D1002); |
| 682 | 708 | |
| 683 | - var password = MD5Encryption.Encrypt(input.userPassword + entity.Secretkey); | |
| 709 | + var password = HashPasswordForStorage(input.userPassword, entity.Secretkey); | |
| 684 | 710 | |
| 685 | 711 | var isOk = await _userRepository.Context.Updateable<UserEntity>().SetColumns(it => new UserEntity() |
| 686 | 712 | { |
| ... | ... | @@ -798,7 +824,9 @@ namespace NCC.System.Service.Permission |
| 798 | 824 | [NonAction] |
| 799 | 825 | public async Task<UserEntity> GetInfoByAccount(string account) |
| 800 | 826 | { |
| 801 | - return await _userRepository.FirstOrDefaultAsync(u => u.Account == account || u.MobilePhone == account && u.DeleteMark == null); | |
| 827 | + // 注意:必须同时过滤 DeleteMark,否则同账号存在“已删除历史记录”时会取错 Secretkey,导致登录永远校验失败 | |
| 828 | + return await _userRepository.FirstOrDefaultAsync(u => | |
| 829 | + (u.Account == account || u.MobilePhone == account) && u.DeleteMark == null); | |
| 802 | 830 | } |
| 803 | 831 | |
| 804 | 832 | /// <summary> |
| ... | ... | @@ -930,6 +958,38 @@ namespace NCC.System.Service.Permission |
| 930 | 958 | var ids = PositionIds.Split(","); |
| 931 | 959 | return await _positionRepository.Entities.In(it => it.Id, ids).Select(it => new { id = it.Id, name = it.FullName }).MergeTable().Select<PositionInfo>().ToListAsync(); |
| 932 | 960 | } |
| 961 | + | |
| 962 | + /// <summary> | |
| 963 | + /// 用户密码入库哈希(与重置密码、个人修改密码、OAuth 登录一致)。 | |
| 964 | + /// </summary> | |
| 965 | + /// <param name="plainPassword">明文密码</param> | |
| 966 | + /// <param name="secretkey">用户秘钥</param> | |
| 967 | + /// <returns>可写入 <see cref="UserEntity.Password"/> 的哈希值</returns> | |
| 968 | + private static string HashPasswordForStorage(string passwordOrMd5, string secretkey) | |
| 969 | + { | |
| 970 | + // 系统密码入库口径(与 OAuth 登录一致): | |
| 971 | + // - 登录/改密/重置密码:前端通常传 MD5(明文),服务端再做 MD5(MD5值 + Secretkey) | |
| 972 | + // - 新建用户:本次新增支持传“明文 password”,这里自动先做一层 MD5,再按同口径入库 | |
| 973 | + var p = (passwordOrMd5 ?? "").Trim(); | |
| 974 | + if (string.IsNullOrEmpty(p)) return MD5Encryption.Encrypt(MD5Encryption.Encrypt(CommonConst.DEFAULT_PASSWORD) + secretkey); | |
| 975 | + | |
| 976 | + static bool LooksLikeMd5(string s) | |
| 977 | + { | |
| 978 | + if (s.Length != 32) return false; | |
| 979 | + foreach (var ch in s) | |
| 980 | + { | |
| 981 | + var isHex = (ch >= '0' && ch <= '9') | |
| 982 | + || (ch >= 'a' && ch <= 'f') | |
| 983 | + || (ch >= 'A' && ch <= 'F'); | |
| 984 | + if (!isHex) return false; | |
| 985 | + } | |
| 986 | + return true; | |
| 987 | + } | |
| 988 | + | |
| 989 | + var md5Once = LooksLikeMd5(p) ? p : MD5Encryption.Encrypt(p); | |
| 990 | + return MD5Encryption.Encrypt(md5Once + secretkey); | |
| 991 | + } | |
| 992 | + | |
| 933 | 993 | #endregion |
| 934 | 994 | } |
| 935 | 995 | } |
| 936 | 996 | \ No newline at end of file | ... | ... |
Antis.Erp.Plat/netcore/src/Modularity/VisualDev/NCC.VisualDev/DashboardService.cs
| ... | ... | @@ -26,6 +26,7 @@ namespace NCC.VisualDev |
| 26 | 26 | private readonly IUserManager _userManager; |
| 27 | 27 | private readonly IDictionaryDataService _dictionaryDataService; |
| 28 | 28 | private readonly SqlSugarScope _db; |
| 29 | + private static bool _wtFysrdAuditColsEnsured; | |
| 29 | 30 | |
| 30 | 31 | /// <summary> |
| 31 | 32 | /// 初始化一个<see cref="DashboardService"/>类型的新实例 |
| ... | ... | @@ -344,6 +345,8 @@ namespace NCC.VisualDev |
| 344 | 345 | /// </summary> |
| 345 | 346 | private async Task<List<FlowTodoOutput>> GetExtendBillTodoListAsync(string userId, string userAccount) |
| 346 | 347 | { |
| 348 | + EnsureWtFysrdAuditColumnsForTodo(); | |
| 349 | + EnsureWtYskzjjsAuditColumnsForTodo(); | |
| 347 | 350 | var list = new List<FlowTodoOutput>(); |
| 348 | 351 | list.AddRange(await QueryWtXsckdAuditTodosAsync("同价调拨单", userId, userAccount, null)); |
| 349 | 352 | // 仅单据来源为「后台」或未标记(ly 空)的销售出库单进待办;备注「抖音订单:」同后端免审规则 |
| ... | ... | @@ -361,12 +364,160 @@ namespace NCC.VisualDev |
| 361 | 364 | list.AddRange(await QueryWtXsckdAuditTodosAsync("委托代销退货单", userId, userAccount, null)); |
| 362 | 365 | list.AddRange(await QueryWtXsckdAuditTodosAsync("委托代销结算单", userId, userAccount, null)); |
| 363 | 366 | list.AddRange(await QueryWtTjdAuditTodosAsync(userId, userAccount)); |
| 367 | + list.AddRange(await QueryWtFysrdQtsrAuditTodosAsync(userId, userAccount)); | |
| 368 | + list.AddRange(await QueryWtYskzjjsQtAuditTodosAsync(userId, userAccount)); | |
| 364 | 369 | return list.OrderByDescending(x => x.creatorTime).ToList(); |
| 365 | 370 | } |
| 366 | 371 | |
| 372 | + /// <summary>与 <c>wt_shrysz.djmc</c>、<c>WtFysrdWorkflowHelper.BillName</c> 一致</summary> | |
| 373 | + private const string FysrdQtsrTodoBillName = "其他收入单"; | |
| 374 | + | |
| 375 | + /// <summary> | |
| 376 | + /// 待办 SQL 依赖列存在;与 Extend 内 <c>WtFysrdWorkflowHelper.EnsureFysrdAuditColumns</c> 保持一致 | |
| 377 | + /// </summary> | |
| 378 | + private void EnsureWtFysrdAuditColumnsForTodo() | |
| 379 | + { | |
| 380 | + if (_wtFysrdAuditColsEnsured) return; | |
| 381 | + lock (typeof(DashboardService)) | |
| 382 | + { | |
| 383 | + if (_wtFysrdAuditColsEnsured) return; | |
| 384 | + try | |
| 385 | + { | |
| 386 | + if (!_db.DbMaintenance.IsAnyTable("wt_fysrd")) { _wtFysrdAuditColsEnsured = true; return; } | |
| 387 | + var cols = _db.DbMaintenance.GetColumnInfosByTableName("wt_fysrd"); | |
| 388 | + var names = cols.Select(c => c.DbColumnName.ToLowerInvariant()).ToHashSet(); | |
| 389 | + if (!names.Contains("djzt")) | |
| 390 | + _db.Ado.ExecuteCommand( | |
| 391 | + "ALTER TABLE `wt_fysrd` ADD COLUMN `djzt` varchar(32) NULL COMMENT '单据状态'"); | |
| 392 | + if (!names.Contains("spbz")) | |
| 393 | + _db.Ado.ExecuteCommand( | |
| 394 | + "ALTER TABLE `wt_fysrd` ADD COLUMN `spbz` text NULL COMMENT '审批备注'"); | |
| 395 | + if (!names.Contains("shr")) | |
| 396 | + _db.Ado.ExecuteCommand( | |
| 397 | + "ALTER TABLE `wt_fysrd` ADD COLUMN `shr` varchar(64) NULL COMMENT '审核人'"); | |
| 398 | + if (!names.Contains("shr1")) | |
| 399 | + _db.Ado.ExecuteCommand( | |
| 400 | + "ALTER TABLE `wt_fysrd` ADD COLUMN `shr1` varchar(500) NULL COMMENT '一级审核人'"); | |
| 401 | + if (!names.Contains("shr2")) | |
| 402 | + _db.Ado.ExecuteCommand( | |
| 403 | + "ALTER TABLE `wt_fysrd` ADD COLUMN `shr2` varchar(500) NULL COMMENT '二级审核人'"); | |
| 404 | + if (!names.Contains("wldw")) | |
| 405 | + _db.Ado.ExecuteCommand( | |
| 406 | + "ALTER TABLE `wt_fysrd` ADD COLUMN `wldw` varchar(64) NULL COMMENT '往来单位'"); | |
| 407 | + } | |
| 408 | + catch (Exception ex) { Console.WriteLine($"EnsureWtFysrdAuditColumnsForTodo: {ex.Message}"); } | |
| 409 | + _wtFysrdAuditColsEnsured = true; | |
| 410 | + } | |
| 411 | + } | |
| 412 | + | |
| 367 | 413 | /// <summary>与 <c>wt_shrysz.djmc</c>、<c>WtTjdWorkflowHelper.BillName</c> 一致</summary> |
| 368 | 414 | private const string TjdTodoBillName = "商品调价单"; |
| 369 | 415 | |
| 416 | + /// <summary>与 <c>wt_shrysz.djmc</c>、其他应收单 djlx 一致</summary> | |
| 417 | + private const string YskzjjsQtTodoBillName = "其他应收单"; | |
| 418 | + | |
| 419 | + private static bool _wtYskzjjsAuditColsEnsured; | |
| 420 | + | |
| 421 | + /// <summary> | |
| 422 | + /// 待办 SQL 依赖列存在;与 Extend 内 WtYskzjjsService 的列映射保持一致 | |
| 423 | + /// </summary> | |
| 424 | + private void EnsureWtYskzjjsAuditColumnsForTodo() | |
| 425 | + { | |
| 426 | + if (_wtYskzjjsAuditColsEnsured) return; | |
| 427 | + lock (typeof(DashboardService)) | |
| 428 | + { | |
| 429 | + if (_wtYskzjjsAuditColsEnsured) return; | |
| 430 | + try | |
| 431 | + { | |
| 432 | + if (!_db.DbMaintenance.IsAnyTable("wt_yskzjjs")) { _wtYskzjjsAuditColsEnsured = true; return; } | |
| 433 | + var cols = _db.DbMaintenance.GetColumnInfosByTableName("wt_yskzjjs"); | |
| 434 | + var names = cols.Select(c => c.DbColumnName.ToLowerInvariant()).ToHashSet(); | |
| 435 | + if (!names.Contains("djzt")) | |
| 436 | + _db.Ado.ExecuteCommand( | |
| 437 | + "ALTER TABLE `wt_yskzjjs` ADD COLUMN `djzt` varchar(32) NULL COMMENT '单据状态'"); | |
| 438 | + if (!names.Contains("spbz")) | |
| 439 | + _db.Ado.ExecuteCommand( | |
| 440 | + "ALTER TABLE `wt_yskzjjs` ADD COLUMN `spbz` text NULL COMMENT '审批备注'"); | |
| 441 | + if (!names.Contains("shr")) | |
| 442 | + _db.Ado.ExecuteCommand( | |
| 443 | + "ALTER TABLE `wt_yskzjjs` ADD COLUMN `shr` varchar(64) NULL COMMENT '审核人'"); | |
| 444 | + if (!names.Contains("shr1")) | |
| 445 | + _db.Ado.ExecuteCommand( | |
| 446 | + "ALTER TABLE `wt_yskzjjs` ADD COLUMN `shr1` varchar(500) NULL COMMENT '一级审核人'"); | |
| 447 | + if (!names.Contains("shr2")) | |
| 448 | + _db.Ado.ExecuteCommand( | |
| 449 | + "ALTER TABLE `wt_yskzjjs` ADD COLUMN `shr2` varchar(500) NULL COMMENT '二级审核人'"); | |
| 450 | + if (!names.Contains("wldw")) | |
| 451 | + _db.Ado.ExecuteCommand( | |
| 452 | + "ALTER TABLE `wt_yskzjjs` ADD COLUMN `wldw` varchar(64) NULL COMMENT '往来单位'"); | |
| 453 | + if (!names.Contains("djlx")) | |
| 454 | + _db.Ado.ExecuteCommand( | |
| 455 | + "ALTER TABLE `wt_yskzjjs` ADD COLUMN `djlx` varchar(64) NULL COMMENT '单据类型'"); | |
| 456 | + if (!names.Contains("djrq")) | |
| 457 | + _db.Ado.ExecuteCommand( | |
| 458 | + "ALTER TABLE `wt_yskzjjs` ADD COLUMN `djrq` datetime NULL COMMENT '单据日期'"); | |
| 459 | + } | |
| 460 | + catch (Exception ex) { Console.WriteLine($"EnsureWtYskzjjsAuditColumnsForTodo: {ex.Message}"); } | |
| 461 | + _wtYskzjjsAuditColsEnsured = true; | |
| 462 | + } | |
| 463 | + } | |
| 464 | + | |
| 465 | + /// <summary> | |
| 466 | + /// 其他收入单待办(wt_fysrd + wt_shrysz) | |
| 467 | + /// </summary> | |
| 468 | + private async Task<List<FlowTodoOutput>> QueryWtFysrdQtsrAuditTodosAsync(string userId, string userAccount) | |
| 469 | + { | |
| 470 | + var result = new List<FlowTodoOutput>(); | |
| 471 | + const string sql = @" | |
| 472 | +SELECT d.F_Id AS id, d.djrq, d.djzt, | |
| 473 | + IFNULL(NULLIF(TRIM(s.shr1), ''), s.shr) AS shr1_eff, | |
| 474 | + IFNULL(NULLIF(TRIM(s.shr2), ''), s.shr) AS shr2_eff | |
| 475 | +FROM wt_fysrd d | |
| 476 | +LEFT JOIN wt_shrysz s ON TRIM(s.djmc) = @billName | |
| 477 | +WHERE (d.F_Id LIKE 'QT%' OR TRIM(IFNULL(d.djlx,'')) IN ('其他收入单','其它收入单','其他收入','其它收入')) | |
| 478 | + AND IFNULL(d.djzt, '') <> '草稿' | |
| 479 | + AND IFNULL(d.djzt, '') <> '已审核' | |
| 480 | + AND IFNULL(d.djzt, '') <> '审核不通过' | |
| 481 | + AND ( | |
| 482 | + d.djzt IN ('待审核', '一级已审', '待二级', '一级已审/待二级') | |
| 483 | + OR d.djzt IS NULL | |
| 484 | + OR TRIM(IFNULL(d.djzt, '')) = '' | |
| 485 | + ) | |
| 486 | +ORDER BY d.djrq DESC"; | |
| 487 | + | |
| 488 | + var rows = await _db.Ado.SqlQueryAsync<dynamic>(sql, new { billName = FysrdQtsrTodoBillName }); | |
| 489 | + if (rows == null || rows.Count == 0) return result; | |
| 490 | + | |
| 491 | + foreach (var row in rows) | |
| 492 | + { | |
| 493 | + var status = Convert.ToString(row.djzt)?.Trim() ?? string.Empty; | |
| 494 | + var level1 = status == "待审核" || string.IsNullOrEmpty(status); | |
| 495 | + var level2 = status == "一级已审" || status == "待二级" || status == "一级已审/待二级"; | |
| 496 | + if (!level1 && !level2) continue; | |
| 497 | + | |
| 498 | + var configUsers = level1 ? Convert.ToString(row.shr1_eff) : Convert.ToString(row.shr2_eff); | |
| 499 | + if (!string.IsNullOrWhiteSpace(configUsers) && !IsInAuditUsers(configUsers, userId, userAccount)) | |
| 500 | + continue; | |
| 501 | + | |
| 502 | + DateTime? createTime = null; | |
| 503 | + var rawTime = Convert.ToString(row.djrq); | |
| 504 | + if (DateTime.TryParse(rawTime, out DateTime dt)) | |
| 505 | + createTime = dt; | |
| 506 | + | |
| 507 | + var id = Convert.ToString(row.id); | |
| 508 | + var levelText = level1 ? "一级审核待办" : "二级审核待办"; | |
| 509 | + result.Add(new FlowTodoOutput | |
| 510 | + { | |
| 511 | + id = id, | |
| 512 | + fullName = $"{FysrdQtsrTodoBillName} {id} - {levelText}", | |
| 513 | + creatorTime = createTime, | |
| 514 | + billType = FysrdQtsrTodoBillName | |
| 515 | + }); | |
| 516 | + } | |
| 517 | + | |
| 518 | + return result; | |
| 519 | + } | |
| 520 | + | |
| 370 | 521 | /// <summary> |
| 371 | 522 | /// 商品调价单待办(wt_tjd + wt_shrysz) |
| 372 | 523 | /// </summary> |
| ... | ... | @@ -424,6 +575,62 @@ ORDER BY d.djrq DESC"; |
| 424 | 575 | } |
| 425 | 576 | |
| 426 | 577 | /// <summary> |
| 578 | + /// 其他应收单待办(wt_yskzjjs + wt_shrysz) | |
| 579 | + /// </summary> | |
| 580 | + private async Task<List<FlowTodoOutput>> QueryWtYskzjjsQtAuditTodosAsync(string userId, string userAccount) | |
| 581 | + { | |
| 582 | + var result = new List<FlowTodoOutput>(); | |
| 583 | + const string sql = @" | |
| 584 | +SELECT d.F_Id AS id, d.djrq, d.djzt, | |
| 585 | + IFNULL(NULLIF(TRIM(s.shr1), ''), s.shr) AS shr1_eff, | |
| 586 | + IFNULL(NULLIF(TRIM(s.shr2), ''), s.shr) AS shr2_eff | |
| 587 | +FROM wt_yskzjjs d | |
| 588 | +LEFT JOIN wt_shrysz s ON TRIM(s.djmc) = @billName | |
| 589 | +WHERE TRIM(IFNULL(d.djlx,'')) IN ('其他应收单','其他应收款') | |
| 590 | + AND IFNULL(d.djzt, '') <> '草稿' | |
| 591 | + AND IFNULL(d.djzt, '') <> '已审核' | |
| 592 | + AND IFNULL(d.djzt, '') <> '审核不通过' | |
| 593 | + AND ( | |
| 594 | + d.djzt IN ('待审核', '一级已审', '待二级', '一级已审/待二级') | |
| 595 | + OR d.djzt IS NULL | |
| 596 | + OR TRIM(IFNULL(d.djzt, '')) = '' | |
| 597 | + ) | |
| 598 | +ORDER BY d.djrq DESC"; | |
| 599 | + | |
| 600 | + var rows = await _db.Ado.SqlQueryAsync<dynamic>(sql, new { billName = YskzjjsQtTodoBillName }); | |
| 601 | + if (rows == null || rows.Count == 0) return result; | |
| 602 | + | |
| 603 | + foreach (var row in rows) | |
| 604 | + { | |
| 605 | + var status = Convert.ToString(row.djzt)?.Trim() ?? string.Empty; | |
| 606 | + var level1 = status == "待审核" || string.IsNullOrEmpty(status); | |
| 607 | + var level2 = status == "一级已审" || status == "待二级" || status == "一级已审/待二级"; | |
| 608 | + if (!level1 && !level2) continue; | |
| 609 | + | |
| 610 | + var configUsers = level1 ? Convert.ToString(row.shr1_eff) : Convert.ToString(row.shr2_eff); | |
| 611 | + if (!string.IsNullOrWhiteSpace(configUsers) && !IsInAuditUsers(configUsers, userId, userAccount)) | |
| 612 | + continue; | |
| 613 | + | |
| 614 | + DateTime? createTime = null; | |
| 615 | + var rawTime = Convert.ToString(row.djrq); | |
| 616 | + if (DateTime.TryParse(rawTime, out DateTime dt)) | |
| 617 | + createTime = dt; | |
| 618 | + | |
| 619 | + var id = Convert.ToString(row.id); | |
| 620 | + var levelText = level1 ? "一级审核待办" : "二级审核待办"; | |
| 621 | + result.Add(new FlowTodoOutput | |
| 622 | + { | |
| 623 | + id = id, | |
| 624 | + fullName = $"{YskzjjsQtTodoBillName} {id} - {levelText}", | |
| 625 | + creatorTime = createTime, | |
| 626 | + billType = YskzjjsQtTodoBillName | |
| 627 | + }); | |
| 628 | + } | |
| 629 | + | |
| 630 | + return result; | |
| 631 | + } | |
| 632 | + | |
| 633 | + /// <summary> | |
| 427 | 634 | /// 按单据类型查询待审核/待二级单据,并按 shr1/shr2(或 shr)过滤当前用户 |
| 428 | 635 | /// </summary> |
| 429 | 636 | /// <param name="billDjlx">与 wt_xsckd.djlx、wt_shrysz.djmc 一致</param> | ... | ... |
Antis.Erp.Plat/sy/home.html
| ... | ... | @@ -475,7 +475,7 @@ |
| 475 | 475 | <svg class="pos-inline-svg pos-header-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true"> |
| 476 | 476 | <path stroke-linecap="round" stroke-linejoin="round" d="M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z" /> |
| 477 | 477 | </svg> |
| 478 | - <span>收银台</span> | |
| 478 | + <span>{{ posCashierHeaderTitle }}</span> | |
| 479 | 479 | </div> |
| 480 | 480 | <div class="home-right pos-header-tool-row"> |
| 481 | 481 | <button type="button" class="pos-header-tool-btn settlement-touch" aria-label="刷新页面" onclick="location.reload()"> |
| ... | ... | @@ -800,6 +800,21 @@ |
| 800 | 800 | }, |
| 801 | 801 | // 添加计算属性 |
| 802 | 802 | computed: { |
| 803 | + /** 顶栏标题:登录所选门店名称 + 收银台 */ | |
| 804 | + posCashierHeaderTitle() { | |
| 805 | + try { | |
| 806 | + var raw = localStorage.getItem('selectedStore'); | |
| 807 | + if (raw) { | |
| 808 | + var s = JSON.parse(raw); | |
| 809 | + var name = String(s.mdmc || s.Mdmc || s.name || '').trim(); | |
| 810 | + if (name) { | |
| 811 | + var withDian = name.lastIndexOf('店') === name.length - 1 ? name : (name + '店'); | |
| 812 | + return withDian + '收银台'; | |
| 813 | + } | |
| 814 | + } | |
| 815 | + } catch (e) {} | |
| 816 | + return '收银台'; | |
| 817 | + }, | |
| 803 | 818 | // 入0出1:仅手动输入序列号 |
| 804 | 819 | isSerialNumberModalR0C1() { |
| 805 | 820 | return this.currentSerialNumberItem && this.currentSerialNumberItem.spxlhType === '2'; | ... | ... |
Antis.Erp.Plat/sy/settlement.html
| ... | ... | @@ -3749,7 +3749,7 @@ |
| 3749 | 3749 | <svg class="pos-inline-svg pos-header-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true"> |
| 3750 | 3750 | <path stroke-linecap="round" stroke-linejoin="round" d="M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z" /> |
| 3751 | 3751 | </svg> |
| 3752 | - <span>收银台</span> | |
| 3752 | + <span>{{ posCashierHeaderTitle }}</span> | |
| 3753 | 3753 | </div> |
| 3754 | 3754 | <div class="home-right pos-header-tool-row"> |
| 3755 | 3755 | <button type="button" class="pos-header-tool-btn settlement-touch" aria-label="刷新页面" onclick="location.reload()"> |
| ... | ... | @@ -4410,6 +4410,21 @@ |
| 4410 | 4410 | // } |
| 4411 | 4411 | }, |
| 4412 | 4412 | computed: { |
| 4413 | + /** 顶栏标题:登录所选门店名称 + 收银台 */ | |
| 4414 | + posCashierHeaderTitle() { | |
| 4415 | + try { | |
| 4416 | + var raw = localStorage.getItem('selectedStore'); | |
| 4417 | + if (raw) { | |
| 4418 | + var s = JSON.parse(raw); | |
| 4419 | + var name = String(s.mdmc || s.Mdmc || s.name || '').trim(); | |
| 4420 | + if (name) { | |
| 4421 | + var withDian = name.lastIndexOf('店') === name.length - 1 ? name : (name + '店'); | |
| 4422 | + return withDian + '收银台'; | |
| 4423 | + } | |
| 4424 | + } | |
| 4425 | + } catch (e) {} | |
| 4426 | + return '收银台'; | |
| 4427 | + }, | |
| 4413 | 4428 | settlementMemberBenefitLine() { |
| 4414 | 4429 | if (!this.hyinfo || this.hyinfo === 'null') return ''; |
| 4415 | 4430 | var h = this.hyinfo; | ... | ... |