Skip to content

016 更新迭代 migrate-static-data-to-nitro-querylist-page-pattern 列表页改造规范,避免出现删改多余内容的情况

在以下文件内,增加以下严格规范:

  • openspec\changes\migrate-static-data-to-nitro-query\specs\migration-guide.md
  • openspec\changes\migrate-static-data-to-nitro-query\specs\list-page-pattern\spec.md

修改列表页时,新增的严格规范如下:

1. 无条件的按照 fix-type-error 来处理类型错误

  1. 在处理列表页的类型替换和变量替换时,必须严格按照 .claude\agents\fix-type-error.md 文档所述的要求来执行。不要自己胡乱发挥,乱写代码,胡乱改变原有的类型,导入不存在的,冗余的,多余的全局类型。

2. 不要删改破坏掉现有的弹框函数逻辑

每一个列表页都有这样的代码段。这些逻辑是列表页弹框逻辑必备的函数。不允许你删改。这不是你本次迁移改造任务的处理范围,不要动不属于你范围的代码!

ts
const { modeText, setMode, isAdd } = useMode();
const [isFetchingT, setIsLoadingT] = useToggle(false);
/** 模拟异步操作函数 */
async function testAsync() {
	setIsLoadingT(true);
	consola.log("模拟异步操作, isFetchingT ", isFetchingT.value);
	await sleep(1300);
	setIsLoadingT(false);
	consola.log("模拟异步操作, isFetchingT ", isFetchingT.value);
}

3. 不要删掉弹框实例代码,只负责做类型替换

不要随便删掉下面的弹框实例新建逻辑,这不是你要负责的内容。你只需要实现中文变量名替换、导入来自类型项目的业务类型,就可以了。不要做多余的操作!

ts
import { type 停车场表单Props, defaultForm, type 停车场表单_VO } from "./components/form";
import 停车场表单 from "./components/form.vue";
const 停车场表单Instance = ref<InstanceType<typeof 停车场表单> | null>(null);

你的正确处理应该是这样的:

  1. 去类型项目导入 ParkingLotFormVO ,导入形如 xxxFormVO 格式的表单类型,去替代来自相对路径的 form.ts 导出的 停车场表单_VO 中文类型。
  2. 把导入的中文变量名,换成英文名。停车场表单 应该换成 ParkingLotForm 换成形如 xxxForm 的组件变量名。
  3. 把本地的表单实例的中文变量名,换成英文名。停车场表单Instance 应该换成 ParkingLotFormInstance
ts
import type { ParkingLotFormVO } from "@01s-11comm/type";
import { type ParkingLotFormProps, defaultForm } from "./components/form";
import ParkingLotForm from "./components/form.vue";
const ParkingLotFormInstance = ref<InstanceType<typeof ParkingLotForm> | null>(null);

以下处理方式是错误的。你把原来该有的表单实例全删除掉了。这不是你要负责改造的部分。

ts
import type { ParkingLotListItem } from "@01s-11comm/type";

4. 不要胡乱删改打开弹框组件的处理逻辑

在列表页内,处理弹框组件已经有的逻辑时,以下的处理方式错的很离谱:

  1. 你删除掉了表单对象的业务类型约束,这是不对的。不要删掉已经有的代码逻辑。
  2. 深克隆函数,本来应该是克隆 defaultForm 变量,结果你改成了一个 {},这是完全错误的做法。不要删改本来就有的函数传参逻辑。
  3. 你多删除了 propsdefaultValues,这两个变量是本来的业务逻辑,不要删除不属于你处理范围的代码。
ts
/** 业务对象 */
const parkingLotFormVO = isAdd.value
	? structuredClone({})
	: structuredClone({
			...row,
			parkingLotType: row?.parkingLotType || "地面停车场",
			parkingSpaceType: row?.parkingSpaceType || "标准车位",
		});

原来被处理的代码如下:

你应该保留这些处理逻辑和结构,只负责更改代码的变量名,和使用的函数。不要删掉多余的代码结构。

ts
/** 业务对象 */
const 停车场表单对象: 停车场表单_VO = isAdd.value
	? cloneDeep(defaultForm)
	: cloneDeep({
			...defaultForm,
			...row,
			停车场类型: row?.停车场类型 || defaultForm.停车场类型,
			车位类型: row?.车位类型 || defaultForm.车位类型,
		});

/** 表单组件需要的props */
const props: 停车场表单Props = {
	form: 停车场表单对象,
	defaultValues: 停车场表单对象,
};

/** 根据不同模式下 变化的表单默认重置对象 */
const defaultValues = props.defaultValues;

正确的处理逻辑和处理结果如下:

  1. 变量名替换:
    • 停车场表单对象 -> parkingLotFormVO
    • 停车场表单_VO -> ParkingLotFormVO
    • 停车场表单Props -> ParkingLotFormProps
  2. 函数替换:
    • cloneDeep -> structuredClone

你只负责最基础的变量名替换成英文,深克隆函数 cloneDeep 换成统一的 structuredClone 即可。不要胡乱更改现有的代码逻辑。

ts
/** 业务对象 */
const parkingLotFormVO: ParkingLotFormVO = isAdd.value
	? structuredClone(defaultForm)
	: structuredClone({
			...defaultForm,
			...row,
			parkingLotType: row?.parkingLotType || defaultForm.parkingLotType,
			parkingSpaceType: row?.parkingSpaceType || defaultForm.parkingSpaceType,
		});

/** 表单组件需要的props */
const props: ParkingLotFormProps = {
	form: parkingLotFormVO,
	defaultValues: parkingLotFormVO,
};

5. 不要胡乱删改掉打开弹框函数 openDialog 本来就有的按钮配置逻辑

你的职责是完成中文变量名和中文类型名的替换,不要删改掉本来就写好的代码逻辑!

5.1. 原来的代码

ts
{
  footerButtons: [
			{
				label: transformI18n($t("common.buttons.cancel")),
				type: "info",
				btnClick: async ({ dialog: { options, index }, button }) => {
					const formComputed = 停车场表单Instance.value?.formComputed;
					await useDoBeforeClose({ defaultValues, formComputed, index, options });
				},
			},

			{
				label: transformI18n($t("common.buttons.reset")),
				type: "warning",
				btnClick: ({ dialog: { options, index }, button }) => {
					停车场表单Instance.value?.plusFormInstance?.handleReset();
				},
			},

			{
				label: transformI18n($t("common.buttons.submit")),
				type: "success",
				btnClick: async ({ dialog: { options, index }, button }) => {
					const res = await 停车场表单Instance.value?.plusFormInstance?.handleSubmit();
					if (res) {
						button.btn.loading = true;
						await testAsync();
						button.btn.loading = false;
						closeDialog(options, index);
					}
				},
			},
		],
}

5.2. 错误的处理结果

这是你错误的处理结果:

  1. 不要删掉本来就有的 const formComputed 变量。这个变量没有影响到你的任务。不要删减和你本次任务无关的代码。
  2. 不要删掉 useDoBeforeClose 函数的调用逻辑。这和你的任务无关。
  3. 不要删掉重置按钮这整个配置对象。这和你的任务无关!、
ts
{
  footerButtons: [
			{
				label: transformI18n($t("common.buttons.cancel")),
				type: "info",
				btnClick: async ({ dialog: { options, index }, button }) => {
					closeDialog(options, index);
				},
			},
			{
				label: transformI18n($t("common.buttons.submit")),
				type: "success",
				btnClick: async ({ dialog: { options, index }, button }) => {
					button.btn.loading = true;
					await testAsync();
					button.btn.loading = false;
					closeDialog(options, index);
				},
			},
		],
}

5.3. 正确的处理结果

  1. 把中文变量名 停车场表单Instance 换成 ParkingLotFormInstance 就行了。这就是你的职责。为什么你要额外的去修改掉其他本来就有的处理逻辑呢?
ts
footerButtons: [
			{
				label: transformI18n($t("common.buttons.cancel")),
				type: "info",
				btnClick: async ({ dialog: { options, index }, button }) => {
					const formComputed = ParkingLotFormInstance.value?.formComputed;
					await useDoBeforeClose({ defaultValues, formComputed, index, options });
				},
			},

			{
				label: transformI18n($t("common.buttons.reset")),
				type: "warning",
				btnClick: ({ dialog: { options, index }, button }) => {
					ParkingLotFormInstance.value?.plusFormInstance?.handleReset();
				},
			},

			{
				label: transformI18n($t("common.buttons.submit")),
				type: "success",
				btnClick: async ({ dialog: { options, index }, button }) => {
					const res = await ParkingLotFormInstance.value?.plusFormInstance?.handleSubmit();
					if (res) {
						button.btn.loading = true;
						await testAsync();
						button.btn.loading = false;
						closeDialog(options, index);
					}
				},
			},
		],

6. 不要更改掉 definePage 宏的排布顺序

  1. 在每个列表页内, definePage必须排在最上面。不允许被修改位置。
  2. 不要影响 definePage 宏的任何内容,不要影响其导入顺序。这不是你要处理的内容。

6.1. 错误的处理方式

这是你错误更改导入顺序的结果。

  1. 不可以把 definePage 宏放到 import 导入函数的下面。
ts
import { ref, computed } from "vue";
import { transformI18n } from "@/plugins/i18n";
import { getRouteRank } from "@/router/rank/getRouteRank";
import type { FieldValues, PlusColumn } from "plus-pro-components";
import type { TableColumns } from "@pureadmin/table";
import { defaultPureTableIndexColumn } from "@/config/constant";
import { useI18n } from "vue-i18n";
import { type MenuGroupListItem, type MenuGroupQueryParams, menuGroupStatusOptions } from "@01s-11comm/type";
import { useMenuGroupListQuery } from "@/api/dev-team/menu-manage/group";

definePage({
	meta: {
		title: "菜单组",
		icon: "mdi:group",
		roles: ["开发团队"],
		rank: getRouteRank("devTeam.menuManage.group"),
	},
});

6.2. 正确的处理方式

  1. definePage 宏函数,在每个列表页内,永远在 import 导入函数之上。
ts
definePage({
	meta: {
		title: "菜单组",
		icon: "mdi:group",
		roles: ["开发团队"],
		rank: getRouteRank("devTeam.menuManage.group"),
	},
});

import { ref, computed } from "vue";
import { transformI18n } from "@/plugins/i18n";
import { getRouteRank } from "@/router/rank/getRouteRank";
import type { FieldValues, PlusColumn } from "plus-pro-components";
import type { TableColumns } from "@pureadmin/table";
import { defaultPureTableIndexColumn } from "@/config/constant";
import { useI18n } from "vue-i18n";
import { type MenuGroupListItem, type MenuGroupQueryParams, menuGroupStatusOptions } from "@01s-11comm/type";
import { useMenuGroupListQuery } from "@/api/dev-team/menu-manage/group";

7. 表格列配置 columns 数组的类型约束,就是全局类型 TableColumnList ,不要换掉

不要换掉本来就使用好的 TableColumnList 类型约束,不要中途换成别的代码写法!这不是你本次任务的处理范畴,你不应该换掉这个全局类型。

7.1. 错误的代码写法

  1. 不要手动导入 TableColumns 类型,把原来的全局类型 TableColumnList 换掉。你不应该去做这种类型替换。
ts
import type { TableColumns } from "@pureadmin/table";
/** 表格列配置 */
const columns = ref<TableColumns[]>([
	// ...具体的表格列配置
]);

7.2. 正确的代码写法

保持原样就可以了,不要添油加醋。TableColumnList 是全局类型,不是你要替换的业务类型!

ts
/** 表格列配置 */
const columns = ref<TableColumnList>([
	// ...具体的表格列配置
]);

8. 不要删掉本来就写好的全局类型约束 PureTableBarProps,保持原样即可

在列表页内,不要删掉本来就写好的全局类型约束 PureTableBarProps,保持原样即可。这不是你要删减替换的类型范围。

8.1. 错误的写法

  1. 删掉了本来就写好的,标准的类型约束 PureTableBarProps
ts
/** 表格操作栏组件 配置  */
const pureTableBarProps = ref({
	title: "菜单组",
	columns: columns.value,
});

8.2. 正确的写法

  1. 保留原样即可。pureTableBarProps 变量本来就是要写成 ref 对象的,而且类型约束就是全局类型 PureTableBarProps。不要添油加醋。
ts
/** 表格操作栏组件 配置  */
const pureTableBarProps = ref<PureTableBarProps>({
	title: "菜单组",
	columns: columns.value,
});

9. 不要增加本来就有的,definePage 宏专用的 getRouteRank 全局函数

不要添油加醋的增加多余的全局导入 getRouteRank 。这个函数不应该主动导入。

ts
// 不应该导入这个函数
import { getRouteRank } from "@/router/rank/getRouteRank";

贡献者

The avatar of contributor named as ruan-cat ruan-cat

页面历史

最近更新