Skip to content
On this page

插槽

模板顶层作用域插槽配置

INFO

用于获取模板配置数据,解决页面样式重新开发等需求

vue
<template>
  <div class="edit-page">
    <q-edit-page-layout ref="layoutRef" v-bind="options">
      <template #default="{ layoutConfig, pageData }">
        <div>layoutConfig: {{ layoutConfig }}</div>
        <div>pageData: {{ pageData }}</div>
      </template>
    </q-edit-page-layout>
  </div>
</template>

模板分组插槽配置

WARNING

设计规则,模板中每个分组均由 prepend、default、append 三部分插槽构成,具名插槽命名规则分别为 布局模式 + 分组编码 + prepend/分组类型/append

vue
<!-- 如:表头分组插槽配置 -->
<template>
  <div class="edit-page">
    <a-spin :spinning="customLoading">
      <q-edit-page-layout
        ref="layoutRef"
        v-bind="options"
        @itemListAdd="handleItemListAdd"
        @supplierAdd="handleSupplierAdd"
        @customPublish="handleCustomPublish"
        @back="back"
      >
        <!-- 基本信息 -->
        <template
          #vertical_baseForm_prepend="{ formFields, rules, data, pageData }"
        >
          <span>vertical_baseForm_prepend</span>
          <div>formFields: {{ formFields }}</div>
          <div>rules: {{ rules }}</div>
          <div>data: {{ data }}</div>
          <div>pageData: {{ pageData }}</div>
        </template>
        <template
          #vertical_baseForm_head="{ formFields, rules, data, pageData }"
        >
          <div>formFields: {{ formFields }}</div>
          <div>rules: {{ rules }}</div>
          <div>data: {{ data }}</div>
          <div>pageData: {{ pageData }}</div>
        </template>
        <template
          #vertical_baseForm_append="{ formFields, rules, data, pageData }"
        >
          <span>vertical_baseForm_append</span>
          <div>formFields: {{ formFields }}</div>
          <div>rules: {{ rules }}</div>
          <div>data: {{ data }}</div>
          <div>pageData: {{ pageData }}</div>
        </template>
        <!-- 供应商信息 -->
        <template
          #vertical_purchaseEbiddingSupplierList_prepend="{
            columns,
            editRules,
            pageData,
            data,
          }"
        >
          <span>vertical_purchaseEbiddingSupplierList_prepend</span>
          <div>columns: {{ columns }}</div>
          <div>editRules: {{ editRules }}</div>
          <div>pageData: {{ pageData }}</div>
          <div>data: {{ data }}</div>
        </template>
        <template
          #vertical_purchaseEbiddingSupplierList_item="{
            columns,
            editRules,
            pageData,
            data,
          }"
        >
          <div>columns: {{ columns }}</div>
          <div>editRules: {{ editRules }}</div>
          <div>pageData: {{ pageData }}</div>
          <div>data: {{ data }}</div>
        </template>
        <template
          #vertical_purchaseEbiddingSupplierList_append="{
            columns,
            editRules,
            pageData,
            data,
          }"
        >
          <span>vertical_purchaseEbiddingSupplierList_append</span>
          <div>columns: {{ columns }}</div>
          <div>editRules: {{ editRules }}</div>
          <div>pageData: {{ pageData }}</div>
          <div>data: {{ data }}</div>
        </template>
      </q-edit-page-layout>
    </a-spin>
  </div>
</template>

<script lang="ts" setup>
// 配置
const options = reactive<Partial<GlobalPageLayoutTypes.EditPageLayoutProps>>({
  // ...
  localConfig: {
    groups: [
      // 注意: 任何需要插槽配置的分组,本地均需要配置相应分组group
      // 不然不会显示
      {
        groupName: "基本信息",
        groupNameI18nKey: "i18n_field_baseForm",
        groupCode: "baseForm",
        groupType: "head",
        sortOrder: "1",
        slot: true, // 设置为true, 过滤分组,不触发模板校验
      },
      {
        groupName: "供应商信息",
        groupNameI18nKey: "i18n_title_supplierInfo",
        groupCode: "purchaseEbiddingSupplierList",
        groupType: "item",
        sortOrder: "3",
        slot: true, // 设置为true, 过滤分组,不触发模板校验
      },
    ],
  },
});
</script>

表头字段自定义插槽

需求: 比如竞价管理表头 竞价单号 需要渲染为超链接

1. edit.vue 编辑模板本地需要配置 竞价单号 字段,并设置类型为 customSlot

2. 如果需要:可以使用 handleAfterRemoteConfig 过滤掉服务端业务模板的重复字段 竞价单号

3. 作用域插槽实现自定义渲染需求

插槽名称规则: 布局模式(vertical*) + 分组编码(baseForm*) + 自定义类型(customSlot_) + 字段如(ebiddingNumber)

vue
<script setup lang="tsx">
// 配置
const options = reactive<Partial<GlobalPageLayoutTypes.EditPageLayoutProps>>({
  // 本地页面数据配置
  localConfig: {
    formFields: [
      {
        groupCode: "baseForm",
        sortOrder: "1",
        fieldType: "customSlot",
        fieldLabel: "竞价单号",
        fieldLabelI18nKey: "i18n_field_ebiddingNumber",
        fieldName: "ebiddingNumber",
      },
    ],
  },
});
</script>
vue
<script setup lang="tsx">
// 过滤业务模板重复字段
const handleAfterRemoteConfig = (config) => {
  const formFields = config.formFields || [];
  formFields;
  config.formFields = formFields.filter(
    (n) => n.fieldName !== "ebiddingNumber"
  );

  return config; // 返回处理后的配置数据, 可以是 promise 对象
};

// 配置
const options = reactive<Partial<GlobalPageLayoutTypes.EditPageLayoutProps>>({
  handleAfterRemoteConfig,
});
</script>
vue
<template>
  <div class="edit-page">
    <q-edit-page-layout ref="layoutRef" v-bind="options" @back="back">
      <template
        #vertical_baseForm_customSlot_ebiddingNumber="{ field, pageData }"
      >
        <a class="ant-typography" href="https://antdv.com" target="_blank">
          表头字段自定义插槽示例 {{ pageData[field.fieldName] || "" }}
        </a>
      </template>
    </q-edit-page-layout>
  </div>
</template>

表行字段自定义插槽

WARNING

配合 vxe-table 自定义插槽模板功能,使用 tsx 实现字段的自定义渲染

vue
<script lang="tsx" setup>
// 省份字段插槽配置
/**
 * @description: 业务规则:
 * 国家/地区的值为”中国“时, 省份字段允许设置为远程下拉搜索,否则为输入框
 */
const provinceColumns: GlobalPageLayoutTypes.ColumnItem = {
  groupCode: "supplierAddressInfoList",
  title: "省份",
  fieldLabelI18nKey: "i18n_title_province",
  field: "province",
  fieldType: "", // 注意, 字段类型必须重置为空
  width: 150,
  editRender: {
    enabled: true,
  },
  slots: {
    default({
      row,
      column,
    }: VxeColumnSlotTypes.DefaultSlotParams<VxeTableDataRow>) {
      return [<span>{row[column.field]}</span>];
    },
    edit({ row, column }: VxeColumnSlotTypes.EditSlotParams<VxeTableDataRow>) {
      // 处理手输
      if (
        row.country === "中国" ||
        row.country === "CN" ||
        row.country === "CN_中国"
      ) {
        const props = {
          config: {
            extend: {
              modalColumns: [
                {
                  field: "provinceName",
                  title: "省份名称",
                  fieldLabelI18nKey: "i18n_field_bzRL_374bc89f",
                  with: 350,
                },
                {
                  field: "cityName",
                  title: "城市名称",
                  fieldLabelI18nKey: "i18n_field_city",
                  with: 350,
                },
                {
                  field: "areasName",
                  title: "地区名称",
                  fieldLabelI18nKey: "i18n_field_nMRL_28e52f0d",
                  with: 350,
                },
                {
                  field: "streetsName",
                  title: "乡道/街道名称",
                  fieldLabelI18nKey: "i18n_field_duyuRL_bb7eb13c",
                  with: 350,
                },
              ],
              modalUrl: "/base/dict/queryDzAddressPage",
              params: {},
              selectModal: "single",
              handleAfter: ({ row }) => {
                row.province = "";
                row.city = "";
                row.address = "";
              },
            },
          },
        };

        const onVxeSelectModalChange = (
          data: GlobalPageLayoutTypes.RecordString[]
        ) => {
          if (!data || !data.length) {
            return;
          }

          const {
            provinceName = "",
            cityName = "",
            areasName = "",
            streetsName = "",
          } = data[0] || {};
          row.province = provinceName;
          row.city = cityName;
          row.address = `${areasName}${streetsName}`;
        };

        return [
          <q-select-modal
            v-model:value={row[column.field]}
            {...props}
            onChange={onVxeSelectModalChange}
          ></q-select-modal>,
        ];
      }

      return [<vxe-input v-model={row[column.field]}></vxe-input>];
    },
  },
};

const handleAfterDetailApiResponse: (
  payload: GlobalPageLayoutTypes.Expose
) => void = (payload) => {
  const { pageData, layoutConfig, defaultValues } = payload;

  if (pageData.id) {
    layoutConfig.groups.forEach((group) => {
      if (group.groupCode === "supplierAddressInfoList") {
        if (group.groupType === "item") {
          let columns = group.columns || [];
          const idx = columns.findIndex((n) => n.field === "province");
          if (idx !== -1) {
            columns.splice(idx, 1, provinceColumns);
            group.columns = columns;
          }
        }
      }
    });
  }
};

// 配置
const options = reactive<Partial<GlobalPageLayoutTypes.EditPageLayoutProps>>({
  handleAfterDetailApiResponse,
});
</script>