vbenjs / vue-vben-admin

A modern vue admin. It is based on Vue3, vite and TypeScript. It's fast!
https://vben.vvbin.cn/
MIT License
22.88k stars 6.24k forks source link

在 FormSchema 中使用 ApiSelect 组件时,params 如何动态设置参数值 #3929

Open fengwenyi opened 1 week ago

fengwenyi commented 1 week ago

Subject of the feature

在 FormSchema 中使用 ApiSelect 组件,params赋值的问题

Problem

我在 x.data.ts 定义了 FormSchema,如下:

export const formAddSchema: FormSchema[] = [ { field: 'companyCode', label: '公司', component: 'ApiSelect', componentProps: { api: companyGetOptionListApi, labelField: 'companyName', valueField: 'companyCode', }, }, { field: 'designerId', label: '设计师', component: 'ApiSelect', componentProps: { api: teamGetOptionListApi, params: { companyCode: '', type: 'designer' }, labelField: 'name', valueField: 'id', }, } ];

查询 designerId 的选项值时,需要参数 companyCode,如何获取 companyCode 的值

export const formUpdateSchema: FormSchema[] = [ { field: 'designerId', label: '设计师', component: 'ApiSelect', componentProps: { api: teamGetOptionListApi, params: { companyCode: '', type: 'designer' }, labelField: 'name', valueField: 'id', }, } ];

这个是一个 修改弹窗,点击修改某条数据时,会弹出,我的需求是,查询 designerId 的选项值时,需要参数 companyCode,如何获取 这条数据的 companyCode 的值。

附,完整示例代码

demo.data.ts 代码:

import { FormSchema } from '/@/components/Table';

export const formAddSchema: FormSchema[] = [
    {
        field: 'companyCode',
        label: '公司',
        component: 'ApiSelect',
        componentProps: {
            api: companyGetOptionListApi,
            labelField: 'companyName',
            valueField: 'companyCode',
        },
    },
    {
        field: 'designerId',
        label: '设计师',
        component: 'ApiSelect',
        componentProps: {
            api: teamGetOptionListApi,
            params: {
                companyCode: '',
                type: 'designer'
            },
            labelField: 'name',
            valueField: 'id',
        },
    }
];

export const formUpdateSchema: FormSchema[] = [
    {
        field: 'designerId',
        label: '设计师',
        component: 'ApiSelect',
        componentProps: {
            api: teamGetOptionListApi,
            params: {
                companyCode: '',
                type: 'designer'
            },
            labelField: 'name',
            valueField: 'id',
        },
    }
];

DemoModal.vue

<template>
  <BasicModal v-bind="$attrs" @register="registerModal" :title="getTitle" @ok="handleSubmit">
    <BasicForm @register="registerForm" />
  </BasicModal>
</template>
<script lang="ts">
  import { defineComponent, ref, computed, unref } from 'vue';
  import { BasicModal, useModalInner } from '/@/components/Modal';
  import { BasicForm, useForm } from '/@/components/Form/index';
  import { formAddSchema, formUpdateSchema } from './demo.data';

  export default defineComponent({
    name: 'DemoModal',
    components: { BasicModal, BasicForm },
    emits: ['success', 'register'],
    setup(_, { emit }) {

      const isUpdate = ref(true);
      const id = ref();

      const formSchema = computed(() => (!unref(isUpdate) ? formAddSchema : formUpdateSchema));

      const [registerForm, { setFieldsValue, resetFields, validate }] = useForm({
        labelWidth: 100,
        baseColProps: { span: 24 },
        schemas: formSchema,
        showActionButtonGroup: false,
        actionColOptions: {
          span: 23,
        },
      });

      const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
        resetFields();
        setModalProps({ confirmLoading: false });
        isUpdate.value = !!data?.isUpdate;

        if (unref(isUpdate)) {
          id.value = data.record.memberId;
          setFieldsValue({
            ...data.record,
          });
        }
      });

      const getTitle = computed(() => (!unref(isUpdate) ? '新增' : '编辑'));

      async function handleSubmit() {
        try {
          const values = await validate();
          setModalProps({ confirmLoading: true });
          if (unref(isUpdate)) {
            companyUpdateApi(id.value, values).then(() => {
              closeModal();
              emit('success');
            });
          } else {
            companyAddApi(values).then(() => {
              closeModal();
              emit('success');
            });
          }
        } finally {
          setModalProps({ confirmLoading: false });
        }
      }

      return { registerModal, registerForm, getTitle, handleSubmit };
    },
  });
</script>

index.vue

<template>
  <PageWrapper dense contentFullHeight fixedHeight contentClass="flex">
    <BasicTable @register="registerTable">
      <template #toolbar>
        <a-button type="primary" @click="handleCreate">新增</a-button>
      </template>
        <template v-if="column.key === 'action'">
          <TableAction
            :actions="[
              {
                icon: 'clarity:note-edit-line',
                tooltip: '编辑',
                onClick: handleEdit.bind(null, record),
              },
            ]"
          />
        </template>
      </template>
    </BasicTable>
    <DemoModal @register="registerModal" @success="handleSuccess" />
  </PageWrapper>
</template>
<script lang="ts">
  import { defineComponent, reactive } from 'vue';

  import { BasicTable, useTable, TableAction } from '/@/components/Table';
  import { PageWrapper } from '/@/components/Page';

  import { useModal } from '/@/components/Modal';
  import DemoModal from './DemoModal.vue';

  import {useGo} from "@/hooks/web/usePage";

  export default defineComponent({
    name: 'Demo',
    components: { Tag, BasicTable, PageWrapper, TableAction, DemoModal },
    setup() {
      const go = useGo();
      const [registerModal, { openModal }] = useModal();
      const searchInfo = reactive<Recordable>({});
      const [registerTable, { reload }] = useTable({
        title: '列表',
        api: caseGetPageApi,
        rowKey: 'id',
        columns,
        formConfig: {
          labelWidth: 120,
          schemas: searchFormSchema,
          autoSubmitOnEnter: true,
        },
        useSearchForm: true,
        showTableSetting: true,
        bordered: true,
        actionColumn: {
          width: 120,
          title: '操作',
          dataIndex: 'action',
        },
      });

      function handleCreate() {
        openModal(true, {
          isUpdate: false,
        });
      }

      function handleEdit(record: Recordable) {
        openModal(true, {
          record,
          isUpdate: true,
        });
      }

      function handleSuccess() {
        reload();
      }

      return {
        registerTable,
        registerModal,
        handleCreate,
        handleEdit,
        handleSuccess,
      };
    },
  });
</script>

Expected behaviour

在新增组件时,获取填写的值; 在修改组件时,获取数据字段值。

Alternatives

What are the alternative solutions? Please describe what else you have considered?

youtao531 commented 6 days ago

同问

li-yi-hong commented 5 days ago

useModalInner这个函数里面,使用 updateSchema,如下示例:

const [registerForm, { updateSchema, validate }] = useForm({
  name: 'attr_relation_form',
  schemas: schemas,
})

const [register, { modalLoading, closeModal }] = useModalInner(async data => {
  modalLoading(true)
  const { attrGroupId } = data
  attrGroupIdRef.value = attrGroupId

  await updateSchema({
    field: 'attrId',
    componentProps: {
      params: { attrGroupId: attrGroupId },
      api: AttrGroupApi.getUnallocatedAttrs,
      afterFetch: data => {
        data.forEach(item => {
          item.attrId = item.attrId.toString()
        })
        return data
      },
    },
  })

  modalLoading(false)
})