feat(web): 随访模板管理页面 — CRUD + 路由 + 菜单迁移
Some checks failed
CI / rust-check (push) Has been cancelled
CI / rust-test (push) Has been cancelled
CI / frontend-build (push) Has been cancelled
CI / security-audit (push) Has been cancelled

- 新增 FollowUpTemplateList.tsx 页面(列表/新建/编辑/详情弹窗)
- 新增 followUpTemplates.ts API 客户端(list/get/create/update/delete)
- 注册路由 /health/follow-up-templates + 菜单标题 fallback
- 新增迁移 seed_follow_up_template_menu 注册菜单和权限
This commit is contained in:
iven
2026-05-03 09:31:43 +08:00
parent 2e4d98c479
commit 32df9c0655
6 changed files with 511 additions and 0 deletions

View File

@@ -0,0 +1,119 @@
import client from '../client';
import type { PaginatedResponse } from '../types';
export type FollowUpType = 'phone' | 'outpatient' | 'home_visit' | 'online' | 'wechat';
export type TemplateStatus = 'active' | 'draft' | 'archived';
export interface TemplateField {
id: string;
template_id: string;
label: string;
field_key: string;
field_type: string;
required: boolean;
options?: string;
placeholder?: string;
validation?: string;
sort_order: number;
created_at: string;
updated_at: string;
version: number;
}
export interface TemplateFieldReq {
label: string;
field_key: string;
field_type: string;
required?: boolean;
options?: string;
placeholder?: string;
validation?: string;
sort_order?: number;
}
export interface FollowUpTemplate {
id: string;
name: string;
description?: string;
follow_up_type: string;
applicable_scope?: string;
status: string;
fields: TemplateField[];
created_at: string;
updated_at: string;
version: number;
}
export interface FollowUpTemplateListItem {
id: string;
name: string;
description?: string;
follow_up_type: string;
status: string;
field_count: number;
created_at: string;
updated_at: string;
version: number;
}
export interface CreateTemplateReq {
name: string;
description?: string;
follow_up_type: string;
applicable_scope?: string;
fields: TemplateFieldReq[];
}
export interface UpdateTemplateReq {
name?: string;
description?: string;
follow_up_type?: string;
applicable_scope?: string;
status?: string;
fields?: TemplateFieldReq[];
}
export const followUpTemplateApi = {
list: async (params?: {
page?: number;
page_size?: number;
follow_up_type?: string;
status?: string;
}) => {
const { data } = await client.get<{
success: boolean;
data: PaginatedResponse<FollowUpTemplateListItem>;
}>('/health/follow-up-templates', { params });
return data.data;
},
get: async (id: string) => {
const { data } = await client.get<{
success: boolean;
data: FollowUpTemplate;
}>(`/health/follow-up-templates/${id}`);
return data.data;
},
create: async (req: CreateTemplateReq) => {
const { data } = await client.post<{
success: boolean;
data: FollowUpTemplate;
}>('/health/follow-up-templates', req);
return data.data;
},
update: async (id: string, req: UpdateTemplateReq & { version: number }) => {
const { data } = await client.put<{
success: boolean;
data: FollowUpTemplate;
}>(`/health/follow-up-templates/${id}`, req);
return data.data;
},
delete: async (id: string, version: number) => {
await client.delete(`/health/follow-up-templates/${id}`, {
data: { version },
});
},
};