Commit d4a6cf6817655b2cd2fb2d70a0e453d170984534

Authored by “wangming”
1 parent 44ba74bd

feat(erp-plat): add '往来单位' field to forms and tables for better data representation

- Introduced a new field for '往来单位' in various forms and tables to enhance data visibility.
- Updated the backend service to support fetching and displaying '往来单位' names based on the corresponding IDs.
- Ensured consistent layout and structure across forms and tables for improved user experience.
- Removed unnecessary fields related to '制单人' to streamline the forms.

Made-with: Cursor
Antis.Erp.Plat/.cursor/rules/project_rules.mdc
@@ -51,6 +51,7 @@ alwaysApply: true @@ -51,6 +51,7 @@ alwaysApply: true
51 - **图标显示**: 所有列表数据都要有图标,不同颜色区分类型 51 - **图标显示**: 所有列表数据都要有图标,不同颜色区分类型
52 - **空值显示**: 没有信息的字段显示"无" 52 - **空值显示**: 没有信息的字段显示"无"
53 - **列表规范**: 列表数据不能换行 53 - **列表规范**: 列表数据不能换行
  54 +- **列表/报表页头部搜索区**: 须与标准业务列表页排版一致——`NCC-common-layout` → `NCC-common-layout-center` → `el-row` 使用 class `NCC-common-search-box`(建议 `:gutter="16"`);内层 `el-form` 使用 `@submit.native.prevent`(与其它列表一致,**不要**在表单上单独套一套与 `wtXsckd` / `wtCgthd` 等常规列表差异过大的自定义外层布局);筛选项默认 `el-col :span="6"`,末列放置「查询」「重置」「展开/收起」;新增或改造带搜索的页面时优先对照上述列表页复制结构再改字段。
54 55
55 ### 性能要求 56 ### 性能要求
56 - 启用懒加载和代码分割 57 - 启用懒加载和代码分割
Antis.Erp.Plat/antis-ncc-admin/src/views/wtCgrkd/Form.vue
@@ -169,12 +169,6 @@ @@ -169,12 +169,6 @@
169 </el-input> 169 </el-input>
170 </el-form-item> 170 </el-form-item>
171 </el-col> 171 </el-col>
172 - <el-col :span="8" v-if="false">  
173 - <el-form-item label="制单人" prop="zdr">  
174 - <user-select v-model="dataForm.zdr" placeholder="请选择" clearable disabled >  
175 - </user-select>  
176 - </el-form-item>  
177 - </el-col>  
178 <el-col :span="8"> 172 <el-col :span="8">
179 <el-form-item label="审核人" prop="shr"> 173 <el-form-item label="审核人" prop="shr">
180 <user-select v-model="dataForm.shr" placeholder="请选择" clearable disabled > 174 <user-select v-model="dataForm.shr" placeholder="请选择" clearable disabled >
@@ -235,7 +229,6 @@ @@ -235,7 +229,6 @@
235 ysje:undefined, 229 ysje:undefined,
236 skzh:undefined, 230 skzh:undefined,
237 skje:undefined, 231 skje:undefined,
238 - zdr:undefined,  
239 shr:undefined, 232 shr:undefined,
240 gzr:undefined, 233 gzr:undefined,
241 bz:undefined, 234 bz:undefined,
Antis.Erp.Plat/antis-ncc-admin/src/views/wtCgrkd/index.vue
@@ -40,11 +40,6 @@ @@ -40,11 +40,6 @@
40 </el-form-item> 40 </el-form-item>
41 </el-col> 41 </el-col>
42 <el-col :span="6"> 42 <el-col :span="6">
43 - <el-form-item label="制单人">  
44 - <userSelect v-model="query.zdr" placeholder="请选择制单人" />  
45 - </el-form-item>  
46 - </el-col>  
47 - <el-col :span="6">  
48 <el-form-item label="审核人"> 43 <el-form-item label="审核人">
49 <userSelect v-model="query.shr" placeholder="请选择审核人" /> 44 <userSelect v-model="query.shr" placeholder="请选择审核人" />
50 </el-form-item> 45 </el-form-item>
@@ -100,7 +95,6 @@ @@ -100,7 +95,6 @@
100 <template slot-scope="scope">{{ scope.row.skzh | dynamicText(skzhOptions) }}</template> 95 <template slot-scope="scope">{{ scope.row.skzh | dynamicText(skzhOptions) }}</template>
101 </el-table-column> 96 </el-table-column>
102 <el-table-column prop="skje" label="付款金额" align="left" /> 97 <el-table-column prop="skje" label="付款金额" align="left" />
103 - <el-table-column prop="zdr" label="制单人" align="left" />  
104 <el-table-column prop="shr" label="审核人" align="left"> 98 <el-table-column prop="shr" label="审核人" align="left">
105 <template slot-scope="scope">{{ getShrDisplay(scope.row) }}</template> 99 <template slot-scope="scope">{{ getShrDisplay(scope.row) }}</template>
106 </el-table-column> 100 </el-table-column>
@@ -163,7 +157,6 @@ @@ -163,7 +157,6 @@
163 jsr:undefined, 157 jsr:undefined,
164 skzh:undefined, 158 skzh:undefined,
165 skje:undefined, 159 skje:undefined,
166 - zdr:undefined,  
167 shr:undefined, 160 shr:undefined,
168 gzr:undefined, 161 gzr:undefined,
169 bz:undefined, 162 bz:undefined,
@@ -188,7 +181,6 @@ @@ -188,7 +181,6 @@
188 { prop: 'jsr', label: '经手人' }, 181 { prop: 'jsr', label: '经手人' },
189 { prop: 'skzh', label: '付款账户' }, 182 { prop: 'skzh', label: '付款账户' },
190 { prop: 'skje', label: '付款金额' }, 183 { prop: 'skje', label: '付款金额' },
191 - { prop: 'zdr', label: '制单人' },  
192 { prop: 'shr', label: '审核人' }, 184 { prop: 'shr', label: '审核人' },
193 { prop: 'gzr', label: '过账人' }, 185 { prop: 'gzr', label: '过账人' },
194 { prop: 'bz', label: '备注' }, 186 { prop: 'bz', label: '备注' },
Antis.Erp.Plat/antis-ncc-admin/src/views/wtCgthd/Form.vue
@@ -27,6 +27,13 @@ @@ -27,6 +27,13 @@
27 </el-form-item> 27 </el-form-item>
28 </el-col> 28 </el-col>
29 <el-col :span="12"> 29 <el-col :span="12">
  30 + <el-form-item label="往来单位" prop="gys">
  31 + <el-select v-model="dataForm.gys" placeholder="请选择或调原入库单带出" clearable :style='{"width":"100%"}' filterable :disabled="!!isDetail">
  32 + <el-option v-for="(item, index) in gysOptions" :key="index" :label="item.dwmc" :value="item.id" />
  33 + </el-select>
  34 + </el-form-item>
  35 + </el-col>
  36 + <el-col :span="12">
30 <el-form-item label="原采购入库单"> 37 <el-form-item label="原采购入库单">
31 <el-button type="primary" icon="el-icon-search" @click="openPurchaseInboundOrderSelect"> 38 <el-button type="primary" icon="el-icon-search" @click="openPurchaseInboundOrderSelect">
32 调原入库单 39 调原入库单
@@ -264,9 +271,11 @@ @@ -264,9 +271,11 @@
264 gzr:undefined, 271 gzr:undefined,
265 bz:undefined, 272 bz:undefined,
266 djlx:"采购退货单", 273 djlx:"采购退货单",
  274 + gys: undefined,
267 }, 275 },
268 rules: { 276 rules: {
269 }, 277 },
  278 + gysOptions: [],
270 cjckOptions : [], 279 cjckOptions : [],
271 rkckOptions : [], 280 rkckOptions : [],
272 rkckOptions : [], 281 rkckOptions : [],
@@ -295,6 +304,7 @@ @@ -295,6 +304,7 @@
295 this.getckckOptions(); 304 this.getckckOptions();
296 this.getspbhOptions(); 305 this.getspbhOptions();
297 this.getskzhOptions(); 306 this.getskzhOptions();
  307 + this.getgysOptions();
298 // 设置单据日期默认为当前日期,经手人默认为当前用户 308 // 设置单据日期默认为当前日期,经手人默认为当前用户
299 if (!this.dataForm.id) { 309 if (!this.dataForm.id) {
300 this.dataForm.djrq = Date.now(); 310 this.dataForm.djrq = Date.now();
@@ -337,6 +347,16 @@ @@ -337,6 +347,16 @@
337 this.skzhOptions = res.data.list 347 this.skzhOptions = res.data.list
338 }); 348 });
339 }, 349 },
  350 + getgysOptions() {
  351 + return request({
  352 + url: '/api/Extend/WtWldw',
  353 + method: 'get',
  354 + data: { pageSize: 1000, currentPage: 1 }
  355 + }).then(res => {
  356 + this.gysOptions = (res.data && res.data.list) ? res.data.list : (res.data || [])
  357 + return res
  358 + })
  359 + },
340 goBack() { 360 goBack() {
341 this.$emit('refresh') 361 this.$emit('refresh')
342 }, 362 },
@@ -354,6 +374,9 @@ @@ -354,6 +374,9 @@
354 if (mainTableInfo && mainTableInfo.rkck) { 374 if (mainTableInfo && mainTableInfo.rkck) {
355 this.dataForm.cjck = mainTableInfo.rkck 375 this.dataForm.cjck = mainTableInfo.rkck
356 } 376 }
  377 + if (mainTableInfo && mainTableInfo.gys) {
  378 + this.dataForm.gys = mainTableInfo.gys
  379 + }
357 for (const detail of inboundDetails) { 380 for (const detail of inboundDetails) {
358 const qty = parseFloat(detail.sl) || 0 381 const qty = parseFloat(detail.sl) || 0
359 const price = parseFloat(detail.dj) || 0 382 const price = parseFloat(detail.dj) || 0
@@ -404,6 +427,9 @@ @@ -404,6 +427,9 @@
404 method: 'get' 427 method: 'get'
405 }).then(res =>{ 428 }).then(res =>{
406 this.dataForm = res.data; 429 this.dataForm = res.data;
  430 + if (res.data.gysId != null && res.data.gysId !== '') {
  431 + this.$set(this.dataForm, 'gys', res.data.gysId);
  432 + }
407 if (!this.dataForm.wtXsckdMxList) { 433 if (!this.dataForm.wtXsckdMxList) {
408 this.dataForm.wtXsckdMxList = []; 434 this.dataForm.wtXsckdMxList = [];
409 } 435 }
Antis.Erp.Plat/antis-ncc-admin/src/views/wtCgthd/detail-view.vue
@@ -61,6 +61,12 @@ @@ -61,6 +61,12 @@
61 {{ cellText(detail.jsr) }} 61 {{ cellText(detail.jsr) }}
62 </span> 62 </span>
63 </el-descriptions-item> 63 </el-descriptions-item>
  64 + <el-descriptions-item label="往来单位">
  65 + <span class="cell-nowrap">
  66 + <i class="el-icon-office-building desc-icon desc-icon--info" />
  67 + {{ cellText(detail.gys) }}
  68 + </span>
  69 + </el-descriptions-item>
64 </el-descriptions> 70 </el-descriptions>
65 71
66 <div class="detail-section-head"> 72 <div class="detail-section-head">
Antis.Erp.Plat/antis-ncc-admin/src/views/wtCgthd/index.vue
@@ -23,6 +23,13 @@ @@ -23,6 +23,13 @@
23 </el-col> 23 </el-col>
24 <template v-if="showAll"> 24 <template v-if="showAll">
25 <el-col :span="6"> 25 <el-col :span="6">
  26 + <el-form-item label="往来单位">
  27 + <el-select v-model="query.gys" placeholder="请选择" clearable filterable style="width: 100%">
  28 + <el-option v-for="item in gysOptions" :key="item.id" :label="item.dwmc" :value="item.id" />
  29 + </el-select>
  30 + </el-form-item>
  31 + </el-col>
  32 + <el-col :span="6">
26 <el-form-item label="经手人"> 33 <el-form-item label="经手人">
27 <userSelect v-model="query.jsr" placeholder="请选择经手人" /> 34 <userSelect v-model="query.jsr" placeholder="请选择经手人" />
28 </el-form-item> 35 </el-form-item>
@@ -101,6 +108,11 @@ @@ -101,6 +108,11 @@
101 <template slot-scope="scope">{{ scope.row.cjck | dynamicText(cjckOptions) }}</template> 108 <template slot-scope="scope">{{ scope.row.cjck | dynamicText(cjckOptions) }}</template>
102 </el-table-column> 109 </el-table-column>
103 <el-table-column prop="jsr" label="经手人" align="left" /> 110 <el-table-column prop="jsr" label="经手人" align="left" />
  111 + <el-table-column prop="gys" label="往来单位" align="left" min-width="120" show-overflow-tooltip>
  112 + <template slot-scope="scope">
  113 + <span class="cell-nowrap">{{ scope.row.gys || '无' }}</span>
  114 + </template>
  115 + </el-table-column>
104 <!-- <el-table-column prop="ysje" label="优惠金额" align="left" /> --> 116 <!-- <el-table-column prop="ysje" label="优惠金额" align="left" /> -->
105 <el-table-column label="退款账户" prop="skzh" align="left"> 117 <el-table-column label="退款账户" prop="skzh" align="left">
106 <template slot-scope="scope">{{ scope.row.skzh | dynamicText(skzhOptions) }}</template> 118 <template slot-scope="scope">{{ scope.row.skzh | dynamicText(skzhOptions) }}</template>
@@ -157,6 +169,7 @@ @@ -157,6 +169,7 @@
157 gzr:undefined, 169 gzr:undefined,
158 bz:undefined, 170 bz:undefined,
159 djlx:undefined, 171 djlx:undefined,
  172 + gys: undefined,
160 }, 173 },
161 list: [], 174 list: [],
162 listLoading: true, 175 listLoading: true,
@@ -175,6 +188,7 @@ @@ -175,6 +188,7 @@
175 { prop: 'djrq', label: '单据日期' }, 188 { prop: 'djrq', label: '单据日期' },
176 { prop: 'cjck', label: '出库仓库' }, 189 { prop: 'cjck', label: '出库仓库' },
177 { prop: 'jsr', label: '经手人' }, 190 { prop: 'jsr', label: '经手人' },
  191 + { prop: 'gys', label: '往来单位' },
178 // { prop: 'ysje', label: '优惠金额' }, 192 // { prop: 'ysje', label: '优惠金额' },
179 { prop: 'skzh', label: '退款账户' }, 193 { prop: 'skzh', label: '退款账户' },
180 { prop: 'skje', label: '退款金额' }, 194 { prop: 'skje', label: '退款金额' },
@@ -188,6 +202,7 @@ @@ -188,6 +202,7 @@
188 cjckOptions : [], 202 cjckOptions : [],
189 rkckOptions : [], 203 rkckOptions : [],
190 skzhOptions : [], 204 skzhOptions : [],
  205 + gysOptions: [],
191 } 206 }
192 }, 207 },
193 computed: {}, 208 computed: {},
@@ -196,6 +211,7 @@ @@ -196,6 +211,7 @@
196 this.getcjckOptions(); 211 this.getcjckOptions();
197 this.getrkckOptions(); 212 this.getrkckOptions();
198 this.getskzhOptions(); 213 this.getskzhOptions();
  214 + this.getgysOptions();
199 }, 215 },
200 methods: { 216 methods: {
201 getcjckOptions(){ 217 getcjckOptions(){
@@ -213,6 +229,15 @@ @@ -213,6 +229,15 @@
213 this.skzhOptions = res.data.list 229 this.skzhOptions = res.data.list
214 }); 230 });
215 }, 231 },
  232 + getgysOptions() {
  233 + request({
  234 + url: '/api/Extend/WtWldw',
  235 + method: 'get',
  236 + data: { pageSize: 1000, currentPage: 1 }
  237 + }).then(res => {
  238 + this.gysOptions = (res.data && res.data.list) ? res.data.list : (res.data || [])
  239 + })
  240 + },
216 initData() { 241 initData() {
217 this.listLoading = true; 242 this.listLoading = true;
218 let _query = { 243 let _query = {
Antis.Erp.Plat/antis-ncc-admin/src/views/wtProductSummary/index.vue
1 <template> 1 <template>
2 - <div class="NCC-common-layout product-summary-page"> 2 + <div class="NCC-common-layout">
3 <div class="NCC-common-layout-center"> 3 <div class="NCC-common-layout-center">
4 <el-row class="NCC-common-search-box" :gutter="16"> 4 <el-row class="NCC-common-search-box" :gutter="16">
5 - <el-form @submit.native.prevent label-width="90px" label-position="right"> 5 + <el-form @submit.native.prevent>
6 <el-col :span="6"> 6 <el-col :span="6">
7 <el-form-item label="查询日期"> 7 <el-form-item label="查询日期">
8 <el-date-picker 8 <el-date-picker
@@ -133,60 +133,12 @@ @@ -133,60 +133,12 @@
133 </el-row> 133 </el-row>
134 134
135 <div class="NCC-common-layout-main NCC-flex-main"> 135 <div class="NCC-common-layout-main NCC-flex-main">
136 - <el-row :gutter="16" class="product-summary-stats">  
137 - <el-col :xs="24" :sm="12" :md="6">  
138 - <div class="product-summary-stat-card product-summary-stat-card--blue">  
139 - <div class="product-summary-stat-card__inner">  
140 - <i class="el-icon-goods product-summary-stat-card__icon" aria-hidden="true" />  
141 - <div class="product-summary-stat-card__text">  
142 - <div class="product-summary-stat-card__label">商品行数</div>  
143 - <div class="product-summary-stat-card__value cell-nowrap">{{ summaryStats.rowCount }}</div>  
144 - </div>  
145 - </div>  
146 - </div>  
147 - </el-col>  
148 - <el-col :xs="24" :sm="12" :md="6">  
149 - <div class="product-summary-stat-card product-summary-stat-card--green">  
150 - <div class="product-summary-stat-card__inner">  
151 - <i class="el-icon-sell product-summary-stat-card__icon" aria-hidden="true" />  
152 - <div class="product-summary-stat-card__text">  
153 - <div class="product-summary-stat-card__label">销售数量合计</div>  
154 - <div class="product-summary-stat-card__value cell-nowrap">{{ summaryStats.totalQtyDisplay }}</div>  
155 - </div>  
156 - </div>  
157 - </div>  
158 - </el-col>  
159 - <el-col :xs="24" :sm="12" :md="6">  
160 - <div class="product-summary-stat-card product-summary-stat-card--orange">  
161 - <div class="product-summary-stat-card__inner">  
162 - <i class="el-icon-coin product-summary-stat-card__icon" aria-hidden="true" />  
163 - <div class="product-summary-stat-card__text">  
164 - <div class="product-summary-stat-card__label">销售金额合计</div>  
165 - <div class="product-summary-stat-card__value cell-nowrap">{{ summaryStats.salesAmountDisplay }}</div>  
166 - </div>  
167 - </div>  
168 - </div>  
169 - </el-col>  
170 - <el-col :xs="24" :sm="12" :md="6">  
171 - <div class="product-summary-stat-card product-summary-stat-card--red">  
172 - <div class="product-summary-stat-card__inner">  
173 - <i class="el-icon-data-analysis product-summary-stat-card__icon" aria-hidden="true" />  
174 - <div class="product-summary-stat-card__text">  
175 - <div class="product-summary-stat-card__label">毛利合计</div>  
176 - <div class="product-summary-stat-card__value cell-nowrap">{{ summaryStats.profitDisplay }}</div>  
177 - </div>  
178 - </div>  
179 - </div>  
180 - </el-col>  
181 - </el-row>  
182 -  
183 <div class="NCC-common-head product-summary-head"> 136 <div class="NCC-common-head product-summary-head">
184 - <div class="product-summary-head__left"> 137 + <div>
185 <span class="product-summary-head__title"> 138 <span class="product-summary-head__title">
186 <i class="el-icon-document product-summary-head__title-icon" aria-hidden="true" /> 139 <i class="el-icon-document product-summary-head__title-icon" aria-hidden="true" />
187 商品销售明细 140 商品销售明细
188 </span> 141 </span>
189 - <span class="product-summary-head__hint">与下方列表同一筛选条件汇总</span>  
190 </div> 142 </div>
191 <div class="NCC-common-head-right"> 143 <div class="NCC-common-head-right">
192 <el-tooltip effect="dark" content="刷新" placement="top"> 144 <el-tooltip effect="dark" content="刷新" placement="top">
@@ -201,55 +153,55 @@ @@ -201,55 +153,55 @@
201 </div> 153 </div>
202 154
203 <NCC-table v-loading="listLoading" :data="list" class="product-summary-table"> 155 <NCC-table v-loading="listLoading" :data="list" class="product-summary-table">
204 - <el-table-column prop="商品编号" label="商品编号" min-width="110" align="left" show-overflow-tooltip> 156 + <el-table-column prop="商品编号" label="商品编号" min-width="110" align="left" show-overflow-tooltip sortable :sort-method="sortText('商品编号')">
205 <template slot-scope="scope">{{ displayText(scope.row['商品编号']) }}</template> 157 <template slot-scope="scope">{{ displayText(scope.row['商品编号']) }}</template>
206 </el-table-column> 158 </el-table-column>
207 - <el-table-column prop="商品名称" label="商品名称" min-width="160" align="left" show-overflow-tooltip> 159 + <el-table-column prop="商品名称" label="商品名称" min-width="160" align="left" show-overflow-tooltip sortable :sort-method="sortText('商品名称')">
208 <template slot-scope="scope">{{ displayText(scope.row['商品名称']) }}</template> 160 <template slot-scope="scope">{{ displayText(scope.row['商品名称']) }}</template>
209 </el-table-column> 161 </el-table-column>
210 - <el-table-column prop="销售" label="销售" min-width="88" align="right" show-overflow-tooltip> 162 + <el-table-column prop="销售" label="销售" min-width="88" align="right" show-overflow-tooltip sortable :sort-method="sortNumeric('销售')">
211 <template slot-scope="scope">{{ formatNumber(scope.row['销售'], 4) }}</template> 163 <template slot-scope="scope">{{ formatNumber(scope.row['销售'], 4) }}</template>
212 </el-table-column> 164 </el-table-column>
213 - <el-table-column prop="单位" label="单位" min-width="72" align="center" show-overflow-tooltip> 165 + <el-table-column prop="单位" label="单位" min-width="72" align="center" show-overflow-tooltip sortable :sort-method="sortText('单位')">
214 <template slot-scope="scope">{{ displayText(scope.row['单位']) }}</template> 166 <template slot-scope="scope">{{ displayText(scope.row['单位']) }}</template>
215 </el-table-column> 167 </el-table-column>
216 - <el-table-column prop="单价" label="单价" min-width="96" align="right" show-overflow-tooltip> 168 + <el-table-column prop="单价" label="单价" min-width="96" align="right" show-overflow-tooltip sortable :sort-method="sortNumeric('单价')">
217 <template slot-scope="scope">{{ formatNumber(scope.row['单价'], 4) }}</template> 169 <template slot-scope="scope">{{ formatNumber(scope.row['单价'], 4) }}</template>
218 </el-table-column> 170 </el-table-column>
219 - <el-table-column prop="折前销售金额" label="折前销售金额" min-width="120" align="right" show-overflow-tooltip> 171 + <el-table-column prop="折前销售金额" label="折前销售金额" min-width="120" align="right" show-overflow-tooltip sortable :sort-method="sortNumeric('折前销售金额')">
220 <template slot-scope="scope">{{ formatNumber(scope.row['折前销售金额'], 2) }}</template> 172 <template slot-scope="scope">{{ formatNumber(scope.row['折前销售金额'], 2) }}</template>
221 </el-table-column> 173 </el-table-column>
222 - <el-table-column prop="销售金额" label="销售金额" min-width="110" align="right" show-overflow-tooltip> 174 + <el-table-column prop="销售金额" label="销售金额" min-width="110" align="right" show-overflow-tooltip sortable :sort-method="sortNumeric('销售金额')">
223 <template slot-scope="scope">{{ formatNumber(scope.row['销售金额'], 2) }}</template> 175 <template slot-scope="scope">{{ formatNumber(scope.row['销售金额'], 2) }}</template>
224 </el-table-column> 176 </el-table-column>
225 - <el-table-column prop="成本单价" label="成本单价" min-width="96" align="right" show-overflow-tooltip> 177 + <el-table-column prop="成本单价" label="成本单价" min-width="96" align="right" show-overflow-tooltip sortable :sort-method="sortNumeric('成本单价')">
226 <template slot-scope="scope">{{ formatNumber(scope.row['成本单价'], 4) }}</template> 178 <template slot-scope="scope">{{ formatNumber(scope.row['成本单价'], 4) }}</template>
227 </el-table-column> 179 </el-table-column>
228 - <el-table-column prop="成本金额" label="成本金额" min-width="110" align="right" show-overflow-tooltip> 180 + <el-table-column prop="成本金额" label="成本金额" min-width="110" align="right" show-overflow-tooltip sortable :sort-method="sortNumeric('成本金额')">
229 <template slot-scope="scope">{{ formatNumber(scope.row['成本金额'], 2) }}</template> 181 <template slot-scope="scope">{{ formatNumber(scope.row['成本金额'], 2) }}</template>
230 </el-table-column> 182 </el-table-column>
231 - <el-table-column prop="费用分摊金额" label="费用分摊金额" min-width="120" align="right" show-overflow-tooltip> 183 + <el-table-column prop="费用分摊金额" label="费用分摊金额" min-width="120" align="right" show-overflow-tooltip sortable :sort-method="sortNumeric('费用分摊金额')">
232 <template slot-scope="scope">{{ formatNumber(scope.row['费用分摊金额'], 2) }}</template> 184 <template slot-scope="scope">{{ formatNumber(scope.row['费用分摊金额'], 2) }}</template>
233 </el-table-column> 185 </el-table-column>
234 - <el-table-column prop="毛利" label="毛利" min-width="96" align="right" show-overflow-tooltip> 186 + <el-table-column prop="毛利" label="毛利" min-width="96" align="right" show-overflow-tooltip sortable :sort-method="sortNumeric('毛利')">
235 <template slot-scope="scope">{{ formatNumber(scope.row['毛利'], 2) }}</template> 187 <template slot-scope="scope">{{ formatNumber(scope.row['毛利'], 2) }}</template>
236 </el-table-column> 188 </el-table-column>
237 - <el-table-column prop="毛利率(%)" label="毛利率(%)" min-width="100" align="right" show-overflow-tooltip> 189 + <el-table-column prop="毛利率(%)" label="毛利率(%)" min-width="100" align="right" show-overflow-tooltip sortable :sort-method="sortNumeric('毛利率(%)')">
238 <template slot-scope="scope">{{ formatNumber(scope.row['毛利率(%)'], 2) }}</template> 190 <template slot-scope="scope">{{ formatNumber(scope.row['毛利率(%)'], 2) }}</template>
239 </el-table-column> 191 </el-table-column>
240 - <el-table-column prop="0单价数量" label="0单价数量" min-width="100" align="right" show-overflow-tooltip> 192 + <el-table-column prop="0单价数量" label="0单价数量" min-width="100" align="right" show-overflow-tooltip sortable :sort-method="sortNumeric('0单价数量')">
241 <template slot-scope="scope">{{ formatNumber(scope.row['0单价数量'], 4) }}</template> 193 <template slot-scope="scope">{{ formatNumber(scope.row['0单价数量'], 4) }}</template>
242 </el-table-column> 194 </el-table-column>
243 - <el-table-column prop="销售权重(%)" label="销售权重(%)" min-width="110" align="right" show-overflow-tooltip> 195 + <el-table-column prop="销售权重(%)" label="销售权重(%)" min-width="110" align="right" show-overflow-tooltip sortable :sort-method="sortNumeric('销售权重(%)')">
244 <template slot-scope="scope">{{ formatNumber(scope.row['销售权重(%)'], 2) }}</template> 196 <template slot-scope="scope">{{ formatNumber(scope.row['销售权重(%)'], 2) }}</template>
245 </el-table-column> 197 </el-table-column>
246 - <el-table-column prop="金额权重(%)" label="金额权重(%)" min-width="110" align="right" show-overflow-tooltip> 198 + <el-table-column prop="金额权重(%)" label="金额权重(%)" min-width="110" align="right" show-overflow-tooltip sortable :sort-method="sortNumeric('金额权重(%)')">
247 <template slot-scope="scope">{{ formatNumber(scope.row['金额权重(%)'], 2) }}</template> 199 <template slot-scope="scope">{{ formatNumber(scope.row['金额权重(%)'], 2) }}</template>
248 </el-table-column> 200 </el-table-column>
249 - <el-table-column prop="利润权重(%)" label="利润权重(%)" min-width="110" align="right" show-overflow-tooltip> 201 + <el-table-column prop="利润权重(%)" label="利润权重(%)" min-width="110" align="right" show-overflow-tooltip sortable :sort-method="sortNumeric('利润权重(%)')">
250 <template slot-scope="scope">{{ formatNumber(scope.row['利润权重(%)'], 2) }}</template> 202 <template slot-scope="scope">{{ formatNumber(scope.row['利润权重(%)'], 2) }}</template>
251 </el-table-column> 203 </el-table-column>
252 - <el-table-column prop="平均利润" label="平均利润" min-width="110" align="right" show-overflow-tooltip> 204 + <el-table-column prop="平均利润" label="平均利润" min-width="110" align="right" show-overflow-tooltip sortable :sort-method="sortNumeric('平均利润')">
253 <template slot-scope="scope">{{ formatNumber(scope.row['平均利润'], 4) }}</template> 205 <template slot-scope="scope">{{ formatNumber(scope.row['平均利润'], 4) }}</template>
254 </el-table-column> 206 </el-table-column>
255 </NCC-table> 207 </NCC-table>
@@ -293,26 +245,6 @@ export default { @@ -293,26 +245,6 @@ export default {
293 productLoading: false 245 productLoading: false
294 } 246 }
295 }, 247 },
296 - computed: {  
297 - summaryStats() {  
298 - const rows = Array.isArray(this.list) ? this.list : []  
299 - let totalQty = 0  
300 - let salesAmount = 0  
301 - let profit = 0  
302 - for (let i = 0; i < rows.length; i++) {  
303 - const r = rows[i] || {}  
304 - totalQty += this.parseNum(r['销售'])  
305 - salesAmount += this.parseNum(r['销售金额'])  
306 - profit += this.parseNum(r['毛利'])  
307 - }  
308 - return {  
309 - rowCount: rows.length,  
310 - totalQtyDisplay: this.formatSummaryNumber(totalQty, 4),  
311 - salesAmountDisplay: this.formatSummaryNumber(salesAmount, 2),  
312 - profitDisplay: this.formatSummaryNumber(profit, 2)  
313 - }  
314 - }  
315 - },  
316 created() { 248 created() {
317 this.loadFilterOptions() 249 this.loadFilterOptions()
318 this.fetchData() 250 this.fetchData()
@@ -332,12 +264,17 @@ export default { @@ -332,12 +264,17 @@ export default {
332 maximumFractionDigits: digits 264 maximumFractionDigits: digits
333 }) 265 })
334 }, 266 },
335 - formatSummaryNumber(n, digits) {  
336 - if (!Number.isFinite(n)) return '无'  
337 - return n.toLocaleString('zh-CN', {  
338 - minimumFractionDigits: 0,  
339 - maximumFractionDigits: digits  
340 - }) 267 + /** 表头排序:按数值字段(含千分位字符串) */
  268 + sortNumeric(prop) {
  269 + return (a, b) => this.parseNum(a[prop]) - this.parseNum(b[prop])
  270 + },
  271 + /** 表头排序:文本字段 */
  272 + sortText(prop) {
  273 + return (a, b) => {
  274 + const sa = String(a[prop] != null ? a[prop] : '').trim()
  275 + const sb = String(b[prop] != null ? b[prop] : '').trim()
  276 + return sa.localeCompare(sb, 'zh-CN')
  277 + }
341 }, 278 },
342 displayText(val) { 279 displayText(val) {
343 if (val == null || String(val).trim() === '') return '无' 280 if (val == null || String(val).trim() === '') return '无'
@@ -469,105 +406,27 @@ export default { @@ -469,105 +406,27 @@ export default {
469 </script> 406 </script>
470 407
471 <style lang="scss" scoped> 408 <style lang="scss" scoped>
472 -.product-summary-page {  
473 - .product-summary-stats {  
474 - margin-bottom: 8px;  
475 - }  
476 -  
477 - .product-summary-stat-card {  
478 - height: 100px;  
479 - padding: 12px;  
480 - border-radius: 12px;  
481 - box-sizing: border-box;  
482 - margin-bottom: 16px;  
483 - background: #fff;  
484 - border: 1px solid #ebeef5;  
485 - box-shadow: 0 2px 12px rgba(15, 23, 42, 0.06);  
486 - display: flex;  
487 - align-items: center;  
488 - }  
489 -  
490 - .product-summary-stat-card__inner {  
491 - display: flex;  
492 - align-items: center;  
493 - width: 100%;  
494 - gap: 12px;  
495 - }  
496 -  
497 - .product-summary-stat-card__icon {  
498 - font-size: 28px;  
499 - flex-shrink: 0;  
500 - }  
501 -  
502 - .product-summary-stat-card__text {  
503 - min-width: 0;  
504 - flex: 1;  
505 - }  
506 -  
507 - .product-summary-stat-card__label {  
508 - font-size: 13px;  
509 - color: #909399;  
510 - line-height: 1.3;  
511 - margin-bottom: 4px;  
512 - }  
513 -  
514 - .product-summary-stat-card__value {  
515 - font-size: 18px;  
516 - font-weight: 700;  
517 - color: #303133;  
518 - line-height: 1.2;  
519 - }  
520 -  
521 - .product-summary-stat-card--blue .product-summary-stat-card__icon {  
522 - color: #409eff;  
523 - }  
524 -  
525 - .product-summary-stat-card--green .product-summary-stat-card__icon {  
526 - color: #67c23a;  
527 - }  
528 -  
529 - .product-summary-stat-card--orange .product-summary-stat-card__icon {  
530 - color: #e6a23c;  
531 - }  
532 -  
533 - .product-summary-stat-card--red .product-summary-stat-card__icon {  
534 - color: #f56c6c;  
535 - }  
536 -  
537 - .product-summary-head {  
538 - align-items: center;  
539 - }  
540 -  
541 - .product-summary-head__left {  
542 - display: flex;  
543 - flex-direction: column;  
544 - align-items: flex-start;  
545 - gap: 4px;  
546 - }  
547 -  
548 - .product-summary-head__title {  
549 - font-size: 15px;  
550 - font-weight: 600;  
551 - color: #303133;  
552 - display: inline-flex;  
553 - align-items: center;  
554 - gap: 8px;  
555 - } 409 +.product-summary-head {
  410 + align-items: center;
  411 +}
556 412
557 - .product-summary-head__title-icon {  
558 - color: #409eff;  
559 - font-size: 18px;  
560 - } 413 +.product-summary-head__title {
  414 + font-size: 15px;
  415 + font-weight: 600;
  416 + color: #303133;
  417 + display: inline-flex;
  418 + align-items: center;
  419 + gap: 8px;
  420 +}
561 421
562 - .product-summary-head__hint {  
563 - font-size: 12px;  
564 - color: #909399;  
565 - } 422 +.product-summary-head__title-icon {
  423 + color: #409eff;
  424 + font-size: 18px;
  425 +}
566 426
567 - .product-summary-table {  
568 - ::v-deep .el-table .cell {  
569 - white-space: nowrap;  
570 - } 427 +.product-summary-table {
  428 + ::v-deep .el-table .cell {
  429 + white-space: nowrap;
571 } 430 }
572 } 431 }
573 </style> 432 </style>
Antis.Erp.Plat/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/WtXsckdInfoOutput.cs
@@ -114,9 +114,14 @@ namespace NCC.Extend.Entitys.Dto.WtXsckd @@ -114,9 +114,14 @@ namespace NCC.Extend.Entitys.Dto.WtXsckd
114 public string hysjh { get; set; } 114 public string hysjh { get; set; }
115 115
116 /// <summary> 116 /// <summary>
117 - /// 供应商 117 + /// 往来单位/供应商展示名(采购类单据可能为 wt_wldw 名称)
118 /// </summary> 118 /// </summary>
119 public string gys { get; set; } 119 public string gys { get; set; }
  120 +
  121 + /// <summary>
  122 + /// 与 wt_xsckd.gys 一致的主键(往来单位 wt_wldw 等,供表单下拉 value)
  123 + /// </summary>
  124 + public string gysId { get; set; }
120 125
121 /// <summary> 126 /// <summary>
122 /// 单据状态 127 /// 单据状态
Antis.Erp.Plat/netcore/src/Modularity/Extend/NCC.Extend/WtXsckdService.cs
@@ -1138,6 +1138,26 @@ namespace NCC.Extend.WtXsckd @@ -1138,6 +1138,26 @@ namespace NCC.Extend.WtXsckd
1138 output.hysjh = entity.Hysjh ?? ""; 1138 output.hysjh = entity.Hysjh ?? "";
1139 } 1139 }
1140 1140
  1141 + // 采购入库/采购退货等:gys 常为 wt_wldw 主键;详情表单用 gysId,展示用名称
  1142 + output.gysId = entity.Gys;
  1143 + if (!string.IsNullOrWhiteSpace(entity.Gys))
  1144 + {
  1145 + var wldwGysMc = await _db.Queryable<WtWldwEntity>()
  1146 + .Where(w => w.Id == entity.Gys)
  1147 + .Select(w => w.Dwmc)
  1148 + .FirstAsync();
  1149 + if (!string.IsNullOrWhiteSpace(wldwGysMc))
  1150 + output.gys = wldwGysMc.Trim();
  1151 + else
  1152 + {
  1153 + var legacyGysMc = await _db.Queryable<WtGysEntity>()
  1154 + .Where(g => g.Id == entity.Gys)
  1155 + .Select(g => g.Gysmc)
  1156 + .FirstAsync();
  1157 + output.gys = string.IsNullOrWhiteSpace(legacyGysMc) ? entity.Gys : legacyGysMc.Trim();
  1158 + }
  1159 + }
  1160 +
1141 // ✅ 经手人/制单人/审核人/过账人:与列表一致,将用户 ID 转为姓名(详情页展示) 1161 // ✅ 经手人/制单人/审核人/过账人:与列表一致,将用户 ID 转为姓名(详情页展示)
1142 await EnrichInfoOutputUserDisplayNamesAsync(output, entity); 1162 await EnrichInfoOutputUserDisplayNamesAsync(output, entity);
1143 1163
@@ -1263,6 +1283,7 @@ namespace NCC.Extend.WtXsckd @@ -1263,6 +1283,7 @@ namespace NCC.Extend.WtXsckd
1263 .WhereIF(!string.IsNullOrEmpty(input.gzr), (xsckd, hy) => xsckd.Gzr.Equals(input.gzr)) 1283 .WhereIF(!string.IsNullOrEmpty(input.gzr), (xsckd, hy) => xsckd.Gzr.Equals(input.gzr))
1264 .WhereIF(!string.IsNullOrEmpty(input.bz), (xsckd, hy) => xsckd.Bz.Contains(input.bz)) 1284 .WhereIF(!string.IsNullOrEmpty(input.bz), (xsckd, hy) => xsckd.Bz.Contains(input.bz))
1265 .WhereIF(!string.IsNullOrEmpty(input.kh), (xsckd, hy) => xsckd.Kh.Contains(input.kh)) 1285 .WhereIF(!string.IsNullOrEmpty(input.kh), (xsckd, hy) => xsckd.Kh.Contains(input.kh))
  1286 + .WhereIF(!string.IsNullOrEmpty(input.gys), (xsckd, hy) => xsckd.Gys == input.gys.Trim())
1266 .WhereIF(!string.IsNullOrEmpty(input.hysjh), (xsckd, hy) => 1287 .WhereIF(!string.IsNullOrEmpty(input.hysjh), (xsckd, hy) =>
1267 (xsckd.Hysjh != null && xsckd.Hysjh.Contains(input.hysjh)) || 1288 (xsckd.Hysjh != null && xsckd.Hysjh.Contains(input.hysjh)) ||
1268 (hy.Sjh != null && hy.Sjh.Contains(input.hysjh))) 1289 (hy.Sjh != null && hy.Sjh.Contains(input.hysjh)))
@@ -1332,6 +1353,7 @@ namespace NCC.Extend.WtXsckd @@ -1332,6 +1353,7 @@ namespace NCC.Extend.WtXsckd
1332 EnrichListOutputYcddhFromRemarkIfNeeded(row); 1353 EnrichListOutputYcddhFromRemarkIfNeeded(row);
1333 await EnrichWtXsckdListWarehouseDisplayAsync(pageRows); 1354 await EnrichWtXsckdListWarehouseDisplayAsync(pageRows);
1334 await EnrichListOutputKhDisplayAsync(pageRows); 1355 await EnrichListOutputKhDisplayAsync(pageRows);
  1356 + await EnrichListOutputGysWldwDisplayAsync(pageRows);
1335 await EnrichListPersonDisplayFromMemberHyAsync(pageRows); 1357 await EnrichListPersonDisplayFromMemberHyAsync(pageRows);
1336 if (pageRows.Any(x => x.djlx == "销售出库单" || x.djlx == "预售出库单")) 1358 if (pageRows.Any(x => x.djlx == "销售出库单" || x.djlx == "预售出库单"))
1337 await EnrichOutboundLinkedReturnBillsAsync(pageRows); 1359 await EnrichOutboundLinkedReturnBillsAsync(pageRows);
@@ -1467,6 +1489,48 @@ namespace NCC.Extend.WtXsckd @@ -1467,6 +1489,48 @@ namespace NCC.Extend.WtXsckd
1467 } 1489 }
1468 1490
1469 /// <summary> 1491 /// <summary>
  1492 + /// 列表:采购入库/采购退货等主表 <c>gys</c> 存 wt_wldw 主键时,将 <c>gys</c> 列展示为往来单位名称(原 SQL 子查 wt_gys 可能为空)。
  1493 + /// </summary>
  1494 + private async Task EnrichListOutputGysWldwDisplayAsync(List<WtXsckdListOutput> items)
  1495 + {
  1496 + if (items == null || items.Count == 0) return;
  1497 + var targets = items.Where(x => x.djlx == "采购入库单" || x.djlx == "采购退货单").ToList();
  1498 + if (targets.Count == 0) return;
  1499 + var billIds = targets.Select(x => x.id).Where(id => !string.IsNullOrEmpty(id)).Select(id => id.Trim()).Distinct().ToList();
  1500 + if (billIds.Count == 0) return;
  1501 + var heads = await _db.Queryable<WtXsckdEntity>()
  1502 + .Where(x => billIds.Contains(x.Id))
  1503 + .Select(x => new { x.Id, x.Gys })
  1504 + .ToListAsync();
  1505 + var gysByBill = heads
  1506 + .Where(h => !string.IsNullOrEmpty(h.Id))
  1507 + .ToDictionary(h => h.Id.Trim(), h => h.Gys ?? "", StringComparer.Ordinal);
  1508 + var rawGysIds = gysByBill.Values
  1509 + .Where(s => !string.IsNullOrWhiteSpace(s))
  1510 + .Select(s => s.Trim())
  1511 + .Distinct()
  1512 + .ToList();
  1513 + if (rawGysIds.Count == 0) return;
  1514 + var wldwRows = await _db.Queryable<WtWldwEntity>()
  1515 + .Where(w => rawGysIds.Contains(w.Id))
  1516 + .Select(w => new { w.Id, w.Dwmc })
  1517 + .ToListAsync();
  1518 + var wldwDwmcById = wldwRows
  1519 + .Where(x => !string.IsNullOrEmpty(x.Id))
  1520 + .ToDictionary(x => x.Id.Trim(), x => x.Dwmc ?? "", StringComparer.Ordinal);
  1521 +
  1522 + foreach (var row in targets)
  1523 + {
  1524 + var bid = row.id?.Trim();
  1525 + if (string.IsNullOrEmpty(bid) || !gysByBill.TryGetValue(bid, out var rawGys) || string.IsNullOrWhiteSpace(rawGys))
  1526 + continue;
  1527 + var key = rawGys.Trim();
  1528 + if (wldwDwmcById.TryGetValue(key, out var dwmc) && !string.IsNullOrWhiteSpace(dwmc))
  1529 + row.gys = dwmc.Trim();
  1530 + }
  1531 + }
  1532 +
  1533 + /// <summary>
1470 /// 销售/预售退货单:经手人应为操作人(系统用户),非会员。 1534 /// 销售/预售退货单:经手人应为操作人(系统用户),非会员。
1471 /// </summary> 1535 /// </summary>
1472 private static bool IsSalesOrPresaleReturnDjlx(string? djlx) => 1536 private static bool IsSalesOrPresaleReturnDjlx(string? djlx) =>
@@ -2268,6 +2332,7 @@ namespace NCC.Extend.WtXsckd @@ -2268,6 +2332,7 @@ namespace NCC.Extend.WtXsckd
2268 .WhereIF(!string.IsNullOrEmpty(input.gzr), (xsckd, hy) => xsckd.Gzr.Equals(input.gzr)) 2332 .WhereIF(!string.IsNullOrEmpty(input.gzr), (xsckd, hy) => xsckd.Gzr.Equals(input.gzr))
2269 .WhereIF(!string.IsNullOrEmpty(input.bz), (xsckd, hy) => xsckd.Bz.Contains(input.bz)) 2333 .WhereIF(!string.IsNullOrEmpty(input.bz), (xsckd, hy) => xsckd.Bz.Contains(input.bz))
2270 .WhereIF(!string.IsNullOrEmpty(input.kh), (xsckd, hy) => xsckd.Kh.Contains(input.kh)) 2334 .WhereIF(!string.IsNullOrEmpty(input.kh), (xsckd, hy) => xsckd.Kh.Contains(input.kh))
  2335 + .WhereIF(!string.IsNullOrEmpty(input.gys), (xsckd, hy) => xsckd.Gys == input.gys.Trim())
2271 .WhereIF(!string.IsNullOrEmpty(input.hysjh), (xsckd, hy) => 2336 .WhereIF(!string.IsNullOrEmpty(input.hysjh), (xsckd, hy) =>
2272 (xsckd.Hysjh != null && xsckd.Hysjh.Contains(input.hysjh)) || 2337 (xsckd.Hysjh != null && xsckd.Hysjh.Contains(input.hysjh)) ||
2273 (hy.Sjh != null && hy.Sjh.Contains(input.hysjh))) 2338 (hy.Sjh != null && hy.Sjh.Contains(input.hysjh)))
@@ -2316,6 +2381,7 @@ namespace NCC.Extend.WtXsckd @@ -2316,6 +2381,7 @@ namespace NCC.Extend.WtXsckd
2316 EnrichListOutputYcddhFromRemarkIfNeeded(row); 2381 EnrichListOutputYcddhFromRemarkIfNeeded(row);
2317 await EnrichWtXsckdListWarehouseDisplayAsync(data); 2382 await EnrichWtXsckdListWarehouseDisplayAsync(data);
2318 await EnrichListOutputKhDisplayAsync(data); 2383 await EnrichListOutputKhDisplayAsync(data);
  2384 + await EnrichListOutputGysWldwDisplayAsync(data);
2319 await EnrichListPersonDisplayFromMemberHyAsync(data); 2385 await EnrichListPersonDisplayFromMemberHyAsync(data);
2320 await EnrichOutboundLinkedReturnBillsAsync(data); 2386 await EnrichOutboundLinkedReturnBillsAsync(data);
2321 if (data.Any(x => x.djlx == "预售出库单")) 2387 if (data.Any(x => x.djlx == "预售出库单"))