bl-common-vue3 3.8.131 → 3.8.133
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 +1 -1
- package/src/components/CustomTable/index.vue +39 -19
- package/src/components/ExtraFieldsItem/date.js +19 -0
- package/src/components/ExtraFieldsItem/index.vue +32 -23
- package/src/components/PublicExtensionField/components/ExtraFieldPreview.vue +86 -0
- package/src/components/PublicExtensionField/components/ExtraManageEdit.vue +147 -227
- package/src/components/PublicExtensionField/constant.js +3 -0
- package/src/components/PublicExtensionField/index.vue +80 -41
- package/src/locale/local/cht.json +13 -1
- package/src/locale/local/en.json +13 -1
- package/src/locale/local/jp.json +13 -1
- package/src/locale/local/zh-HK.json +13 -1
- package/src/locale/local/zh.json +13 -1
- package/test/customTableExport.test.js +114 -0
- package/test/extraFieldsItem.test.js +69 -0
- package/test/publicExtensionField.test.js +156 -0
package/package.json
CHANGED
|
@@ -760,11 +760,11 @@
|
|
|
760
760
|
</a-button>
|
|
761
761
|
</template>
|
|
762
762
|
|
|
763
|
-
<a-dropdown v-if="hasMoreAction">
|
|
763
|
+
<a-dropdown v-if="hasMoreAction" v-model:visible="moreActionVisible">
|
|
764
764
|
<template #overlay>
|
|
765
765
|
<a-menu>
|
|
766
766
|
<a-menu-item key="into" v-if="!excludeImport">
|
|
767
|
-
<a-button type="text" @click.stop="handleImport">
|
|
767
|
+
<a-button type="text" @click.stop="handleMoreAction(handleImport, $event)">
|
|
768
768
|
<template #icon>
|
|
769
769
|
<bl-icon type="daoru" />
|
|
770
770
|
</template>
|
|
@@ -772,7 +772,7 @@
|
|
|
772
772
|
</a-button>
|
|
773
773
|
</a-menu-item>
|
|
774
774
|
<a-menu-item key="derive" v-if="!excludeExport">
|
|
775
|
-
<a-button type="text" @click.stop="handleExport">
|
|
775
|
+
<a-button type="text" @click.stop="handleMoreAction(handleExport, $event)">
|
|
776
776
|
<template #icon>
|
|
777
777
|
<bl-icon type="daochu" />
|
|
778
778
|
</template>
|
|
@@ -782,7 +782,7 @@
|
|
|
782
782
|
<a-menu-item
|
|
783
783
|
v-if="showDictSetting && dictMenuAlias"
|
|
784
784
|
key="dictionary"
|
|
785
|
-
@click.stop="handleDictionarySetting">
|
|
785
|
+
@click.stop="handleMoreAction(handleDictionarySetting, $event)">
|
|
786
786
|
<a-button type="text">
|
|
787
787
|
<template #icon>
|
|
788
788
|
<bl-icon type="cidian" />
|
|
@@ -794,7 +794,7 @@
|
|
|
794
794
|
<a-menu-item
|
|
795
795
|
v-if="ApprovalProcessSettings && approvalList.length > 0"
|
|
796
796
|
key="Approval_process"
|
|
797
|
-
@click.stop="handleApprovalProcess">
|
|
797
|
+
@click.stop="handleMoreAction(handleApprovalProcess, $event)">
|
|
798
798
|
<a-button type="text">
|
|
799
799
|
<template #icon>
|
|
800
800
|
<bl-icon type="shenpiliucheng" />
|
|
@@ -806,7 +806,7 @@
|
|
|
806
806
|
<a-menu-item
|
|
807
807
|
v-if="showExpandFields"
|
|
808
808
|
key="expandFields"
|
|
809
|
-
@click.stop="handleExpandFieldsSetting">
|
|
809
|
+
@click.stop="handleMoreAction(handleExpandFieldsSetting, $event)">
|
|
810
810
|
<a-button type="text">
|
|
811
811
|
<template #icon>
|
|
812
812
|
<bl-icon type="tuozhanziduan" />
|
|
@@ -815,7 +815,7 @@
|
|
|
815
815
|
</a-button>
|
|
816
816
|
</a-menu-item>
|
|
817
817
|
<a-menu-item key="setting" v-if="tableId">
|
|
818
|
-
<a-button type="text" @click.stop="handleColumnSetting">
|
|
818
|
+
<a-button type="text" @click.stop="handleMoreAction(handleColumnSetting, $event)">
|
|
819
819
|
<template #icon>
|
|
820
820
|
<bl-icon type="lieshezhi" />
|
|
821
821
|
</template>
|
|
@@ -823,7 +823,7 @@
|
|
|
823
823
|
</a-button>
|
|
824
824
|
</a-menu-item>
|
|
825
825
|
<a-menu-item key="setting" v-if="dataMigration">
|
|
826
|
-
<a-button type="text" @click.stop="handledataMigration">
|
|
826
|
+
<a-button type="text" @click.stop="handleMoreAction(handledataMigration, $event)">
|
|
827
827
|
<template #icon>
|
|
828
828
|
<bl-icon type="shujuqianyi" />
|
|
829
829
|
</template>
|
|
@@ -844,7 +844,7 @@
|
|
|
844
844
|
</template>
|
|
845
845
|
<template v-for="(child) in item.children" :key="child.key">
|
|
846
846
|
<a-menu-item v-if="child?.show ?? true" :key="child.key">
|
|
847
|
-
<a-button v-bind="{ ...(child?.props || {}), }" @click.stop="child?.onClick">
|
|
847
|
+
<a-button v-bind="{ ...(child?.props || {}), }" @click.stop="handleMoreAction(child?.onClick, $event)">
|
|
848
848
|
<template #icon v-if="buttonIconSlots.indexOf(`${child.key}`) > -1">
|
|
849
849
|
<slot :name="`buttonIcon-${child.key}`"></slot>
|
|
850
850
|
</template>
|
|
@@ -856,7 +856,7 @@
|
|
|
856
856
|
</template>
|
|
857
857
|
<template v-if="((item?.show ?? true) && !item?.children?.length)">
|
|
858
858
|
<a-menu-item :key="item.key">
|
|
859
|
-
<a-button v-bind="{ ...(item?.props || {}), }" @click.stop="item?.onClick">
|
|
859
|
+
<a-button v-bind="{ ...(item?.props || {}), }" @click.stop="handleMoreAction(item?.onClick, $event)">
|
|
860
860
|
<template
|
|
861
861
|
#icon
|
|
862
862
|
v-if="buttonIconSlots.indexOf(`${item.key}`) > -1">
|
|
@@ -1342,7 +1342,7 @@
|
|
|
1342
1342
|
:url="requestInfo?.serviceUrl"
|
|
1343
1343
|
:service="requestInfo?.service"
|
|
1344
1344
|
:method="requestInfo?.serviceType"
|
|
1345
|
-
:params="
|
|
1345
|
+
:params="exportParams"
|
|
1346
1346
|
:limit="exportLimit"
|
|
1347
1347
|
:columnstitle="exportColumnsTitle"
|
|
1348
1348
|
:merge_options="exportMergeOptions"
|
|
@@ -1878,6 +1878,7 @@ export default defineComponent({
|
|
|
1878
1878
|
},
|
|
1879
1879
|
setup(props, { slots, expose, emit, attrs }) {
|
|
1880
1880
|
const state = reactive({
|
|
1881
|
+
moreActionVisible: false,
|
|
1881
1882
|
localLoading: false,
|
|
1882
1883
|
selectedRowKeys: [],
|
|
1883
1884
|
selectedRows: [],
|
|
@@ -1891,6 +1892,7 @@ export default defineComponent({
|
|
|
1891
1892
|
dictMenuAlias: "", // 后端返回的字典标识
|
|
1892
1893
|
isExport: false,
|
|
1893
1894
|
listParams: {},
|
|
1895
|
+
exportParams: {},
|
|
1894
1896
|
exportResultData: [], // 导出结果处理
|
|
1895
1897
|
importVisible: false,
|
|
1896
1898
|
tableScrollHeight: 0,
|
|
@@ -2439,7 +2441,8 @@ export default defineComponent({
|
|
|
2439
2441
|
let columnIndexObj = {};
|
|
2440
2442
|
let haveSlot = false;
|
|
2441
2443
|
cloneDeep(realColumns.value).forEach((columnItem, index) => {
|
|
2442
|
-
//
|
|
2444
|
+
// 不导出的展示列可能没有 dataIndex,也可能返回 VNode,不能参与数据转换。
|
|
2445
|
+
if (columnItem.exportHidden) return;
|
|
2443
2446
|
let virtualDataIndex = replaceObjDataIndex(columnItem.dataIndex);
|
|
2444
2447
|
if (columnItem.columnType) {
|
|
2445
2448
|
columnIndexObj[virtualDataIndex] = {
|
|
@@ -2487,20 +2490,21 @@ export default defineComponent({
|
|
|
2487
2490
|
localRowSelection.value?.selectedRowKeys
|
|
2488
2491
|
);
|
|
2489
2492
|
}
|
|
2493
|
+
// 导出组件会更新分页并追加选中条件,使用快照避免污染列表的后续查询。
|
|
2494
|
+
state.exportParams = cloneDeep(state.listParams);
|
|
2495
|
+
state.exportParams.filters = (state.exportParams.filters || []).filter(
|
|
2496
|
+
(item) => item.field !== "ids"
|
|
2497
|
+
);
|
|
2490
2498
|
if (localRowSelection.value?.selectedRowKeys.length > 0) {
|
|
2491
|
-
state.
|
|
2499
|
+
state.exportParams.filters.push({
|
|
2492
2500
|
field: "ids",
|
|
2493
2501
|
type: "custom",
|
|
2494
|
-
value: localRowSelection.value
|
|
2502
|
+
value: [...localRowSelection.value.selectedRowKeys],
|
|
2495
2503
|
});
|
|
2496
|
-
} else {
|
|
2497
|
-
state.listParams.filters = state.listParams.filters.filter(
|
|
2498
|
-
(item) => item.field != "ids"
|
|
2499
|
-
);
|
|
2500
2504
|
}
|
|
2501
2505
|
if (props.customExport) {
|
|
2502
2506
|
/* 自定义导出 */
|
|
2503
|
-
props.customExport(state.
|
|
2507
|
+
props.customExport(state.exportParams);
|
|
2504
2508
|
} else {
|
|
2505
2509
|
/* 默认导出 */
|
|
2506
2510
|
state.isExport = true;
|
|
@@ -2814,6 +2818,12 @@ export default defineComponent({
|
|
|
2814
2818
|
};
|
|
2815
2819
|
});
|
|
2816
2820
|
|
|
2821
|
+
// 菜单按钮使用 stop 阻止冒泡,需要主动收起,避免弹层打开后菜单仍遮挡操作。
|
|
2822
|
+
const handleMoreAction = (callback, event) => {
|
|
2823
|
+
state.moreActionVisible = false;
|
|
2824
|
+
return callback?.(event);
|
|
2825
|
+
};
|
|
2826
|
+
|
|
2817
2827
|
// 刷新表格数据
|
|
2818
2828
|
const refresh = (isInit = false) => {
|
|
2819
2829
|
state.hasDictionary = false;
|
|
@@ -2821,6 +2831,14 @@ export default defineComponent({
|
|
|
2821
2831
|
loadData(isInit);
|
|
2822
2832
|
};
|
|
2823
2833
|
|
|
2834
|
+
// 业务端异步取得完整列定义后更新表头,保留当前筛选、分页和勾选状态。
|
|
2835
|
+
const setColumns = async (columns) => {
|
|
2836
|
+
state.defaultColumns = cloneDeep(columns || []);
|
|
2837
|
+
state.initColumns = cloneDeep(state.defaultColumns);
|
|
2838
|
+
await getLocalColumns();
|
|
2839
|
+
createColumnSlots();
|
|
2840
|
+
};
|
|
2841
|
+
|
|
2824
2842
|
const actionBtnShow = computed(
|
|
2825
2843
|
() =>
|
|
2826
2844
|
({ item, text, record, index, column }) =>
|
|
@@ -4111,6 +4129,7 @@ export default defineComponent({
|
|
|
4111
4129
|
expose({
|
|
4112
4130
|
refresh,
|
|
4113
4131
|
loadData,
|
|
4132
|
+
setColumns,
|
|
4114
4133
|
setExportData,
|
|
4115
4134
|
getFilterList,
|
|
4116
4135
|
clearData,
|
|
@@ -4370,6 +4389,7 @@ export default defineComponent({
|
|
|
4370
4389
|
columnsProcess,
|
|
4371
4390
|
getDateValueFormat,
|
|
4372
4391
|
handleOperationClick,
|
|
4392
|
+
handleMoreAction,
|
|
4373
4393
|
refresh,
|
|
4374
4394
|
roomClick,
|
|
4375
4395
|
toOwnerDetail,
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import dayjs from 'dayjs';
|
|
2
|
+
import customParseFormat from 'dayjs/plugin/customParseFormat';
|
|
3
|
+
|
|
4
|
+
dayjs.extend(customParseFormat);
|
|
5
|
+
|
|
6
|
+
export const EXTRA_DATE_FORMATS = Object.freeze({
|
|
7
|
+
1: 'YYYY-MM-DD',
|
|
8
|
+
2: 'YYYY-MM-DD HH:mm',
|
|
9
|
+
3: 'HH:mm',
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
// 兼容历史秒级值及日期类型调整;展示和再次保存均统一为分钟精度。
|
|
13
|
+
export const formatExtraDate = (value, dateType) => {
|
|
14
|
+
if (value == null || value === '') return value;
|
|
15
|
+
const format = EXTRA_DATE_FORMATS[dateType];
|
|
16
|
+
if (!format) return value;
|
|
17
|
+
const parsed = dayjs(value, ['YYYY-MM-DD HH:mm', 'YYYY-MM-DD HH:mm:ss', 'YYYY-MM-DD', 'HH:mm', 'HH:mm:ss'], true);
|
|
18
|
+
return parsed.isValid() ? parsed.format(format) : value;
|
|
19
|
+
};
|
|
@@ -65,10 +65,10 @@
|
|
|
65
65
|
<a-date-picker v-model:value="value" :disabled="disabled" style="width: 100%" @change="changediv" format="YYYY-MM-DD" valueFormat="YYYY-MM-DD" />
|
|
66
66
|
</div>
|
|
67
67
|
<div v-if="data?.date_type == 2">
|
|
68
|
-
<a-date-picker show-time v-model:value="value" :disabled="disabled" style="width: 100%" @change="changediv" format="YYYY-MM-DD HH:mm" valueFormat="YYYY-MM-DD HH:mm" />
|
|
68
|
+
<a-date-picker :show-time="{ format: 'HH:mm', showSecond: false }" v-model:value="value" :disabled="disabled" style="width: 100%" @change="changediv" format="YYYY-MM-DD HH:mm" valueFormat="YYYY-MM-DD HH:mm" />
|
|
69
69
|
</div>
|
|
70
70
|
<div v-if="data?.date_type == 3">
|
|
71
|
-
<a-time-picker v-model:value="value" style="width: 100%" :disabled="disabled" @change="changediv" format="HH:mm" valueFormat="HH:mm" />
|
|
71
|
+
<a-time-picker :show-second="false" v-model:value="value" style="width: 100%" :disabled="disabled" @change="changediv" format="HH:mm" valueFormat="HH:mm" />
|
|
72
72
|
</div>
|
|
73
73
|
</div>
|
|
74
74
|
<!-- 下拉单选 -->
|
|
@@ -78,6 +78,7 @@
|
|
|
78
78
|
v-model:value="value"
|
|
79
79
|
style="width: 100%"
|
|
80
80
|
:options="data?.option_value"
|
|
81
|
+
:allowClear="!data?.fill"
|
|
81
82
|
@change="changediv"
|
|
82
83
|
:disabled="disabled"
|
|
83
84
|
></a-select>
|
|
@@ -90,6 +91,7 @@
|
|
|
90
91
|
v-model:value="value"
|
|
91
92
|
style="width: 100%"
|
|
92
93
|
:options="data?.option_value"
|
|
94
|
+
:allowClear="!data?.fill"
|
|
93
95
|
@change="changediv"
|
|
94
96
|
:disabled="disabled"
|
|
95
97
|
></a-select>
|
|
@@ -137,7 +139,7 @@
|
|
|
137
139
|
:before-upload="beforeUpload"
|
|
138
140
|
:accept="accept"
|
|
139
141
|
>
|
|
140
|
-
<a-button v-if="value.length < data?.option_max">
|
|
142
|
+
<a-button v-if="!data?.option_max || value.length < data?.option_max">
|
|
141
143
|
<UploadOutlined />
|
|
142
144
|
{{ t('ExtraFieldsItem.index.831918-0') }}
|
|
143
145
|
</a-button>
|
|
@@ -170,7 +172,8 @@
|
|
|
170
172
|
</div>
|
|
171
173
|
<!-- 数字 -->
|
|
172
174
|
<div v-if="data?.fields_type == 'number'">
|
|
173
|
-
|
|
175
|
+
<!-- 数字 0 是有效字段值,只有未填写时才显示占位符。 -->
|
|
176
|
+
{{data?.value === '' ? '--' : (data?.value ?? '--')}}
|
|
174
177
|
</div>
|
|
175
178
|
<!-- 单选 -->
|
|
176
179
|
<div v-if="data?.fields_type == 'radio'">
|
|
@@ -196,7 +199,7 @@
|
|
|
196
199
|
</div>
|
|
197
200
|
<!-- 日期时间 -->
|
|
198
201
|
<div v-if="data?.fields_type == 'date'">
|
|
199
|
-
{{data?.value || '--'}}
|
|
202
|
+
{{formatExtraDate(data?.value, data?.date_type) || '--'}}
|
|
200
203
|
</div>
|
|
201
204
|
<!-- 下拉单选 -->
|
|
202
205
|
<div v-if="data?.fields_type == 'select_single'">
|
|
@@ -257,10 +260,11 @@
|
|
|
257
260
|
</template>
|
|
258
261
|
|
|
259
262
|
<script>
|
|
260
|
-
import { cloneDeep } from "lodash";
|
|
263
|
+
import { cloneDeep } from "lodash";
|
|
261
264
|
import {
|
|
262
265
|
defineComponent,
|
|
263
266
|
reactive,
|
|
267
|
+
onUnmounted,
|
|
264
268
|
ref,
|
|
265
269
|
toRefs,
|
|
266
270
|
} from "vue";
|
|
@@ -268,9 +272,11 @@ import { message } from "ant-design-vue";
|
|
|
268
272
|
import {PlusOutlined,DownloadOutlined,UploadOutlined,DeleteOutlined} from "@ant-design/icons-vue";
|
|
269
273
|
import {t, loadLanguageAsync} from "../../locale";
|
|
270
274
|
import utils from "../../common/utils/util";
|
|
275
|
+
import { formatExtraDate } from './date';
|
|
271
276
|
|
|
272
277
|
export default defineComponent({
|
|
273
278
|
name: "ExtraFieldsItem",
|
|
279
|
+
emits: ["close", "uploading"],
|
|
274
280
|
components: {PlusOutlined , DownloadOutlined , UploadOutlined , DeleteOutlined},
|
|
275
281
|
props: {
|
|
276
282
|
Objectdata: {
|
|
@@ -306,6 +312,7 @@ export default defineComponent({
|
|
|
306
312
|
}
|
|
307
313
|
|
|
308
314
|
const handleInventoryUploadChange = (info) => {
|
|
315
|
+
emit('uploading', info.fileList.some((file) => file.status === 'uploading'));
|
|
309
316
|
let resFileList = [...info.fileList];
|
|
310
317
|
if (resFileList?.length) {
|
|
311
318
|
resFileList.map((file, index) => {
|
|
@@ -359,19 +366,16 @@ export default defineComponent({
|
|
|
359
366
|
// 上传视频
|
|
360
367
|
const fileListVideo = ref([]);
|
|
361
368
|
const handleChange = (info) => {
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
result =
|
|
365
|
-
if (result && result.response) {
|
|
369
|
+
emit('uploading', info.fileList.some((file) => file.status === 'uploading'));
|
|
370
|
+
// 连续选择附件会并行上传,应处理本次变化的文件,并保留其他未完成任务。
|
|
371
|
+
const result = info.file;
|
|
372
|
+
if (result?.status === 'done' && result.response) {
|
|
366
373
|
if (result.response.code == 1000) {
|
|
367
|
-
|
|
368
|
-
list.fileUrl = result.response?.data?.fileUrl
|
|
369
|
-
list.name = resFileList.slice(-1)[0].name
|
|
370
|
-
state.value.push(list)
|
|
371
|
-
fileListVideo.value = []
|
|
374
|
+
state.value.push({fileUrl: result.response.data?.fileUrl, name: result.name});
|
|
372
375
|
} else {
|
|
373
376
|
message.warning(result.response.msg);
|
|
374
377
|
}
|
|
378
|
+
fileListVideo.value = info.fileList.filter((file) => file.uid !== result.uid);
|
|
375
379
|
}
|
|
376
380
|
changediv()
|
|
377
381
|
};
|
|
@@ -398,16 +402,18 @@ export default defineComponent({
|
|
|
398
402
|
changediv()
|
|
399
403
|
}
|
|
400
404
|
if(state.data.fields_type == 'radio'){
|
|
401
|
-
state.value = state.data.value
|
|
405
|
+
state.value = state.data.value ?? ''
|
|
402
406
|
}
|
|
403
407
|
if(state.data.fields_type == 'multiple_choice'){
|
|
404
|
-
state.value = state.data.value ||
|
|
408
|
+
state.value = state.data.value || []
|
|
405
409
|
}
|
|
406
410
|
if(state.data.fields_type == 'date'){
|
|
407
|
-
state.value = state.data.value || ''
|
|
411
|
+
state.value = formatExtraDate(state.data.value, state.data.date_type) || ''
|
|
412
|
+
// 历史秒值同步到表单模型,保证未操作日期控件时再次保存也使用分钟精度。
|
|
413
|
+
if (state.data.value && state.value !== state.data.value) changediv()
|
|
408
414
|
}
|
|
409
415
|
if(state.data.fields_type == 'select_single'){
|
|
410
|
-
state.value = state.data.value
|
|
416
|
+
state.value = state.data.value ?? null
|
|
411
417
|
}
|
|
412
418
|
if(state.data.fields_type == 'select_multiple'){
|
|
413
419
|
state.value = state.data.value || []
|
|
@@ -440,12 +446,15 @@ export default defineComponent({
|
|
|
440
446
|
|
|
441
447
|
loadLanguageAsync(utils.getLang());
|
|
442
448
|
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
loadLanguageAsync(
|
|
446
|
-
}
|
|
449
|
+
// 列表单元格会频繁卸载,必须同步释放语言事件监听。
|
|
450
|
+
const handleLanguageChange = (event) => {
|
|
451
|
+
loadLanguageAsync(event.newValue);
|
|
452
|
+
};
|
|
453
|
+
window.addEventListener('setBLLang', handleLanguageChange);
|
|
454
|
+
onUnmounted(() => window.removeEventListener('setBLLang', handleLanguageChange));
|
|
447
455
|
|
|
448
456
|
return {
|
|
457
|
+
formatExtraDate,
|
|
449
458
|
t,
|
|
450
459
|
...toRefs(state),
|
|
451
460
|
init,
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<aside class="extra-field-preview">
|
|
3
|
+
<div class="preview-heading"><span class="live-dot"></span>{{ t('PublicExtensionField.previewTitle') }}</div>
|
|
4
|
+
<div class="preview-card">
|
|
5
|
+
<div class="preview-section">{{ t('PublicExtensionField.previewSection') }}</div>
|
|
6
|
+
<label class="preview-label"><span v-if="field.fill" class="required-mark">*</span>{{ field.fields_name || t('PublicExtensionField.unnamed') }}</label>
|
|
7
|
+
<a-input v-if="field.fields_type === 'single_text'" v-model:value="value" :placeholder="placeholder" :maxlength="maxLength" />
|
|
8
|
+
<a-textarea v-else-if="field.fields_type === 'multiple_text'" v-model:value="value" :placeholder="placeholder" :maxlength="maxLength" :rows="3" />
|
|
9
|
+
<a-input-number v-else-if="field.fields_type === 'number'" v-model:value="value" :placeholder="placeholder" :min="minValue" :max="maxValue" class="preview-control" />
|
|
10
|
+
<a-radio-group v-else-if="field.fields_type === 'radio'" v-model:value="value" :options="options" />
|
|
11
|
+
<a-checkbox-group v-else-if="field.fields_type === 'multiple_choice'" v-model:value="value" :options="options" />
|
|
12
|
+
<a-select v-else-if="field.fields_type === 'select_single' || field.fields_type === 'select_multiple'"
|
|
13
|
+
v-model:value="value" :mode="field.fields_type === 'select_multiple' ? 'multiple' : undefined"
|
|
14
|
+
:options="options" :placeholder="t('common.please.choose')" :allowClear="!field.fill" class="preview-control" />
|
|
15
|
+
<template v-else-if="field.fields_type === 'date'">
|
|
16
|
+
<a-time-picker v-if="field.date_type == 3" v-model:value="value" format="HH:mm" value-format="HH:mm" :show-second="false" class="preview-control" />
|
|
17
|
+
<a-date-picker v-else v-model:value="value" :format="dateFormat" :value-format="dateFormat"
|
|
18
|
+
:show-time="field.date_type == 2 ? { format: 'HH:mm', showSecond: false } : false" class="preview-control" />
|
|
19
|
+
</template>
|
|
20
|
+
<!-- 维护预览不上传文件,避免试填配置时产生业务附件。 -->
|
|
21
|
+
<div v-else-if="field.fields_type === 'image' || field.fields_type === 'attachment'" class="upload-preview">
|
|
22
|
+
<PictureOutlined v-if="field.fields_type === 'image'" /><UploadOutlined v-else />
|
|
23
|
+
<div>{{ t(field.fields_type === 'image' ? 'ExtraFieldsItem.index.243488-0' : 'ExtraFieldsItem.index.831918-0') }}</div>
|
|
24
|
+
</div>
|
|
25
|
+
</div>
|
|
26
|
+
<p class="preview-description">{{ t('PublicExtensionField.previewHint') }}</p>
|
|
27
|
+
<div class="preview-note">{{ t(field.fill ? 'PublicExtensionField.requiredHint' : 'PublicExtensionField.optionalHint') }}</div>
|
|
28
|
+
</aside>
|
|
29
|
+
</template>
|
|
30
|
+
|
|
31
|
+
<script>
|
|
32
|
+
import { computed, defineComponent, ref, watch } from 'vue';
|
|
33
|
+
import { Input, InputNumber, Radio, Checkbox, Select, DatePicker, TimePicker } from 'ant-design-vue';
|
|
34
|
+
import { PictureOutlined, UploadOutlined } from '@ant-design/icons-vue';
|
|
35
|
+
import { t } from '../../../locale';
|
|
36
|
+
import { EXTRA_DATE_FORMATS } from '../../ExtraFieldsItem/date';
|
|
37
|
+
|
|
38
|
+
export default defineComponent({
|
|
39
|
+
name: 'ExtraFieldPreview',
|
|
40
|
+
components: {
|
|
41
|
+
'a-input': Input, 'a-textarea': Input.TextArea, 'a-input-number': InputNumber,
|
|
42
|
+
'a-radio-group': Radio.Group, 'a-checkbox-group': Checkbox.Group,
|
|
43
|
+
'a-select': Select, 'a-date-picker': DatePicker, 'a-time-picker': TimePicker,
|
|
44
|
+
PictureOutlined, UploadOutlined,
|
|
45
|
+
},
|
|
46
|
+
props: { field: { type: Object, required: true } },
|
|
47
|
+
setup(props) {
|
|
48
|
+
const value = ref();
|
|
49
|
+
const options = computed(() => (props.field.option_value || []).filter((item) => item.label));
|
|
50
|
+
const placeholder = computed(() => props.field.placeholder || t('common.please.enter'));
|
|
51
|
+
const dateFormat = computed(() => EXTRA_DATE_FORMATS[props.field.date_type] || EXTRA_DATE_FORMATS[1]);
|
|
52
|
+
const toLimit = (limit) => limit === '' || limit == null ? undefined : Number(limit);
|
|
53
|
+
const minValue = computed(() => toLimit(props.field.min_length));
|
|
54
|
+
const maxValue = computed(() => toLimit(props.field.max_length));
|
|
55
|
+
const maxLength = computed(() => maxValue.value > 0 ? maxValue.value : undefined);
|
|
56
|
+
watch(() => [props.field.fields_type, props.field.date_type, props.field.default_value], () => {
|
|
57
|
+
if (['single_text', 'multiple_text', 'number'].includes(props.field.fields_type)) {
|
|
58
|
+
value.value = props.field.default_value ?? '';
|
|
59
|
+
} else {
|
|
60
|
+
value.value = ['select_multiple', 'multiple_choice'].includes(props.field.fields_type) ? [] : undefined;
|
|
61
|
+
}
|
|
62
|
+
}, { immediate: true });
|
|
63
|
+
watch(() => [props.field.fill, options.value], () => {
|
|
64
|
+
if (props.field.fields_type === 'select_single' && props.field.fill && options.value.length === 1) {
|
|
65
|
+
value.value = options.value[0].value;
|
|
66
|
+
}
|
|
67
|
+
}, { immediate: true, deep: true });
|
|
68
|
+
return { t, value, options, placeholder, dateFormat, minValue, maxValue, maxLength };
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
</script>
|
|
72
|
+
|
|
73
|
+
<style lang="less" scoped>
|
|
74
|
+
.extra-field-preview { padding: 24px; background: #f7f9fc; border-left: 1px solid #edf0f4; }
|
|
75
|
+
.preview-heading { display: flex; align-items: center; gap: 8px; margin-bottom: 20px; color: #758499; font-size: 12px; }
|
|
76
|
+
.live-dot { width: 6px; height: 6px; border-radius: 50%; background: #52b89a; }
|
|
77
|
+
.preview-card { padding: 20px 18px 24px; border: 1px solid #e4eaf2; border-radius: 6px; background: #fff; }
|
|
78
|
+
.preview-section { padding-bottom: 14px; margin-bottom: 18px; border-bottom: 1px solid #edf0f4; color: #718095; font-size: 13px; }
|
|
79
|
+
.preview-label { display: block; margin-bottom: 10px; overflow-wrap: anywhere; }
|
|
80
|
+
.required-mark { margin-right: 4px; color: #ff4d4f; }
|
|
81
|
+
.preview-control { width: 100%; }
|
|
82
|
+
.preview-description { margin: 16px 0; color: #8b97a8; line-height: 1.8; font-size: 12px; }
|
|
83
|
+
.preview-note { padding: 9px 12px; border-radius: 4px; background: #edf3fb; color: #6584a9; font-size: 12px; }
|
|
84
|
+
.upload-preview { padding: 24px 10px; text-align: center; border: 1px dashed #cfd9e6; border-radius: 4px; color: #8295ae; }
|
|
85
|
+
@media (max-width: 767px) { .extra-field-preview { border-left: 0; border-top: 1px solid #edf0f4; } }
|
|
86
|
+
</style>
|