bl-common-vue3 3.8.131 → 3.8.132
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 +27 -10
- 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 +79 -40
- 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/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">
|
|
@@ -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: [],
|
|
@@ -2814,6 +2815,12 @@ export default defineComponent({
|
|
|
2814
2815
|
};
|
|
2815
2816
|
});
|
|
2816
2817
|
|
|
2818
|
+
// 菜单按钮使用 stop 阻止冒泡,需要主动收起,避免弹层打开后菜单仍遮挡操作。
|
|
2819
|
+
const handleMoreAction = (callback, event) => {
|
|
2820
|
+
state.moreActionVisible = false;
|
|
2821
|
+
return callback?.(event);
|
|
2822
|
+
};
|
|
2823
|
+
|
|
2817
2824
|
// 刷新表格数据
|
|
2818
2825
|
const refresh = (isInit = false) => {
|
|
2819
2826
|
state.hasDictionary = false;
|
|
@@ -2821,6 +2828,14 @@ export default defineComponent({
|
|
|
2821
2828
|
loadData(isInit);
|
|
2822
2829
|
};
|
|
2823
2830
|
|
|
2831
|
+
// 业务端异步取得完整列定义后更新表头,保留当前筛选、分页和勾选状态。
|
|
2832
|
+
const setColumns = async (columns) => {
|
|
2833
|
+
state.defaultColumns = cloneDeep(columns || []);
|
|
2834
|
+
state.initColumns = cloneDeep(state.defaultColumns);
|
|
2835
|
+
await getLocalColumns();
|
|
2836
|
+
createColumnSlots();
|
|
2837
|
+
};
|
|
2838
|
+
|
|
2824
2839
|
const actionBtnShow = computed(
|
|
2825
2840
|
() =>
|
|
2826
2841
|
({ item, text, record, index, column }) =>
|
|
@@ -4111,6 +4126,7 @@ export default defineComponent({
|
|
|
4111
4126
|
expose({
|
|
4112
4127
|
refresh,
|
|
4113
4128
|
loadData,
|
|
4129
|
+
setColumns,
|
|
4114
4130
|
setExportData,
|
|
4115
4131
|
getFilterList,
|
|
4116
4132
|
clearData,
|
|
@@ -4370,6 +4386,7 @@ export default defineComponent({
|
|
|
4370
4386
|
columnsProcess,
|
|
4371
4387
|
getDateValueFormat,
|
|
4372
4388
|
handleOperationClick,
|
|
4389
|
+
handleMoreAction,
|
|
4373
4390
|
refresh,
|
|
4374
4391
|
roomClick,
|
|
4375
4392
|
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>
|