diff --git a/src/components/DictSelect/index.ts b/src/components/DictSelect/index.ts new file mode 100644 index 00000000..164035fd --- /dev/null +++ b/src/components/DictSelect/index.ts @@ -0,0 +1,3 @@ +import DictSelect from './src/DictSelect.vue' + +export { DictSelect } diff --git a/src/components/DictSelect/src/DictSelect.vue b/src/components/DictSelect/src/DictSelect.vue new file mode 100644 index 00000000..c0d585ab --- /dev/null +++ b/src/components/DictSelect/src/DictSelect.vue @@ -0,0 +1,53 @@ + + + diff --git a/src/components/FormCreate/src/config/index.ts b/src/components/FormCreate/src/config/index.ts index e098ce48..5403ce0e 100644 --- a/src/components/FormCreate/src/config/index.ts +++ b/src/components/FormCreate/src/config/index.ts @@ -1,5 +1,13 @@ import { useUploadFileRule } from './useUploadFileRule' import { useUploadImgRule } from './useUploadImgRule' import { useUploadImgsRule } from './useUploadImgsRule' +import { useDictSelectRule } from './useDictSelectRule' +import { useUserSelectRule } from './useUserSelectRule' -export { useUploadFileRule, useUploadImgRule, useUploadImgsRule } +export { + useUploadFileRule, + useUploadImgRule, + useUploadImgsRule, + useDictSelectRule, + useUserSelectRule +} diff --git a/src/components/FormCreate/src/config/useDictSelectRule.ts b/src/components/FormCreate/src/config/useDictSelectRule.ts new file mode 100644 index 00000000..51cd33b7 --- /dev/null +++ b/src/components/FormCreate/src/config/useDictSelectRule.ts @@ -0,0 +1,124 @@ +import { generateUUID } from '@/utils' +import * as DictDataApi from '@/api/system/dict/dict.type' +import { localeProps, makeRequiredRule } from '@/components/FormCreate/src/utils' + +export const useDictSelectRule = () => { + const label = '字典选择器' + const name = 'DictSelect' + const dictOptions = ref<{ label: string; value: string }[]>([]) // 字典类型下拉数据 + onMounted(async () => { + const data = await DictDataApi.getSimpleDictTypeList() + if (!data || data.length === 0) { + return + } + dictOptions.value = + data?.map((item: DictDataApi.DictTypeVO) => ({ + label: item.name, + value: item.type + })) ?? [] + }) + return { + icon: 'icon-select', + label, + name, + rule() { + return { + type: name, + field: generateUUID(), + title: label, + info: '', + $required: false + } + }, + props(_, { t }) { + return localeProps(t, name + '.props', [ + makeRequiredRule(), + { + type: 'select', + field: 'dictType', + title: '字典类型', + value: '', + options: dictOptions.value + }, + { + type: 'select', + field: 'valueType', + title: '字典值类型', + value: 'str', + options: [ + { label: '数字', value: 'int' }, + { label: '字符串', value: 'str' }, + { label: '布尔值', value: 'bool' } + ] + }, + { type: 'switch', field: 'multiple', title: '是否多选' }, + { + type: 'switch', + field: 'disabled', + title: '是否禁用' + }, + { type: 'switch', field: 'clearable', title: '是否可以清空选项' }, + { + type: 'switch', + field: 'collapseTags', + title: '多选时是否将选中值按文字的形式展示' + }, + { + type: 'inputNumber', + field: 'multipleLimit', + title: '多选时用户最多可以选择的项目数,为 0 则不限制', + props: { min: 0 } + }, + { + type: 'input', + field: 'autocomplete', + title: 'autocomplete 属性' + }, + { type: 'input', field: 'placeholder', title: '占位符' }, + { + type: 'switch', + field: 'filterable', + title: '是否可搜索' + }, + { type: 'switch', field: 'allowCreate', title: '是否允许用户创建新条目' }, + { + type: 'input', + field: 'noMatchText', + title: '搜索条件无匹配时显示的文字' + }, + { + type: 'switch', + field: 'remote', + title: '其中的选项是否从服务器远程加载' + }, + { + type: 'Struct', + field: 'remoteMethod', + title: '自定义远程搜索方法' + }, + { type: 'input', field: 'noDataText', title: '选项为空时显示的文字' }, + { + type: 'switch', + field: 'reserveKeyword', + title: '多选且可搜索时,是否在选中一个选项后保留当前的搜索关键词' + }, + { + type: 'switch', + field: 'defaultFirstOption', + title: '在输入框按下回车,选择第一个匹配项' + }, + { + type: 'switch', + field: 'popperAppendToBody', + title: '是否将弹出框插入至 body 元素', + value: true + }, + { + type: 'switch', + field: 'automaticDropdown', + title: '对于不可搜索的 Select,是否在输入框获得焦点后自动弹出选项菜单' + } + ]) + } + } +} diff --git a/src/components/FormCreate/src/config/useUserSelectRule.ts b/src/components/FormCreate/src/config/useUserSelectRule.ts new file mode 100644 index 00000000..23521134 --- /dev/null +++ b/src/components/FormCreate/src/config/useUserSelectRule.ts @@ -0,0 +1,107 @@ +import { generateUUID } from '@/utils' +import * as UserApi from '@/api/system/user' +import { localeProps, makeOptionsRule, makeRequiredRule } from '@/components/FormCreate/src/utils' + +export const useUserSelectRule = () => { + const label = 'aa选择器' + const name = 'select' + const userOptions = ref<{ label: string; value: number }[]>([]) // 用户下拉数据 + onMounted(async () => { + const data = await UserApi.getSimpleUserList() + if (!data || data.length === 0) { + return + } + userOptions.value = + data?.map((item: UserApi.UserVO) => ({ + label: item.nickname, + value: item.id + })) ?? [] + }) + return { + icon: 'icon-select', + label, + name, + rule() { + return { + type: name, + field: generateUUID(), + title: label, + info: '', + $required: false + } + }, + props(_, { t }) { + return localeProps(t, name + '.props', [ + makeRequiredRule(), + makeOptionsRule(t, 'options', userOptions.value), + { type: 'switch', field: 'multiple', title: '是否多选' }, + { + type: 'switch', + field: 'disabled', + title: '是否禁用' + }, + { type: 'switch', field: 'clearable', title: '是否可以清空选项' }, + { + type: 'switch', + field: 'collapseTags', + title: '多选时是否将选中值按文字的形式展示' + }, + { + type: 'inputNumber', + field: 'multipleLimit', + title: '多选时用户最多可以选择的项目数,为 0 则不限制', + props: { min: 0 } + }, + { + type: 'input', + field: 'autocomplete', + title: 'autocomplete 属性' + }, + { type: 'input', field: 'placeholder', title: '占位符' }, + { + type: 'switch', + field: 'filterable', + title: '是否可搜索' + }, + { type: 'switch', field: 'allowCreate', title: '是否允许用户创建新条目' }, + { + type: 'input', + field: 'noMatchText', + title: '搜索条件无匹配时显示的文字' + }, + { + type: 'switch', + field: 'remote', + title: '其中的选项是否从服务器远程加载' + }, + { + type: 'Struct', + field: 'remoteMethod', + title: '自定义远程搜索方法' + }, + { type: 'input', field: 'noDataText', title: '选项为空时显示的文字' }, + { + type: 'switch', + field: 'reserveKeyword', + title: '多选且可搜索时,是否在选中一个选项后保留当前的搜索关键词' + }, + { + type: 'switch', + field: 'defaultFirstOption', + title: '在输入框按下回车,选择第一个匹配项' + }, + { + type: 'switch', + field: 'popperAppendToBody', + title: '是否将弹出框插入至 body 元素', + value: true + }, + { + type: 'switch', + field: 'automaticDropdown', + title: '对于不可搜索的 Select,是否在输入框获得焦点后自动弹出选项菜单' + } + ]) + } + } +} diff --git a/src/components/FormCreate/src/useFormCreateDesigner.ts b/src/components/FormCreate/src/useFormCreateDesigner.ts index b6855a99..e142970d 100644 --- a/src/components/FormCreate/src/useFormCreateDesigner.ts +++ b/src/components/FormCreate/src/useFormCreateDesigner.ts @@ -1,4 +1,10 @@ -import { useUploadFileRule, useUploadImgRule, useUploadImgsRule } from './config' +import { + useDictSelectRule, + useUploadFileRule, + useUploadImgRule, + useUploadImgsRule, + useUserSelectRule +} from './config' import { Ref } from 'vue' /** @@ -12,11 +18,19 @@ export const useFormCreateDesigner = (designer: Ref) => { const uploadFileRule = useUploadFileRule() const uploadImgRule = useUploadImgRule() const uploadImgsRule = useUploadImgsRule() + const dictSelectRule = useDictSelectRule() + const userSelectRule = useUserSelectRule() onMounted(() => { // 移除自带的上传组件规则,使用 uploadFileRule、uploadImgRule、uploadImgsRule 替代 designer.value?.removeMenuItem('upload') - const components = [uploadFileRule, uploadImgRule, uploadImgsRule] + const components = [ + uploadFileRule, + uploadImgRule, + uploadImgsRule, + dictSelectRule, + userSelectRule + ] components.forEach((component) => { // 插入组件规则 designer.value?.addComponent(component) diff --git a/src/components/FormCreate/src/utils/index.ts b/src/components/FormCreate/src/utils/index.ts index 49901b5f..e5480981 100644 --- a/src/components/FormCreate/src/utils/index.ts +++ b/src/components/FormCreate/src/utils/index.ts @@ -17,3 +17,63 @@ export const localeProps = (t, prefix, rules) => { return rule }) } + +export function upper(str) { + return str.replace(str[0], str[0].toLocaleUpperCase()) +} + +export function makeOptionsRule(t, to, userOptions) { + console.log(userOptions[0]) + const options = [ + { label: t('props.optionsType.struct'), value: 0 }, + { label: t('props.optionsType.json'), value: 1 }, + { label: '用户数据', value: 2 } + ] + + const control = [ + { + value: 0, + rule: [ + { + type: 'TableOptions', + field: 'formCreate' + upper(to).replace('.', '>'), + props: { defaultValue: [] } + } + ] + }, + { + value: 1, + rule: [ + { + type: 'Struct', + field: 'formCreate' + upper(to).replace('.', '>'), + props: { defaultValue: [] } + } + ] + }, + { + value: 2, + rule: [ + { + type: 'TableOptions', + field: 'formCreate' + upper(to).replace('.', '>'), + props: { modelValue: [] } + } + ] + } + ] + options.splice(0, 0) + control.push() + + return { + type: 'radio', + title: t('props.options'), + field: '_optionType', + value: 0, + options, + props: { + type: 'button' + }, + control + } +} diff --git a/src/plugins/formCreate/index.ts b/src/plugins/formCreate/index.ts index ffbcc010..9e083641 100644 --- a/src/plugins/formCreate/index.ts +++ b/src/plugins/formCreate/index.ts @@ -19,6 +19,7 @@ import formCreate from '@form-create/element-ui' import install from '@form-create/element-ui/auto-import' //======================= 自定义组件 ======================= import { UploadFile, UploadImg, UploadImgs } from '@/components/UploadFile' +import { DictSelect } from '@/components/DictSelect' const components = [ ElAside, @@ -35,7 +36,8 @@ const components = [ ElTabPane, UploadImg, UploadImgs, - UploadFile + UploadFile, + DictSelect ] // 参考 http://www.form-create.com/v3/element-ui/auto-import.html 文档