first commit

This commit is contained in:
ye1023
2026-04-09 15:09:34 +08:00
commit d8e3a63df1
2246 changed files with 352109 additions and 0 deletions
+191
View File
@@ -0,0 +1,191 @@
<template>
<PageWrapper title="可折叠表单示例">
<CollapseContainer title="基础收缩示例">
<BasicForm @register="register" />
</CollapseContainer>
<CollapseContainer title="超过5列自动收起,折叠时保留2行" class="mt-4">
<BasicForm @register="register1" />
</CollapseContainer>
</PageWrapper>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { BasicForm, FormSchema, useForm } from '/@/components/Form/index';
import { CollapseContainer } from '/@/components/Container';
import { PageWrapper } from '/@/components/Page';
const getSchamas = (): FormSchema[] => {
return [
{
field: 'field1',
component: 'Input',
label: '字段1',
colProps: {
span: 8,
},
componentProps: {
placeholder: '自定义placeholder',
onChange: (e: any) => {
console.log(e);
},
},
},
{
field: 'field2',
component: 'Input',
label: '字段2',
colProps: {
span: 8,
},
},
{
field: 'field3',
component: 'DatePicker',
label: '字段3',
colProps: {
span: 8,
},
},
{
field: 'field4',
component: 'Select',
label: '字段4',
colProps: {
span: 8,
},
componentProps: {
options: [
{
label: '选项1',
value: '1',
key: '1',
},
{
label: '选项2',
value: '2',
key: '2',
},
],
},
},
{
field: 'field5',
component: 'CheckboxGroup',
label: '字段5',
colProps: {
span: 8,
},
componentProps: {
options: [
{
label: '选项1',
value: '1',
},
{
label: '选项2',
value: '2',
},
],
},
},
// {
// field: 'field7',
// component: 'RadioGroup',
// label: '字段7',
// colProps: {
// span: 8,
// },
// componentProps: {
// options: [
// {
// label: '选项1',
// value: '1',
// },
// {
// label: '选项2',
// value: '2',
// },
// ],
// },
// },
];
};
function getAppendSchemas(): FormSchema[] {
return [
{
field: 'field10',
component: 'Input',
label: '字段10',
colProps: {
span: 8,
},
},
{
field: 'field11',
component: 'Input',
label: '字段11',
colProps: {
span: 8,
},
},
{
field: 'field12',
component: 'Input',
label: '字段12',
colProps: {
span: 8,
},
},
{
field: 'field13',
component: 'Input',
label: '字段13',
colProps: {
span: 8,
},
},
];
}
export default defineComponent({
components: { BasicForm, CollapseContainer, PageWrapper },
setup() {
const [register] = useForm({
labelWidth: 120,
schemas: getSchamas(),
actionColOptions: {
span: 24,
},
compact: true,
showAdvancedButton: true,
});
const extraSchemas: FormSchema[] = [];
for (let i = 14; i < 30; i++) {
extraSchemas.push({
field: 'field' + i,
component: 'Input',
label: '字段' + i,
colProps: {
span: 8,
},
});
}
const [register1] = useForm({
labelWidth: 120,
schemas: [...getSchamas(), ...getAppendSchemas(), { field: '', component: 'Divider', label: '更多字段' }, ...extraSchemas],
actionColOptions: {
span: 8,
},
compact: true,
showAdvancedButton: true,
autoAdvancedCol: 2,
alwaysShowLines: 1,
});
return {
register,
register1,
};
},
});
</script>
+118
View File
@@ -0,0 +1,118 @@
<template>
<PageWrapper title="表单增删示例">
<CollapseContainer title="表单增删">
<BasicForm @register="register" @submit="handleSubmit">
<template #add="{ field }">
<Button v-if="Number(field) === 0" @click="add">+</Button>
<Button v-if="field > 0" @click="del(field)">-</Button>
</template>
</BasicForm>
</CollapseContainer>
</PageWrapper>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
import { BasicForm, useForm } from '/@/components/Form/index';
import { CollapseContainer } from '/@/components/Container/index';
import { Input } from 'ant-design-vue';
import { PageWrapper } from '/@/components/Page';
import { Button } from '/@/components/Button';
export default defineComponent({
components: { BasicForm, CollapseContainer, PageWrapper, [Input.name]: Input, Button },
setup() {
const [register, { appendSchemaByField, removeSchemaByFiled, validate }] = useForm({
schemas: [
{
field: 'field0a',
component: 'Input',
label: '字段0',
colProps: {
span: 8,
},
required: true,
},
{
field: 'field0b',
component: 'Input',
label: '字段0',
colProps: {
span: 8,
},
required: true,
},
{
field: '0',
component: 'Input',
label: ' ',
colProps: {
span: 8,
},
slot: 'add',
},
],
labelWidth: 100,
actionColOptions: { span: 24 },
});
async function handleSubmit() {
try {
const data = await validate();
console.log(data);
} catch (e) {
console.log(e);
}
}
const n = ref(1);
function add() {
appendSchemaByField(
{
field: `field${n.value}a`,
component: 'Input',
label: '字段' + n.value,
colProps: {
span: 8,
},
required: true,
},
''
);
appendSchemaByField(
{
field: `field${n.value}b`,
component: 'Input',
label: '字段' + n.value,
colProps: {
span: 8,
},
required: true,
},
''
);
appendSchemaByField(
{
field: `${n.value}`,
component: 'Input',
label: ' ',
colProps: {
span: 8,
},
slot: 'add',
},
''
);
n.value++;
}
function del(field) {
removeSchemaByFiled([`field${field}a`, `field${field}b`, `${field}`]);
n.value--;
}
return { register, handleSubmit, add, del };
},
});
</script>
+85
View File
@@ -0,0 +1,85 @@
<template>
<PageWrapper title="自定义组件示例">
<CollapseContainer title="自定义表单">
<BasicForm @register="register" @submit="handleSubmit">
<template #f3="{ model, field }">
<a-input v-model:value="model[field]" placeholder="自定义slot" />
</template>
</BasicForm>
</CollapseContainer>
</PageWrapper>
</template>
<script lang="ts">
import { defineComponent, h } from 'vue';
import { BasicForm, FormSchema, useForm } from '/@/components/Form/index';
import { CollapseContainer } from '/@/components/Container/index';
import { useMessage } from '/@/hooks/web/useMessage';
import { Input } from 'ant-design-vue';
import { PageWrapper } from '/@/components/Page';
const schemas: FormSchema[] = [
{
field: 'field1',
component: 'Input',
label: 'render方式',
colProps: {
span: 8,
},
rules: [{ required: true }],
render: ({ model, field }) => {
return h(Input, {
placeholder: '请输入',
value: model[field],
onChange: (e: ChangeEvent) => {
model[field] = e.target.value;
},
});
},
},
{
field: 'field2',
component: 'Input',
label: 'render组件slot',
colProps: {
span: 8,
},
rules: [{ required: true }],
renderComponentContent: () => {
return {
suffix: () => 'suffix',
};
},
},
{
field: 'field3',
component: 'Input',
label: '自定义Slot',
slot: 'f3',
colProps: {
span: 8,
},
rules: [{ required: true }],
},
];
export default defineComponent({
components: { BasicForm, CollapseContainer, PageWrapper, [Input.name]: Input },
setup() {
const { createMessage } = useMessage();
const [register, { setProps }] = useForm({
labelWidth: 120,
schemas,
actionColOptions: {
span: 24,
},
});
return {
register,
schemas,
handleSubmit: (values: any) => {
createMessage.success('click search,values:' + JSON.stringify(values));
},
setProps,
};
},
});
</script>
+258
View File
@@ -0,0 +1,258 @@
<template>
<PageWrapper title="动态表单示例">
<div class="mb-4">
<a-button @click="changeLabel3" class="mr-2"> 更改字段3label </a-button>
<a-button @click="changeLabel34" class="mr-2"> 同时更改字段3,4label </a-button>
<a-button @click="appendField" class="mr-2"> 往字段3后面插入字段10 </a-button>
<a-button @click="deleteField" class="mr-2"> 删除字段11 </a-button>
</div>
<CollapseContainer title="动态表单示例,动态根据表单内其他值改变">
<BasicForm @register="register" />
</CollapseContainer>
<CollapseContainer class="mt-5" title="componentProps动态改变">
<BasicForm @register="register1" />
</CollapseContainer>
</PageWrapper>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { BasicForm, FormSchema, useForm } from '/@/components/Form/index';
import { CollapseContainer } from '/@/components/Container/index';
import { PageWrapper } from '/@/components/Page';
import { usePermission } from '/@/hooks/web/usePermission';
const { hasPermission } = usePermission();
const schemas: FormSchema[] = [
{
field: 'field5',
component: 'Switch',
label: '是否显示字段1(css控制)',
defaultValue: true,
colProps: {
span: 12,
},
labelWidth: 200,
},
{
field: 'field1',
component: 'Input',
label: '字段1',
colProps: {
span: 12,
},
show: ({ values }) => {
return hasPermission('test001');
},
},
{
field: 'field6',
component: 'Switch',
label: '是否显示字段2(dom控制)',
defaultValue: true,
colProps: {
span: 12,
},
labelWidth: 200,
},
{
field: 'field2',
component: 'Input',
label: '字段2',
colProps: {
span: 12,
},
ifShow: ({ values }) => {
return !!values.field6;
},
},
{
field: 'field7',
component: 'Switch',
label: '是否禁用字段3',
colProps: {
span: 12,
},
labelWidth: 200,
},
{
field: 'field3',
component: 'DatePicker',
label: '字段3',
colProps: {
span: 12,
},
dynamicDisabled: ({ values }) => {
return !!values.field7;
},
},
{
field: 'field8',
component: 'Switch',
label: '字段4是否必填',
colProps: {
span: 12,
},
labelWidth: 200,
},
{
field: 'field4',
component: 'Select',
label: '字段4',
colProps: {
span: 12,
},
dynamicRules: ({ values }) => {
return values.field8 ? [{ required: true, message: '字段必填' }] : [];
},
componentProps: {
options: [
{
label: '选项1',
value: '1',
key: '1',
},
{
label: '选项2',
value: '2',
key: '2',
},
],
},
},
{
field: 'field11',
component: 'DatePicker',
label: '字段11',
colProps: {
span: 8,
},
},
];
const schemas1: FormSchema[] = [
{
field: 'f1',
component: 'Input',
label: 'F1',
colProps: {
span: 12,
},
labelWidth: 200,
componentProps: ({ formModel }) => {
return {
placeholder: '同步f2的值为f1',
onChange: (e: ChangeEvent) => {
formModel.f2 = e.target.value;
},
};
},
},
{
field: 'f2',
component: 'Input',
label: 'F2',
colProps: {
span: 12,
},
labelWidth: 200,
componentProps: { disabled: true },
},
{
field: 'f3',
component: 'Input',
label: 'F3',
colProps: {
span: 12,
},
labelWidth: 200,
// @ts-ignore
componentProps: ({ formActionType }) => {
return {
placeholder: '值改变时执行查询,查看控制台',
onChange: async () => {
const { validate } = formActionType;
// tableAction只适用于在表格内开启表单的例子
// const { reload } = tableAction;
const res = await validate();
console.log(res);
},
};
},
},
];
export default defineComponent({
components: { BasicForm, CollapseContainer, PageWrapper },
setup() {
const [register, { setProps, updateSchema, appendSchemaByField, removeSchemaByFiled }] = useForm({
labelWidth: 120,
schemas,
//禁用表单所有组件
disabled: true,
labelCol: {
xs: { span: 24 },
sm: { span: 6 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 18 },
},
actionColOptions: {
span: 24,
},
});
const [register1] = useForm({
labelWidth: 120,
schemas: schemas1,
actionColOptions: {
span: 24,
},
});
function changeLabel3() {
updateSchema({
field: 'field3',
label: '字段3 New',
});
}
function changeLabel34() {
updateSchema([
{
field: 'field3',
label: '字段3 New++',
},
{
field: 'field4',
label: '字段4 New++',
},
]);
}
function appendField() {
appendSchemaByField(
{
field: 'field10',
label: '字段10',
component: 'Input',
colProps: {
span: 8,
},
},
'field3'
);
}
function deleteField() {
removeSchemaByFiled('field11');
}
return {
register,
register1,
schemas,
setProps,
changeLabel3,
changeLabel34,
appendField,
deleteField,
};
},
});
</script>
+174
View File
@@ -0,0 +1,174 @@
<template>
<PageWrapper title="Ref操作示例">
<div class="mb-4">
<a-button @click="setProps({ labelWidth: 150 })" class="mr-2"> 更改labelWidth </a-button>
<a-button @click="setProps({ labelWidth: 120 })" class="mr-2"> 还原labelWidth </a-button>
<a-button @click="setProps({ size: 'large' })" class="mr-2"> 更改Size </a-button>
<a-button @click="setProps({ size: 'default' })" class="mr-2"> 还原Size </a-button>
<a-button @click="setProps({ disabled: true })" class="mr-2"> 禁用表单 </a-button>
<a-button @click="setProps({ disabled: false })" class="mr-2"> 解除禁用 </a-button>
<a-button @click="setProps({ compact: true })" class="mr-2"> 紧凑表单 </a-button>
<a-button @click="setProps({ compact: false })" class="mr-2"> 还原正常间距 </a-button>
<a-button @click="setProps({ actionColOptions: { span: 8 } })" class="mr-2"> 操作按钮位置 </a-button>
</div>
<div class="mb-4">
<a-button @click="setProps({ showActionButtonGroup: false })" class="mr-2"> 隐藏操作按钮 </a-button>
<a-button @click="setProps({ showActionButtonGroup: true })" class="mr-2"> 显示操作按钮 </a-button>
<a-button @click="setProps({ showResetButton: false })" class="mr-2"> 隐藏重置按钮 </a-button>
<a-button @click="setProps({ showResetButton: true })" class="mr-2"> 显示重置按钮 </a-button>
<a-button @click="setProps({ showSubmitButton: false })" class="mr-2"> 隐藏查询按钮 </a-button>
<a-button @click="setProps({ showSubmitButton: true })" class="mr-2"> 显示查询按钮 </a-button>
<a-button
@click="
setProps({
resetButtonOptions: {
disabled: true,
text: '重置New',
},
})
"
class="mr-2"
>
修改重置按钮
</a-button>
<a-button
@click="
setProps({
submitButtonOptions: {
disabled: true,
loading: true,
},
})
"
class="mr-2"
>
修改查询按钮
</a-button>
</div>
<CollapseContainer title="使用ref调用表单内部函数示例">
<BasicForm :schemas="schemas" ref="formElRef" :labelWidth="100" @submit="handleSubmit" :actionColOptions="{ span: 24 }" />
</CollapseContainer>
</PageWrapper>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
import { BasicForm, FormSchema, FormActionType, FormProps } from '/@/components/Form/index';
import { CollapseContainer } from '/@/components/Container/index';
import { useMessage } from '/@/hooks/web/useMessage';
import { PageWrapper } from '/@/components/Page';
const schemas: FormSchema[] = [
{
field: 'field1',
component: 'Input',
label: '字段1',
colProps: {
span: 8,
},
componentProps: {
placeholder: '自定义placeholder',
onChange: (e: any) => {
console.log(e);
},
},
},
{
field: 'field2',
component: 'Input',
label: '字段2',
colProps: {
span: 8,
},
},
{
field: 'field3',
component: 'DatePicker',
label: '字段3',
colProps: {
span: 8,
},
},
{
field: 'field4',
component: 'Select',
label: '字段4',
colProps: {
span: 8,
},
componentProps: {
options: [
{
label: '选项1',
value: '1',
key: '1',
},
{
label: '选项2',
value: '2',
key: '2',
},
],
},
},
{
field: 'field5',
component: 'CheckboxGroup',
label: '字段5',
colProps: {
span: 8,
},
componentProps: {
options: [
{
label: '选项1',
value: '1',
},
{
label: '选项2',
value: '2',
},
],
},
},
{
field: 'field7',
component: 'RadioGroup',
label: '字段7',
colProps: {
span: 8,
},
componentProps: {
options: [
{
label: '选项1',
value: '1',
},
{
label: '选项2',
value: '2',
},
],
},
},
];
export default defineComponent({
components: { BasicForm, CollapseContainer, PageWrapper },
setup() {
const formElRef = ref<Nullable<FormActionType>>(null);
const { createMessage } = useMessage();
return {
formElRef,
schemas,
handleSubmit: (values: any) => {
createMessage.success('click search,values:' + JSON.stringify(values));
},
setProps(props: FormProps) {
const formEl = formElRef.value;
if (!formEl) return;
formEl.setProps(props);
},
};
},
});
</script>
+260
View File
@@ -0,0 +1,260 @@
<template>
<PageWrapper title="表单校验示例">
<div class="mb-4">
<a-button @click="validateForm" class="mr-2"> 手动校验表单</a-button>
<a-button @click="resetValidate" class="mr-2"> 清空校验信息</a-button>
<a-button @click="getFormValues" class="mr-2"> 获取表单值</a-button>
<a-button @click="setFormValues" class="mr-2"> 设置表单值</a-button>
<a-button @click="resetFields" class="mr-2"> 重置</a-button>
</div>
<CollapseContainer title="表单校验">
<BasicForm @register="register" @submit="handleSubmit" />
</CollapseContainer>
</PageWrapper>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { BasicForm, FormSchema, useForm } from '/@/components/Form/index';
import { CollapseContainer } from '/@/components/Container';
import { useMessage } from '/@/hooks/web/useMessage';
import { PageWrapper } from '/@/components/Page';
import { isAccountExist } from '/@/api/demo/system';
const schemas: FormSchema[] = [
{
field: 'field1',
component: 'Input',
label: '字段1',
colProps: {
span: 8,
},
required: true,
},
{
field: 'field2',
component: 'Input',
label: '字段2',
colProps: {
span: 8,
},
required: true,
},
{
field: 'id',
label: 'id',
required: true,
defaultValue: 0,
component: 'InputNumber',
show: false,
},
{
field: 'field3',
component: 'DatePicker',
label: '字段3',
colProps: {
span: 8,
},
required: true,
},
{
field: 'field33',
component: 'DatePicker',
label: '字段33',
colProps: {
span: 8,
},
componentProps: {
valueFormat: 'YYYY-MM-DD',
},
rules: [{ required: true, type: 'string' }],
},
{
field: 'field44',
component: 'InputCountDown',
label: '验证码',
colProps: {
span: 8,
},
required: true,
},
{
field: 'field4',
component: 'Select',
label: '字段4',
colProps: {
span: 8,
},
componentProps: {
mode: 'multiple',
options: [
{
label: '选项1',
value: '1',
key: '1',
},
{
label: '选项2',
value: '2',
key: '2',
},
],
},
rules: [
{
required: true,
message: '请输入规则',
type: 'array',
},
],
},
{
field: 'field441',
component: 'Input',
label: '自定义校验',
colProps: {
span: 8,
},
rules: [
{
required: true,
// @ts-ignore
validator: async (rule, value) => {
if (!value) {
/* eslint-disable-next-line */
return Promise.reject('值不能为空');
}
if (value === '1') {
/* eslint-disable-next-line */
return Promise.reject('值不能为1');
}
return Promise.resolve();
},
trigger: 'change',
},
],
},
{
field: 'field5',
component: 'CheckboxGroup',
label: '字段5',
colProps: {
span: 8,
},
componentProps: {
options: [
{
label: '选项1',
value: '1',
},
{
label: '选项2',
value: '2',
},
],
},
rules: [{ required: true }],
},
{
field: 'field7',
component: 'RadioGroup',
label: '字段7',
colProps: {
span: 8,
},
componentProps: {
options: [
{
label: '选项1',
value: '1',
},
{
label: '选项2',
value: '2',
},
],
},
rules: [{ required: true, message: '覆盖默认生成的校验信息' }],
},
{
field: 'field8',
component: 'Input',
label: '后端异步验证',
colProps: {
span: 8,
},
helpMessage: ['本字段演示异步验证', '本地规则:必须填写', '后端规则:不能包含admin'],
rules: [
{
required: true,
message: '请输入数据',
},
{
validator(_, value) {
return new Promise((resolve, reject) => {
isAccountExist(value)
.then(() => resolve())
.catch((err) => {
reject(err.message || '验证失败');
});
});
},
},
],
},
];
export default defineComponent({
components: { BasicForm, CollapseContainer, PageWrapper },
setup() {
const { createMessage } = useMessage();
const [register, { validateFields, clearValidate, getFieldsValue, resetFields, setFieldsValue }] = useForm({
labelWidth: 120,
schemas,
actionColOptions: {
span: 24,
},
});
async function validateForm() {
try {
const res = await validateFields();
console.log('passing', res);
} catch (error) {
console.log('not passing', error);
}
}
async function resetValidate() {
clearValidate();
}
function getFormValues() {
const values = getFieldsValue();
createMessage.success('values:' + JSON.stringify(values));
}
function setFormValues() {
setFieldsValue({
field1: 1111,
field5: ['1'],
field7: '1',
field33: '2020-12-12',
field3: '2020-12-12',
});
}
return {
register,
schemas,
handleSubmit: (values: any) => {
createMessage.success('click search,values:' + JSON.stringify(values));
},
getFormValues,
setFormValues,
validateForm,
resetValidate,
resetFields,
};
},
});
</script>
+190
View File
@@ -0,0 +1,190 @@
<template>
<PageWrapper title="UseForm操作示例">
<div class="mb-4">
<a-button @click="setProps({ labelWidth: 150 })" class="mr-2"> 更改labelWidth </a-button>
<a-button @click="setProps({ labelWidth: 120 })" class="mr-2"> 还原labelWidth </a-button>
<a-button @click="setProps({ size: 'large' })" class="mr-2"> 更改Size </a-button>
<a-button @click="setProps({ size: 'default' })" class="mr-2"> 还原Size </a-button>
<a-button @click="setProps({ disabled: true })" class="mr-2"> 禁用表单 </a-button>
<a-button @click="setProps({ disabled: false })" class="mr-2"> 解除禁用 </a-button>
<a-button @click="setProps({ compact: true })" class="mr-2"> 紧凑表单 </a-button>
<a-button @click="setProps({ compact: false })" class="mr-2"> 还原正常间距 </a-button>
<a-button @click="setProps({ actionColOptions: { span: 8 } })" class="mr-2"> 操作按钮位置 </a-button>
</div>
<div class="mb-4">
<a-button @click="setProps({ showActionButtonGroup: false })" class="mr-2"> 隐藏操作按钮 </a-button>
<a-button @click="setProps({ showActionButtonGroup: true })" class="mr-2"> 显示操作按钮 </a-button>
<a-button @click="setProps({ showResetButton: false })" class="mr-2"> 隐藏重置按钮 </a-button>
<a-button @click="setProps({ showResetButton: true })" class="mr-2"> 显示重置按钮 </a-button>
<a-button @click="setProps({ showSubmitButton: false })" class="mr-2"> 隐藏查询按钮 </a-button>
<a-button @click="setProps({ showSubmitButton: true })" class="mr-2"> 显示查询按钮 </a-button>
<a-button
@click="
setProps({
resetButtonOptions: {
disabled: true,
text: '重置New',
},
})
"
class="mr-2"
>
修改重置按钮
</a-button>
<a-button
@click="
setProps({
submitButtonOptions: {
disabled: true,
loading: true,
},
})
"
class="mr-2"
>
修改查询按钮
</a-button>
</div>
<CollapseContainer title="useForm示例">
<BasicForm @register="register" @submit="handleSubmit" />
</CollapseContainer>
</PageWrapper>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { BasicForm, FormSchema, useForm } from '/@/components/Form/index';
import { CollapseContainer } from '/@/components/Container/index';
import { useMessage } from '/@/hooks/web/useMessage';
import { PageWrapper } from '/@/components/Page';
const schemas: FormSchema[] = [
{
field: 'field1',
component: 'Input',
label: '字段1',
colProps: {
span: 8,
},
componentProps: {
placeholder: '自定义placeholder',
onChange: (e: any) => {
console.log(e);
},
},
},
{
field: 'field2',
component: 'Input',
label: '字段2',
colProps: {
span: 8,
},
},
{
field: 'field3',
component: 'DatePicker',
label: '字段3',
colProps: {
span: 8,
},
},
{
field: 'fieldTime',
component: 'RangePicker',
label: '时间字段',
defaultValue: [new Date("2024-03-21"), new Date("2024-03-27")],
componentProps: {
valueType: 'Date',
},
colProps: {
span: 8,
},
},
{
field: 'field4',
component: 'Select',
label: '字段4',
colProps: {
span: 8,
},
componentProps: {
options: [
{
label: '选项1',
value: '1',
key: '1',
},
{
label: '选项2',
value: '2',
key: '2',
},
],
},
},
{
field: 'field5',
component: 'CheckboxGroup',
label: '字段5',
colProps: {
span: 8,
},
componentProps: {
options: [
{
label: '选项1',
value: '1',
},
{
label: '选项2',
value: '2',
},
],
},
},
{
field: 'field7',
component: 'RadioGroup',
label: '字段7',
colProps: {
span: 8,
},
componentProps: {
options: [
{
label: '选项1',
value: '1',
},
{
label: '选项2',
value: '2',
},
],
},
},
];
export default defineComponent({
components: { BasicForm, CollapseContainer, PageWrapper },
setup() {
const { createMessage } = useMessage();
const [register, { setProps }] = useForm({
labelWidth: 120,
schemas,
actionColOptions: {
span: 24,
},
fieldMapToTime: [['fieldTime', ['startTime', 'endTime'], 'YYYY-MM']],
});
return {
register,
schemas,
handleSubmit: (values: Recordable) => {
createMessage.success('click search,values:' + JSON.stringify(values));
},
setProps,
};
},
});
</script>
+622
View File
@@ -0,0 +1,622 @@
<template>
<PageWrapper title="表单基础示例" contentFullHeight>
<CollapseContainer title="基础示例">
<BasicForm
autoFocusFirstItem
:labelWidth="200"
:schemas="schemas"
:actionColOptions="{ span: 24 }"
:labelCol="{ span: 8 }"
@submit="handleSubmit"
@reset="handleReset"
>
<template #jAreaLinkage="{ model, field }">
<JAreaLinkage v-model:value="model[field]" :showArea="true" :showAll="false" />
</template>
<template #localSearch="{ model, field }">
<ApiSelect
:api="optionsListApi"
showSearch
v-model:value="model[field]"
optionFilterProp="label"
resultField="list"
labelField="name"
valueField="id"
/>
</template>
<template #selectA="{ model, field }">
<a-select :options="optionsA" mode="multiple" v-model:value="model[field]" @change="valueSelectA = model[field]" allowClear />
</template>
<template #selectB="{ model, field }">
<a-select :options="optionsB" mode="multiple" v-model:value="model[field]" @change="valueSelectB = model[field]" allowClear />
</template>
<template #remoteSearch="{ model, field }">
<ApiSelect
:api="optionsListApi"
showSearch
v-model:value="model[field]"
:filterOption="false"
resultField="list"
labelField="name"
valueField="id"
@search="onSearch"
:params="searchParams"
/>
</template>
</BasicForm>
</CollapseContainer>
</PageWrapper>
</template>
<script lang="ts">
import { computed, defineComponent, unref, ref } from 'vue';
import { BasicForm, FormSchema, ApiSelect, JAreaLinkage } from '/@/components/Form/index';
import { CollapseContainer } from '/@/components/Container';
import { useMessage } from '/@/hooks/web/useMessage';
import { PageWrapper } from '/@/components/Page';
import { optionsListApi } from '/@/api/demo/select';
import { useDebounceFn } from '@vueuse/core';
import { treeOptionsListApi } from '/@/api/demo/tree';
import { Select } from 'ant-design-vue';
import { cloneDeep } from 'lodash-es';
const valueSelectA = ref<string[]>([]);
const valueSelectB = ref<string[]>([]);
const options = ref<Recordable[]>([]);
for (let i = 1; i < 10; i++) options.value.push({ label: '选项' + i, value: `${i}` });
const optionsA = computed(() => {
return cloneDeep(unref(options)).map((op) => {
op.disabled = unref(valueSelectB).indexOf(op.value) !== -1;
return op;
});
});
const optionsB = computed(() => {
return cloneDeep(unref(options)).map((op) => {
op.disabled = unref(valueSelectA).indexOf(op.value) !== -1;
return op;
});
});
const provincesOptions = [
{
id: 'guangdong',
label: '广东省',
value: '1',
key: '1',
},
{
id: 'jiangsu',
label: '江苏省',
value: '2',
key: '2',
},
];
const citiesOptionsData = {
guangdong: [
{
label: '珠海市',
value: '1',
key: '1',
},
{
label: '深圳市',
value: '2',
key: '2',
},
{
label: '广州市',
value: '3',
key: '3',
},
],
jiangsu: [
{
label: '南京市',
value: '1',
key: '1',
},
{
label: '无锡市',
value: '2',
key: '2',
},
{
label: '苏州市',
value: '3',
key: '3',
},
],
};
const schemas: FormSchema[] = [
{
field: 'divider-basic',
component: 'Divider',
label: '基础字段',
},
{
field: 'field1',
component: 'Input',
label: '字段1',
colProps: {
span: 8,
},
// componentProps:{},
// can func
componentProps: ({ schema, formModel }) => {
console.log('form:', schema);
console.log('formModel:', formModel);
return {
placeholder: '自定义placeholder',
onChange: (e: any) => {
console.log(e);
},
};
},
renderComponentContent: () => {
return {
prefix: () => 'pSlot',
suffix: () => 'sSlot',
};
},
},
{
field: 'field2',
component: 'Input',
label: '字段2',
defaultValue: '111',
colProps: {
span: 8,
},
componentProps: {
onChange: (e: any) => {
console.log(e);
},
},
suffix: '天',
},
{
field: 'field3',
component: 'DatePicker',
label: '字段3',
colProps: {
span: 8,
},
},
{
field: 'field4',
component: 'Select',
label: '字段4',
colProps: {
span: 8,
},
componentProps: {
options: [
{
label: '选项1',
value: '1',
key: '1',
},
{
label: '选项2',
value: '2',
key: '2',
},
],
},
},
{
field: 'field5',
component: 'CheckboxGroup',
label: '字段5',
colProps: {
span: 8,
},
componentProps: {
options: [
{
label: '选项1',
value: '1',
},
{
label: '选项2',
value: '2',
},
],
},
},
{
field: 'field7',
component: 'RadioGroup',
label: '字段7',
colProps: {
span: 8,
},
componentProps: {
options: [
{
label: '选项1',
value: '1',
},
{
label: '选项2',
value: '2',
},
],
},
},
{
field: 'field8',
component: 'Checkbox',
label: '字段8',
colProps: {
span: 8,
},
renderComponentContent: 'Check',
},
{
field: 'field9',
component: 'Switch',
label: '字段9',
colProps: {
span: 8,
},
},
{
field: 'field10',
component: 'RadioButtonGroup',
label: '字段10',
colProps: {
span: 8,
},
componentProps: {
options: [
{
label: '选项1',
value: '1',
},
{
label: '选项2',
value: '2',
},
],
},
},
{
field: 'field11',
component: 'Cascader',
label: '字段11',
colProps: {
span: 8,
},
componentProps: {
options: [
{
value: 'zhejiang',
label: 'Zhejiang',
children: [
{
value: 'hangzhou',
label: 'Hangzhou',
children: [
{
value: 'xihu',
label: 'West Lake',
},
],
},
],
},
{
value: 'jiangsu',
label: 'Jiangsu',
children: [
{
value: 'nanjing',
label: 'Nanjing',
children: [
{
value: 'zhonghuamen',
label: 'Zhong Hua Men',
},
],
},
],
},
],
},
},
{
field: 'divider-api-select',
component: 'Divider',
label: '远程下拉演示',
},
{
field: 'field30',
component: 'ApiSelect',
label: '懒加载远程下拉',
required: true,
componentProps: {
// more details see /src/components/Form/src/components/ApiSelect.vue
api: optionsListApi,
params: {
id: 1,
},
resultField: 'list',
// use name as label
labelField: 'name',
// use id as value
valueField: 'id',
// not request untill to select
immediate: false,
onChange: (e) => {
console.log('selected:', e);
},
// atfer request callback
onOptionsChange: (options) => {
console.log('get options', options.length, options);
},
},
colProps: {
span: 8,
},
defaultValue: '0',
},
{
field: 'field311',
component: 'JAreaLinkage',
label: '省市区选择',
helpMessage: ['JAreaLinkage组件', '省市区选择'],
required: true,
slot: 'jAreaLinkage',
colProps: {
span: 8,
},
defaultValue: ['130000', '130200'],
},
{
field: 'field31',
component: 'Input',
label: '下拉本地搜索',
helpMessage: ['ApiSelect组件', '远程数据源本地搜索', '只发起一次请求获取所有选项'],
required: true,
slot: 'localSearch',
colProps: {
span: 8,
},
defaultValue: '0',
},
{
field: 'field32',
component: 'Input',
label: '下拉远程搜索',
helpMessage: ['ApiSelect组件', '将关键词发送到接口进行远程搜索'],
required: true,
slot: 'remoteSearch',
colProps: {
span: 8,
},
defaultValue: '0',
},
{
field: 'field33',
component: 'ApiTreeSelect',
label: '远程下拉树',
helpMessage: ['ApiTreeSelect组件', '使用接口提供的数据生成选项'],
required: true,
componentProps: {
api: treeOptionsListApi,
resultField: 'list',
},
colProps: {
span: 8,
},
},
{
field: 'field34',
component: 'ApiRadioGroup',
label: '远程Radio',
helpMessage: ['ApiRadioGroup组件', '使用接口提供的数据生成选项'],
required: true,
componentProps: {
api: optionsListApi,
params: {
count: 2,
},
resultField: 'list',
// use name as label
labelField: 'name',
// use id as value
valueField: 'id',
},
defaultValue: '1',
colProps: {
span: 8,
},
},
{
field: 'field35',
component: 'ApiRadioGroup',
label: '远程Radio',
helpMessage: ['ApiRadioGroup组件', '使用接口提供的数据生成选项'],
required: true,
componentProps: {
api: optionsListApi,
params: {
count: 2,
},
resultField: 'list',
// use name as label
labelField: 'name',
// use id as value
valueField: 'id',
isBtn: true,
},
colProps: {
span: 8,
},
},
{
field: 'divider-linked',
component: 'Divider',
label: '字段联动',
},
{
field: 'province',
component: 'Select',
label: '省份',
colProps: {
span: 8,
},
componentProps: ({ formModel, formActionType }) => {
return {
options: provincesOptions,
placeholder: '省份与城市联动',
onChange: (e: any) => {
// console.log(e)
let citiesOptions = e == 1 ? citiesOptionsData[provincesOptions[0].id] : citiesOptionsData[provincesOptions[1].id];
// console.log(citiesOptions)
if (e === undefined) {
citiesOptions = [];
}
formModel.city = undefined; // reset city value
const { updateSchema } = formActionType;
updateSchema({
field: 'city',
componentProps: {
options: citiesOptions,
},
});
},
};
},
},
{
field: 'city',
component: 'Select',
label: '城市',
colProps: {
span: 8,
},
componentProps: {
options: [], // defalut []
placeholder: '省份与城市联动',
},
},
{
field: 'divider-selects',
component: 'Divider',
label: '互斥多选',
helpMessage: ['两个Select共用数据源', '但不可选择对方已选中的项目'],
},
{
field: 'selectA',
component: 'Select',
label: '互斥SelectA',
slot: 'selectA',
defaultValue: [],
colProps: {
span: 8,
},
},
{
field: 'selectB',
component: 'Select',
label: '互斥SelectB',
slot: 'selectB',
defaultValue: [],
colProps: {
span: 8,
},
},
{
field: 'divider-others',
component: 'Divider',
label: '其它',
},
{
field: 'field20',
component: 'InputNumber',
label: '字段20',
required: true,
colProps: {
span: 8,
},
},
{
field: 'field21',
component: 'Slider',
label: '字段21',
componentProps: {
min: 0,
max: 100,
range: true,
marks: {
20: '20°C',
60: '60°C',
},
},
colProps: {
span: 8,
},
},
{
field: 'field22',
component: 'Rate',
label: '字段22',
defaultValue: 3,
colProps: {
span: 8,
},
componentProps: {
disabled: false,
allowHalf: true,
},
},
];
export default defineComponent({
components: {
BasicForm,
CollapseContainer,
PageWrapper,
ApiSelect,
JAreaLinkage,
ASelect: Select,
},
setup() {
const check = ref(null);
const { createMessage } = useMessage();
const keyword = ref<string>('');
const searchParams = computed<Recordable>(() => {
return { keyword: unref(keyword) };
});
function onSearch(value: string) {
keyword.value = value;
}
function areaChange(value) {
alert(value);
}
return {
schemas,
optionsListApi,
optionsA,
optionsB,
valueSelectA,
valueSelectB,
onSearch: useDebounceFn(onSearch, 300),
searchParams,
handleReset: () => {
keyword.value = '';
},
handleSubmit: (values: any) => {
createMessage.success('click search,values:' + JSON.stringify(values));
},
check,
};
},
});
</script>