cloud-web-corejs 1.1.0-dev.30 → 1.1.0-dev.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +5 -5
- package/src/components/xform/form-designer/designer.js +52 -6
- package/src/components/xform/form-designer/form-widget/field-widget/row-col-select-widget.vue +64 -0
- package/src/components/xform/form-designer/setting-panel/property-editor/container-detail/detail-temp-edito.vue +13 -1
- package/src/components/xform/form-designer/widget-panel/widgetsConfig.js +2 -0
- package/src/views/demo/bizTab/bill/billConfig.js +0 -41
- package/src/views/demo/bizTab/bill/detail.vue +0 -436
- package/src/views/demo/bizTab/bill/list.vue +0 -288
- package/src/views/demo/bizTab/bill/productDialog.vue +0 -176
- package/src/views/demo/bizTab/simple/billApi.js +0 -123
- package/src/views/demo/bizTab/simple/detail.vue +0 -407
- package/src/views/demo/bizTab/simple/list.vue +0 -217
- package/src/views/demo/bizTab/standalone/index.vue +0 -121
- package/src/views/demo/bizTab/wf/billConfig.js +0 -44
- package/src/views/demo/bizTab/wf/detail.vue +0 -661
- package/src/views/demo/bizTab/wf/list.vue +0 -242
|
@@ -1,407 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div class="detail-wrap">
|
|
3
|
-
<!--
|
|
4
|
-
结构约定(即便本 demo 不接流程也照着写,将来加流程不用改结构):
|
|
5
|
-
wfUtil 把「流程信息」面板挂到 .el-form .d-cont、侧边导航挂到 .el-form .slide-wrap,
|
|
6
|
-
所以 el-form 必须包住 baseTabs。
|
|
7
|
-
:disabled="billDisabled" 一绑,表单里的字段就整片自动禁用(本 demo 无流程,恒为 false)。
|
|
8
|
-
-->
|
|
9
|
-
<el-form ref="editForm" :model="billModel" :disabled="billDisabled">
|
|
10
|
-
<!-- 这层空 el-form 用来隔断 disabled 注入,头部按钮不受单据只读态影响 -->
|
|
11
|
-
<el-form>
|
|
12
|
-
<div class="d-header clearfix">
|
|
13
|
-
<div class="fl">
|
|
14
|
-
<i class="el-icon-info" />
|
|
15
|
-
{{ isAdd ? $t1("新增单据") : $t1("单据") + " " + (billModel.sn || "") }}
|
|
16
|
-
</div>
|
|
17
|
-
<!-- 上一单/下一单、重置、保存:显隐与禁用都由组件统一处理 -->
|
|
18
|
-
<biz-bill-actions :detail="_self">
|
|
19
|
-
<!-- 业务自己的按钮往默认插槽放 -->
|
|
20
|
-
<el-button
|
|
21
|
-
v-if="!isAdd"
|
|
22
|
-
type="primary"
|
|
23
|
-
plain
|
|
24
|
-
class="button-sty"
|
|
25
|
-
icon="el-icon-document-copy"
|
|
26
|
-
:disabled="billSaving"
|
|
27
|
-
@click="copyToNew"
|
|
28
|
-
>{{ $t1("复制新增") }}</el-button
|
|
29
|
-
>
|
|
30
|
-
</biz-bill-actions>
|
|
31
|
-
</div>
|
|
32
|
-
</el-form>
|
|
33
|
-
|
|
34
|
-
<baseTabs>
|
|
35
|
-
<baseTabPane :label="$t1('基本信息')">
|
|
36
|
-
<template #default>
|
|
37
|
-
<table class="table-detail">
|
|
38
|
-
<tbody>
|
|
39
|
-
<tr>
|
|
40
|
-
<th>{{ $t1("单号") }}</th>
|
|
41
|
-
<td>{{ billModel.sn || $t1("保存后自动生成") }}</td>
|
|
42
|
-
<th>{{ $t1("状态") }}</th>
|
|
43
|
-
<td>
|
|
44
|
-
<div :class="statusInfo.cls">{{ statusInfo.label }}</div>
|
|
45
|
-
</td>
|
|
46
|
-
</tr>
|
|
47
|
-
<tr>
|
|
48
|
-
<th><em class="f-red">*</em>{{ $t1("名称") }}</th>
|
|
49
|
-
<td>
|
|
50
|
-
<el-form-item
|
|
51
|
-
prop="name"
|
|
52
|
-
:rules="[
|
|
53
|
-
{
|
|
54
|
-
required: true,
|
|
55
|
-
message: $t1('名称不能为空'),
|
|
56
|
-
trigger: ['blur', 'change'],
|
|
57
|
-
},
|
|
58
|
-
]"
|
|
59
|
-
>
|
|
60
|
-
<el-input v-model="billModel.name" clearable />
|
|
61
|
-
</el-form-item>
|
|
62
|
-
</td>
|
|
63
|
-
<th>{{ $t1("负责人") }}</th>
|
|
64
|
-
<td>
|
|
65
|
-
<el-form-item prop="owner">
|
|
66
|
-
<el-input v-model="billModel.owner" clearable />
|
|
67
|
-
</el-form-item>
|
|
68
|
-
</td>
|
|
69
|
-
</tr>
|
|
70
|
-
<tr>
|
|
71
|
-
<th>{{ $t1("金额") }}</th>
|
|
72
|
-
<td>
|
|
73
|
-
<el-form-item prop="amount">
|
|
74
|
-
<base-input-number v-model="billModel.amount" />
|
|
75
|
-
</el-form-item>
|
|
76
|
-
</td>
|
|
77
|
-
<th>{{ $t1("备注") }}</th>
|
|
78
|
-
<td>
|
|
79
|
-
<el-form-item prop="remark">
|
|
80
|
-
<el-input v-model="billModel.remark" clearable />
|
|
81
|
-
</el-form-item>
|
|
82
|
-
</td>
|
|
83
|
-
</tr>
|
|
84
|
-
<tr>
|
|
85
|
-
<!-- 表头多选必填:el-form-item 上写 required 校不出来(空数组会被 async-validator
|
|
86
|
-
放行),靠 validateBillData() 里的 checkBillRequired + type:"multi" -->
|
|
87
|
-
<th><em class="f-red">*</em>{{ $t1("适用区域") }}</th>
|
|
88
|
-
<td>
|
|
89
|
-
<el-form-item prop="areas">
|
|
90
|
-
<el-select v-model="billModel.areas" multiple clearable>
|
|
91
|
-
<el-option
|
|
92
|
-
v-for="item in AREAS"
|
|
93
|
-
:key="item"
|
|
94
|
-
:label="item"
|
|
95
|
-
:value="item"
|
|
96
|
-
/>
|
|
97
|
-
</el-select>
|
|
98
|
-
</el-form-item>
|
|
99
|
-
</td>
|
|
100
|
-
<!-- 表头附件必填:同理,靠 type:"attachment" -->
|
|
101
|
-
<th><em class="f-red">*</em>{{ $t1("附件") }}</th>
|
|
102
|
-
<td colspan="3">
|
|
103
|
-
<el-form-item prop="attachments">
|
|
104
|
-
<baseUpload
|
|
105
|
-
accept="file"
|
|
106
|
-
multi="true"
|
|
107
|
-
:file.sync="billModel.attachments"
|
|
108
|
-
></baseUpload>
|
|
109
|
-
</el-form-item>
|
|
110
|
-
</td>
|
|
111
|
-
</tr>
|
|
112
|
-
</tbody>
|
|
113
|
-
</table>
|
|
114
|
-
</template>
|
|
115
|
-
</baseTabPane>
|
|
116
|
-
|
|
117
|
-
<baseTabPane :label="$t1('明细')">
|
|
118
|
-
<template #default>
|
|
119
|
-
<div class="clearfix screen-btns">
|
|
120
|
-
<div class="fl">
|
|
121
|
-
<vxe-button
|
|
122
|
-
status="primary"
|
|
123
|
-
type="text"
|
|
124
|
-
plain
|
|
125
|
-
class="button-sty"
|
|
126
|
-
icon="el-icon-plus"
|
|
127
|
-
@click="addItem"
|
|
128
|
-
>{{ $t1("增行") }}</vxe-button
|
|
129
|
-
>
|
|
130
|
-
<vxe-button
|
|
131
|
-
status="danger"
|
|
132
|
-
type="text"
|
|
133
|
-
plain
|
|
134
|
-
class="button-sty"
|
|
135
|
-
icon="el-icon-delete"
|
|
136
|
-
@click="removeItems"
|
|
137
|
-
>{{ $t1("删行") }}</vxe-button
|
|
138
|
-
>
|
|
139
|
-
</div>
|
|
140
|
-
</div>
|
|
141
|
-
<vxe-table ref="itemTable" :data="billModel.items" border height="260" size="small">
|
|
142
|
-
<vxe-column type="checkbox" width="48" />
|
|
143
|
-
<!--
|
|
144
|
-
单元格里的必填要两样东西才看得见:
|
|
145
|
-
① 表头星号自己加(element 的 * 是 el-form-item 按 label 渲染的,表格里没有 label);
|
|
146
|
-
② 单元格套 el-form-item + 指向 model 的真实 prop 路径(items.0.qty),
|
|
147
|
-
element 才会加 is-error 让输入框标红 —— 裸着写 el-input 永远不会红。
|
|
148
|
-
错误文案在窄单元格里放不下,所以 show-message 关掉,具体哪行哪个字段
|
|
149
|
-
由 validateBillData() 的提示说明;可靠性也在那边(屏外行没有 form-item)。
|
|
150
|
-
-->
|
|
151
|
-
<vxe-column field="itemCode" :title="$t1('物料编码')" width="140">
|
|
152
|
-
<template #header>
|
|
153
|
-
<span><em class="f-red">*</em>{{ $t1("物料编码") }}</span>
|
|
154
|
-
</template>
|
|
155
|
-
<template #default="{ row, rowIndex }">
|
|
156
|
-
<el-form-item
|
|
157
|
-
:prop="`items.${rowIndex}.itemCode`"
|
|
158
|
-
:rules="[{ required: true, trigger: ['blur', 'change'] }]"
|
|
159
|
-
:show-message="false"
|
|
160
|
-
>
|
|
161
|
-
<el-input v-model="row.itemCode" size="small" />
|
|
162
|
-
</el-form-item>
|
|
163
|
-
</template>
|
|
164
|
-
</vxe-column>
|
|
165
|
-
<vxe-column field="itemName" :title="$t1('物料名称')" min-width="160">
|
|
166
|
-
<template #default="{ row }">
|
|
167
|
-
<el-input v-model="row.itemName" size="small" />
|
|
168
|
-
</template>
|
|
169
|
-
</vxe-column>
|
|
170
|
-
<vxe-column field="qty" :title="$t1('数量')" width="120">
|
|
171
|
-
<template #header>
|
|
172
|
-
<span><em class="f-red">*</em>{{ $t1("数量") }}</span>
|
|
173
|
-
</template>
|
|
174
|
-
<template #default="{ row, rowIndex }">
|
|
175
|
-
<el-form-item
|
|
176
|
-
:prop="`items.${rowIndex}.qty`"
|
|
177
|
-
:rules="[{ required: true, trigger: ['blur', 'change'] }]"
|
|
178
|
-
:show-message="false"
|
|
179
|
-
>
|
|
180
|
-
<base-input-number v-model="row.qty" />
|
|
181
|
-
</el-form-item>
|
|
182
|
-
</template>
|
|
183
|
-
</vxe-column>
|
|
184
|
-
<vxe-column field="price" :title="$t1('单价')" width="120">
|
|
185
|
-
<template #default="{ row }">
|
|
186
|
-
<base-input-number v-model="row.price" />
|
|
187
|
-
</template>
|
|
188
|
-
</vxe-column>
|
|
189
|
-
<!-- 行内多选 / 行内附件的必填也一样:行内 form-item 只覆盖已渲染的行,
|
|
190
|
-
靠 validateBillData() 里的 checkRowsRequired 按 fullData 兜 -->
|
|
191
|
-
<vxe-column field="areas" :title="$t1('适用区域')" width="200">
|
|
192
|
-
<template #header>
|
|
193
|
-
<span><em class="f-red">*</em>{{ $t1("适用区域") }}</span>
|
|
194
|
-
</template>
|
|
195
|
-
<template #default="{ row }">
|
|
196
|
-
<!-- 多选的必填不写 form-item 的 rules:空数组会被 async-validator 放行,
|
|
197
|
-
写了也不会红也不会拦,一律交给 validateBillData() 的 type:"multi" -->
|
|
198
|
-
<el-select v-model="row.areas" multiple size="small" clearable>
|
|
199
|
-
<el-option
|
|
200
|
-
v-for="item in AREAS"
|
|
201
|
-
:key="item"
|
|
202
|
-
:label="item"
|
|
203
|
-
:value="item"
|
|
204
|
-
/>
|
|
205
|
-
</el-select>
|
|
206
|
-
</template>
|
|
207
|
-
</vxe-column>
|
|
208
|
-
<vxe-column field="files" :title="$t1('附件')" min-width="220">
|
|
209
|
-
<template #header>
|
|
210
|
-
<span><em class="f-red">*</em>{{ $t1("附件") }}</span>
|
|
211
|
-
</template>
|
|
212
|
-
<template #default="{ row }">
|
|
213
|
-
<baseUpload accept="file" multi="true" :file.sync="row.files"></baseUpload>
|
|
214
|
-
</template>
|
|
215
|
-
</vxe-column>
|
|
216
|
-
</vxe-table>
|
|
217
|
-
</template>
|
|
218
|
-
</baseTabPane>
|
|
219
|
-
</baseTabs>
|
|
220
|
-
</el-form>
|
|
221
|
-
</div>
|
|
222
|
-
</template>
|
|
223
|
-
|
|
224
|
-
<script>
|
|
225
|
-
/**
|
|
226
|
-
* demo A 详情:不走 $http,所以整个覆盖了 loadBill()。
|
|
227
|
-
*
|
|
228
|
-
* 混入 bizBillDetailMixin 后本文件只关心业务:
|
|
229
|
-
* billOptions / loadBill(或 buildLoadRequest) / applyBillData / saveBill
|
|
230
|
-
* 页签升编辑态、标题同步、翻单、关页签拦截都由 mixin + 宿主完成。
|
|
231
|
-
*/
|
|
232
|
-
import { bizBillDetailMixin } from "@base/components/bizTab";
|
|
233
|
-
import BizBillActions from "@base/components/bizTab/BizBillActions.vue";
|
|
234
|
-
import { getOne, save, STATUS_MAP } from "./billApi";
|
|
235
|
-
|
|
236
|
-
// 多选选项(demo 用)
|
|
237
|
-
const AREAS = ["华东", "华南", "华北", "西南"];
|
|
238
|
-
|
|
239
|
-
export default {
|
|
240
|
-
name: "demoBizTabSimpleDetail",
|
|
241
|
-
components: { BizBillActions },
|
|
242
|
-
mixins: [bizBillDetailMixin],
|
|
243
|
-
data() {
|
|
244
|
-
return {
|
|
245
|
-
AREAS,
|
|
246
|
-
billModel: this.getDefaultModel(),
|
|
247
|
-
// 脏数据判定用的初始快照
|
|
248
|
-
billSnapshot: null,
|
|
249
|
-
};
|
|
250
|
-
},
|
|
251
|
-
computed: {
|
|
252
|
-
billOptions() {
|
|
253
|
-
return {
|
|
254
|
-
titleField: "sn",
|
|
255
|
-
wfEnabled: false, // 本 demo 不接流程,流程相关按钮全部不出
|
|
256
|
-
};
|
|
257
|
-
},
|
|
258
|
-
statusInfo() {
|
|
259
|
-
return STATUS_MAP[this.billModel.status] || { label: "-", cls: "" };
|
|
260
|
-
},
|
|
261
|
-
},
|
|
262
|
-
mounted() {
|
|
263
|
-
this.loadBill();
|
|
264
|
-
},
|
|
265
|
-
methods: {
|
|
266
|
-
getDefaultModel() {
|
|
267
|
-
return {
|
|
268
|
-
id: null,
|
|
269
|
-
sn: null,
|
|
270
|
-
name: null,
|
|
271
|
-
status: 0,
|
|
272
|
-
owner: null,
|
|
273
|
-
amount: null,
|
|
274
|
-
remark: null,
|
|
275
|
-
areas: [], // 表头多选
|
|
276
|
-
attachments: [], // 表头附件
|
|
277
|
-
items: [],
|
|
278
|
-
};
|
|
279
|
-
},
|
|
280
|
-
|
|
281
|
-
/**
|
|
282
|
-
* 数据级校验:附件、多选、子表至少一行、行内附件/多选 —— 这几类
|
|
283
|
-
* el-form-item 的 required 都兜不住(空数组被 async-validator 放行;
|
|
284
|
-
* 子表超 20 行开虚拟滚动,屏外行的 form-item 压根不存在)。
|
|
285
|
-
*/
|
|
286
|
-
validateBillData() {
|
|
287
|
-
return (
|
|
288
|
-
this.checkBillRequired([
|
|
289
|
-
{ field: "areas", label: this.$t1("适用区域"), type: "multi" },
|
|
290
|
-
{ field: "attachments", label: this.$t1("附件"), type: "attachment" },
|
|
291
|
-
])
|
|
292
|
-
|| this.checkRowsRequired({
|
|
293
|
-
label: this.$t1("明细"),
|
|
294
|
-
rows: this.$refs.itemTable
|
|
295
|
-
? this.$refs.itemTable.getTableData().fullData
|
|
296
|
-
: this.billModel.items,
|
|
297
|
-
minRows: 1,
|
|
298
|
-
fields: [
|
|
299
|
-
{ field: "itemCode", label: this.$t1("物料编码") },
|
|
300
|
-
{ field: "qty", label: this.$t1("数量") },
|
|
301
|
-
{ field: "areas", label: this.$t1("适用区域"), type: "multi" },
|
|
302
|
-
{ field: "files", label: this.$t1("附件"), type: "attachment" },
|
|
303
|
-
],
|
|
304
|
-
})
|
|
305
|
-
);
|
|
306
|
-
},
|
|
307
|
-
|
|
308
|
-
// ===== 取数:不走 $http 就整个覆盖 loadBill(默认实现是拿 buildLoadRequest 去 _getBillInfo) =====
|
|
309
|
-
loadBill() {
|
|
310
|
-
if (this.isAdd) {
|
|
311
|
-
this.applyBillData(null);
|
|
312
|
-
return Promise.resolve();
|
|
313
|
-
}
|
|
314
|
-
return getOne(this.dataId).then((objx) => this.applyBillData(objx));
|
|
315
|
-
},
|
|
316
|
-
applyBillData(objx) {
|
|
317
|
-
this.billModel = objx
|
|
318
|
-
? Object.assign(this.getDefaultModel(), objx)
|
|
319
|
-
: this.getDefaultModel();
|
|
320
|
-
if (!Array.isArray(this.billModel.items)) this.billModel.items = [];
|
|
321
|
-
this.billModel.items.forEach((row) => {
|
|
322
|
-
if (!Array.isArray(row.areas)) row.areas = [];
|
|
323
|
-
if (!Array.isArray(row.files)) row.files = [];
|
|
324
|
-
});
|
|
325
|
-
this.takeSnapshot();
|
|
326
|
-
},
|
|
327
|
-
|
|
328
|
-
// ===== 保存:返回单号(新增返回新单号),取消/失败返回 null =====
|
|
329
|
-
saveBill(options) {
|
|
330
|
-
let opts = options || {};
|
|
331
|
-
let done = () =>
|
|
332
|
-
save(this.billModel).then((res) => {
|
|
333
|
-
// 后台回填的单号/状态等要写回模型,页签标题就是从 titleField 取的
|
|
334
|
-
this.billModel = Object.assign({}, this.billModel, res);
|
|
335
|
-
this.takeSnapshot();
|
|
336
|
-
if (opts.successMsg !== false) {
|
|
337
|
-
this.$message({
|
|
338
|
-
message: this.$t1("保存成功"),
|
|
339
|
-
type: "success",
|
|
340
|
-
duration: 500,
|
|
341
|
-
});
|
|
342
|
-
}
|
|
343
|
-
return res.id;
|
|
344
|
-
});
|
|
345
|
-
if (opts.confirm === false) return done();
|
|
346
|
-
return this.$baseConfirm(this.$t1("您确定要保存吗?")).then(done, () => null);
|
|
347
|
-
},
|
|
348
|
-
|
|
349
|
-
// ===== 关页签拦截:实现了它,宿主关页签时就问它脏没脏 =====
|
|
350
|
-
isBillDirty() {
|
|
351
|
-
return JSON.stringify(this.billModel) !== this.billSnapshot;
|
|
352
|
-
},
|
|
353
|
-
takeSnapshot() {
|
|
354
|
-
this.billSnapshot = JSON.stringify(this.billModel);
|
|
355
|
-
},
|
|
356
|
-
|
|
357
|
-
// ===== 业务按钮 =====
|
|
358
|
-
copyToNew() {
|
|
359
|
-
let host = this.bizTabHost;
|
|
360
|
-
if (!host) return;
|
|
361
|
-
let tabName = host.openAdd();
|
|
362
|
-
if (!tabName) return;
|
|
363
|
-
// 等新页签的详情挂载完,把当前单据内容灌进去(去掉主键与单号)
|
|
364
|
-
this.$nextTick(() => {
|
|
365
|
-
setTimeout(() => {
|
|
366
|
-
let tab = host.getTab(tabName);
|
|
367
|
-
let detail = host.getDetail(tab);
|
|
368
|
-
if (!detail) return;
|
|
369
|
-
let copy = JSON.parse(JSON.stringify(this.billModel));
|
|
370
|
-
copy.id = null;
|
|
371
|
-
copy.sn = null;
|
|
372
|
-
copy.status = 0;
|
|
373
|
-
copy.createDate = null;
|
|
374
|
-
(copy.items || []).forEach((item) => {
|
|
375
|
-
item.id = null;
|
|
376
|
-
});
|
|
377
|
-
detail.applyBillData(copy);
|
|
378
|
-
detail.billModel.id = null;
|
|
379
|
-
detail.billSnapshot = null; // 复制来的内容算「未保存」,关页签时要拦一下
|
|
380
|
-
}, 300);
|
|
381
|
-
});
|
|
382
|
-
},
|
|
383
|
-
addItem() {
|
|
384
|
-
this.billModel.items.push({
|
|
385
|
-
id: null,
|
|
386
|
-
itemCode: null,
|
|
387
|
-
itemName: null,
|
|
388
|
-
qty: null,
|
|
389
|
-
price: null,
|
|
390
|
-
areas: [],
|
|
391
|
-
files: [],
|
|
392
|
-
});
|
|
393
|
-
},
|
|
394
|
-
removeItems() {
|
|
395
|
-
let table = this.$refs.itemTable;
|
|
396
|
-
let records = table ? table.getCheckboxRecords() : [];
|
|
397
|
-
if (!records.length) {
|
|
398
|
-
this.$message.warning(this.$t1("请先勾选要删除的明细"));
|
|
399
|
-
return;
|
|
400
|
-
}
|
|
401
|
-
this.billModel.items = this.billModel.items.filter(
|
|
402
|
-
(row) => records.indexOf(row) < 0
|
|
403
|
-
);
|
|
404
|
-
},
|
|
405
|
-
},
|
|
406
|
-
};
|
|
407
|
-
</script>
|
|
@@ -1,217 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<biz-tab-list-page
|
|
3
|
-
ref="bizTab"
|
|
4
|
-
v-model="activeTab"
|
|
5
|
-
:listLabel="$t1('列表')"
|
|
6
|
-
titleField="sn"
|
|
7
|
-
:addTitle="$t1('新增')"
|
|
8
|
-
:maxTabs="6"
|
|
9
|
-
@refresh-list="loadList"
|
|
10
|
-
@tab-removed="onTabRemoved"
|
|
11
|
-
>
|
|
12
|
-
<!-- ===== 列表页签 ===== -->
|
|
13
|
-
<template #list>
|
|
14
|
-
<div class="clearfix screen-btns">
|
|
15
|
-
<div class="fl">
|
|
16
|
-
<vxe-button
|
|
17
|
-
status="primary"
|
|
18
|
-
type="text"
|
|
19
|
-
plain
|
|
20
|
-
class="button-sty"
|
|
21
|
-
icon="el-icon-plus"
|
|
22
|
-
@click="openAdd"
|
|
23
|
-
>{{ $t1("新增") }}</vxe-button
|
|
24
|
-
>
|
|
25
|
-
<vxe-button
|
|
26
|
-
type="text"
|
|
27
|
-
status="primary"
|
|
28
|
-
plain
|
|
29
|
-
class="button-sty"
|
|
30
|
-
icon="el-icon-question"
|
|
31
|
-
@click="showTip = true"
|
|
32
|
-
>{{ $t1("这个 demo 在演示什么") }}</vxe-button
|
|
33
|
-
>
|
|
34
|
-
</div>
|
|
35
|
-
<div class="fr">
|
|
36
|
-
<vxe-button
|
|
37
|
-
icon="el-icon-brush"
|
|
38
|
-
class="button-sty"
|
|
39
|
-
type="text"
|
|
40
|
-
status="primary"
|
|
41
|
-
plain
|
|
42
|
-
@click="resetEvent"
|
|
43
|
-
>{{ $t1("重置") }}</vxe-button
|
|
44
|
-
>
|
|
45
|
-
<vxe-button
|
|
46
|
-
status="warning"
|
|
47
|
-
icon="el-icon-search"
|
|
48
|
-
class="button-sty"
|
|
49
|
-
@click="loadList"
|
|
50
|
-
>{{ $t1("搜索") }}</vxe-button
|
|
51
|
-
>
|
|
52
|
-
</div>
|
|
53
|
-
</div>
|
|
54
|
-
<vxe-form class="screen-box" title-width="80px" title-align="right" :data="formData">
|
|
55
|
-
<vxe-form-item :title="$t1('单号') + ':'" field="sn">
|
|
56
|
-
<template v-slot>
|
|
57
|
-
<el-input v-model="formData.sn" size="small" clearable />
|
|
58
|
-
</template>
|
|
59
|
-
</vxe-form-item>
|
|
60
|
-
<vxe-form-item :title="$t1('名称') + ':'" field="name">
|
|
61
|
-
<template v-slot>
|
|
62
|
-
<el-input v-model="formData.name" size="small" clearable />
|
|
63
|
-
</template>
|
|
64
|
-
</vxe-form-item>
|
|
65
|
-
<vxe-form-item :title="$t1('状态') + ':'" field="status">
|
|
66
|
-
<template v-slot>
|
|
67
|
-
<el-select v-model="formData.status" size="small" clearable>
|
|
68
|
-
<el-option
|
|
69
|
-
v-for="(item, key) in STATUS_MAP"
|
|
70
|
-
:key="key"
|
|
71
|
-
:label="item.label"
|
|
72
|
-
:value="key"
|
|
73
|
-
/>
|
|
74
|
-
</el-select>
|
|
75
|
-
</template>
|
|
76
|
-
</vxe-form-item>
|
|
77
|
-
</vxe-form>
|
|
78
|
-
<vxe-table
|
|
79
|
-
ref="table"
|
|
80
|
-
:data="rows"
|
|
81
|
-
:loading="listLoading"
|
|
82
|
-
border
|
|
83
|
-
height="auto"
|
|
84
|
-
size="small"
|
|
85
|
-
>
|
|
86
|
-
<vxe-column field="sn" :title="$t1('单号')" width="140">
|
|
87
|
-
<template #default="{ row, rowIndex }">
|
|
88
|
-
<a href="javascript:void(0);" class="a-link" @click="openDetail(row, rowIndex)">
|
|
89
|
-
{{ row.sn }}
|
|
90
|
-
</a>
|
|
91
|
-
</template>
|
|
92
|
-
</vxe-column>
|
|
93
|
-
<vxe-column field="name" :title="$t1('名称')" min-width="180" />
|
|
94
|
-
<vxe-column field="status" :title="$t1('状态')" width="100">
|
|
95
|
-
<template #default="{ row }">
|
|
96
|
-
<div :class="getStatus(row).cls">{{ getStatus(row).label }}</div>
|
|
97
|
-
</template>
|
|
98
|
-
</vxe-column>
|
|
99
|
-
<vxe-column field="owner" :title="$t1('负责人')" width="100" />
|
|
100
|
-
<vxe-column field="amount" :title="$t1('金额')" width="100" align="right" />
|
|
101
|
-
<vxe-column field="remark" :title="$t1('备注')" min-width="160" />
|
|
102
|
-
<vxe-column field="createDate" :title="$t1('创建时间')" width="160" />
|
|
103
|
-
<vxe-column :title="''" width="47" fixed="right">
|
|
104
|
-
<template #default="{ row, rowIndex }">
|
|
105
|
-
<a href="javascript:void(0);" class="a-link" @click="openDetail(row, rowIndex)">
|
|
106
|
-
<el-tooltip
|
|
107
|
-
:enterable="false"
|
|
108
|
-
effect="dark"
|
|
109
|
-
:content="$t1('查看')"
|
|
110
|
-
placement="top"
|
|
111
|
-
popper-class="tooltip-skin"
|
|
112
|
-
><i class="el-icon-view"
|
|
113
|
-
/></el-tooltip>
|
|
114
|
-
</a>
|
|
115
|
-
</template>
|
|
116
|
-
</vxe-column>
|
|
117
|
-
</vxe-table>
|
|
118
|
-
</template>
|
|
119
|
-
|
|
120
|
-
<!-- ===== 详情页签(新增/查看共用同一个组件) ===== -->
|
|
121
|
-
<template #detail="{ tab }">
|
|
122
|
-
<bill-detail :tab="tab" />
|
|
123
|
-
</template>
|
|
124
|
-
|
|
125
|
-
<!-- ===== 页签之外:各类弹框挂这里(默认插槽) ===== -->
|
|
126
|
-
<el-dialog
|
|
127
|
-
:title="$t1('这个 demo 在演示什么')"
|
|
128
|
-
:visible.sync="showTip"
|
|
129
|
-
width="520px"
|
|
130
|
-
custom-class="dialog-style"
|
|
131
|
-
append-to-body
|
|
132
|
-
>
|
|
133
|
-
<ul class="demo-tip">
|
|
134
|
-
<li>{{ $t1("新增、查看详情都开独立页签;同一单据不重复开,新增可连开多个") }}</li>
|
|
135
|
-
<li>{{ $t1("新增页保存后就地升为编辑态(页签标题换成单号),不重新取数、不闪") }}</li>
|
|
136
|
-
<li>{{ $t1("详情里改了内容没保存,关页签会拦一下(isBillDirty 钩子)") }}</li>
|
|
137
|
-
<li>{{ $t1("详情头部「上一单/下一单」按列表当时的顺序翻单") }}</li>
|
|
138
|
-
<li>{{ $t1("关掉页签或手动切回列表,列表都会自动刷新") }}</li>
|
|
139
|
-
<li>{{ $t1("本 demo 不接流程、不打后台,数据在 billApi.js 里") }}</li>
|
|
140
|
-
</ul>
|
|
141
|
-
</el-dialog>
|
|
142
|
-
</biz-tab-list-page>
|
|
143
|
-
</template>
|
|
144
|
-
|
|
145
|
-
<script>
|
|
146
|
-
/**
|
|
147
|
-
* demo A:手写接口版(前端 mock,无流程)。
|
|
148
|
-
*
|
|
149
|
-
* 不依赖任何后台前置条件,clone 下来就能跑,可以当手写单据页面的模板抄。
|
|
150
|
-
* 数据源集中在 ./billApi.js,换真实接口只改那一个文件。
|
|
151
|
-
* 要看「保存并提交流程 / 通过自动保存 / 提交后关页签」,看 demo B:../bill/list.vue
|
|
152
|
-
*
|
|
153
|
-
* 菜单/路由:@base/views/demo/bizTab/simple/list(本地已在 router/modules/customer.js 注册)
|
|
154
|
-
*/
|
|
155
|
-
import BizTabListPage from "@base/components/bizTab/BizTabListPage.vue";
|
|
156
|
-
import billDetail from "./detail.vue";
|
|
157
|
-
import { getPage, STATUS_MAP } from "./billApi";
|
|
158
|
-
|
|
159
|
-
export default {
|
|
160
|
-
name: "demo_bizTab_simple:list",
|
|
161
|
-
components: { BizTabListPage, billDetail },
|
|
162
|
-
data() {
|
|
163
|
-
return {
|
|
164
|
-
STATUS_MAP,
|
|
165
|
-
activeTab: "second",
|
|
166
|
-
formData: {},
|
|
167
|
-
rows: [],
|
|
168
|
-
listLoading: false,
|
|
169
|
-
showTip: false,
|
|
170
|
-
};
|
|
171
|
-
},
|
|
172
|
-
mounted() {
|
|
173
|
-
this.loadList();
|
|
174
|
-
},
|
|
175
|
-
methods: {
|
|
176
|
-
loadList() {
|
|
177
|
-
this.listLoading = true;
|
|
178
|
-
return getPage(this.formData)
|
|
179
|
-
.then((rows) => {
|
|
180
|
-
this.rows = rows || [];
|
|
181
|
-
})
|
|
182
|
-
.finally(() => {
|
|
183
|
-
this.listLoading = false;
|
|
184
|
-
});
|
|
185
|
-
},
|
|
186
|
-
resetEvent() {
|
|
187
|
-
this.formData = {};
|
|
188
|
-
this.loadList();
|
|
189
|
-
},
|
|
190
|
-
getStatus(row) {
|
|
191
|
-
return STATUS_MAP[row.status] || { label: "", cls: "" };
|
|
192
|
-
},
|
|
193
|
-
// 新增页签也传快照:保存成功后新单会被插到序列首位,翻单按钮随即可用
|
|
194
|
-
openAdd() {
|
|
195
|
-
this.$refs.bizTab.openAdd(null, { navRows: this.rows });
|
|
196
|
-
},
|
|
197
|
-
// 把当前列表顺序和行下标一起传进去,详情头部就有「上一单/下一单」
|
|
198
|
-
openDetail(row, rowIndex) {
|
|
199
|
-
this.$refs.bizTab.openDetail(row, null, {
|
|
200
|
-
navRows: this.rows,
|
|
201
|
-
navIndex: rowIndex,
|
|
202
|
-
});
|
|
203
|
-
},
|
|
204
|
-
onTabRemoved(tabName) {
|
|
205
|
-
// 列表刷新由组件在「回到列表页签」时统一收口,这里只是演示事件可用
|
|
206
|
-
console.log("[demo] 页签已关闭:", tabName);
|
|
207
|
-
},
|
|
208
|
-
},
|
|
209
|
-
};
|
|
210
|
-
</script>
|
|
211
|
-
|
|
212
|
-
<style scoped>
|
|
213
|
-
.demo-tip {
|
|
214
|
-
padding-left: 18px;
|
|
215
|
-
line-height: 26px;
|
|
216
|
-
}
|
|
217
|
-
</style>
|