<template>
|
<Page v-if="isAdmin && pageId" :auto-content-height="true">
|
<BasicTable
|
:key="tableKey"
|
:table-title="pageDesignDetail?.name || '模板列表'"
|
:grid-options="gridOptions"
|
>
|
<template #toolbar-tools>
|
<Space>
|
<a-button v-if="showAction('add')" type="primary" @click="handleAdd">新增</a-button>
|
</Space>
|
</template>
|
<template #action="{ row }">
|
<Space>
|
<ghost-button v-if="showAction('edit')" @click="handleEdit(row)">编辑</ghost-button>
|
<Popconfirm v-if="showAction('delete')" :get-popup-container="getVxePopupContainer" placement="left" title="确认删除?" @confirm="handleDelete(row)">
|
<ghost-button danger @click.stop="">删除</ghost-button>
|
</Popconfirm>
|
</Space>
|
</template>
|
</BasicTable>
|
<TemplateDrawer ref="templateModalRef" @reload="tableApi.query()" />
|
</Page>
|
<Fallback v-else description="未指定 pageId,无法访问此页面" status="403" />
|
</template>
|
|
<script setup lang="ts">
|
import type { VbenFormProps } from '@vben/common-ui';
|
import type { VxeGridProps } from '#/adapter/vxe-table';
|
import { computed, ref, onMounted, watch } from 'vue';
|
import { useRoute, useRouter } from 'vue-router';
|
import { useAccess } from '@vben/access';
|
import { Fallback, Page } from '@vben/common-ui';
|
import { getVxePopupContainer } from '@vben/utils';
|
import { Popconfirm, Space, Spin as ASpin } from 'ant-design-vue';
|
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
import { columns as baseColumns, querySchema } from './data';
|
import TemplateDrawer from './template-drawer.vue';
|
import { templateList, templateRemove } from '#/api/tool/template';
|
import { pageInfo } from '#/api/tool/page-designer';
|
|
const route = useRoute();
|
const router = useRouter();
|
const pageId = ref<string | number>('');
|
const pageDesignDetail = ref<any>(null); // 页面设计详情
|
const loading = ref(true); // 加载中
|
|
// 动态columns
|
const dynamicColumns = ref([
|
{ field: 'id', title: 'ID', width: 100 },
|
{ field: 'formData', title: '表单数据', minWidth: 160 },
|
{ field: 'action', title: '操作', width: 160, slots: { default: 'action' } }
|
]);
|
|
// 用于表格重新渲染的 key
|
const tableKey = ref(0);
|
|
// 更新动态列的函数
|
function updateDynamicColumns() {
|
if (!pageDesignDetail.value || !pageDesignDetail.value.showColumn || !pageDesignDetail.value.formJson) {
|
console.log('使用默认列');
|
return;
|
}
|
|
try {
|
const showFields = JSON.parse(pageDesignDetail.value.showColumn);
|
const formFields = JSON.parse(pageDesignDetail.value.formJson);
|
const cols = showFields.map(field => {
|
const fieldDef = formFields.find(f => f.field === field);
|
return {
|
field: field,
|
title: fieldDef ? fieldDef.title : field,
|
minWidth: 120,
|
align: 'center',
|
};
|
});
|
|
cols.push({
|
field: 'action',
|
title: '操作',
|
width: 160,
|
slots: { default: 'action' },
|
});
|
|
dynamicColumns.value = cols;
|
gridOptions.value = { ...gridOptions.value, columns: cols };
|
tableKey.value++;
|
} catch (error) {
|
const fallbackCols = [
|
{ field: 'id', title: 'ID', width: 100 },
|
{ field: 'formData', title: '表单数据', minWidth: 160 },
|
{ field: 'action', title: '操作', width: 160, slots: { default: 'action' } }
|
];
|
dynamicColumns.value = fallbackCols;
|
gridOptions.value = { ...gridOptions.value, columns: fallbackCols };
|
tableKey.value++;
|
}
|
}
|
|
|
// 动态按钮
|
function showAction(action: string) {
|
if (!pageDesignDetail.value || !pageDesignDetail.value.actionsFunc) {
|
return true;
|
}
|
|
try {
|
const actions = JSON.parse(pageDesignDetail.value.actionsFunc);
|
if (!Array.isArray(actions)) {
|
console.warn('actionsFunc 不是数组格式:', pageDesignDetail.value.actionsFunc);
|
return true;
|
}
|
|
return actions.includes(action);
|
} catch (error) {
|
console.error('解析 actionsFunc 失败:', error);
|
return true;
|
}
|
}
|
|
// 获取 pageId,只用 params
|
function getPageId() {
|
const segments = window.location.pathname.split('/');
|
return segments[segments.length - 1] || '';
|
}
|
|
onMounted(() => {
|
const initialPageId = getPageId();
|
console.log('获取到的 pageId:', initialPageId);
|
|
if (initialPageId) {
|
pageId.value = initialPageId;
|
handlePageIdChange();
|
} else {
|
loading.value = false;
|
}
|
});
|
|
// 监听路由变化,自动更新 pageId
|
watch(
|
() => [route.meta.pageId, route.params.pageId, route.query.pageId],
|
(newValues, oldValues) => {
|
// 只有当值真正变化时才处理
|
if (JSON.stringify(newValues) !== JSON.stringify(oldValues)) {
|
const newPageId = getPageId();
|
console.log('路由变化后 pageId:', newPageId);
|
|
// 只有当 pageId 真正变化时才更新
|
if (newPageId !== pageId.value) {
|
pageId.value = newPageId;
|
handlePageIdChange();
|
tableApi.query();
|
}
|
}
|
},
|
{ deep: true }
|
);
|
|
// pageId变化时自动获取页面设计详情
|
async function handlePageIdChange() {
|
loading.value = true;
|
console.log(`[handlePageIdChange] 开始处理 pageId: ${pageId.value}`);
|
try {
|
if (pageId.value) {
|
const detail = await pageInfo(pageId.value);
|
console.log('[handlePageIdChange] 获取到的页面设计详情 (detail):', JSON.parse(JSON.stringify(detail)));
|
|
// 处理数据,避免循环引用
|
const safeDetail = {
|
id: detail.id,
|
name: detail.name,
|
menuParentId: detail.menuId,
|
status: detail.status,
|
remark: detail.remark,
|
formJson: detail.formJson,
|
showColumn: detail.showColumn,
|
actionsFunc: detail.actionsFunc,
|
createTime: detail.createTime,
|
updateTime: detail.updateTime,
|
createBy: detail.createBy,
|
updateBy: detail.updateBy,
|
createDept: detail.createDept
|
};
|
|
pageDesignDetail.value = safeDetail;
|
console.log('[handlePageIdChange] 设置的 pageDesignDetail.value:', JSON.parse(JSON.stringify(pageDesignDetail.value)));
|
updateDynamicColumns();
|
} else {
|
pageDesignDetail.value = null;
|
updateDynamicColumns();
|
}
|
} catch (error) {
|
console.error('[handlePageIdChange] 获取页面设计详情失败:', error);
|
pageDesignDetail.value = null;
|
updateDynamicColumns();
|
} finally {
|
loading.value = false;
|
}
|
}
|
|
const formOptions: VbenFormProps = {
|
commonConfig: {
|
labelWidth: 80,
|
componentProps: {
|
allowClear: true,
|
},
|
},
|
schema: querySchema(),
|
wrapperClass: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4',
|
};
|
|
const gridOptions = ref<VxeGridProps>({
|
columns: dynamicColumns.value,
|
height: 'auto',
|
keepSource: true,
|
pagerConfig: {
|
enabled: true,
|
},
|
proxyConfig: {
|
ajax: {
|
query: async ({ page }, formValues = {}) => {
|
try {
|
console.log('查询参数:', { page, formValues });
|
const queryParams = {
|
pageNum: page.currentPage,
|
pageSize: page.pageSize,
|
...formValues,
|
};
|
if (pageId.value) {
|
queryParams.pageId = pageId.value;
|
}
|
const resp = await templateList(queryParams);
|
// 处理每条 row 的 formData
|
const rows = (resp.rows || []).map(row => {
|
let formData = {};
|
try {
|
if (row.formData) {
|
formData = JSON.parse(row.formData);
|
console.log('解析后的 formData:', formData);
|
// 删除原始的 formData 字段,因为我们已经展开它的内容
|
const { formData: _, ...restRow } = row;
|
// 返回展开后的数据
|
return {
|
...restRow,
|
...formData
|
};
|
}
|
} catch (e) {
|
console.error('解析 formData 失败:', e);
|
}
|
return row;
|
});
|
console.log('处理后的 rows:', rows);
|
return {
|
rows,
|
total: resp.total || 0,
|
};
|
} catch (error) {
|
console.error('查询模板列表失败:', error);
|
return {
|
rows: [],
|
total: 0,
|
};
|
}
|
},
|
},
|
},
|
rowConfig: {
|
keyField: 'id',
|
},
|
id: 'tool-template-index',
|
columnConfig: { resizable: true },
|
});
|
|
const [BasicTable, tableApi] = useVbenVxeGrid({
|
formOptions,
|
gridOptions: computed(() => ({
|
...gridOptions.value,
|
columns: dynamicColumns.value
|
})),
|
});
|
|
const templateModalRef = ref();
|
const generateModalRef = ref();
|
|
function handleAdd() {
|
// 如果有 pageId,传递给新增
|
const params: any = { update: false };
|
if (pageId.value) {
|
params.pageId = pageId.value;
|
}
|
// 动态传递formJson,先JSON.parse,保证是纯对象
|
if (pageDesignDetail.value && pageDesignDetail.value.formJson) {
|
try {
|
const formJson = JSON.parse(pageDesignDetail.value.formJson);
|
params.formJson = formJson;
|
console.log('传递动态表单字段:', formJson);
|
} catch (error) {
|
console.error('解析 formJson 失败:', error);
|
params.formJson = undefined;
|
}
|
}
|
templateModalRef.value.open(params);
|
}
|
|
function handleEdit(record) {
|
// 编辑时也传递formJson,先JSON.parse,保证是纯对象
|
const params: any = {
|
id: record.id,
|
update: true,
|
pageId: pageId.value, // 传递页面设计ID
|
record: record // 传递完整的记录数据
|
};
|
|
if (pageDesignDetail.value && pageDesignDetail.value.formJson) {
|
try {
|
const formJson = JSON.parse(pageDesignDetail.value.formJson);
|
params.formJson = formJson;
|
console.log('编辑时传递数据:', { record, formJson, pageId: pageId.value });
|
} catch (error) {
|
console.error('解析 formJson 失败:', error);
|
params.formJson = undefined;
|
}
|
}
|
templateModalRef.value.open(params);
|
}
|
|
async function handleDelete(row: any) {
|
try {
|
await templateRemove([row.id]);
|
await tableApi.query();
|
} catch (error) {
|
console.error('删除模板失败:', error);
|
}
|
}
|
|
function handleGenerate(row) {
|
try {
|
generateModalRef.value.open(row);
|
} catch (error) {
|
console.error('打开生成页面失败:', error);
|
}
|
}
|
|
function handlePreview(row) {
|
try {
|
// 打开预览窗口
|
const url = `/tool/template/preview/${row.id}`;
|
window.open(url, '_blank');
|
} catch (error) {
|
console.error('打开预览失败:', error);
|
}
|
}
|
|
const { hasAccessByRoles } = useAccess();
|
const isAdmin = computed(() => {
|
try {
|
return hasAccessByRoles(['admin', 'superadmin']);
|
} catch (error) {
|
console.error('检查权限失败:', error);
|
return false;
|
}
|
});
|
|
const isReady = computed(() => {
|
try {
|
// 简化判断逻辑,减少不必要的计算
|
return !!(pageDesignDetail.value && !loading.value);
|
} catch (error) {
|
console.error('检查页面准备状态失败:', error);
|
return false;
|
}
|
});
|
</script>
|
|
<style scoped>
|
.template-page {
|
background: #f5f6fa;
|
padding: 16px;
|
min-height: 100vh;
|
height: 100vh;
|
overflow: hidden;
|
}
|
|
/* 确保表格容器高度稳定 */
|
:deep(.vxe-table--main-wrapper) {
|
height: 600px !important;
|
}
|
|
/* 确保分页器位置固定 */
|
:deep(.vxe-pager) {
|
position: sticky;
|
bottom: 0;
|
background: white;
|
z-index: 10;
|
}
|
</style>
|