Files
orange-admin/OrangeFormsOpen-VUE3/src/online/components/OnlineCustomWidget.vue

580 lines
18 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<component
v-bind="getWidgetProps"
:ref="widget.variableName"
:is="getComponent"
:style="getWidgetStyle"
:disabled="getDisabledStatus()"
:widget="widget"
v-model="bindValue"
:value="bindValue"
@change="onValueChange"
:change="onValueChange"
@widgetClick="onWidgetClick"
>
<template v-if="form().mode === 'pc'" v-slot="scope">
<template v-if="widget.widgetType === SysCustomWidgetType.Radio">
<el-radio v-for="item in getAllDropdownData" :key="item.id" :value="item.id">
{{ item.name }}
</el-radio>
</template>
<template
v-else-if="
widget.widgetType === SysCustomWidgetType.Date ||
widget.widgetType === SysCustomWidgetType.DateRange
"
>
<div class="el-date-table-cell">
<span class="el-date-table-cell__text">{{ scope.text }}</span>
</div>
</template>
<template v-else-if="widget.widgetType === SysCustomWidgetType.CheckBox">
<el-checkbox v-for="item in getAllDropdownData" :key="item.id" :label="item.id">
{{ item.name }}
</el-checkbox>
</template>
<template v-else-if="widget.widgetType === SysCustomWidgetType.Select">
<el-option
v-for="item in getAllDropdownData"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</template>
<template v-if="widget.widgetType === SysCustomWidgetType.Link">
<span>{{ widget.props.showText || widget.showName }}</span>
</template>
</template>
</component>
</template>
<script setup lang="ts">
import {
ElCascader,
ElCheckboxGroup,
ElDatePicker,
ElInput,
ElInputNumber,
ElLink,
ElRadioGroup,
ElSelect,
ElSwitch,
} from 'element-plus';
import { ANY_OBJECT } from '@/types/generic';
import { OnlineFormEventType, SysCustomWidgetType, SysOnlineFormType } from '@/common/staticDict';
import { SysOnlineColumnFilterType, SysOnlineFieldKind } from '@/common/staticDict/online';
import {
treeDataTranslate,
findTreeNode,
findItemFromList,
findTreeNodePath,
} from '@/common/utils';
import RichEditor from '@/components/RichEditor/index.vue';
import UserSelect from '@/components/UserSelect/index.vue';
import DeptSelect from '@/components/DeptSelect/index.vue';
import InputNumberRange from '@/components/InputNumberRange/index.vue';
import OnlineCustomLabel from './OnlineCustomLabel.vue';
import OnlineCustomUpload from './OnlineCustomUpload.vue';
import OnlineCustomTree from './OnlineCustomTree.vue';
import OnlineCustomText from './OnlineCustomText.vue';
import OnlineCustomImage from './OnlineCustomImage.vue';
import { WidgetEmit, WidgetProps } from './types/widget';
import { useWidget } from './hooks/widget';
type ValueType = string | boolean | Date | number | ANY_OBJECT | Array<ANY_OBJECT>;
interface IEmit extends WidgetEmit {
(event: 'change', value: ANY_OBJECT | undefined, params: ANY_OBJECT | null): void;
(event: 'update:value', value: ValueType | undefined): void;
(event: 'update:modelValue', value: ValueType | undefined): void;
(event: 'update:widget', value: ANY_OBJECT): void;
(event: 'input', value: ValueType | undefined): void;
}
const emit = defineEmits<IEmit>();
interface IProps extends WidgetProps {
value?: ValueType;
widget: ANY_OBJECT;
}
const pps = withDefaults(defineProps<IProps>(), {});
console.log('widget pps', pps);
const form = inject('form', () => {
console.error('OnlineCustomWidget: form not injected');
return { isEdit: false } as ANY_OBJECT;
});
const parentWidget = inject<ANY_OBJECT | null>('parentWidget', null);
const { propsWidget, onWidgetClick } = useWidget(pps, emit);
const dictDataList = ref<ANY_OBJECT[]>([]);
const tempValue = ref();
const multiSelect = computed(() => {
if (
[
SysCustomWidgetType.Select,
SysCustomWidgetType.CheckBox,
SysCustomWidgetType.Cascader,
SysCustomWidgetType.Tree,
].indexOf(pps.widget.widgetType) === -1
) {
return false;
}
if (pps.widget.widgetType === SysCustomWidgetType.CheckBox) return true;
if (
form().formType === SysOnlineFormType.QUERY ||
form().formType === SysOnlineFormType.ADVANCE_QUERY
) {
return (
pps.widget.column &&
pps.widget.column.filterType === SysOnlineColumnFilterType.MULTI_SELECT_FILTER
);
} else if (form().formType === SysOnlineFormType.REPORT) {
return SysCustomWidgetType.CheckBox === pps.widget.widgetType;
} else {
return pps.widget.column && pps.widget.column.fieldKind === SysOnlineFieldKind.MULTI_SELECT;
}
});
const isMobileFilter = computed(() => {
return (
[
SysCustomWidgetType.MobileRadioFilter,
SysCustomWidgetType.MobileCheckBoxFilter,
SysCustomWidgetType.MobileInputFilter,
SysCustomWidgetType.MobileDateRangeFilter,
SysCustomWidgetType.MobileNumberRangeFilter,
SysCustomWidgetType.MobileSwitchFilter,
].indexOf(pps.widget.widgetType) !== -1
);
});
const getAllDropdownData = computed(() => {
console.log('widget getAllDropdownData', pps.widget.props.supportAll, dictDataList);
if (pps.widget.props.supportAll) {
return [
{
id: '',
name: '全部',
},
...dictDataList.value,
];
} else {
return dictDataList.value;
}
});
const getWidgetStyle = computed(() => {
return {
width: pps.widget.widgetType !== SysCustomWidgetType.Link ? '100%' : undefined,
};
});
const getComponent = computed(() => {
console.log(
'widget getComponent',
pps.widget.widgetType,
SysCustomWidgetType.getValue(pps.widget.widgetType),
);
if (
[
SysCustomWidgetType.Text,
SysCustomWidgetType.Image,
SysCustomWidgetType.Upload,
SysCustomWidgetType.Link,
].indexOf(pps.widget.widgetType) === -1 &&
form().readOnly
) {
return OnlineCustomLabel;
}
let mode = form().mode;
console.log('widget getComponent mode', mode);
switch (pps.widget.widgetType) {
case SysCustomWidgetType.Label:
return OnlineCustomLabel;
case SysCustomWidgetType.Input:
return ElInput;
case SysCustomWidgetType.NumberInput:
return ElInputNumber;
case SysCustomWidgetType.NumberRange:
return InputNumberRange;
case SysCustomWidgetType.Switch:
return ElSwitch;
case SysCustomWidgetType.Radio:
return ElRadioGroup;
case SysCustomWidgetType.CheckBox:
return ElCheckboxGroup;
case SysCustomWidgetType.Select:
return ElSelect;
case SysCustomWidgetType.Cascader:
return ElCascader;
case SysCustomWidgetType.Date:
return ElDatePicker;
case SysCustomWidgetType.DateRange:
return ElDatePicker;
case SysCustomWidgetType.Upload:
return OnlineCustomUpload;
case SysCustomWidgetType.RichEditor:
return RichEditor;
case SysCustomWidgetType.Link:
return ElLink;
case SysCustomWidgetType.UserSelect:
return UserSelect;
case SysCustomWidgetType.DeptSelect:
return DeptSelect;
case SysCustomWidgetType.Tree:
return OnlineCustomTree;
case SysCustomWidgetType.Text:
return OnlineCustomText;
case SysCustomWidgetType.Image:
return OnlineCustomImage;
default:
console.warn('widget getComponent 未知类型');
return 'div';
}
});
const getLinkHerf = computed(() => {
let temp = pps.widget.widgetType === SysCustomWidgetType.Link ? pps.widget.props.href : undefined;
return temp;
});
const isDictWidget = computed(() => {
return (
[
SysCustomWidgetType.Select,
SysCustomWidgetType.CheckBox,
SysCustomWidgetType.Radio,
SysCustomWidgetType.Cascader,
SysCustomWidgetType.Tree,
SysCustomWidgetType.MobileCheckBoxFilter,
SysCustomWidgetType.MobileRadioFilter,
].indexOf(pps.widget.widgetType) !== -1
);
});
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const bindValue = computed<string | number | boolean | any[] | ANY_OBJECT | Date | undefined>({
get() {
console.log('widget bind props.value >>', pps.value);
let tempValue = pps.value === undefined ? '' : pps.value;
if (isDictWidget.value) tempValue = tempValue == null ? '' : tempValue + '';
if (multiSelect.value && pps.value && typeof tempValue === 'string') {
tempValue = tempValue.split(',');
if (Array.isArray(tempValue)) {
tempValue = tempValue.filter(item => {
return item != null && item !== '';
});
}
}
if (pps.widget.widgetType === SysCustomWidgetType.CheckBox) {
return tempValue || [];
} else if (pps.widget.widgetType === SysCustomWidgetType.Cascader) {
if (multiSelect.value) {
// 多选
if (Array.isArray(tempValue)) {
return tempValue
.map(item => {
let temp = findTreeNodePath(dictDataList.value, item);
if (Array.isArray(temp) && temp.length > 0) return temp;
return null;
})
.filter(item => item != null);
} else {
let temp = findTreeNodePath(dictDataList.value, tempValue.toString());
return temp || [];
}
} else {
// 单选
let temp = findTreeNodePath(dictDataList.value, tempValue.toString());
return temp.length > 0 ? temp : tempValue;
}
} else if (pps.widget.widgetType === SysCustomWidgetType.NumberInput) {
return tempValue as number;
} else {
return tempValue;
}
},
set(val) {
console.log('widget .......bindValue..........', val, typeof val);
onValueInput(val as ANY_OBJECT | undefined);
},
});
const isUploadImage = computed(() => {
if (pps.widget.widgetType !== SysCustomWidgetType.Upload) return false;
let column = pps.widget.bindData.column || pps.widget.column;
return column ? column.fieldKind === SysOnlineFieldKind.UPLOAD_IMAGE : false;
});
const showRightIcon = computed(() => {
return (
[
SysCustomWidgetType.Select,
SysCustomWidgetType.Cascader,
SysCustomWidgetType.Date,
SysCustomWidgetType.UserSelect,
SysCustomWidgetType.DeptSelect,
SysCustomWidgetType.Calendar,
].indexOf(pps.widget.widgetType) !== -1
);
});
const getWidgetProps = computed(() => {
let props = {
...(pps.widget.props || {}),
};
// 日期组件根据类型设置format
if (
pps.widget.widgetType === SysCustomWidgetType.Date ||
pps.widget.widgetType === SysCustomWidgetType.DateRange
) {
props['value-format'] = 'YYYY-MM-DD HH:mm:ss';
}
console.log('widget props', SysCustomWidgetType.getValue(pps.widget.widgetType), props);
return {
...props,
clearable: true,
filterable: true,
readOnly:
pps.widget.widgetType === SysCustomWidgetType.Upload
? form().readOnly || props.readOnly
: undefined,
options:
pps.widget.widgetType === SysCustomWidgetType.Cascader ? dictDataList.value : undefined,
props:
pps.widget.widgetType === SysCustomWidgetType.Cascader
? {
label: 'name',
value: 'id',
multiple: multiSelect.value,
checkStrictly: true,
}
: undefined,
operationList: pps.widget.operationList,
multiple: multiSelect.value,
'collapse-tags': multiSelect.value,
dataList: pps.widget.widgetType === SysCustomWidgetType.Tree ? dictDataList.value : undefined,
dictDataList: isMobileFilter.value ? getAllDropdownData.value : undefined,
href: getLinkHerf.value,
widget: pps.widget,
};
});
const getDisabledStatus = () => {
return pps.widget.props.disabled;
};
const parseValue = (val: ValueType): ANY_OBJECT => {
if (pps.widget.widgetType === SysCustomWidgetType.Cascader) {
if (multiSelect.value && Array.isArray(val)) {
return val
.map((item: ANY_OBJECT) => {
return item[item.length - 1];
})
.filter((item: ANY_OBJECT) => item != null);
} else {
return Array.isArray(val) ? val[val.length - 1] : undefined;
}
} else {
return val as ANY_OBJECT;
}
};
const onValueInput = (val: ANY_OBJECT | undefined) => {
let tempValue: ValueType | undefined = undefined;
if (val) {
console.log('widget typeof val', typeof val, val instanceof InputEvent, val instanceof Event);
if (val instanceof InputEvent) {
console.warn('widget input value is InputEvent');
return;
} else if (val instanceof Event) {
console.log('wiget >>>>>>> value >>>>>>', val, val.target instanceof HTMLInputElement);
if (val.target instanceof HTMLInputElement) {
tempValue = val.target.value;
}
} else {
tempValue = parseValue(val);
}
if (multiSelect.value && Array.isArray(tempValue) /*&& tempValue.length > 0*/) {
tempValue = tempValue.join(',') + ',';
}
}
console.log('widget update:value', tempValue);
emit('update:value', tempValue);
emit('update:modelValue', tempValue);
// ElDatePicker(DateRange)有了这个事件才能更新显示
emit('input', tempValue);
};
const onValueChange = (
val: ANY_OBJECT | undefined,
selectRow: ANY_OBJECT | undefined = undefined,
) => {
let tempVal: ValueType | undefined = undefined;
let dictData = null;
console.log('widget onValueChange >>>', val);
if (val) {
tempVal = parseValue(val);
if (multiSelect.value) {
dictData = val
.map((item: string) => {
if (pps.widget.widgetType === SysCustomWidgetType.Cascader) {
if (Array.isArray(item)) {
item = item[item.length - 1];
}
return findTreeNode(dictDataList.value, item, 'id', 'children');
} else {
return findItemFromList(dictDataList.value, item, 'id');
}
})
.filter((item: ANY_OBJECT) => item != null);
} else {
let id = val.toString();
if (pps.widget.widgetType === SysCustomWidgetType.Cascader) {
if (Array.isArray(val)) {
val = val[val.length - 1];
}
dictData = findTreeNode(dictDataList.value, id, 'id', 'children');
} else {
dictData = findItemFromList(dictDataList.value, id, 'id');
}
}
}
// 这个似乎没有起到什么作用
emit('change', tempVal, {
dictData: dictData,
selectRow: selectRow,
});
onValueInput(tempVal);
};
const loadDropdownData = () => {
if (pps.widget == null || !isDictWidget.value) {
return;
}
dictDataList.value = [];
setTimeout(() => {
let dictInfo = (pps.widget.props.dictInfo || {}).dict;
console.log('widget OnlineCustomWidget loadDropdownData', dictInfo, pps);
if (dictInfo && form().getDictDataList) {
let dictCall;
if (form().pageCode != null) {
// 报表字典
dictCall = form().getDictDataList(dictInfo, form().getDropdownParams(pps.widget));
} else {
// 在线表单字典
dictCall = form().getDictDataList(dictInfo, form().getDropdownParams(pps.widget));
}
dictCall
.then((res: ANY_OBJECT[]) => {
console.log('OnlineCustomWidget loadDropdownData', res);
res.forEach((item: ANY_OBJECT) => {
item.id = item.id + '';
if (item.parentId) item.parentId = item.parentId + '';
});
// 级联组件将列表转换成树
if (pps.widget.widgetType === SysCustomWidgetType.Cascader) {
res = treeDataTranslate(res, 'id', 'parentId');
}
dictDataList.value = res;
})
.catch((e: Error) => {
console.log(e);
});
}
}, 30);
};
const getHtml = () => {
console.log('widget call getHtml()');
const refs = (getCurrentInstance()?.refs || {}) as ANY_OBJECT;
console.log('refs', refs);
if (pps.widget.widgetType === SysCustomWidgetType.RichEditor) {
return refs[pps.widget.variableName] ? refs[pps.widget.variableName].getHtml() : undefined;
}
};
const reset = () => {
console.log('widget call reset()');
onValueInput(undefined);
onValueChange(undefined);
nextTick(() => {
loadDropdownData();
});
};
const refresh = () => {
const refs = (getCurrentInstance()?.refs || {}) as ANY_OBJECT;
console.log('widget call refresh() refs:', refs);
if (
refs[pps.widget.variableName] &&
typeof refs[pps.widget.variableName].refresh === 'function'
) {
refs[pps.widget.variableName].refresh();
}
};
defineExpose({
getHtml,
reset,
refresh,
});
watch(
() => pps.widget,
() => {
console.log('props widget change', pps.widget);
if (pps.widget) loadDropdownData();
},
{
deep: true,
immediate: true,
},
);
// watch(
// () => pps.widget.props.dictInfo,
// () => {
// if (pps.widget) loadDropdownData();
// },
// {
// deep: true,
// immediate: true,
// },
// );
// 如果父组件为数据表格或者列表组件,那么子组件绑定表必须跟父组件一致
watch(
() => parentWidget,
(newValue, oldValue) => {
const widget = { ...propsWidget.value };
if (parentWidget != null && propsWidget.value) {
// 如果绑定的数据表改变了,修改子组件绑定的数据表
if (parentWidget.bindData.tableId !== propsWidget.value.bindData.tableId) {
widget.props.bindData = {
...parentWidget.bindData,
};
widget.showName = undefined;
if (widget.widgetType === SysCustomWidgetType.Text) {
widget.props.text = '文本内容';
}
}
} else {
if (newValue == null && oldValue != null) {
widget.bindData = {
dataType: 0,
tableId: undefined,
table: undefined,
columnId: undefined,
column: undefined,
};
}
}
propsWidget.value = widget;
},
{
deep: true,
immediate: true,
},
);
onMounted(() => {
console.log('getComponent', getComponent.value, getWidgetProps.value);
//propsWidget.value.widgetImpl = getCurrentInstance();
//propsWidget.value.parent = parentWidget;
});
</script>