Skip to content

手动修改与定制开发

本文档引用文件

目录

  1. 引言
  2. 可安全修改的文件
  3. 可能被覆盖的文件
  4. 典型定制场景示例
  5. 代码可维护性策略
  6. 代码风格与类型安全
  7. 结论

引言

本指南旨在为开发者提供在自动生成代码基础上进行手动修改和定制开发的完整指导。通过分析项目结构与代码生成机制,明确哪些文件可以安全修改,哪些文件可能在重新生成时被覆盖,并提供典型扩展场景的实现方法。文档强调通过继承与装饰器模式保持代码可维护性,同时确保代码风格一致性和类型安全。

可安全修改的文件

以下类型的文件通常可以安全地进行手动修改,因为它们不属于代码生成器的直接输出范围,或位于可扩展的自定义目录中。

服务层文件(Service)

服务层文件(如 usr.service.ts)是业务逻辑的核心承载者,通常允许开发者添加自定义方法。这些文件由代码生成器创建初始结构,但后续的业务扩展可安全添加。

Section sources

详情页面组件(Detail.vue)

前端详情页组件(如 Detail.vue)是用户交互的关键部分,支持添加自定义表单验证、UI逻辑和事件处理。此类文件位于 __out__ 目录下,但设计上允许开发者进行个性化调整。

Section sources

移动端 API 扩展(Api2.ts)

移动端专用 API 文件(如 Api2.ts)用于扩展查询参数或添加移动端特有接口。这类文件通常作为补充存在,不会被代码生成器覆盖。

Section sources

可能被覆盖的文件

以下文件在代码重新生成时可能被完全覆盖,因此不建议直接修改:

  • 位于 codegen/__out__ 下的自动生成文件(如 .dao.ts, .model.ts, .resolver.ts
  • 由模板引擎生成的路由配置文件(如 gen.ts
  • GraphQL 模式定义文件(如 *.graphql.ts

建议通过继承、AOP 装饰器或配置注入方式实现功能扩展,而非直接修改上述文件。

典型定制场景示例

在 usr.service.ts 中添加业务逻辑

可在 usr.service.ts 中新增业务方法,例如添加用户权限校验逻辑:

typescript
/**
 * 检查用户是否具有特定角色
 */
export async function hasRole(usr_id: UsrId, role_code: string): Promise<boolean> {
  const user = await findByIdOkUsr(usr_id);
  const roles = await findByIdsRole(user.role_ids || []);
  return roles.some(role => role.code === role_code);
}

此方法可被其他服务调用,增强权限控制能力。

Section sources

在 Detail.vue 中增加自定义表单验证

Detail.vue 中可通过扩展 form_rules 实现复杂验证逻辑,例如用户名唯一性检查:

ts
form_rules = {
  ...form_rules,
  username: [
    ...form_rules.username,
    {
      validator: async (_rule: any, value: string) => {
        if (!value) return;
        const exists = await existUsr({ username: value });
        if (exists) throw new Error('用户名已存在');
      },
      trigger: 'blur'
    }
  ]
};

该验证在提交前异步执行,提升用户体验。

Section sources

在移动端 Api2.ts 中扩展查询参数

Api2.ts 中可添加移动端专用查询,例如获取发布状态:

ts
/// 移动端是否发版中 uni_releasing
export async function getUniReleasing(opt?: GqlOpt) {
  const res: { getUniReleasing: boolean; } = await mutation({
    query: /* GraphQL */ `
      query {
        getUniReleasing
      }
    `,
  }, opt);
  return res.getUniReleasing;
}

此接口可用于控制移动端功能开关。

Section sources

代码可维护性策略

继承模式

对于服务类,可通过创建子类继承原始服务,添加新功能:

ts
class CustomUsrService extends UsrService {
  async sendWelcomeEmail(usr_id: UsrId) {
    // 发送欢迎邮件逻辑
  }
}

装饰器模式

使用装饰器增强方法行为,如日志记录或权限检查:

ts
function LogExecution(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
  const originalMethod = descriptor.value;
  descriptor.value = function(...args: any[]) {
    console.log(`Executing ${propertyKey}`);
    return originalMethod.apply(this, args);
  };
}

@LogExecution
async function createUsr(input: UsrInput) {
  // 创建用户逻辑
}

代码风格与类型安全

所有手动修改必须遵循项目既定的代码风格规范,包括:

  • 使用 PascalCase 命名类,camelCase 命名变量和方法
  • 所有函数参数和返回值必须显式声明类型
  • 使用 Promise<T> 明确异步返回类型
  • 避免 any 类型,优先使用接口或联合类型

类型安全检查应通过 TypeScript 编译器严格启用,确保所有修改均通过 tsc --noEmit 验证。

Section sources

结论

在自动生成代码框架下进行定制开发时,应优先选择可安全修改的文件(如 Service、Detail.vue、Api2.ts),避免直接修改可能被覆盖的生成文件。通过继承与装饰器模式实现功能扩展,既能保持代码可维护性,又能确保系统稳定性。同时,严格遵守代码风格与类型安全规范,是保障团队协作效率和系统健壮性的关键。