Appearance
插槽
模板顶层作用域插槽配置
INFO
用于获取模板配置数据,解决页面样式重新开发等需求
vue
<template>
<div class="edit-page">
<q-detail-page-layout ref="layoutRef" v-bind="options">
<template #default="{ layoutConfig, pageData }">
<div>layoutConfig: {{ layoutConfig }}</div>
<div>pageData: {{ pageData }}</div>
</template>
</q-detail-page-layout>
</div>
</template>
模板分组插槽配置
WARNING
设计规则,模板中每个分组均由 prepend、default、append 三部分插槽构成,具名插槽命名规则分别为 布局模式 + 分组编码 + prepend/分组类型/append
vue
<!-- 如:表头分组插槽配置 -->
<template>
<div class="edit-page">
<a-spin :spinning="customLoading">
<q-detail-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-detail-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. detail.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-detail-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-detail-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>
表行分组插槽使用示例
WARNING
如表行数据分页查询、请求其他接口,额外的表格配置等需求;从 UI 库解构 VXE 表格配置,从插槽中解构表行列配置,满足部分二开需求;
vue
<!-- 询价管理 详情 -->
<template>
<div class="detail-page">
<a-spin :spinning="loading">
<q-detail-page-layout ref="layoutRef" v-bind="options">
<template
#vertical_purchaseEnquiryItemList_item="{ columns }"
v-if="!currentRow._isAudit"
>
<vxe-grid
ref="xGrid"
v-bind="editVxeTableConfig"
:pager-config="pagerConfig"
:loading="tableLoading"
:columns="columns"
:data="purchaseEnquiryItemList"
@page-change="handlePageChange"
>
<template #empty>
<q-empty></q-empty>
</template>
</vxe-grid>
</template>
</q-detail-page-layout>
</a-spin>
</div>
</template>
<script setup lang="tsx">
import { ref, reactive, nextTick } from "vue";
import { editVxeTableConfig } from "@qqt-product/ui";
// 全局数据缓存
// 当前行 currentRow, 当前用户信息 userInfo
import { useGlobalStoreWithDefaultValue } from "@/use/useGlobalStore";
const { getCurrentRow } = useGlobalStoreWithDefaultValue();
const currentRow = getCurrentRow();
const pagerConfig = ref({
total: 0,
currentPage: 1,
pageSize: 20,
});
const loading = ref<boolean>(false);
const probeData = ref<GlobalPageLayoutTypes.RecordString[]>([]);
const xGrid = ref<VxeGridInstance>();
const tableLoading = ref<boolean>(false);
const purchaseEnquiryItemList = ref<GlobalPageLayoutTypes.RecordString[]>([]);
// 配置
const options = reactive<Partial<GlobalPageLayoutTypes.EditPageLayoutProps>>({
// 本地页面数据配置
localConfig: {
groups: [
{
groupName: "询价行信息",
groupNameI18nKey: "i18n_title_RFQLineInformation",
groupCode: "purchaseEnquiryItemList",
groupType: "item",
sortOrder: "2",
},
],
},
});
const handlePageChange: VxePagerEvents.PageChange = ({
currentPage,
pageSize,
}) => {
pagerConfig.value.currentPage = currentPage;
pagerConfig.value.pageSize = pageSize;
getItemListData();
};
const getItemListData = () => {
const url = "/enquiry/purchaseEnquiryHead/itemList";
const params = {
headId: currentRow.id,
pageSize: pagerConfig.value.pageSize,
pageNo: pagerConfig.value.currentPage,
column: "id",
order: "asc",
};
tableLoading.value = true;
Request.get({ url, params })
.then((res) => {
if (res.success) {
const records = res.result.records || [];
purchaseEnquiryItemList.value = records;
pagerConfig.value.total = res.result.total;
}
})
.finally(() => {
tableLoading.value = false;
});
};
if (!currentRow._isAudit) {
getItemListData();
}
</script>