|
|
@@ -0,0 +1,943 @@
|
|
|
1
|
+<template>
|
|
|
2
|
+ <div class="contract-container">
|
|
|
3
|
+ <h1>采购合同管理 - 期初数据批量导入</h1>
|
|
|
4
|
+
|
|
|
5
|
+ <!-- 文件导入区域 -->
|
|
|
6
|
+ <div class="import-section">
|
|
|
7
|
+ <el-upload
|
|
|
8
|
+ class="upload-demo"
|
|
|
9
|
+ action=""
|
|
|
10
|
+ :auto-upload="false"
|
|
|
11
|
+ :on-change="handleFileChange"
|
|
|
12
|
+ :show-file-list="true"
|
|
|
13
|
+ accept=".xlsx,.xls"
|
|
|
14
|
+ :multiple="false"
|
|
|
15
|
+ drag
|
|
|
16
|
+ >
|
|
|
17
|
+ <el-icon class="el-icon--upload"><UploadFilled /></el-icon>
|
|
|
18
|
+ <div class="el-upload__text">
|
|
|
19
|
+ 拖放文件到此处,或 <em>点击上传</em>
|
|
|
20
|
+ </div>
|
|
|
21
|
+ <template #tip>
|
|
|
22
|
+ <div class="el-upload__tip">
|
|
|
23
|
+ 请上传符合模板格式的Excel文件(.xlsx/.xls),支持"采购合同导入模板2.0改.xlsx"格式
|
|
|
24
|
+ </div>
|
|
|
25
|
+ </template>
|
|
|
26
|
+ </el-upload>
|
|
|
27
|
+
|
|
|
28
|
+ <div class="import-actions">
|
|
|
29
|
+ <el-button type="primary" @click="handleImport" :disabled="!selectedFile" :loading="importLoading">
|
|
|
30
|
+ {{ importLoading ? '导入中...' : '导入文件' }}
|
|
|
31
|
+ </el-button>
|
|
|
32
|
+ <el-button @click="handleDownloadTemplate">下载模板</el-button>
|
|
|
33
|
+ <el-button type="warning" @click="handleBatchSave" :disabled="!contractsData || contractsData.main.length === 0" :loading="saveLoading">
|
|
|
34
|
+ {{ saveLoading ? '批量保存中...' : '批量保存所有合同' }}
|
|
|
35
|
+ </el-button>
|
|
|
36
|
+ </div>
|
|
|
37
|
+
|
|
|
38
|
+ <!-- 导入进度和统计信息 -->
|
|
|
39
|
+ <div v-if="importStats" class="import-stats">
|
|
|
40
|
+ <el-alert
|
|
|
41
|
+ title="导入统计"
|
|
|
42
|
+ type="info"
|
|
|
43
|
+ :closable="false"
|
|
|
44
|
+ show-icon
|
|
|
45
|
+ >
|
|
|
46
|
+ <div class="stats-content">
|
|
|
47
|
+ <span>合同总数: {{ importStats.contractCount }} 个</span>
|
|
|
48
|
+ <span>产品明细: {{ importStats.productsCount }} 条</span>
|
|
|
49
|
+ <span>付款计划: {{ importStats.paymentsCount }} 条</span>
|
|
|
50
|
+ <span>责任中心: {{ importStats.responsibilityCount }} 条</span>
|
|
|
51
|
+ </div>
|
|
|
52
|
+ </el-alert>
|
|
|
53
|
+ </div>
|
|
|
54
|
+ </div>
|
|
|
55
|
+
|
|
|
56
|
+ <!-- 合同数据展示区域 -->
|
|
|
57
|
+ <div class="contracts-info" v-if="contractsData && contractsData.main.length > 0">
|
|
|
58
|
+ <el-tabs v-model="activeTab" type="border-card">
|
|
|
59
|
+ <!-- 合同主表信息 -->
|
|
|
60
|
+ <el-tab-pane label="合同基本信息" name="main">
|
|
|
61
|
+ <div class="table-section">
|
|
|
62
|
+ <el-table
|
|
|
63
|
+ :data="paginatedContracts"
|
|
|
64
|
+ style="width: 100%"
|
|
|
65
|
+ v-loading="tableLoading"
|
|
|
66
|
+ border
|
|
|
67
|
+ height="600"
|
|
|
68
|
+ :default-sort="{ prop: 'fno', order: 'ascending' }"
|
|
|
69
|
+ >
|
|
|
70
|
+ <el-table-column prop="fno" label="采购合同号" width="180" fixed="left"></el-table-column>
|
|
|
71
|
+ <el-table-column prop="contractName" label="合同名称" width="200"></el-table-column>
|
|
|
72
|
+ <el-table-column prop="bizType" label="合同类型" width="120"></el-table-column>
|
|
|
73
|
+ <el-table-column prop="bizProductType" label="合同产品类型" width="120"></el-table-column>
|
|
|
74
|
+ <el-table-column prop="serviceType" label="业务类型" width="120"></el-table-column>
|
|
|
75
|
+ <el-table-column prop="curcy" label="币别" width="100"></el-table-column>
|
|
|
76
|
+ <el-table-column prop="supName" label="供应商名称" width="200"></el-table-column>
|
|
|
77
|
+ <el-table-column prop="supCode" label="供应商代码" width="120"></el-table-column>
|
|
|
78
|
+ <el-table-column prop="supContact" label="供应商联系人" width="120"></el-table-column>
|
|
|
79
|
+ <el-table-column prop="supBank" label="供应商开户银行" width="180"></el-table-column>
|
|
|
80
|
+ <el-table-column prop="supAcc" label="供应商银行账户" width="150"></el-table-column>
|
|
|
81
|
+ <el-table-column prop="fours" label="我方编号" width="120"></el-table-column>
|
|
|
82
|
+ <el-table-column prop="foursname" label="我方名称" width="180"></el-table-column>
|
|
|
83
|
+ <el-table-column prop="ourBankNm" label="我方开户银行" width="180"></el-table-column>
|
|
|
84
|
+ <el-table-column prop="ourBankAcct" label="我方银行账号" width="150"></el-table-column>
|
|
|
85
|
+ <el-table-column prop="createBy" label="制单人代码" width="120"></el-table-column>
|
|
|
86
|
+ <el-table-column prop="createByName" label="制单人名称" width="120"></el-table-column>
|
|
|
87
|
+ <el-table-column prop="contrExecCd" label="合同执行人代码" width="140"></el-table-column>
|
|
|
88
|
+ <el-table-column prop="contrExecNm" label="合同执行人名称" width="140"></el-table-column>
|
|
|
89
|
+ <el-table-column prop="ifLongTerm" label="是否长协" width="100">
|
|
|
90
|
+ <template #default="scope">
|
|
|
91
|
+ <el-tag :type="scope.row.ifLongTerm === '是' ? 'success' : 'info'">
|
|
|
92
|
+ {{ scope.row.ifLongTerm || '否' }}
|
|
|
93
|
+ </el-tag>
|
|
|
94
|
+ </template>
|
|
|
95
|
+ </el-table-column>
|
|
|
96
|
+ <el-table-column prop="ifClearBottom" label="是否清底" width="100">
|
|
|
97
|
+ <template #default="scope">
|
|
|
98
|
+ <el-tag :type="scope.row.ifClearBottom === '是' ? 'success' : 'info'">
|
|
|
99
|
+ {{ scope.row.ifClearBottom || '否' }}
|
|
|
100
|
+ </el-tag>
|
|
|
101
|
+ </template>
|
|
|
102
|
+ </el-table-column>
|
|
|
103
|
+ <el-table-column prop="fundOccupyFlg" label="是否占用资金" width="120">
|
|
|
104
|
+ <template #default="scope">
|
|
|
105
|
+ <el-tag :type="scope.row.fundOccupyFlg === '是' ? 'success' : 'info'">
|
|
|
106
|
+ {{ scope.row.fundOccupyFlg || '否' }}
|
|
|
107
|
+ </el-tag>
|
|
|
108
|
+ </template>
|
|
|
109
|
+ </el-table-column>
|
|
|
110
|
+ <el-table-column prop="ifBidding" label="是否招投标" width="120">
|
|
|
111
|
+ <template #default="scope">
|
|
|
112
|
+ {{ scope.row.ifBidding || '-' }}
|
|
|
113
|
+ </template>
|
|
|
114
|
+ </el-table-column>
|
|
|
115
|
+ <el-table-column prop="lPort" label="装运港" width="120"></el-table-column>
|
|
|
116
|
+ <el-table-column prop="lPortCtry" label="装运国" width="120"></el-table-column>
|
|
|
117
|
+ <el-table-column prop="dPort" label="目的港" width="120"></el-table-column>
|
|
|
118
|
+ <el-table-column prop="dPortCtry" label="目的国" width="120"></el-table-column>
|
|
|
119
|
+ <el-table-column prop="tranWay" label="运输方式" width="120"></el-table-column>
|
|
|
120
|
+ <el-table-column prop="delivMtd" label="交货方式" width="120"></el-table-column>
|
|
|
121
|
+ <el-table-column prop="delivLoc" label="交货地点" width="120"></el-table-column>
|
|
|
122
|
+ <el-table-column prop="estArrDt" label="最迟集港日期" width="120"></el-table-column>
|
|
|
123
|
+ <el-table-column prop="estLoadDt" label="最迟装运日期" width="120"></el-table-column>
|
|
|
124
|
+ <el-table-column prop="whetherChartering" label="是否租船" width="100">
|
|
|
125
|
+ <template #default="scope">
|
|
|
126
|
+ <el-tag :type="scope.row.whetherChartering === '是' ? 'success' : 'info'">
|
|
|
127
|
+ {{ scope.row.whetherChartering || '否' }}
|
|
|
128
|
+ </el-tag>
|
|
|
129
|
+ </template>
|
|
|
130
|
+ </el-table-column>
|
|
|
131
|
+ <el-table-column prop="chnShipName" label="中文船名" width="120"></el-table-column>
|
|
|
132
|
+ <el-table-column prop="engShipName" label="英文船名" width="120"></el-table-column>
|
|
|
133
|
+ <el-table-column prop="terms" label="价格条款" width="120"></el-table-column>
|
|
|
134
|
+ <el-table-column prop="rate" label="人民币汇率" width="120">
|
|
|
135
|
+ <template #default="scope">
|
|
|
136
|
+ {{ formatNumber(scope.row.rate) }}
|
|
|
137
|
+ </template>
|
|
|
138
|
+ </el-table-column>
|
|
|
139
|
+ <el-table-column prop="rateUs" label="美元汇率" width="120">
|
|
|
140
|
+ <template #default="scope">
|
|
|
141
|
+ {{ formatNumber(scope.row.rateUs) }}
|
|
|
142
|
+ </template>
|
|
|
143
|
+ </el-table-column>
|
|
|
144
|
+ <el-table-column prop="qtyOver" label="数量溢装%" width="120">
|
|
|
145
|
+ <template #default="scope">
|
|
|
146
|
+ {{ scope.row.qtyOver || '0' }}
|
|
|
147
|
+ </template>
|
|
|
148
|
+ </el-table-column>
|
|
|
149
|
+ <el-table-column prop="qtyShort" label="数量短装%" width="120">
|
|
|
150
|
+ <template #default="scope">
|
|
|
151
|
+ {{ scope.row.qtyShort || '0' }}
|
|
|
152
|
+ </template>
|
|
|
153
|
+ </el-table-column>
|
|
|
154
|
+ <el-table-column prop="amtOver" label="金额溢装%" width="120">
|
|
|
155
|
+ <template #default="scope">
|
|
|
156
|
+ {{ scope.row.amtOver || '0' }}
|
|
|
157
|
+ </template>
|
|
|
158
|
+ </el-table-column>
|
|
|
159
|
+ <el-table-column prop="amtShort" label="金额短装%" width="120">
|
|
|
160
|
+ <template #default="scope">
|
|
|
161
|
+ {{ scope.row.amtShort || '0' }}
|
|
|
162
|
+ </template>
|
|
|
163
|
+ </el-table-column>
|
|
|
164
|
+ <el-table-column prop="insuranceType" label="保险种类" width="120"></el-table-column>
|
|
|
165
|
+ <el-table-column prop="insuranceAmt" label="保险费率%" width="120">
|
|
|
166
|
+ <template #default="scope">
|
|
|
167
|
+ {{ scope.row.insuranceAmt || '0' }}
|
|
|
168
|
+ </template>
|
|
|
169
|
+ </el-table-column>
|
|
|
170
|
+ <el-table-column prop="signLoc" label="签约地点" width="120"></el-table-column>
|
|
|
171
|
+ <el-table-column prop="contrDesc" label="合同描述" width="200">
|
|
|
172
|
+ <template #default="scope">
|
|
|
173
|
+ <el-tooltip :content="scope.row.contrDesc" placement="top" v-if="scope.row.contrDesc">
|
|
|
174
|
+ <span class="text-ellipsis">{{ scope.row.contrDesc }}</span>
|
|
|
175
|
+ </el-tooltip>
|
|
|
176
|
+ <span v-else>-</span>
|
|
|
177
|
+ </template>
|
|
|
178
|
+ </el-table-column>
|
|
|
179
|
+ <el-table-column prop="remark" label="备注" width="200">
|
|
|
180
|
+ <template #default="scope">
|
|
|
181
|
+ <el-tooltip :content="scope.row.remark" placement="top" v-if="scope.row.remark">
|
|
|
182
|
+ <span class="text-ellipsis">{{ scope.row.remark }}</span>
|
|
|
183
|
+ </el-tooltip>
|
|
|
184
|
+ <span v-else>-</span>
|
|
|
185
|
+ </template>
|
|
|
186
|
+ </el-table-column>
|
|
|
187
|
+ </el-table>
|
|
|
188
|
+ <div class="pagination-section" v-if="contractsData.main.length > 0">
|
|
|
189
|
+ <el-pagination
|
|
|
190
|
+ :total="contractsData.main.length"
|
|
|
191
|
+ :page-size="pageSize"
|
|
|
192
|
+ :current-page="currentPage"
|
|
|
193
|
+ @current-change="handlePageChange"
|
|
|
194
|
+ layout="total, prev, pager, next, jumper"
|
|
|
195
|
+ />
|
|
|
196
|
+ </div>
|
|
|
197
|
+ </div>
|
|
|
198
|
+ </el-tab-pane>
|
|
|
199
|
+
|
|
|
200
|
+ <!-- 合同产品明细 -->
|
|
|
201
|
+ <el-tab-pane label="合同产品明细" name="products">
|
|
|
202
|
+ <div class="table-section">
|
|
|
203
|
+ <el-table
|
|
|
204
|
+ :data="paginatedProducts"
|
|
|
205
|
+ style="width: 100%"
|
|
|
206
|
+ height="600"
|
|
|
207
|
+ v-loading="tableLoading"
|
|
|
208
|
+ border
|
|
|
209
|
+ :default-sort="{ prop: 'fno', order: 'ascending' }"
|
|
|
210
|
+ >
|
|
|
211
|
+ <el-table-column prop="fno" label="采购合同号" width="150" fixed="left"></el-table-column>
|
|
|
212
|
+ <el-table-column prop="itemno" label="商品编号" width="120"></el-table-column>
|
|
|
213
|
+ <el-table-column prop="sdesc" label="中文品名" width="150"></el-table-column>
|
|
|
214
|
+ <el-table-column prop="edesc" label="英文品名" width="150"></el-table-column>
|
|
|
215
|
+ <el-table-column prop="brand" label="牌号" width="100">
|
|
|
216
|
+ <template #default="scope">
|
|
|
217
|
+ {{ scope.row.brand || '-' }}
|
|
|
218
|
+ </template>
|
|
|
219
|
+ </el-table-column>
|
|
|
220
|
+ <el-table-column prop="ftype3" label="规格描述" width="120">
|
|
|
221
|
+ <template #default="scope">
|
|
|
222
|
+ {{ scope.row.ftype3 || '-' }}
|
|
|
223
|
+ </template>
|
|
|
224
|
+ </el-table-column>
|
|
|
225
|
+ <el-table-column prop="resourceNo" label="资源号" width="120">
|
|
|
226
|
+ <template #default="scope">
|
|
|
227
|
+ {{ scope.row.resourceNo || '-' }}
|
|
|
228
|
+ </template>
|
|
|
229
|
+ </el-table-column>
|
|
|
230
|
+ <el-table-column prop="SMRNo" label="钢厂资源号" width="120">
|
|
|
231
|
+ <template #default="scope">
|
|
|
232
|
+ {{ scope.row.SMRNo || '-' }}
|
|
|
233
|
+ </template>
|
|
|
234
|
+ </el-table-column>
|
|
|
235
|
+ <el-table-column prop="batchNo" label="批次号" width="120">
|
|
|
236
|
+ <template #default="scope">
|
|
|
237
|
+ {{ scope.row.batchNo || '-' }}
|
|
|
238
|
+ </template>
|
|
|
239
|
+ </el-table-column>
|
|
|
240
|
+ <el-table-column prop="curcyPo" label="采购币种" width="100"></el-table-column>
|
|
|
241
|
+ <el-table-column prop="qty" label="数量" width="100">
|
|
|
242
|
+ <template #default="scope">
|
|
|
243
|
+ {{ formatNumber(scope.row.qty) }}
|
|
|
244
|
+ </template>
|
|
|
245
|
+ </el-table-column>
|
|
|
246
|
+ <el-table-column prop="poprice" label="采购单价" width="100">
|
|
|
247
|
+ <template #default="scope">
|
|
|
248
|
+ {{ formatNumber(scope.row.poprice) }}
|
|
|
249
|
+ </template>
|
|
|
250
|
+ </el-table-column>
|
|
|
251
|
+ <el-table-column prop="poamt" label="金额" width="100">
|
|
|
252
|
+ <template #default="scope">
|
|
|
253
|
+ {{ formatNumber(scope.row.poamt) }}
|
|
|
254
|
+ </template>
|
|
|
255
|
+ </el-table-column>
|
|
|
256
|
+ <el-table-column prop="inTaxRate" label="增值税率%" width="100">
|
|
|
257
|
+ <template #default="scope">
|
|
|
258
|
+ {{ scope.row.inTaxRate || '-' }}
|
|
|
259
|
+ </template>
|
|
|
260
|
+ </el-table-column>
|
|
|
261
|
+ <el-table-column prop="ironCont" label="含铁量%" width="100">
|
|
|
262
|
+ <template #default="scope">
|
|
|
263
|
+ {{ scope.row.ironCont || '-' }}
|
|
|
264
|
+ </template>
|
|
|
265
|
+ </el-table-column>
|
|
|
266
|
+ <el-table-column prop="moisture" label="水分%" width="80">
|
|
|
267
|
+ <template #default="scope">
|
|
|
268
|
+ {{ scope.row.moisture || '-' }}
|
|
|
269
|
+ </template>
|
|
|
270
|
+ </el-table-column>
|
|
|
271
|
+ <el-table-column prop="coalMoisture" label="煤焦计价水%" width="120">
|
|
|
272
|
+ <template #default="scope">
|
|
|
273
|
+ {{ scope.row.coalMoisture || '-' }}
|
|
|
274
|
+ </template>
|
|
|
275
|
+ </el-table-column>
|
|
|
276
|
+ <el-table-column prop="priceMtd" label="计价方式" width="100">
|
|
|
277
|
+ <template #default="scope">
|
|
|
278
|
+ {{ scope.row.priceMtd || '-' }}
|
|
|
279
|
+ </template>
|
|
|
280
|
+ </el-table-column>
|
|
|
281
|
+ <el-table-column prop="ratePo" label="采购汇率" width="100">
|
|
|
282
|
+ <template #default="scope">
|
|
|
283
|
+ {{ scope.row.ratePo || '-' }}
|
|
|
284
|
+ </template>
|
|
|
285
|
+ </el-table-column>
|
|
|
286
|
+ <el-table-column prop="reTaxRate" label="退税率%" width="100">
|
|
|
287
|
+ <template #default="scope">
|
|
|
288
|
+ {{ scope.row.reTaxRate || '-' }}
|
|
|
289
|
+ </template>
|
|
|
290
|
+ </el-table-column>
|
|
|
291
|
+ <el-table-column prop="ut" label="单位" width="80"></el-table-column>
|
|
|
292
|
+ <el-table-column prop="ftype4" label="计重方式" width="100">
|
|
|
293
|
+ <template #default="scope">
|
|
|
294
|
+ {{ scope.row.ftype4 || '-' }}
|
|
|
295
|
+ </template>
|
|
|
296
|
+ </el-table-column>
|
|
|
297
|
+ <el-table-column prop="fnw" label="净重" width="100">
|
|
|
298
|
+ <template #default="scope">
|
|
|
299
|
+ {{ formatNumber(scope.row.fnw) }}
|
|
|
300
|
+ </template>
|
|
|
301
|
+ </el-table-column>
|
|
|
302
|
+ <el-table-column prop="fgw" label="毛重" width="100">
|
|
|
303
|
+ <template #default="scope">
|
|
|
304
|
+ {{ formatNumber(scope.row.fgw) }}
|
|
|
305
|
+ </template>
|
|
|
306
|
+ </el-table-column>
|
|
|
307
|
+ <el-table-column prop="taxAmt" label="税额" width="100">
|
|
|
308
|
+ <template #default="scope">
|
|
|
309
|
+ {{ formatNumber(scope.row.taxAmt) }}
|
|
|
310
|
+ </template>
|
|
|
311
|
+ </el-table-column>
|
|
|
312
|
+ <el-table-column prop="spec" label="QP描述" width="150">
|
|
|
313
|
+ <template #default="scope">
|
|
|
314
|
+ {{ scope.row.spec || '-' }}
|
|
|
315
|
+ </template>
|
|
|
316
|
+ </el-table-column>
|
|
|
317
|
+ <el-table-column prop="hsCode" label="海关编码" width="120">
|
|
|
318
|
+ <template #default="scope">
|
|
|
319
|
+ {{ scope.row.hsCode || '-' }}
|
|
|
320
|
+ </template>
|
|
|
321
|
+ </el-table-column>
|
|
|
322
|
+ <el-table-column prop="hsNameCn" label="海关中文名称" width="150">
|
|
|
323
|
+ <template #default="scope">
|
|
|
324
|
+ {{ scope.row.hsNameCn || '-' }}
|
|
|
325
|
+ </template>
|
|
|
326
|
+ </el-table-column>
|
|
|
327
|
+ <el-table-column prop="hsNameEn" label="海关英文名称" width="150">
|
|
|
328
|
+ <template #default="scope">
|
|
|
329
|
+ {{ scope.row.hsNameEn || '-' }}
|
|
|
330
|
+ </template>
|
|
|
331
|
+ </el-table-column>
|
|
|
332
|
+ <el-table-column prop="dryTonQty" label="干吨数量" width="100">
|
|
|
333
|
+ <template #default="scope">
|
|
|
334
|
+ {{ formatNumber(scope.row.dryTonQty) }}
|
|
|
335
|
+ </template>
|
|
|
336
|
+ </el-table-column>
|
|
|
337
|
+ <el-table-column prop="wetTonQty" label="湿吨数量" width="100">
|
|
|
338
|
+ <template #default="scope">
|
|
|
339
|
+ {{ formatNumber(scope.row.wetTonQty) }}
|
|
|
340
|
+ </template>
|
|
|
341
|
+ </el-table-column>
|
|
|
342
|
+ <el-table-column prop="ftype5" label="色标" width="80">
|
|
|
343
|
+ <template #default="scope">
|
|
|
344
|
+ {{ scope.row.ftype5 || '-' }}
|
|
|
345
|
+ </template>
|
|
|
346
|
+ </el-table-column>
|
|
|
347
|
+ <el-table-column prop="dutyRate" label="进口关税税率%" width="120">
|
|
|
348
|
+ <template #default="scope">
|
|
|
349
|
+ {{ scope.row.dutyRate || '-' }}
|
|
|
350
|
+ </template>
|
|
|
351
|
+ </el-table-column>
|
|
|
352
|
+ <el-table-column prop="ntPoAmt" label="未税金额" width="100">
|
|
|
353
|
+ <template #default="scope">
|
|
|
354
|
+ {{ formatNumber(scope.row.ntPoAmt) }}
|
|
|
355
|
+ </template>
|
|
|
356
|
+ </el-table-column>
|
|
|
357
|
+ <el-table-column prop="ntPoPrice" label="未税单价" width="100">
|
|
|
358
|
+ <template #default="scope">
|
|
|
359
|
+ {{ formatNumber(scope.row.ntPoPrice) }}
|
|
|
360
|
+ </template>
|
|
|
361
|
+ </el-table-column>
|
|
|
362
|
+ <el-table-column prop="amtRate" label="金额占比" width="100">
|
|
|
363
|
+ <template #default="scope">
|
|
|
364
|
+ {{ scope.row.amtRate || '-' }}
|
|
|
365
|
+ </template>
|
|
|
366
|
+ </el-table-column>
|
|
|
367
|
+ <el-table-column prop="cnypoamt" label="人民币含税金额" width="140">
|
|
|
368
|
+ <template #default="scope">
|
|
|
369
|
+ {{ formatNumber(scope.row.cnypoamt) }}
|
|
|
370
|
+ </template>
|
|
|
371
|
+ </el-table-column>
|
|
|
372
|
+ <el-table-column prop="usdpoamt" label="美元含税金额" width="140">
|
|
|
373
|
+ <template #default="scope">
|
|
|
374
|
+ {{ formatNumber(scope.row.usdpoamt) }}
|
|
|
375
|
+ </template>
|
|
|
376
|
+ </el-table-column>
|
|
|
377
|
+ <el-table-column prop="remark" label="备注" width="150">
|
|
|
378
|
+ <template #default="scope">
|
|
|
379
|
+ <el-tooltip :content="scope.row.remark" placement="top" v-if="scope.row.remark">
|
|
|
380
|
+ <span class="text-ellipsis">{{ scope.row.remark }}</span>
|
|
|
381
|
+ </el-tooltip>
|
|
|
382
|
+ <span v-else>-</span>
|
|
|
383
|
+ </template>
|
|
|
384
|
+ </el-table-column>
|
|
|
385
|
+ </el-table>
|
|
|
386
|
+ <div class="pagination-section" v-if="allProducts.length > 0">
|
|
|
387
|
+ <el-pagination
|
|
|
388
|
+ :total="allProducts.length"
|
|
|
389
|
+ :page-size="productPageSize"
|
|
|
390
|
+ :current-page="productCurrentPage"
|
|
|
391
|
+ @current-change="handleProductPageChange"
|
|
|
392
|
+ layout="total, prev, pager, next, jumper"
|
|
|
393
|
+ />
|
|
|
394
|
+ </div>
|
|
|
395
|
+ </div>
|
|
|
396
|
+ </el-tab-pane>
|
|
|
397
|
+
|
|
|
398
|
+ <!-- 付款计划 -->
|
|
|
399
|
+ <el-tab-pane label="付款计划" name="payments">
|
|
|
400
|
+ <div class="table-section">
|
|
|
401
|
+ <el-table :data="allPayments" style="width: 100%" border height="500">
|
|
|
402
|
+ <el-table-column prop="fno" label="采购合同号" width="150" fixed="left"></el-table-column>
|
|
|
403
|
+ <el-table-column prop="create_by" label="制单人代码" width="120"></el-table-column>
|
|
|
404
|
+ <el-table-column prop="dept_name" label="部门名称" width="150"></el-table-column>
|
|
|
405
|
+ <el-table-column prop="payMethod" label="付款方式" width="120"></el-table-column>
|
|
|
406
|
+ <el-table-column prop="payType" label="款项类别" width="120"></el-table-column>
|
|
|
407
|
+ <el-table-column prop="payDays" label="账期(天)" width="100">
|
|
|
408
|
+ <template #default="scope">
|
|
|
409
|
+ {{ scope.row.payDays || '0' }}
|
|
|
410
|
+ </template>
|
|
|
411
|
+ </el-table-column>
|
|
|
412
|
+ <el-table-column prop="payRatio" label="款项比例%" width="120">
|
|
|
413
|
+ <template #default="scope">
|
|
|
414
|
+ {{ scope.row.payRatio || '0' }}
|
|
|
415
|
+ </template>
|
|
|
416
|
+ </el-table-column>
|
|
|
417
|
+ <el-table-column prop="payAmt" label="金额" width="120">
|
|
|
418
|
+ <template #default="scope">
|
|
|
419
|
+ {{ formatNumber(scope.row.payAmt) }}
|
|
|
420
|
+ </template>
|
|
|
421
|
+ </el-table-column>
|
|
|
422
|
+ </el-table>
|
|
|
423
|
+ </div>
|
|
|
424
|
+ </el-tab-pane>
|
|
|
425
|
+
|
|
|
426
|
+ <!-- 责任中心 -->
|
|
|
427
|
+ <el-tab-pane label="责任中心" name="responsibility">
|
|
|
428
|
+ <div class="table-section">
|
|
|
429
|
+ <el-table :data="allResponsibilities" style="width: 100%" border height="500">
|
|
|
430
|
+ <el-table-column prop="fno" label="采购合同号" width="150" fixed="left"></el-table-column>
|
|
|
431
|
+ <el-table-column prop="create_by" label="制单人代码" width="120"></el-table-column>
|
|
|
432
|
+ <el-table-column prop="personDeptNm" label="部门名称" width="150"></el-table-column>
|
|
|
433
|
+ <el-table-column prop="assessQtyRate" label="利润考核占比%" width="120">
|
|
|
434
|
+ <template #default="scope">
|
|
|
435
|
+ {{ scope.row.assessQtyRate || '0' }}
|
|
|
436
|
+ </template>
|
|
|
437
|
+ </el-table-column>
|
|
|
438
|
+ <el-table-column prop="assessRatio" label="金额考核占比%" width="120">
|
|
|
439
|
+ <template #default="scope">
|
|
|
440
|
+ {{ scope.row.assessRatio || '0' }}
|
|
|
441
|
+ </template>
|
|
|
442
|
+ </el-table-column>
|
|
|
443
|
+ <el-table-column prop="InstitutionId" label="公司代码" width="120">
|
|
|
444
|
+ <template #default="scope">
|
|
|
445
|
+ {{ scope.row.InstitutionId || '-' }}
|
|
|
446
|
+ </template>
|
|
|
447
|
+ </el-table-column>
|
|
|
448
|
+ <el-table-column prop="InstitutionNm" label="公司名称" width="150">
|
|
|
449
|
+ <template #default="scope">
|
|
|
450
|
+ {{ scope.row.InstitutionNm || '-' }}
|
|
|
451
|
+ </template>
|
|
|
452
|
+ </el-table-column>
|
|
|
453
|
+ <el-table-column prop="personDeptId" label="部门代码" width="120">
|
|
|
454
|
+ <template #default="scope">
|
|
|
455
|
+ {{ scope.row.personDeptId || '-' }}
|
|
|
456
|
+ </template>
|
|
|
457
|
+ </el-table-column>
|
|
|
458
|
+ <el-table-column prop="personid" label="人员代码" width="120">
|
|
|
459
|
+ <template #default="scope">
|
|
|
460
|
+ {{ scope.row.personid || '-' }}
|
|
|
461
|
+ </template>
|
|
|
462
|
+ </el-table-column>
|
|
|
463
|
+ <el-table-column prop="personname" label="人员名称" width="150">
|
|
|
464
|
+ <template #default="scope">
|
|
|
465
|
+ {{ scope.row.personname || '-' }}
|
|
|
466
|
+ </template>
|
|
|
467
|
+ </el-table-column>
|
|
|
468
|
+ </el-table>
|
|
|
469
|
+ </div>
|
|
|
470
|
+ </el-tab-pane>
|
|
|
471
|
+ </el-tabs>
|
|
|
472
|
+ </div>
|
|
|
473
|
+ </div>
|
|
|
474
|
+</template>
|
|
|
475
|
+
|
|
|
476
|
+<script setup>
|
|
|
477
|
+import { ref, onMounted, computed } from 'vue'
|
|
|
478
|
+import { ElMessage, ElMessageBox } from 'element-plus'
|
|
|
479
|
+import { UploadFilled } from '@element-plus/icons-vue'
|
|
|
480
|
+import { importContractExcel } from '../api/contractApi'
|
|
|
481
|
+import * as XLSX from 'xlsx'
|
|
|
482
|
+
|
|
|
483
|
+// 响应式数据
|
|
|
484
|
+const selectedFile = ref(null)
|
|
|
485
|
+const contractsData = ref({
|
|
|
486
|
+ main: [],
|
|
|
487
|
+ products: [],
|
|
|
488
|
+ payments: [],
|
|
|
489
|
+ responsibility: []
|
|
|
490
|
+})
|
|
|
491
|
+const activeTab = ref('main')
|
|
|
492
|
+const importLoading = ref(false)
|
|
|
493
|
+const saveLoading = ref(false)
|
|
|
494
|
+const tableLoading = ref(false)
|
|
|
495
|
+const importStats = ref(null)
|
|
|
496
|
+const currentPage = ref(1)
|
|
|
497
|
+const pageSize = ref(50)
|
|
|
498
|
+const productCurrentPage = ref(1)
|
|
|
499
|
+const productPageSize = ref(50)
|
|
|
500
|
+
|
|
|
501
|
+// 计算分页后的合同数据
|
|
|
502
|
+const paginatedContracts = computed(() => {
|
|
|
503
|
+ if (!contractsData.value.main || contractsData.value.main.length === 0) return []
|
|
|
504
|
+ const start = (currentPage.value - 1) * pageSize.value
|
|
|
505
|
+ const end = start + pageSize.value
|
|
|
506
|
+ return contractsData.value.main.slice(start, end)
|
|
|
507
|
+})
|
|
|
508
|
+
|
|
|
509
|
+// 计算所有产品的数据
|
|
|
510
|
+const allProducts = computed(() => {
|
|
|
511
|
+ return contractsData.value.products || []
|
|
|
512
|
+})
|
|
|
513
|
+
|
|
|
514
|
+// 计算分页后的产品数据
|
|
|
515
|
+const paginatedProducts = computed(() => {
|
|
|
516
|
+ const start = (productCurrentPage.value - 1) * productPageSize.value
|
|
|
517
|
+ const end = start + productPageSize.value
|
|
|
518
|
+ return allProducts.value.slice(start, end)
|
|
|
519
|
+})
|
|
|
520
|
+
|
|
|
521
|
+// 计算所有付款计划
|
|
|
522
|
+const allPayments = computed(() => {
|
|
|
523
|
+ return contractsData.value.payments || []
|
|
|
524
|
+})
|
|
|
525
|
+
|
|
|
526
|
+// 计算所有责任中心
|
|
|
527
|
+const allResponsibilities = computed(() => {
|
|
|
528
|
+ return contractsData.value.responsibility || []
|
|
|
529
|
+})
|
|
|
530
|
+
|
|
|
531
|
+// 处理文件选择
|
|
|
532
|
+const handleFileChange = (file) => {
|
|
|
533
|
+ selectedFile.value = file.raw
|
|
|
534
|
+}
|
|
|
535
|
+
|
|
|
536
|
+// 格式化数字显示
|
|
|
537
|
+const formatNumber = (value) => {
|
|
|
538
|
+ if (value === null || value === undefined || value === '') return '-'
|
|
|
539
|
+ const num = Number(value)
|
|
|
540
|
+ return isNaN(num) ? value : num.toLocaleString()
|
|
|
541
|
+}
|
|
|
542
|
+
|
|
|
543
|
+// 解析Excel文件并预览内容
|
|
|
544
|
+const previewFileContent = async (file) => {
|
|
|
545
|
+ try {
|
|
|
546
|
+ tableLoading.value = true
|
|
|
547
|
+ const data = await parseExcelFile(file);
|
|
|
548
|
+ contractsData.value = data;
|
|
|
549
|
+
|
|
|
550
|
+ console.log('解析完成的数据:', data)
|
|
|
551
|
+
|
|
|
552
|
+ // 计算统计信息
|
|
|
553
|
+ importStats.value = {
|
|
|
554
|
+ contractCount: data.main ? data.main.length : 0,
|
|
|
555
|
+ productsCount: data.products ? data.products.length : 0,
|
|
|
556
|
+ paymentsCount: data.payments ? data.payments.length : 0,
|
|
|
557
|
+ responsibilityCount: data.responsibility ? data.responsibility.length : 0
|
|
|
558
|
+ }
|
|
|
559
|
+
|
|
|
560
|
+ ElMessage.success(`成功导入 ${importStats.value.contractCount} 个合同,共 ${importStats.value.productsCount} 条产品记录`)
|
|
|
561
|
+ } catch (error) {
|
|
|
562
|
+ console.error('文件解析错误:', error)
|
|
|
563
|
+ ElMessage.error('文件解析失败:' + (error.message || '未知错误'));
|
|
|
564
|
+ contractsData.value = {
|
|
|
565
|
+ main: [],
|
|
|
566
|
+ products: [],
|
|
|
567
|
+ payments: [],
|
|
|
568
|
+ responsibility: []
|
|
|
569
|
+ }
|
|
|
570
|
+ } finally {
|
|
|
571
|
+ tableLoading.value = false
|
|
|
572
|
+ }
|
|
|
573
|
+};
|
|
|
574
|
+
|
|
|
575
|
+// 解析Excel文件 - 只做数据收集,不进行关联
|
|
|
576
|
+const parseExcelFile = (file) => {
|
|
|
577
|
+ return new Promise((resolve, reject) => {
|
|
|
578
|
+ const reader = new FileReader();
|
|
|
579
|
+
|
|
|
580
|
+ reader.onload = (e) => {
|
|
|
581
|
+ try {
|
|
|
582
|
+ const data = new Uint8Array(e.target.result);
|
|
|
583
|
+ const workbook = XLSX.read(data, {
|
|
|
584
|
+ type: 'array',
|
|
|
585
|
+ cellDates: true,
|
|
|
586
|
+ raw: false
|
|
|
587
|
+ });
|
|
|
588
|
+
|
|
|
589
|
+ console.log('Excel Sheet Names:', workbook.SheetNames)
|
|
|
590
|
+
|
|
|
591
|
+ const result = {
|
|
|
592
|
+ main: [],
|
|
|
593
|
+ products: [],
|
|
|
594
|
+ payments: [],
|
|
|
595
|
+ responsibility: []
|
|
|
596
|
+ }
|
|
|
597
|
+
|
|
|
598
|
+ // 解析主表(第一个sheet)
|
|
|
599
|
+ const mainSheet = workbook.Sheets[workbook.SheetNames[0]];
|
|
|
600
|
+ const mainData = XLSX.utils.sheet_to_json(mainSheet, {
|
|
|
601
|
+ header: ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'AA', 'AB', 'AC', 'AD', 'AE', 'AF', 'AG', 'AH', 'AI', 'AJ', 'AK', 'AL', 'AM', 'AN', 'AO', 'AP', 'AQ', 'AR', 'AS', 'AT', 'AU', 'AV', 'AW', 'AX', 'AY', 'AZ', 'BA', 'BB', 'BC', 'BD', 'BE', 'BF', 'BG', 'BH', 'BI', 'BJ', 'BK', 'BL', 'BM', 'BN', 'BO', 'BP', 'BQ', 'BR', 'BS', 'BT', 'BU', 'BV', 'BW', 'BX', 'BY', 'BZ', 'CA', 'CB', 'CC', 'CD', 'CE', 'CF', 'CG', 'CH', 'CI', 'CJ', 'CK', 'CL', 'CM', 'CN', 'CO', 'CP', 'CQ', 'CR', 'CS', 'CT', 'CU', 'CV'],
|
|
|
602
|
+ range: 1
|
|
|
603
|
+ });
|
|
|
604
|
+
|
|
|
605
|
+ console.log('主表数据:', mainData)
|
|
|
606
|
+
|
|
|
607
|
+ // 处理主表数据
|
|
|
608
|
+ mainData.forEach((row, index) => {
|
|
|
609
|
+ // 跳过空行和标题行
|
|
|
610
|
+ if (!row.B || row.B === '采购合同号' || row.B === '标题') return;
|
|
|
611
|
+
|
|
|
612
|
+ const mainInfo = mapMainTableFields(row);
|
|
|
613
|
+ result.main.push(mainInfo);
|
|
|
614
|
+ });
|
|
|
615
|
+
|
|
|
616
|
+ // 解析产品明细(第二个sheet)
|
|
|
617
|
+ if (workbook.SheetNames.length >= 2) {
|
|
|
618
|
+ const productsSheet = workbook.Sheets[workbook.SheetNames[1]];
|
|
|
619
|
+ const productsData = XLSX.utils.sheet_to_json(productsSheet, {
|
|
|
620
|
+ header: ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'AA', 'AB', 'AC', 'AD', 'AE', 'AF', 'AG', 'AH', 'AI', 'AJ', 'AK', 'AL', 'AM', 'AN', 'AO', 'AP', 'AQ', 'AR', 'AS', 'AT', 'AU', 'AV', 'AW', 'AX', 'AY', 'AZ', 'BA', 'BB', 'BC', 'BD'],
|
|
|
621
|
+ range: 1
|
|
|
622
|
+ });
|
|
|
623
|
+
|
|
|
624
|
+ console.log('产品明细数据:', productsData)
|
|
|
625
|
+
|
|
|
626
|
+ // 处理产品明细数据
|
|
|
627
|
+ productsData.forEach(row => {
|
|
|
628
|
+ if (!row.A || row.A === '采购合同号' || row.A === '标题') return;
|
|
|
629
|
+
|
|
|
630
|
+ const productItem = mapProductTableFields(row);
|
|
|
631
|
+ result.products.push(productItem);
|
|
|
632
|
+ });
|
|
|
633
|
+ }
|
|
|
634
|
+
|
|
|
635
|
+ // 解析付款计划(第三个sheet)
|
|
|
636
|
+ if (workbook.SheetNames.length >= 3) {
|
|
|
637
|
+ const paymentsSheet = workbook.Sheets[workbook.SheetNames[2]];
|
|
|
638
|
+ const paymentsData = XLSX.utils.sheet_to_json(paymentsSheet, {
|
|
|
639
|
+ header: ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I'],
|
|
|
640
|
+ range: 1
|
|
|
641
|
+ });
|
|
|
642
|
+
|
|
|
643
|
+ console.log('付款计划数据:', paymentsData)
|
|
|
644
|
+
|
|
|
645
|
+ // 处理付款计划数据
|
|
|
646
|
+ paymentsData.forEach(row => {
|
|
|
647
|
+ if (!row.A || row.A === '合同号' || row.A === '标题') return;
|
|
|
648
|
+
|
|
|
649
|
+ const paymentItem = mapPaymentTableFields(row);
|
|
|
650
|
+ result.payments.push(paymentItem);
|
|
|
651
|
+ });
|
|
|
652
|
+ }
|
|
|
653
|
+
|
|
|
654
|
+ // 解析责任中心(第四个sheet)
|
|
|
655
|
+ if (workbook.SheetNames.length >= 4) {
|
|
|
656
|
+ const responsibilitySheet = workbook.Sheets[workbook.SheetNames[3]];
|
|
|
657
|
+ const responsibilityData = XLSX.utils.sheet_to_json(responsibilitySheet, {
|
|
|
658
|
+ header: ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L'],
|
|
|
659
|
+ range: 1
|
|
|
660
|
+ });
|
|
|
661
|
+
|
|
|
662
|
+ console.log('责任中心数据:', responsibilityData)
|
|
|
663
|
+
|
|
|
664
|
+ // 处理责任中心数据
|
|
|
665
|
+ responsibilityData.forEach(row => {
|
|
|
666
|
+ if (!row.A || row.A === '合同号' || row.A === '标题') return;
|
|
|
667
|
+
|
|
|
668
|
+ const respItem = mapResponsibilityTableFields(row);
|
|
|
669
|
+ result.responsibility.push(respItem);
|
|
|
670
|
+ });
|
|
|
671
|
+ }
|
|
|
672
|
+
|
|
|
673
|
+ console.log('最终解析的数据:', result)
|
|
|
674
|
+ resolve(result);
|
|
|
675
|
+ } catch (error) {
|
|
|
676
|
+ console.error('解析过程中出错:', error)
|
|
|
677
|
+ reject(error);
|
|
|
678
|
+ }
|
|
|
679
|
+ };
|
|
|
680
|
+
|
|
|
681
|
+ reader.onerror = () => {
|
|
|
682
|
+ reject(new Error('文件读取失败'));
|
|
|
683
|
+ };
|
|
|
684
|
+
|
|
|
685
|
+ reader.readAsArrayBuffer(file);
|
|
|
686
|
+ });
|
|
|
687
|
+};
|
|
|
688
|
+
|
|
|
689
|
+// 主表字段映射 - 根据Excel结构调整
|
|
|
690
|
+const mapMainTableFields = (row) => {
|
|
|
691
|
+ return {
|
|
|
692
|
+ fno: row.A || '', // 采购合同号 (A列)
|
|
|
693
|
+ contractName: row.W || '', // 合同名称 (W列)
|
|
|
694
|
+ bizType: row.G || '', // 合同类型 (G列)
|
|
|
695
|
+ bizProductType: row.H || '', // 合同产品类型 (H列)
|
|
|
696
|
+ serviceType: row.F || '', // 业务类型 (F列)
|
|
|
697
|
+ curcy: row.AA || '', // 币别 (AA列)
|
|
|
698
|
+ supName: row.CM || '', // 供应商名称 (CM列)
|
|
|
699
|
+ supCode: row.CK || '', // 供应商代码 (CK列)
|
|
|
700
|
+ supContact: row.CL || '', // 供应商联系人名称 (CL列)
|
|
|
701
|
+ supBank: row.CJ || '', // 供应商开户银行 (CJ列)
|
|
|
702
|
+ supAcc: row.CI || '', // 供应商银行账户 (CI列)
|
|
|
703
|
+ fours: row.I || '', // 我方编号 (I列)
|
|
|
704
|
+ foursname: row.J || '', // 我方名称 (J列)
|
|
|
705
|
+ ourBankNm: row.AQ || '', // 我方开户银行 (AQ列)
|
|
|
706
|
+ ourBankAcct: row.AP || '', // 我方银行账号 (AP列)
|
|
|
707
|
+ createBy: row.C || '', // 制单人代码 (C列)
|
|
|
708
|
+ createByName: row.D || '', // 制单人名称 (D列)
|
|
|
709
|
+ contrExecCd: row.E || '', // 合同执行人代码 (E列)
|
|
|
710
|
+ contrExecNm: row.U || '', // 合同执行人名称 (U列)
|
|
|
711
|
+ ifLongTerm: row.AX || '', // 是否长协 (AX列)
|
|
|
712
|
+ ifClearBottom: row.AT || '', // 是否清底 (AT列)
|
|
|
713
|
+ fundOccupyFlg: row.AR || '', // 是否占用资金 (AR列)
|
|
|
714
|
+ ifBidding: row.AS || '', // 是否招投标 (AS列)
|
|
|
715
|
+ lPort: row.BF || '', // 装运港 (BF列)
|
|
|
716
|
+ lPortCtry: row.BG || '', // 装运国 (BG列)
|
|
|
717
|
+ dPort: row.AF || '', // 目的港 (AF列)
|
|
|
718
|
+ dPortCtry: row.AG || '', // 目的国 (AG列)
|
|
|
719
|
+ tranWay: row.CQ || '', // 运输方式 (CQ列)
|
|
|
720
|
+ delivMtd: row.AE || '', // 交货方式 (AE列)
|
|
|
721
|
+ delivLoc: row.AD || '', // 交货地点 (AD列)
|
|
|
722
|
+ estArrDt: row.AL || '', // 最迟集港日期 (AL列)
|
|
|
723
|
+ estLoadDt: row.AM || '', // 最迟装运日期 (AM列)
|
|
|
724
|
+ whetherChartering: row.CT || '', // 是否租船 (CT列)
|
|
|
725
|
+ chnShipName: row.R || '', // 中文船名 (R列)
|
|
|
726
|
+ engShipName: row.AK || '', // 英文船名 (AK列)
|
|
|
727
|
+ terms: row.CN || '', // 价格条款 (CN列)
|
|
|
728
|
+ rate: row.BY || 0, // 折人民币汇率 (BY列)
|
|
|
729
|
+ rateUs: row.BZ || 0, // 执行美元汇率 (BZ列)
|
|
|
730
|
+ qtyOver: row.BW || 0, // 数量溢装% (BW列)
|
|
|
731
|
+ qtyShort: row.BX || 0, // 数量短装% (BX列)
|
|
|
732
|
+ amtOver: row.K || 0, // 金额溢装% (K列)
|
|
|
733
|
+ amtShort: row.L || 0, // 金额短装% (L列)
|
|
|
734
|
+ insuranceType: row.BD || '', // 保险种类 (BD列)
|
|
|
735
|
+ insuranceAmt: row.BE || 0, // 保险费率% (BE列)
|
|
|
736
|
+ signLoc: row.CG || '', // 签约地点 (CG列)
|
|
|
737
|
+ contrDesc: row.AB || '', // 合同描述 (AB列)
|
|
|
738
|
+ };
|
|
|
739
|
+};
|
|
|
740
|
+
|
|
|
741
|
+// 产品明细字段映射 - 根据Excel结构调整
|
|
|
742
|
+const mapProductTableFields = (row) => {
|
|
|
743
|
+ return {
|
|
|
744
|
+ fno: row.A || '', // 采购合同号 (A列)
|
|
|
745
|
+ itemno: row.F || '', // 商品编号 (F列)
|
|
|
746
|
+ sdesc: row.G || '', // 中文品名 (G列)
|
|
|
747
|
+ edesc: row.H || '', // 英文品名 (H列)
|
|
|
748
|
+ brand: row.I || '', // 牌号 (I列)
|
|
|
749
|
+ ftype3: row.J || '', // 规格描述 (J列)
|
|
|
750
|
+ resourceNo: row.C || '', // 资源号 (C列)
|
|
|
751
|
+ SMRNo: row.D || '', // 钢厂资源号 (D列)
|
|
|
752
|
+ batchNo: row.E || '', // 批次号 (E列)
|
|
|
753
|
+ curcyPo: row.AL || '', // 采购币种 (AL列)
|
|
|
754
|
+ qty: row.S || 0, // 数量 (S列)
|
|
|
755
|
+ poprice: row.T || 0, // 采购单价 (T列)
|
|
|
756
|
+ poamt: row.U || 0, // 金额 (U列)
|
|
|
757
|
+ inTaxRate: row.AG || 0, // 增值税率% (AG列)
|
|
|
758
|
+ ironCont: row.W || 0, // 含铁量% (W列)
|
|
|
759
|
+ moisture: row.V || 0, // 水分% (V列)
|
|
|
760
|
+ coalMoisture: row.AM || 0, // 煤焦计价水% (AM列)
|
|
|
761
|
+ priceMtd: row.AC || '', // 计价方式 (AC列)
|
|
|
762
|
+ ratePo: row.AX || 0, // 采购汇率 (AX列)
|
|
|
763
|
+ reTaxRate: row.AY || 0, // 退税率% (AY列)
|
|
|
764
|
+ ut: row.R || '', // 单位 (R列)
|
|
|
765
|
+ ftype4: row.AB || '', // 计重方式 (AB列)
|
|
|
766
|
+ fnw: row.AE || 0, // 净重 (AE列)
|
|
|
767
|
+ fgw: row.AD || 0, // 毛重 (AD列)
|
|
|
768
|
+ taxAmt: row.BC || 0, // 税额 (BC列)
|
|
|
769
|
+ spec: row.AH || '', // QP描述 (AH列)
|
|
|
770
|
+ hsCode: row.AI || '', // 海关编码 (AI列)
|
|
|
771
|
+ hsNameCn: row.AJ || '', // 海关中文名称 (AJ列)
|
|
|
772
|
+ hsNameEn: row.AK || '', // 海关英文名称 (AK列)
|
|
|
773
|
+ dryTonQty: row.Y || 0, // 干吨数量 (Y列)
|
|
|
774
|
+ wetTonQty: row.Z || 0, // 湿吨数量 (Z列)
|
|
|
775
|
+ ftype5: row.AA || '', // 色标 (AA列)
|
|
|
776
|
+ dutyRate: row.AF || 0, // 进口关税税率% (AF列)
|
|
|
777
|
+ ntPoAmt: row.AN || 0, // 未税金额 (AN列)
|
|
|
778
|
+ ntPoPrice: row.AO || 0, // 未税单价 (AO列)
|
|
|
779
|
+ amtRate: row.AP || 0, // 金额占比 (AP列)
|
|
|
780
|
+ cnypoamt: row.AQ || 0, // 人民币含税金额 (AQ列)
|
|
|
781
|
+ usdpoamt: row.BD || 0, // 美元含税金额 (BD列)
|
|
|
782
|
+ remark: row.AR || '' // 备注 (AR列)
|
|
|
783
|
+ };
|
|
|
784
|
+};
|
|
|
785
|
+
|
|
|
786
|
+// 付款计划字段映射 - 根据Excel结构调整
|
|
|
787
|
+const mapPaymentTableFields = (row) => {
|
|
|
788
|
+ return {
|
|
|
789
|
+ fno: row.A || '', // 合同号 (A列)
|
|
|
790
|
+ create_by: row.B || '', // 制单人代码 (B列)
|
|
|
791
|
+ dept_name: row.C || '', // 部门名称 (C列)
|
|
|
792
|
+ payMethod: row.D || '', // 付款方式 (D列)
|
|
|
793
|
+ payType: row.E || '', // 款项类别 (E列)
|
|
|
794
|
+ payDays: row.F || 0, // 账期(天) (F列)
|
|
|
795
|
+ payRatio: row.G || 0, // 款项比例% (G列)
|
|
|
796
|
+ payAmt: row.H || 0 // 金额 (H列)
|
|
|
797
|
+ };
|
|
|
798
|
+};
|
|
|
799
|
+
|
|
|
800
|
+// 责任中心字段映射 - 根据Excel结构调整
|
|
|
801
|
+const mapResponsibilityTableFields = (row) => {
|
|
|
802
|
+ return {
|
|
|
803
|
+ fno: row.A || '', // 合同号 (A列)
|
|
|
804
|
+ create_by: row.B || '', // 制单人代码 (B列)
|
|
|
805
|
+ personDeptNm: row.C || '', // 部门名称 (C列)
|
|
|
806
|
+ assessQtyRate: row.D || 0, // 利润考核占比% (D列)
|
|
|
807
|
+ assessRatio: row.E || 0, // 金额考核占比% (E列)
|
|
|
808
|
+ InstitutionId: row.F || '', // 人员公司代码 (F列)
|
|
|
809
|
+ InstitutionNm: row.G || '', // 人员公司名称 (G列)
|
|
|
810
|
+ personDeptId: row.H || '', // 人员部门代码 (H列)
|
|
|
811
|
+ personid: row.I || '', // 人员代码 (I列)
|
|
|
812
|
+ personname: row.J || '' // 人员名称 (J列)
|
|
|
813
|
+ };
|
|
|
814
|
+};
|
|
|
815
|
+
|
|
|
816
|
+// 处理文件导入
|
|
|
817
|
+const handleImport = async () => {
|
|
|
818
|
+ if (!selectedFile.value) {
|
|
|
819
|
+ ElMessage.warning('请先选择文件');
|
|
|
820
|
+ return;
|
|
|
821
|
+ }
|
|
|
822
|
+
|
|
|
823
|
+ try {
|
|
|
824
|
+ importLoading.value = true;
|
|
|
825
|
+ ElMessage.info('正在解析文件,请稍候...');
|
|
|
826
|
+
|
|
|
827
|
+ await previewFileContent(selectedFile.value);
|
|
|
828
|
+
|
|
|
829
|
+ ElMessage.success('文件解析完成');
|
|
|
830
|
+ } catch (error) {
|
|
|
831
|
+ ElMessage.error('导入失败:' + (error.message || '未知错误'));
|
|
|
832
|
+ } finally {
|
|
|
833
|
+ importLoading.value = false;
|
|
|
834
|
+ }
|
|
|
835
|
+};
|
|
|
836
|
+
|
|
|
837
|
+// 分页处理
|
|
|
838
|
+const handlePageChange = (page) => {
|
|
|
839
|
+ currentPage.value = page;
|
|
|
840
|
+};
|
|
|
841
|
+
|
|
|
842
|
+const handleProductPageChange = (page) => {
|
|
|
843
|
+ productCurrentPage.value = page;
|
|
|
844
|
+};
|
|
|
845
|
+
|
|
|
846
|
+// 下载模板
|
|
|
847
|
+const handleDownloadTemplate = () => {
|
|
|
848
|
+ ElMessage.info('模板下载功能开发中...');
|
|
|
849
|
+};
|
|
|
850
|
+
|
|
|
851
|
+// 批量保存所有合同
|
|
|
852
|
+const handleBatchSave = async () => {
|
|
|
853
|
+ if (!contractsData.value || contractsData.value.main.length === 0) {
|
|
|
854
|
+ ElMessage.warning('请先导入合同数据');
|
|
|
855
|
+ return;
|
|
|
856
|
+ }
|
|
|
857
|
+
|
|
|
858
|
+ try {
|
|
|
859
|
+ await ElMessageBox.confirm(
|
|
|
860
|
+ `确定要批量保存 ${importStats.value.contractCount} 个合同吗?`,
|
|
|
861
|
+ '批量保存确认',
|
|
|
862
|
+ {
|
|
|
863
|
+ confirmButtonText: '确定',
|
|
|
864
|
+ cancelButtonText: '取消',
|
|
|
865
|
+ type: 'warning'
|
|
|
866
|
+ }
|
|
|
867
|
+ );
|
|
|
868
|
+
|
|
|
869
|
+ saveLoading.value = true;
|
|
|
870
|
+ ElMessage.info('开始批量保存,请勿关闭页面...');
|
|
|
871
|
+
|
|
|
872
|
+ try {
|
|
|
873
|
+ await importContractExcel(contractsData.value);
|
|
|
874
|
+ ElMessage.success(`成功保存所有 ${importStats.value.contractCount} 个合同`);
|
|
|
875
|
+ } catch (error) {
|
|
|
876
|
+ console.error('保存失败:', error);
|
|
|
877
|
+ ElMessage.error('批量保存失败:' + (error.message || '未知错误'));
|
|
|
878
|
+ }
|
|
|
879
|
+ } catch (error) {
|
|
|
880
|
+ if (error !== 'cancel') {
|
|
|
881
|
+ ElMessage.error('批量保存失败:' + (error.message || '未知错误'));
|
|
|
882
|
+ }
|
|
|
883
|
+ } finally {
|
|
|
884
|
+ saveLoading.value = false;
|
|
|
885
|
+ }
|
|
|
886
|
+};
|
|
|
887
|
+</script>
|
|
|
888
|
+
|
|
|
889
|
+<style scoped>
|
|
|
890
|
+.contract-container {
|
|
|
891
|
+ padding: 20px;
|
|
|
892
|
+}
|
|
|
893
|
+
|
|
|
894
|
+.import-section {
|
|
|
895
|
+ margin-bottom: 30px;
|
|
|
896
|
+ padding: 20px;
|
|
|
897
|
+ background-color: #f5f7fa;
|
|
|
898
|
+ border-radius: 8px;
|
|
|
899
|
+}
|
|
|
900
|
+
|
|
|
901
|
+.el-upload {
|
|
|
902
|
+ margin-bottom: 20px;
|
|
|
903
|
+}
|
|
|
904
|
+
|
|
|
905
|
+.import-actions {
|
|
|
906
|
+ margin-top: 20px;
|
|
|
907
|
+ display: flex;
|
|
|
908
|
+ gap: 10px;
|
|
|
909
|
+}
|
|
|
910
|
+
|
|
|
911
|
+.import-stats {
|
|
|
912
|
+ margin-top: 20px;
|
|
|
913
|
+}
|
|
|
914
|
+
|
|
|
915
|
+.stats-content {
|
|
|
916
|
+ display: flex;
|
|
|
917
|
+ gap: 20px;
|
|
|
918
|
+ flex-wrap: wrap;
|
|
|
919
|
+}
|
|
|
920
|
+
|
|
|
921
|
+.contracts-info {
|
|
|
922
|
+ margin-top: 30px;
|
|
|
923
|
+}
|
|
|
924
|
+
|
|
|
925
|
+.table-section {
|
|
|
926
|
+ padding: 20px;
|
|
|
927
|
+ background-color: #fff;
|
|
|
928
|
+}
|
|
|
929
|
+
|
|
|
930
|
+.pagination-section {
|
|
|
931
|
+ margin-top: 20px;
|
|
|
932
|
+ text-align: center;
|
|
|
933
|
+}
|
|
|
934
|
+
|
|
|
935
|
+.text-ellipsis {
|
|
|
936
|
+ display: inline-block;
|
|
|
937
|
+ max-width: 180px;
|
|
|
938
|
+ overflow: hidden;
|
|
|
939
|
+ text-overflow: ellipsis;
|
|
|
940
|
+ white-space: nowrap;
|
|
|
941
|
+ vertical-align: middle;
|
|
|
942
|
+}
|
|
|
943
|
+</style>
|