2023-12-21 13:07:02 +08:00
|
|
|
|
<template>
|
2024-05-10 19:59:49 +08:00
|
|
|
|
<div class="string-input-container w100" v-if="dataType == DataType.String || dataType == DataType.Number">
|
2023-12-22 12:29:46 +08:00
|
|
|
|
<el-input
|
2024-12-08 13:04:23 +08:00
|
|
|
|
:ref="
|
|
|
|
|
|
(el: any) => {
|
|
|
|
|
|
nextTick(() => {
|
|
|
|
|
|
focus && el?.focus();
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
"
|
2024-01-29 04:20:23 +00:00
|
|
|
|
:disabled="disabled"
|
2023-12-22 17:04:06 +08:00
|
|
|
|
@blur="handleBlur"
|
|
|
|
|
|
:class="`w100 mb4 ${showEditorIcon ? 'string-input-container-show-icon' : ''}`"
|
2023-12-22 12:29:46 +08:00
|
|
|
|
size="small"
|
|
|
|
|
|
v-model="itemValue"
|
2024-12-08 13:04:23 +08:00
|
|
|
|
:placeholder="placeholder ?? $t('common.pleaseInput')"
|
2023-12-22 12:29:46 +08:00
|
|
|
|
/>
|
2023-12-22 17:04:06 +08:00
|
|
|
|
<SvgIcon v-if="showEditorIcon" @mousedown="openEditor" class="string-input-container-icon" name="FullScreen" :size="10" />
|
2023-12-22 12:29:46 +08:00
|
|
|
|
</div>
|
2023-12-21 13:07:02 +08:00
|
|
|
|
|
|
|
|
|
|
<el-date-picker
|
2023-12-21 15:02:35 +08:00
|
|
|
|
v-else-if="dataType == DataType.Date"
|
2024-12-08 13:04:23 +08:00
|
|
|
|
:ref="
|
|
|
|
|
|
(el: any) => {
|
|
|
|
|
|
nextTick(() => {
|
|
|
|
|
|
focus && el?.focus();
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
"
|
2024-01-29 04:20:23 +00:00
|
|
|
|
:disabled="disabled"
|
2024-12-08 13:04:23 +08:00
|
|
|
|
@change="handleBlur"
|
2023-12-22 17:04:06 +08:00
|
|
|
|
@blur="handleBlur"
|
2023-12-21 13:07:02 +08:00
|
|
|
|
class="edit-time-picker mb4"
|
|
|
|
|
|
popper-class="edit-time-picker-popper"
|
|
|
|
|
|
size="small"
|
|
|
|
|
|
v-model="itemValue"
|
|
|
|
|
|
:clearable="false"
|
2024-12-08 13:04:23 +08:00
|
|
|
|
type="date"
|
2023-12-21 13:07:02 +08:00
|
|
|
|
value-format="YYYY-MM-DD"
|
2024-12-08 13:04:23 +08:00
|
|
|
|
:placeholder="`date-${placeholder ?? $t('common.pleaseSelect')}`"
|
2023-12-21 13:07:02 +08:00
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
|
|
<el-date-picker
|
2023-12-21 15:02:35 +08:00
|
|
|
|
v-else-if="dataType == DataType.DateTime"
|
2024-12-08 13:04:23 +08:00
|
|
|
|
:ref="
|
|
|
|
|
|
(el: any) => {
|
|
|
|
|
|
nextTick(() => {
|
|
|
|
|
|
focus && el?.focus();
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
"
|
2024-01-29 04:20:23 +00:00
|
|
|
|
:disabled="disabled"
|
2023-12-22 17:04:06 +08:00
|
|
|
|
@change="handleBlur"
|
|
|
|
|
|
@blur="handleBlur"
|
2023-12-21 13:07:02 +08:00
|
|
|
|
class="edit-time-picker mb4"
|
|
|
|
|
|
popper-class="edit-time-picker-popper"
|
|
|
|
|
|
size="small"
|
|
|
|
|
|
v-model="itemValue"
|
|
|
|
|
|
:clearable="false"
|
|
|
|
|
|
type="datetime"
|
|
|
|
|
|
value-format="YYYY-MM-DD HH:mm:ss"
|
2024-12-08 13:04:23 +08:00
|
|
|
|
:placeholder="`datetime-${placeholder ?? $t('common.pleaseSelect')}`"
|
2023-12-21 13:07:02 +08:00
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
|
|
<el-time-picker
|
2023-12-21 15:02:35 +08:00
|
|
|
|
v-else-if="dataType == DataType.Time"
|
2024-12-08 13:04:23 +08:00
|
|
|
|
:ref="
|
|
|
|
|
|
(el: any) => {
|
|
|
|
|
|
nextTick(() => {
|
|
|
|
|
|
focus && el?.focus();
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
"
|
2024-01-29 04:20:23 +00:00
|
|
|
|
:disabled="disabled"
|
2023-12-22 17:04:06 +08:00
|
|
|
|
@change="handleBlur"
|
|
|
|
|
|
@blur="handleBlur"
|
2023-12-21 13:07:02 +08:00
|
|
|
|
class="edit-time-picker mb4"
|
|
|
|
|
|
popper-class="edit-time-picker-popper"
|
|
|
|
|
|
size="small"
|
|
|
|
|
|
v-model="itemValue"
|
|
|
|
|
|
:clearable="false"
|
|
|
|
|
|
value-format="HH:mm:ss"
|
2024-12-08 13:04:23 +08:00
|
|
|
|
:placeholder="`time-${placeholder ?? $t('common.pleaseSelect')}`"
|
2023-12-21 13:07:02 +08:00
|
|
|
|
/>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script lang="ts" setup>
|
2024-12-08 13:04:23 +08:00
|
|
|
|
import { computed, nextTick, ref, Ref } from 'vue';
|
2024-05-10 19:59:49 +08:00
|
|
|
|
import { ElInput, ElMessage } from 'element-plus';
|
2023-12-21 13:07:02 +08:00
|
|
|
|
import { DataType } from '../../dialect/index';
|
2023-12-22 12:29:46 +08:00
|
|
|
|
import SvgIcon from '@/components/svgIcon/index.vue';
|
|
|
|
|
|
import MonacoEditorDialog from '@/components/monaco/MonacoEditorDialog';
|
2024-11-20 22:43:53 +08:00
|
|
|
|
import { useI18n } from 'vue-i18n';
|
|
|
|
|
|
|
|
|
|
|
|
const { t } = useI18n();
|
2023-12-21 13:07:02 +08:00
|
|
|
|
|
|
|
|
|
|
export interface ColumnFormItemProps {
|
|
|
|
|
|
modelValue: string | number; // 绑定的值
|
|
|
|
|
|
dataType: DataType; // 数据类型
|
|
|
|
|
|
focus?: boolean; // 是否获取焦点
|
|
|
|
|
|
placeholder?: string;
|
2023-12-22 12:29:46 +08:00
|
|
|
|
columnName?: string;
|
2024-01-29 04:20:23 +00:00
|
|
|
|
disabled?: boolean;
|
2023-12-21 13:07:02 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const props = withDefaults(defineProps<ColumnFormItemProps>(), {
|
|
|
|
|
|
focus: false,
|
|
|
|
|
|
dataType: DataType.String,
|
2024-01-29 04:20:23 +00:00
|
|
|
|
disabled: false,
|
2023-12-21 13:07:02 +08:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const emit = defineEmits(['update:modelValue', 'blur']);
|
|
|
|
|
|
|
2023-12-22 17:04:06 +08:00
|
|
|
|
const itemValue: Ref<any> = ref(props.modelValue);
|
2023-12-22 12:29:46 +08:00
|
|
|
|
|
|
|
|
|
|
const showEditorIcon = computed(() => {
|
|
|
|
|
|
return typeof itemValue.value === 'string' && itemValue.value.length > 50;
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const editorOpening = ref(false);
|
|
|
|
|
|
|
|
|
|
|
|
const openEditor = () => {
|
|
|
|
|
|
editorOpening.value = true;
|
|
|
|
|
|
// 编辑器语言,如:json、html、text
|
|
|
|
|
|
let editorLang = getEditorLangByValue(itemValue.value);
|
|
|
|
|
|
MonacoEditorDialog({
|
|
|
|
|
|
content: itemValue.value,
|
2024-11-20 22:43:53 +08:00
|
|
|
|
title: `${t('db.editField')} [${props.columnName}]`,
|
2023-12-22 12:29:46 +08:00
|
|
|
|
language: editorLang,
|
|
|
|
|
|
confirmFn: (newVal: any) => {
|
|
|
|
|
|
itemValue.value = newVal;
|
|
|
|
|
|
closeEditorDialog();
|
|
|
|
|
|
},
|
|
|
|
|
|
cancelFn: closeEditorDialog,
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const closeEditorDialog = () => {
|
|
|
|
|
|
editorOpening.value = false;
|
2023-12-22 17:04:06 +08:00
|
|
|
|
handleBlur();
|
2023-12-22 12:29:46 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
2023-12-22 17:04:06 +08:00
|
|
|
|
const handleBlur = () => {
|
2023-12-22 12:29:46 +08:00
|
|
|
|
if (editorOpening.value) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2024-05-11 12:09:55 +08:00
|
|
|
|
if (props.dataType == DataType.Number && itemValue.value && !/^-?\d*\.?\d+$/.test(itemValue.value)) {
|
2024-11-20 22:43:53 +08:00
|
|
|
|
ElMessage.error(t('db.valueTypeNoMatch'));
|
2024-05-10 19:59:49 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
2023-12-22 17:04:06 +08:00
|
|
|
|
emit('update:modelValue', itemValue.value);
|
2023-12-22 12:29:46 +08:00
|
|
|
|
emit('blur');
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const getEditorLangByValue = (value: any) => {
|
|
|
|
|
|
// 判断是否是json
|
|
|
|
|
|
try {
|
|
|
|
|
|
if (typeof JSON.parse(value) === 'object') {
|
|
|
|
|
|
return 'json';
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (e) {
|
|
|
|
|
|
/* empty */
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 判断是否是html
|
|
|
|
|
|
try {
|
|
|
|
|
|
const doc = new DOMParser().parseFromString(value, 'text/html');
|
|
|
|
|
|
if (Array.from(doc.body.childNodes).some((node) => node.nodeType === 1)) {
|
|
|
|
|
|
return 'html';
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (e) {
|
|
|
|
|
|
/* empty */
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return 'text';
|
|
|
|
|
|
};
|
2023-12-21 13:07:02 +08:00
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style lang="scss">
|
2023-12-22 12:29:46 +08:00
|
|
|
|
.string-input-container {
|
|
|
|
|
|
position: relative;
|
2024-05-31 12:12:40 +08:00
|
|
|
|
|
|
|
|
|
|
.el-input__wrapper {
|
|
|
|
|
|
padding: 1px 3px;
|
|
|
|
|
|
}
|
2023-12-22 12:29:46 +08:00
|
|
|
|
}
|
2023-12-22 17:04:06 +08:00
|
|
|
|
.string-input-container-show-icon {
|
|
|
|
|
|
.el-input__inner {
|
|
|
|
|
|
padding-right: 10px;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2023-12-22 12:29:46 +08:00
|
|
|
|
.string-input-container-icon {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
top: 5px; /* 调整图标的垂直位置 */
|
2023-12-22 17:04:06 +08:00
|
|
|
|
right: 3px; /* 调整图标的水平位置 */
|
|
|
|
|
|
color: var(--el-color-primary);
|
|
|
|
|
|
}
|
|
|
|
|
|
.string-input-container-icon:hover {
|
|
|
|
|
|
color: var(--el-color-success);
|
2023-12-22 12:29:46 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-12-21 13:07:02 +08:00
|
|
|
|
.edit-time-picker {
|
|
|
|
|
|
height: 26px;
|
|
|
|
|
|
width: 100% !important;
|
|
|
|
|
|
.el-input__prefix {
|
|
|
|
|
|
display: none;
|
|
|
|
|
|
}
|
2024-05-31 12:12:40 +08:00
|
|
|
|
|
|
|
|
|
|
.el-input__wrapper {
|
|
|
|
|
|
padding: 1px 3px;
|
|
|
|
|
|
}
|
2023-12-21 13:07:02 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.edit-time-picker-popper {
|
|
|
|
|
|
.el-date-picker {
|
|
|
|
|
|
width: 250px !important;
|
|
|
|
|
|
.el-date-picker__header {
|
|
|
|
|
|
margin: 0 5px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.el-picker-panel__content {
|
|
|
|
|
|
width: unset;
|
|
|
|
|
|
margin: 0 5px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.el-date-picker__header-label {
|
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.el-picker-panel__footer {
|
|
|
|
|
|
padding: 0 5px;
|
|
|
|
|
|
button {
|
|
|
|
|
|
font-size: 11px;
|
|
|
|
|
|
padding: 5px 6px;
|
|
|
|
|
|
height: 20px;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
.el-date-table {
|
|
|
|
|
|
th {
|
|
|
|
|
|
font-size: 10px;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
padding: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
td {
|
|
|
|
|
|
padding: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
.el-time-panel {
|
|
|
|
|
|
width: 100px;
|
|
|
|
|
|
|
|
|
|
|
|
.el-time-spinner__list {
|
|
|
|
|
|
&::after,
|
|
|
|
|
|
&::before {
|
|
|
|
|
|
height: 10px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.el-time-spinner__item {
|
|
|
|
|
|
height: 20px;
|
|
|
|
|
|
line-height: 20px;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
</style>
|