AreaForm.tsx 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. import React from 'react';
  2. import { useForm } from 'react-hook-form';
  3. import { zodResolver } from '@hookform/resolvers/zod';
  4. import { Button } from '@d8d/shared-ui-components/components/ui/button';
  5. import { Input } from '@d8d/shared-ui-components/components/ui/input';
  6. import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@d8d/shared-ui-components/components/ui/select';
  7. import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from '@d8d/shared-ui-components/components/ui/form';
  8. import { createAreaSchemaMt, updateAreaSchemaMt, AreaLevel } from '@d8d/geo-areas-mt/schemas';
  9. import type { CreateAreaInputMt, UpdateAreaInputMt } from '@d8d/geo-areas-mt/schemas';
  10. // 禁用状态枚举
  11. enum DisabledStatus {
  12. ENABLED = 0,
  13. DISABLED = 1
  14. }
  15. interface AreaFormProps {
  16. area?: UpdateAreaInputMt & { id?: number };
  17. onSubmit: (data: CreateAreaInputMt | UpdateAreaInputMt) => Promise<void>;
  18. onCancel: () => void;
  19. isLoading?: boolean;
  20. /** 智能预填的层级 */
  21. smartLevel?: number;
  22. /** 智能预填的父级ID */
  23. smartParentId?: number;
  24. }
  25. // 辅助函数:根据层级值获取显示名称
  26. const getLevelDisplayName = (level: number | undefined): string => {
  27. switch (level) {
  28. case AreaLevel.PROVINCE:
  29. return '省/直辖市';
  30. case AreaLevel.CITY:
  31. return '市';
  32. case AreaLevel.DISTRICT:
  33. return '区/县';
  34. case AreaLevel.TOWN:
  35. return '街道/乡镇';
  36. default:
  37. return '未知层级';
  38. }
  39. };
  40. export const AreaForm: React.FC<AreaFormProps> = ({
  41. area,
  42. onSubmit,
  43. onCancel,
  44. isLoading = false,
  45. smartLevel,
  46. smartParentId
  47. }) => {
  48. const isEditing = !!area;
  49. const form = useForm<CreateAreaInputMt | UpdateAreaInputMt>({
  50. resolver: zodResolver(isEditing ? updateAreaSchemaMt : createAreaSchemaMt),
  51. defaultValues: area ? {
  52. tenantId: area.tenantId,
  53. parentId: area.parentId,
  54. name: area.name,
  55. level: area.level,
  56. code: area.code,
  57. isDisabled: area.isDisabled,
  58. } : {
  59. tenantId: 1, // 测试环境使用默认tenantId
  60. parentId: smartParentId || null,
  61. name: '',
  62. level: smartLevel ?? AreaLevel.PROVINCE,
  63. code: '',
  64. isDisabled: DisabledStatus.ENABLED,
  65. },
  66. });
  67. const handleSubmit = async (data: CreateAreaInputMt | UpdateAreaInputMt) => {
  68. await onSubmit(data);
  69. };
  70. return (
  71. <Form {...form}>
  72. <form onSubmit={form.handleSubmit(handleSubmit)} className="space-y-6">
  73. <div className="grid grid-cols-1 gap-6">
  74. {/* 层级显示(只读) */}
  75. <FormField
  76. control={form.control}
  77. name="level"
  78. render={({ field }) => (
  79. <FormItem>
  80. <FormLabel>层级</FormLabel>
  81. <FormControl>
  82. <Input
  83. value={getLevelDisplayName(field.value)}
  84. disabled
  85. className="bg-muted"
  86. />
  87. </FormControl>
  88. <FormDescription>
  89. 根据操作上下文自动设置的层级
  90. </FormDescription>
  91. <FormMessage />
  92. </FormItem>
  93. )}
  94. />
  95. {/* 父级区域显示(只读) */}
  96. <FormField
  97. control={form.control}
  98. name="parentId"
  99. render={({ field }) => (
  100. <FormItem>
  101. <FormLabel>父级区域</FormLabel>
  102. <FormControl>
  103. <Input
  104. type="number"
  105. value={field.value || ''}
  106. disabled
  107. className="bg-muted"
  108. placeholder="顶级区域(无父级)"
  109. />
  110. </FormControl>
  111. <FormDescription>
  112. 根据操作上下文自动设置的父级区域ID
  113. </FormDescription>
  114. <FormMessage />
  115. </FormItem>
  116. )}
  117. />
  118. {/* 区域名称 */}
  119. <FormField
  120. control={form.control}
  121. name="name"
  122. render={({ field }) => (
  123. <FormItem>
  124. <FormLabel>区域名称</FormLabel>
  125. <FormControl>
  126. <Input
  127. placeholder="输入区域名称"
  128. {...field}
  129. />
  130. </FormControl>
  131. <FormDescription>
  132. 输入省市区名称,如:北京市、上海市、朝阳区等
  133. </FormDescription>
  134. <FormMessage />
  135. </FormItem>
  136. )}
  137. />
  138. {/* 行政区划代码 */}
  139. <FormField
  140. control={form.control}
  141. name="code"
  142. render={({ field }) => (
  143. <FormItem>
  144. <FormLabel>行政区划代码</FormLabel>
  145. <FormControl>
  146. <Input
  147. placeholder="输入行政区划代码"
  148. {...field}
  149. />
  150. </FormControl>
  151. <FormDescription>
  152. 输入标准的行政区划代码
  153. </FormDescription>
  154. <FormMessage />
  155. </FormItem>
  156. )}
  157. />
  158. {/* 状态选择 */}
  159. <FormField
  160. control={form.control}
  161. name="isDisabled"
  162. render={({ field }) => (
  163. <FormItem>
  164. <FormLabel>状态</FormLabel>
  165. <Select onValueChange={(value) => field.onChange(Number(value))} defaultValue={field.value?.toString()}>
  166. <FormControl>
  167. <SelectTrigger>
  168. <SelectValue placeholder="选择状态" />
  169. </SelectTrigger>
  170. </FormControl>
  171. <SelectContent>
  172. <SelectItem value={DisabledStatus.ENABLED.toString()}>
  173. 启用
  174. </SelectItem>
  175. <SelectItem value={DisabledStatus.DISABLED.toString()}>
  176. 禁用
  177. </SelectItem>
  178. </SelectContent>
  179. </Select>
  180. <FormDescription>
  181. 选择省市区状态
  182. </FormDescription>
  183. <FormMessage />
  184. </FormItem>
  185. )}
  186. />
  187. </div>
  188. {/* 表单操作按钮 */}
  189. <div className="flex justify-end gap-4">
  190. <Button
  191. type="button"
  192. variant="outline"
  193. onClick={onCancel}
  194. disabled={isLoading}
  195. >
  196. 取消
  197. </Button>
  198. <Button
  199. type="submit"
  200. disabled={isLoading}
  201. >
  202. {isLoading ? '提交中...' : isEditing ? '更新' : '创建'}
  203. </Button>
  204. </div>
  205. </form>
  206. </Form>
  207. );
  208. };