|
|
@@ -0,0 +1,2095 @@
|
|
|
+**User:**
|
|
|
+
|
|
|
+<task>Command 'shadcn-manage-page' (see below for command content) Command 'file-relation' (see below for command content) Command 'generic-crud' (see below for command content) docs/旧数据表.sql
|
|
|
+其中 广告,广告类别 已完成
|
|
|
+</task>
|
|
|
+
|
|
|
+<command name="shadcn-manage-page">
|
|
|
+Description: Shadcn-ui 管理页开发指令
|
|
|
+
|
|
|
+## 概述
|
|
|
+基于 `src/client/admin-shadcn/pages/Users.tsx` 中用户管理页的实现,提取可复用的开发模式和最佳实践,适用于基于 Shadcn-ui 的管理后台页面开发。
|
|
|
+
|
|
|
+## 页面结构规范
|
|
|
+
|
|
|
+### 1. 文件位置
|
|
|
+- **管理后台页面**: `src/client/admin-shadcn/pages/[EntityName].tsx`
|
|
|
+
|
|
|
+### 2. 页面组件结构
|
|
|
+```typescript
|
|
|
+// 1. 类型导入和定义
|
|
|
+type CreateRequest = InferRequestType<typeof client.$post>['json'];
|
|
|
+type UpdateRequest = InferRequestType<typeof client[':id']['$put']>['json'];
|
|
|
+type EntityResponse = InferResponseType<typeof client.$get, 200>['data'][0];
|
|
|
+
|
|
|
+// 2. 表单Schema直接使用后端定义
|
|
|
+const createFormSchema = CreateEntityDto;
|
|
|
+const updateFormSchema = UpdateEntityDto;
|
|
|
+
|
|
|
+// 3. 主页面组件
|
|
|
+export const EntityPage = () => {
|
|
|
+ // 状态管理
|
|
|
+ const [searchParams, setSearchParams] = useState({ page: 1, limit: 10, search: '' });
|
|
|
+ const [isModalOpen, setIsModalOpen] = useState(false);
|
|
|
+ const [editingEntity, setEditingEntity] = useState<any>(null);
|
|
|
+ const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
|
|
|
+ const [entityToDelete, setEntityToDelete] = useState<number | null>(null);
|
|
|
+
|
|
|
+ // 表单实例
|
|
|
+ const createForm = useForm<CreateRequest>({...});
|
|
|
+ const updateForm = useForm<UpdateRequest>({...});
|
|
|
+
|
|
|
+ // 数据查询
|
|
|
+ const { data, isLoading, refetch } = useQuery({...});
|
|
|
+
|
|
|
+ // 业务逻辑函数
|
|
|
+ const handleSearch = () => {...};
|
|
|
+ const handleCreateEntity = () => {...};
|
|
|
+ const handleEditEntity = () => {...};
|
|
|
+ const handleDeleteEntity = () => {...};
|
|
|
+
|
|
|
+ // 渲染
|
|
|
+ return (...);
|
|
|
+};
|
|
|
+```
|
|
|
+
|
|
|
+## 核心开发模式
|
|
|
+
|
|
|
+### 1. 类型驱动的开发
|
|
|
+- **RPC类型提取**: 使用 `InferRequestType` 和 `InferResponseType` 从后端API自动提取类型
|
|
|
+- **Schema复用**: 直接使用后端定义的Zod Schema作为表单验证
|
|
|
+- **类型安全**: 所有API调用都有完整的TypeScript类型支持
|
|
|
+
|
|
|
+### 2. 状态管理模式
|
|
|
+```typescript
|
|
|
+// 分页和搜索参数
|
|
|
+const [searchParams, setSearchParams] = useState({
|
|
|
+ page: 1,
|
|
|
+ limit: 10,
|
|
|
+ search: '',
|
|
|
+ // 其他筛选条件...
|
|
|
+});
|
|
|
+
|
|
|
+// 模态框状态
|
|
|
+const [isModalOpen, setIsModalOpen] = useState(false);
|
|
|
+const [editingEntity, setEditingEntity] = useState<any>(null);
|
|
|
+const [isCreateForm, setIsCreateForm] = useState(true);
|
|
|
+```
|
|
|
+
|
|
|
+### 3. 数据获取模式
|
|
|
+```typescript
|
|
|
+const { data, isLoading, refetch } = useQuery({
|
|
|
+ queryKey: ['entities', searchParams],
|
|
|
+ queryFn: async () => {
|
|
|
+ const res = await entityClient.$get({
|
|
|
+ query: {
|
|
|
+ page: searchParams.page,
|
|
|
+ pageSize: searchParams.limit,
|
|
|
+ keyword: searchParams.search,
|
|
|
+ // 其他查询参数...
|
|
|
+ }
|
|
|
+ });
|
|
|
+ if (res.status !== 200) throw new Error('获取列表失败');
|
|
|
+ return await res.json();
|
|
|
+ }
|
|
|
+});
|
|
|
+```
|
|
|
+
|
|
|
+## 页面布局规范
|
|
|
+
|
|
|
+### 1. 页面标题区域
|
|
|
+```tsx
|
|
|
+<div className="flex justify-between items-center">
|
|
|
+ <h1 className="text-2xl font-bold">页面标题</h1>
|
|
|
+ <Button onClick={handleCreateEntity}>
|
|
|
+ <Plus className="mr-2 h-4 w-4" />
|
|
|
+ 创建实体
|
|
|
+ </Button>
|
|
|
+</div>
|
|
|
+```
|
|
|
+
|
|
|
+### 2. 搜索区域
|
|
|
+```tsx
|
|
|
+<Card>
|
|
|
+ <CardHeader>
|
|
|
+ <CardTitle>列表标题</CardTitle>
|
|
|
+ <CardDescription>列表描述信息</CardDescription>
|
|
|
+ </CardHeader>
|
|
|
+ <CardContent>
|
|
|
+ <div className="mb-4">
|
|
|
+ <form onSubmit={handleSearch} className="flex gap-2">
|
|
|
+ <div className="relative flex-1 max-w-sm">
|
|
|
+ <Search className="absolute left-2 top-2.5 h-4 w-4 text-muted-foreground" />
|
|
|
+ <Input
|
|
|
+ placeholder="搜索提示..."
|
|
|
+ value={searchParams.search}
|
|
|
+ onChange={(e) => setSearchParams(prev => ({ ...prev, search: e.target.value }))}
|
|
|
+ className="pl-8"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <Button type="submit" variant="outline">
|
|
|
+ 搜索
|
|
|
+ </Button>
|
|
|
+ </form>
|
|
|
+ </div>
|
|
|
+ </CardContent>
|
|
|
+</Card>
|
|
|
+```
|
|
|
+
|
|
|
+### 3. 数据表格
|
|
|
+```tsx
|
|
|
+<div className="rounded-md border">
|
|
|
+ <Table>
|
|
|
+ <TableHeader>
|
|
|
+ <TableRow>
|
|
|
+ <TableHead>列标题1</TableHead>
|
|
|
+ <TableHead>列标题2</TableHead>
|
|
|
+ <TableHead className="text-right">操作</TableHead>
|
|
|
+ </TableRow>
|
|
|
+ </TableHeader>
|
|
|
+ <TableBody>
|
|
|
+ {data.map((item) => (
|
|
|
+ <TableRow key={item.id}>
|
|
|
+ <TableCell>{item.field1}</TableCell>
|
|
|
+ <TableCell>{item.field2}</TableCell>
|
|
|
+ <TableCell className="text-right">
|
|
|
+ <div className="flex justify-end gap-2">
|
|
|
+ <Button variant="ghost" size="icon" onClick={() => handleEdit(item)}>
|
|
|
+ <Edit className="h-4 w-4" />
|
|
|
+ </Button>
|
|
|
+ <Button variant="ghost" size="icon" onClick={() => handleDelete(item.id)}>
|
|
|
+ <Trash2 className="h-4 w-4" />
|
|
|
+ </Button>
|
|
|
+ </div>
|
|
|
+ </TableCell>
|
|
|
+ </TableRow>
|
|
|
+ ))}
|
|
|
+ </TableBody>
|
|
|
+ </Table>
|
|
|
+</div>
|
|
|
+```
|
|
|
+
|
|
|
+## 表单开发模式
|
|
|
+
|
|
|
+### 1. 表单组件结构
|
|
|
+```typescript
|
|
|
+// 创建表单
|
|
|
+const createForm = useForm<CreateRequest>({
|
|
|
+ resolver: zodResolver(createFormSchema),
|
|
|
+ defaultValues: {
|
|
|
+ // 默认值设置
|
|
|
+ },
|
|
|
+});
|
|
|
+
|
|
|
+// 更新表单
|
|
|
+const updateForm = useForm<UpdateRequest>({
|
|
|
+ resolver: zodResolver(updateFormSchema),
|
|
|
+ defaultValues: {
|
|
|
+ // 更新时默认值
|
|
|
+ },
|
|
|
+});
|
|
|
+```
|
|
|
+
|
|
|
+### 2. 模态框表单(创建/编辑分离模式)
|
|
|
+```tsx
|
|
|
+<Dialog open={isModalOpen} onOpenChange={setIsModalOpen}>
|
|
|
+ <DialogContent className="sm:max-w-[500px] max-h-[90vh] overflow-y-auto">
|
|
|
+ <DialogHeader>
|
|
|
+ <DialogTitle>{isCreateForm ? '创建实体' : '编辑实体'}</DialogTitle>
|
|
|
+ <DialogDescription>
|
|
|
+ {isCreateForm ? '创建一个新的实体' : '编辑现有实体信息'}
|
|
|
+ </DialogDescription>
|
|
|
+ </DialogHeader>
|
|
|
+
|
|
|
+ {isCreateForm ? (
|
|
|
+ // 创建表单
|
|
|
+ <Form {...createForm}>
|
|
|
+ <form onSubmit={createForm.handleSubmit(handleCreateSubmit)} className="space-y-4">
|
|
|
+ {/* 创建专用字段 */}
|
|
|
+ <DialogFooter>
|
|
|
+ <Button type="button" variant="outline" onClick={() => setIsModalOpen(false)}>
|
|
|
+ 取消
|
|
|
+ </Button>
|
|
|
+ <Button type="submit">创建</Button>
|
|
|
+ </DialogFooter>
|
|
|
+ </form>
|
|
|
+ </Form>
|
|
|
+ ) : (
|
|
|
+ // 编辑表单
|
|
|
+ <Form {...updateForm}>
|
|
|
+ <form onSubmit={updateForm.handleSubmit(handleUpdateSubmit)} className="space-y-4">
|
|
|
+ {/* 编辑专用字段 */}
|
|
|
+ <DialogFooter>
|
|
|
+ <Button type="button" variant="outline" onClick={() => setIsModalOpen(false)}>
|
|
|
+ 取消
|
|
|
+ </Button>
|
|
|
+ <Button type="submit">更新</Button>
|
|
|
+ </DialogFooter>
|
|
|
+ </form>
|
|
|
+ </Form>
|
|
|
+ )}
|
|
|
+ </DialogContent>
|
|
|
+</Dialog>
|
|
|
+```
|
|
|
+
|
|
|
+### 3. 表单字段模式
|
|
|
+```tsx
|
|
|
+<FormField
|
|
|
+ control={form.control}
|
|
|
+ name="fieldName"
|
|
|
+ render={({ field }) => (
|
|
|
+ <FormItem>
|
|
|
+ <FormLabel className="flex items-center">
|
|
|
+ 字段标签
|
|
|
+ {isRequired && <span className="text-red-500 ml-1">*</span>}
|
|
|
+ </FormLabel>
|
|
|
+ <FormControl>
|
|
|
+ <Input placeholder="请输入..." {...field} />
|
|
|
+ </FormControl>
|
|
|
+ <FormDescription>字段描述信息</FormDescription>
|
|
|
+ <FormMessage />
|
|
|
+ </FormItem>
|
|
|
+ )}
|
|
|
+/>
|
|
|
+```
|
|
|
+
|
|
|
+## 图片上传集成
|
|
|
+
|
|
|
+### 1. AvatarSelector组件使用
|
|
|
+```tsx
|
|
|
+<FormField
|
|
|
+ control={form.control}
|
|
|
+ name="avatarFileId"
|
|
|
+ render={({ field }) => (
|
|
|
+ <FormItem>
|
|
|
+ <FormLabel>头像</FormLabel>
|
|
|
+ <FormControl>
|
|
|
+ <AvatarSelector
|
|
|
+ value={field.value || undefined}
|
|
|
+ onChange={(value) => field.onChange(value)}
|
|
|
+ maxSize={2} // MB
|
|
|
+ uploadPath="/avatars"
|
|
|
+ uploadButtonText="上传头像"
|
|
|
+ previewSize="medium"
|
|
|
+ placeholder="选择头像"
|
|
|
+ />
|
|
|
+ </FormControl>
|
|
|
+ <FormMessage />
|
|
|
+ </FormItem>
|
|
|
+ )}
|
|
|
+/>
|
|
|
+```
|
|
|
+
|
|
|
+## 状态管理最佳实践
|
|
|
+
|
|
|
+### 1. 状态提升策略
|
|
|
+- **表单状态**: 使用React Hook Form管理
|
|
|
+- **UI状态**: 使用useState管理模态框、加载状态等
|
|
|
+- **服务器状态**: 使用React Query管理数据获取和缓存
|
|
|
+
|
|
|
+### 2. 数据刷新策略
|
|
|
+```typescript
|
|
|
+// 操作成功后刷新数据
|
|
|
+const handleCreateSubmit = async (data: CreateRequest) => {
|
|
|
+ try {
|
|
|
+ const res = await entityClient.$post({ json: data });
|
|
|
+ if (res.status !== 201) throw new Error('创建失败');
|
|
|
+ toast.success('创建成功');
|
|
|
+ setIsModalOpen(false);
|
|
|
+ refetch(); // 刷新数据
|
|
|
+ } catch (error) {
|
|
|
+ toast.error('操作失败,请重试');
|
|
|
+ }
|
|
|
+};
|
|
|
+```
|
|
|
+
|
|
|
+## 加载状态处理
|
|
|
+
|
|
|
+### 1. 骨架屏模式
|
|
|
+```tsx
|
|
|
+if (isLoading) {
|
|
|
+ return (
|
|
|
+ <div className="space-y-4">
|
|
|
+ <div className="flex justify-between items-center">
|
|
|
+ <h1 className="text-2xl font-bold">页面标题</h1>
|
|
|
+ <Button disabled>
|
|
|
+ <Plus className="mr-2 h-4 w-4" />
|
|
|
+ 创建实体
|
|
|
+ </Button>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <Card>
|
|
|
+ <CardHeader>
|
|
|
+ <Skeleton className="h-6 w-1/4" />
|
|
|
+ </CardHeader>
|
|
|
+ <CardContent>
|
|
|
+ <div className="space-y-2">
|
|
|
+ <Skeleton className="h-4 w-full" />
|
|
|
+ <Skeleton className="h-4 w-full" />
|
|
|
+ <Skeleton className="h-4 w-full" />
|
|
|
+ </div>
|
|
|
+ </CardContent>
|
|
|
+ </Card>
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 2. 空数据状态
|
|
|
+```tsx
|
|
|
+{users.length === 0 && !isLoading && (
|
|
|
+ <div className="text-center py-8">
|
|
|
+ <p className="text-muted-foreground">暂无数据</p>
|
|
|
+ </div>
|
|
|
+)}
|
|
|
+```
|
|
|
+
|
|
|
+## 错误处理模式
|
|
|
+
|
|
|
+### 1. API错误处理
|
|
|
+```typescript
|
|
|
+try {
|
|
|
+ const res = await entityClient.$post({ json: data });
|
|
|
+ if (res.status !== 201) throw new Error('操作失败');
|
|
|
+ toast.success('操作成功');
|
|
|
+} catch (error) {
|
|
|
+ console.error('操作失败:', error);
|
|
|
+ toast.error('操作失败,请重试');
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 2. 删除确认模式
|
|
|
+```tsx
|
|
|
+const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
|
|
|
+const [entityToDelete, setEntityToDelete] = useState<number | null>(null);
|
|
|
+
|
|
|
+// 删除确认对话框
|
|
|
+<Dialog open={deleteDialogOpen} onOpenChange={setDeleteDialogOpen}>
|
|
|
+ <DialogContent>
|
|
|
+ <DialogHeader>
|
|
|
+ <DialogTitle>确认删除</DialogTitle>
|
|
|
+ <DialogDescription>
|
|
|
+ 确定要删除这个实体吗?此操作无法撤销。
|
|
|
+ </DialogDescription>
|
|
|
+ </DialogHeader>
|
|
|
+ <DialogFooter>
|
|
|
+ <Button variant="outline" onClick={() => setDeleteDialogOpen(false)}>
|
|
|
+ 取消
|
|
|
+ </Button>
|
|
|
+ <Button variant="destructive" onClick={confirmDelete}>
|
|
|
+ 删除
|
|
|
+ </Button>
|
|
|
+ </DialogFooter>
|
|
|
+ </DialogContent>
|
|
|
+</Dialog>
|
|
|
+```
|
|
|
+
|
|
|
+## 样式规范
|
|
|
+
|
|
|
+### 1. 间距系统
|
|
|
+- 页面标题区域: `space-y-4`
|
|
|
+- 卡片内容: `space-y-4`
|
|
|
+- 表单字段: `space-y-4`
|
|
|
+- 按钮组: `gap-2`
|
|
|
+
|
|
|
+### 2. 响应式设计
|
|
|
+- 模态框最大宽度: `sm:max-w-[500px]`
|
|
|
+- 模态框最大高度: `max-h-[90vh]`
|
|
|
+- 搜索输入框: `max-w-sm`
|
|
|
+
|
|
|
+### 3. 视觉层次
|
|
|
+- 标题: `text-2xl font-bold`
|
|
|
+- 卡片标题: `text-lg font-semibold`
|
|
|
+- 描述文字: `text-sm text-muted-foreground`
|
|
|
+
|
|
|
+## 开发流程
|
|
|
+
|
|
|
+### 1. 创建新管理页面
|
|
|
+1. 复制 `Users.tsx` 作为模板
|
|
|
+2. 替换以下部分:
|
|
|
+ - API客户端导入
|
|
|
+ - 类型定义
|
|
|
+ - 表单Schema引用
|
|
|
+ - 页面标题和描述
|
|
|
+ - 表格列定义
|
|
|
+ - 表单字段定义
|
|
|
+3. 根据业务需求调整字段和逻辑
|
|
|
+
|
|
|
+### 2. 字段映射规范
|
|
|
+- **文本字段**: 使用 `Input`
|
|
|
+- **长文本**: 使用 `Textarea`
|
|
|
+- **选择字段**: 使用 `Select`
|
|
|
+- **开关字段**: 使用 `Switch`
|
|
|
+- **日期字段**: 使用 `DatePicker`
|
|
|
+- **图片字段**: 使用 `AvatarSelector`
|
|
|
+
|
|
|
+### 3. 业务逻辑复用
|
|
|
+- 保持相同的CRUD操作模式
|
|
|
+- 复用分页、搜索、排序逻辑
|
|
|
+- 统一的状态管理模式
|
|
|
+- 一致的表单验证和错误处理
|
|
|
+</command>
|
|
|
+
|
|
|
+<command name="file-relation">
|
|
|
+Description: 实体与文件关联开发指令 - 指导如何在实体中添加文件关联字段
|
|
|
+
|
|
|
+# 实体与文件关联开发指令
|
|
|
+
|
|
|
+## 概述
|
|
|
+本指令指导如何在实体中添加与文件管理系统的关联关系,基于用户实体(UserEntity)的最佳实践。
|
|
|
+
|
|
|
+## 文件关联标准实现
|
|
|
+
|
|
|
+### 1. 实体定义规范
|
|
|
+
|
|
|
+在实体类中添加文件关联字段:
|
|
|
+
|
|
|
+```typescript
|
|
|
+// 1. 导入文件实体
|
|
|
+import { File } from '@/server/modules/files/file.entity';
|
|
|
+
|
|
|
+// 2. 在实体类中添加字段
|
|
|
+@Column({
|
|
|
+ name: '{field_prefix}_file_id',
|
|
|
+ type: 'int',
|
|
|
+ unsigned: true,
|
|
|
+ nullable: true,
|
|
|
+ comment: '{描述}文件ID'
|
|
|
+})
|
|
|
+{fieldPrefix}FileId!: number | null;
|
|
|
+
|
|
|
+@ManyToOne(() => File, { nullable: true })
|
|
|
+@JoinColumn({
|
|
|
+ name: '{field_prefix}_file_id',
|
|
|
+ referencedColumnName: 'id'
|
|
|
+})
|
|
|
+{fieldPrefix}File!: File | null;
|
|
|
+```
|
|
|
+
|
|
|
+### 2. Schema定义规范
|
|
|
+
|
|
|
+在实体的schema文件中添加文件关联字段:
|
|
|
+
|
|
|
+```typescript
|
|
|
+// 基础字段定义
|
|
|
+{fieldPrefix}FileId: z.number()
|
|
|
+ .int()
|
|
|
+ .positive()
|
|
|
+ .nullable()
|
|
|
+ .openapi({
|
|
|
+ example: 1,
|
|
|
+ description: '{描述}文件ID'
|
|
|
+ }),
|
|
|
+
|
|
|
+// 关联文件对象(用于响应)
|
|
|
+{fieldPrefix}File: z.object({
|
|
|
+ id: z.number().int().positive().openapi({ description: '文件ID' }),
|
|
|
+ name: z.string().max(255).openapi({ description: '文件名', example: 'example.jpg' }),
|
|
|
+ fullUrl: z.string().openapi({ description: '文件完整URL', example: 'https://example.com/file.jpg' }),
|
|
|
+ type: z.string().nullable().openapi({ description: '文件类型', example: 'image/jpeg' }),
|
|
|
+ size: z.number().nullable().openapi({ description: '文件大小(字节)', example: 102400 })
|
|
|
+}).nullable().optional().openapi({
|
|
|
+ description: '{描述}文件信息'
|
|
|
+}),
|
|
|
+```
|
|
|
+
|
|
|
+### 3. 命名规范
|
|
|
+
|
|
|
+| 类型 | 命名格式 | 示例 |
|
|
|
+|------|----------|------|
|
|
|
+| 数据库字段 | `{前缀}_file_id` | `avatar_file_id` |
|
|
|
+| 实体字段 | `{前缀}FileId` | `avatarFileId` |
|
|
|
+| 关联实体 | `{前缀}File` | `avatarFile` |
|
|
|
+| 描述注释 | `{描述}文件ID` | `头像文件ID` |
|
|
|
+
|
|
|
+### 4. 完整示例 - 基于用户实体
|
|
|
+
|
|
|
+**实体类** ([`src/server/modules/users/user.entity.ts`](src/server/modules/users/user.entity.ts:29-34)):
|
|
|
+```typescript
|
|
|
+@Column({ name: 'avatar_file_id', type: 'int', unsigned: true, nullable: true, comment: '头像文件ID' })
|
|
|
+avatarFileId!: number | null;
|
|
|
+
|
|
|
+@ManyToOne(() => File, { nullable: true })
|
|
|
+@JoinColumn({ name: 'avatar_file_id', referencedColumnName: 'id' })
|
|
|
+avatarFile!: File | null;
|
|
|
+```
|
|
|
+
|
|
|
+**Schema定义** ([`src/server/modules/users/user.schema.ts`](src/server/modules/users/user.schema.ts:33-45)):
|
|
|
+```typescript
|
|
|
+avatarFileId: z.number().int().positive().nullable().openapi({
|
|
|
+ example: 1,
|
|
|
+ description: '头像文件ID'
|
|
|
+}),
|
|
|
+avatarFile: z.object({
|
|
|
+ id: z.number().int().positive().openapi({ description: '文件ID' }),
|
|
|
+ name: z.string().max(255).openapi({ description: '文件名', example: 'avatar.jpg' }),
|
|
|
+ fullUrl: z.string().openapi({ description: '文件完整URL', example: 'https://example.com/avatar.jpg' }),
|
|
|
+ type: z.string().nullable().openapi({ description: '文件类型', example: 'image/jpeg' }),
|
|
|
+ size: z.number().nullable().openapi({ description: '文件大小(字节)', example: 102400 })
|
|
|
+}).nullable().optional().openapi({
|
|
|
+ description: '头像文件信息'
|
|
|
+}),
|
|
|
+```
|
|
|
+
|
|
|
+## 使用步骤
|
|
|
+
|
|
|
+### 步骤1: 添加实体字段
|
|
|
+1. 在实体类中添加 `{prefix}FileId` 和 `{prefix}File` 字段
|
|
|
+2. 使用 `@ManyToOne` 关联 `File` 实体
|
|
|
+3. 配置 `@JoinColumn` 指定外键字段名
|
|
|
+
|
|
|
+### 步骤2: 添加Schema定义
|
|
|
+1. 在 `Create{Entity}Dto` 中添加 `{prefix}FileId` 字段
|
|
|
+2. 在 `Update{Entity}Dto` 中添加可选的 `{prefix}FileId` 字段
|
|
|
+3. 在实体Schema中添加 `{prefix}File` 对象用于响应
|
|
|
+
|
|
|
+### 步骤3: 数据库迁移
|
|
|
+确保数据库表包含 `{prefix}_file_id` 字段,类型为 INT UNSIGNED NULL
|
|
|
+
|
|
|
+## 使用场景
|
|
|
+
|
|
|
+### 场景1: 单文件关联
|
|
|
+适用于实体只需要关联单个文件的情况,如:
|
|
|
+- 用户头像
|
|
|
+- 商品封面图
|
|
|
+- 文档附件
|
|
|
+
|
|
|
+### 场景2: 多文件关联
|
|
|
+如需关联多个文件,请使用 ManyToMany 关联,参考广告实体的实现。
|
|
|
+
|
|
|
+## 注意事项
|
|
|
+
|
|
|
+1. **空值处理**: 字段必须支持 `null`,允许无文件关联
|
|
|
+2. **级联操作**: 默认不级联,删除文件不会影响关联实体
|
|
|
+3. **文件验证**: 前端需先上传文件获取文件ID,再进行实体关联
|
|
|
+4. **类型安全**: 确保所有字段类型定义一致(number | null)
|
|
|
+
|
|
|
+## 扩展说明
|
|
|
+
|
|
|
+此标准基于用户实体的头像文件关联实现,适用于项目中所有需要文件关联的实体。后续实体按此标准实现即可保持统一性。
|
|
|
+</command>
|
|
|
+
|
|
|
+<command name="generic-crud">
|
|
|
+Description: 通用curd开发指令
|
|
|
+
|
|
|
+按通用curd开发规范开发
|
|
|
+
|
|
|
+创建实体类 your-entity.entity.ts
|
|
|
+创建实体Zod Schema定义 your-entity.schema.ts
|
|
|
+注册实体到数据源
|
|
|
+创建服务类继承GenericCrudService
|
|
|
+创建通用CRUD路由
|
|
|
+注册路由到API
|
|
|
+创建客户端API调用方法
|
|
|
+创建管理后台页面,按照 .roo/commands/shadcn-manage-form.md 指令规范
|
|
|
+注册路由和菜单
|
|
|
+</command>
|
|
|
+<environment_details>
|
|
|
+# VSCode Visible Files
|
|
|
+docs/旧数据表.sql
|
|
|
+
|
|
|
+# VSCode Open Tabs
|
|
|
+docs/旧数据表.sql
|
|
|
+
|
|
|
+# Current Time
|
|
|
+Current time in ISO 8601 UTC format: 2025-08-13T03:09:12.332Z
|
|
|
+User time zone: UTC, UTC+0:00
|
|
|
+
|
|
|
+# Current Cost
|
|
|
+$0.00
|
|
|
+
|
|
|
+# Current Mode
|
|
|
+<slug>code</slug>
|
|
|
+<name>💻 代码</name>
|
|
|
+<model>d8d-ai-model</model>
|
|
|
+
|
|
|
+
|
|
|
+# Current Workspace Directory (/mnt/code/161-145-template-10) Files
|
|
|
+.gitignore
|
|
|
+.npmrc
|
|
|
+🔒 .rooignore
|
|
|
+components.json
|
|
|
+docker-compose.yml
|
|
|
+Dockerfile.release
|
|
|
+Dockerfile.test
|
|
|
+index.html
|
|
|
+🔒 .gitea/
|
|
|
+.roo/
|
|
|
+docs/
|
|
|
+docs/mini-code-login.md
|
|
|
+docs/tailwind-merge.md
|
|
|
+docs/旧数据表.sql
|
|
|
+mini/
|
|
|
+mini/.husky/
|
|
|
+mini/config/
|
|
|
+mini/src/
|
|
|
+mini/src/components/
|
|
|
+mini/src/components/ui/
|
|
|
+mini/src/layouts/
|
|
|
+mini/src/pages/
|
|
|
+mini/src/pages/explore/
|
|
|
+mini/src/pages/index/
|
|
|
+mini/src/pages/login/
|
|
|
+mini/src/pages/profile/
|
|
|
+mini/src/pages/register/
|
|
|
+mini/src/schemas/
|
|
|
+mini/src/utils/
|
|
|
+mini/types/
|
|
|
+mini-starter/
|
|
|
+mini-starter/package.json
|
|
|
+mini-starter/pnpm-lock.yaml
|
|
|
+mini-starter/server.js
|
|
|
+🔒 mini-starter/.gitea/
|
|
|
+mini-starter/.roo/
|
|
|
+mini-starter/docs/
|
|
|
+mini-starter/docs/前台页面/
|
|
|
+mini-starter/docs/后台服务/
|
|
|
+mini-starter/docs/小程序/
|
|
|
+mini-starter/docs/旧代码/
|
|
|
+mini-starter/mini/
|
|
|
+mini-starter/mini/stylelint.config.mjs
|
|
|
+mini-starter/mini/tailwind.config.js
|
|
|
+mini-starter/mini/tsconfig.json
|
|
|
+mini-starter/mini/.husky/
|
|
|
+mini-starter/mini/config/
|
|
|
+mini-starter/mini/src/
|
|
|
+mini-starter/mini/src/components/
|
|
|
+mini-starter/mini/src/components/ui/
|
|
|
+mini-starter/mini/src/layouts/
|
|
|
+mini-starter/mini/src/pages/
|
|
|
+mini-starter/mini/src/pages/duihuan/
|
|
|
+mini-starter/mini/src/pages/explore/
|
|
|
+mini-starter/mini/src/pages/index/
|
|
|
+mini-starter/mini/src/pages/login/
|
|
|
+mini-starter/mini/src/pages/profile/
|
|
|
+mini-starter/mini/src/pages/register/
|
|
|
+mini-starter/mini/src/schemas/
|
|
|
+mini-starter/mini/src/utils/
|
|
|
+mini-starter/mini/types/
|
|
|
+mini-starter/public/
|
|
|
+mini-starter/public/vite.svg
|
|
|
+🔒 mini-starter/scripts/
|
|
|
+🔒 mini-starter/scripts/release_tag.sh
|
|
|
+mini-starter/src/
|
|
|
+mini-starter/src/assets/
|
|
|
+mini-starter/src/assets/react.svg
|
|
|
+mini-starter/src/client/
|
|
|
+mini-starter/src/client/api.ts
|
|
|
+mini-starter/src/client/index.tsx
|
|
|
+mini-starter/src/client/admin-shadcn/
|
|
|
+mini-starter/src/client/admin-shadcn/routes.tsx
|
|
|
+mini-starter/src/client/admin-shadcn/components/
|
|
|
+mini-starter/src/client/admin-shadcn/hooks/
|
|
|
+mini-starter/src/client/admin-shadcn/layouts/
|
|
|
+mini-starter/src/client/admin-shadcn/pages/
|
|
|
+mini-starter/src/client/admin-shadcn/pages/Advertisements.tsx
|
|
|
+mini-starter/src/client/admin-shadcn/pages/CouponLogs.tsx
|
|
|
+mini-starter/src/client/admin-shadcn/pages/Dashboard.tsx
|
|
|
+mini-starter/src/client/admin-shadcn/pages/Files.tsx
|
|
|
+mini-starter/src/client/admin-shadcn/pages/Login.tsx
|
|
|
+mini-starter/src/client/admin-shadcn/pages/RedemptionCodes.tsx
|
|
|
+mini-starter/src/client/admin-shadcn/pages/Users.tsx
|
|
|
+mini-starter/src/client/admin-shadcn/pages/WechatCoupons.tsx
|
|
|
+mini-starter/src/client/admin-shadcn/pages/WechatCouponStocks.tsx
|
|
|
+mini-starter/src/client/admin-shadcn/pages/WechatPayConfig.tsx
|
|
|
+mini-starter/src/client/components/
|
|
|
+mini-starter/src/client/components/ui/
|
|
|
+mini-starter/src/client/components/ui/slider.tsx
|
|
|
+mini-starter/src/client/components/ui/sonner.tsx
|
|
|
+mini-starter/src/client/components/ui/switch.tsx
|
|
|
+mini-starter/src/client/components/ui/table.tsx
|
|
|
+mini-starter/src/client/components/ui/tabs.tsx
|
|
|
+mini-starter/src/client/components/ui/textarea.tsx
|
|
|
+mini-starter/src/client/components/ui/toggle-group.tsx
|
|
|
+mini-starter/src/client/components/ui/toggle.tsx
|
|
|
+mini-starter/src/client/components/ui/tooltip.tsx
|
|
|
+mini-starter/src/client/home-shadcn/
|
|
|
+mini-starter/src/client/home-shadcn/routes.tsx
|
|
|
+mini-starter/src/client/home-shadcn/components/
|
|
|
+mini-starter/src/client/home-shadcn/hooks/
|
|
|
+mini-starter/src/client/home-shadcn/layouts/
|
|
|
+mini-starter/src/client/home-shadcn/pages/
|
|
|
+mini-starter/src/client/home-shadcn/pages/HomePage.tsx
|
|
|
+mini-starter/src/client/home-shadcn/pages/LoginPage.tsx
|
|
|
+mini-starter/src/client/home-shadcn/pages/MemberPage.tsx
|
|
|
+mini-starter/src/client/home-shadcn/pages/RegisterPage.tsx
|
|
|
+mini-starter/src/client/hooks/
|
|
|
+mini-starter/src/client/hooks/use-mobile.ts
|
|
|
+mini-starter/src/client/lib/
|
|
|
+mini-starter/src/client/lib/utils.ts
|
|
|
+mini-starter/src/client/utils/
|
|
|
+mini-starter/src/client/utils/axios-fetch.ts
|
|
|
+mini-starter/src/client/utils/ClientOnly.tsx
|
|
|
+mini-starter/src/client/utils/logger.ts
|
|
|
+mini-starter/src/server/
|
|
|
+mini-starter/src/server/api/
|
|
|
+mini-starter/src/server/api/advertisements/
|
|
|
+mini-starter/src/server/api/auth/
|
|
|
+mini-starter/src/server/api/auth/login/
|
|
|
+mini-starter/src/server/api/auth/me/
|
|
|
+mini-starter/src/server/api/auth/mini-login/
|
|
|
+mini-starter/src/server/api/auth/register/
|
|
|
+mini-starter/src/server/api/coupon-logs/
|
|
|
+mini-starter/src/server/api/files/
|
|
|
+mini-starter/src/server/api/files/[id]/
|
|
|
+mini-starter/src/server/api/files/multipart-complete/
|
|
|
+mini-starter/src/server/api/files/multipart-policy/
|
|
|
+mini-starter/src/server/api/files/upload-policy/
|
|
|
+mini-starter/src/server/api/public/
|
|
|
+mini-starter/src/server/api/public/advertisements/
|
|
|
+mini-starter/src/server/api/public/wechat-coupon-stocks/
|
|
|
+mini-starter/src/server/api/redemption-codes/
|
|
|
+mini-starter/src/server/api/roles/
|
|
|
+mini-starter/src/server/api/users/
|
|
|
+mini-starter/src/server/api/users/[id]/
|
|
|
+mini-starter/src/server/api/wechat-coupon-stocks/
|
|
|
+mini-starter/src/server/api/wechat-coupons/
|
|
|
+mini-starter/src/server/api/wechat-pay/
|
|
|
+mini-starter/src/server/api/wechat-pay/actions/
|
|
|
+mini-starter/src/server/api/wechat-pay-config/
|
|
|
+mini-starter/src/server/middleware/
|
|
|
+mini-starter/src/server/modules/
|
|
|
+mini-starter/src/server/modules/advertisements/
|
|
|
+mini-starter/src/server/modules/auth/
|
|
|
+mini-starter/src/server/modules/coupon-logs/
|
|
|
+mini-starter/src/server/modules/files/
|
|
|
+mini-starter/src/server/modules/redemption-codes/
|
|
|
+mini-starter/src/server/modules/users/
|
|
|
+mini-starter/src/server/modules/wechat-pay/
|
|
|
+mini-starter/src/server/types/
|
|
|
+mini-starter/src/server/utils/
|
|
|
+mini-starter/src/share/
|
|
|
+public/
|
|
|
+🔒 scripts/
|
|
|
+src/
|
|
|
+src/assets/
|
|
|
+src/client/
|
|
|
+src/client/admin-shadcn/
|
|
|
+src/client/admin-shadcn/components/
|
|
|
+src/client/admin-shadcn/hooks/
|
|
|
+src/client/admin-shadcn/layouts/
|
|
|
+src/client/admin-shadcn/pages/
|
|
|
+src/client/components/
|
|
|
+src/client/components/ui/
|
|
|
+src/client/home-shadcn/
|
|
|
+src/client/home-shadcn/components/
|
|
|
+src/client/home-shadcn/hooks/
|
|
|
+src/client/home-shadcn/layouts/
|
|
|
+src/client/home-shadcn/pages/
|
|
|
+src/client/hooks/
|
|
|
+src/client/lib/
|
|
|
+src/client/utils/
|
|
|
+src/server/
|
|
|
+src/server/api/
|
|
|
+src/server/api/advertisement-types/
|
|
|
+src/server/api/advertisements/
|
|
|
+src/server/api/auth/
|
|
|
+src/server/api/auth/login/
|
|
|
+src/server/api/auth/me/
|
|
|
+src/server/api/auth/mini-login/
|
|
|
+src/server/api/auth/register/
|
|
|
+src/server/api/files/
|
|
|
+src/server/api/files/[id]/
|
|
|
+src/server/api/files/multipart-complete/
|
|
|
+src/server/api/files/multipart-policy/
|
|
|
+src/server/api/files/upload-policy/
|
|
|
+src/server/api/roles/
|
|
|
+src/server/api/users/
|
|
|
+src/server/api/users/[id]/
|
|
|
+src/server/middleware/
|
|
|
+src/server/modules/
|
|
|
+src/server/modules/advertisements/
|
|
|
+src/server/modules/auth/
|
|
|
+src/server/modules/files/
|
|
|
+src/server/modules/users/
|
|
|
+src/server/types/
|
|
|
+src/server/utils/
|
|
|
+src/share/
|
|
|
+
|
|
|
+(File list truncated. Use list_files on specific subdirectories if you need to explore further.)
|
|
|
+You have not created a todo list yet. Create one with `update_todo_list` if your task is complicated or involves multiple steps.
|
|
|
+</environment_details>
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+**Assistant:**
|
|
|
+
|
|
|
+我需要分析现有的旧数据表结构,然后基于通用CRUD规范创建相应的实体和API。让我先查看旧数据表的内容。
|
|
|
+
|
|
|
+<read_file>
|
|
|
+<path>docs/旧数据表.sql</path>
|
|
|
+</read_file>
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+**User:**
|
|
|
+
|
|
|
+[read_file for 'docs/旧数据表.sql'. Reading multiple files at once is more efficient for the LLM. If other files are relevant to your current task, please read them simultaneously.] Result:
|
|
|
+<files>
|
|
|
+<file><path>docs/旧数据表.sql</path>
|
|
|
+<content lines="1-528">
|
|
|
+ 1 |
|
|
|
+ 2 | DROP TABLE IF EXISTS `ad`;
|
|
|
+ 3 | /*!40101 SET @saved_cs_client = @@character_set_client */;
|
|
|
+ 4 | /*!50503 SET character_set_client = utf8mb4 */;
|
|
|
+ 5 | CREATE TABLE `ad` (
|
|
|
+ 6 | `id` int unsigned NOT NULL AUTO_INCREMENT,
|
|
|
+ 7 | `title` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '标题',
|
|
|
+ 8 | `type_id` int DEFAULT NULL COMMENT '广告类型',
|
|
|
+ 9 | `code` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '调用别名',
|
|
|
+ 10 | `url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 'url',
|
|
|
+ 11 | `img` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '图片',
|
|
|
+ 12 | `sort` int DEFAULT '0' COMMENT '排序',
|
|
|
+ 13 | `create_time` int DEFAULT NULL COMMENT '创建时间',
|
|
|
+ 14 | `update_time` int DEFAULT '0' COMMENT '更新时间',
|
|
|
+ 15 | `status` int unsigned DEFAULT '0' COMMENT '状态',
|
|
|
+ 16 | `action_type` int DEFAULT '1' COMMENT '跳转类型 0 不跳转 1webview 2小程序页面',
|
|
|
+ 17 | PRIMARY KEY (`id`) USING BTREE
|
|
|
+ 18 | ) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC COMMENT='广告';
|
|
|
+ 19 | /*!40101 SET character_set_client = @saved_cs_client */;
|
|
|
+ 20 |
|
|
|
+ 21 | --
|
|
|
+ 22 | -- Dumping data for table `ad`
|
|
|
+ 23 | --
|
|
|
+ 24 |
|
|
|
+ 25 | --
|
|
|
+ 26 | -- Table structure for table `ad_type`
|
|
|
+ 27 | --
|
|
|
+ 28 |
|
|
|
+ 29 | DROP TABLE IF EXISTS `ad_type`;
|
|
|
+ 30 | /*!40101 SET @saved_cs_client = @@character_set_client */;
|
|
|
+ 31 | /*!50503 SET character_set_client = utf8mb4 */;
|
|
|
+ 32 | CREATE TABLE `ad_type` (
|
|
|
+ 33 | `id` int unsigned NOT NULL AUTO_INCREMENT,
|
|
|
+ 34 | `name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '类型名称',
|
|
|
+ 35 | `code` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '调用别名',
|
|
|
+ 36 | `remark` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '备注',
|
|
|
+ 37 | `create_time` int unsigned DEFAULT NULL COMMENT '创建时间',
|
|
|
+ 38 | `update_time` int unsigned DEFAULT NULL COMMENT '更新时间',
|
|
|
+ 39 | `status` int DEFAULT '0' COMMENT '状态',
|
|
|
+ 40 | PRIMARY KEY (`id`) USING BTREE
|
|
|
+ 41 | ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC COMMENT='广告类型';
|
|
|
+ 42 | /*!40101 SET character_set_client = @saved_cs_client */;
|
|
|
+ 43 |
|
|
|
+ 44 | --
|
|
|
+ 45 | -- Dumping data for table `ad_type`
|
|
|
+ 46 | --
|
|
|
+ 47 |
|
|
|
+ 48 |
|
|
|
+ 49 | --
|
|
|
+ 50 | -- Dumping data for table `agent`
|
|
|
+ 51 | --
|
|
|
+ 52 |
|
|
|
+ 53 |
|
|
|
+ 54 | --
|
|
|
+ 55 | -- Table structure for table `card`
|
|
|
+ 56 | --
|
|
|
+ 57 |
|
|
|
+ 58 | DROP TABLE IF EXISTS `card`;
|
|
|
+ 59 | /*!40101 SET @saved_cs_client = @@character_set_client */;
|
|
|
+ 60 | /*!50503 SET character_set_client = utf8mb4 */;
|
|
|
+ 61 | CREATE TABLE `card` (
|
|
|
+ 62 | `id` int unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
|
|
|
+ 63 | `agent_id` int DEFAULT NULL,
|
|
|
+ 64 | `card_type` int DEFAULT NULL COMMENT '1盛京通卡 2通用联名电子卡',
|
|
|
+ 65 | `card_no` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '卡号',
|
|
|
+ 66 | `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
|
|
|
+ 67 | `create_time` int unsigned NOT NULL DEFAULT '0' COMMENT '创建时间',
|
|
|
+ 68 | `update_time` int unsigned NOT NULL DEFAULT '0' COMMENT '修改时间',
|
|
|
+ 69 | `state` int unsigned NOT NULL DEFAULT '1' COMMENT '状态 1绑定 2解绑 通用联名电子卡不可解绑',
|
|
|
+ 70 | `face_value` decimal(10,2) unsigned NOT NULL DEFAULT '0.00' COMMENT '面值',
|
|
|
+ 71 | PRIMARY KEY (`id`) USING BTREE,
|
|
|
+ 72 | UNIQUE KEY `card_no` (`card_no`) USING BTREE
|
|
|
+ 73 | ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=COMPACT COMMENT='卡';
|
|
|
+ 74 | /*!40101 SET character_set_client = @saved_cs_client */;
|
|
|
+ 75 |
|
|
|
+ 76 | --
|
|
|
+ 77 | -- Dumping data for table `card`
|
|
|
+ 78 | --
|
|
|
+ 79 |
|
|
|
+ 80 |
|
|
|
+ 81 | --
|
|
|
+ 82 | -- Table structure for table `category`
|
|
|
+ 83 | --
|
|
|
+ 84 |
|
|
|
+ 85 | DROP TABLE IF EXISTS `category`;
|
|
|
+ 86 | /*!40101 SET @saved_cs_client = @@character_set_client */;
|
|
|
+ 87 | /*!50503 SET character_set_client = utf8mb4 */;
|
|
|
+ 88 | CREATE TABLE `category` (
|
|
|
+ 89 | `id` int NOT NULL AUTO_INCREMENT COMMENT '类别id',
|
|
|
+ 90 | `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '类别名称',
|
|
|
+ 91 | `parent_id` int DEFAULT '0' COMMENT '上级id',
|
|
|
+ 92 | `image` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '分类图片',
|
|
|
+ 93 | `level` int DEFAULT '0' COMMENT '层级',
|
|
|
+ 94 | `state` int DEFAULT '1' COMMENT '状态1可用2不可用',
|
|
|
+ 95 | PRIMARY KEY (`id`) USING BTREE
|
|
|
+ 96 | ) ENGINE=InnoDB AUTO_INCREMENT=777709 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC COMMENT='分类表';
|
|
|
+ 97 | /*!40101 SET character_set_client = @saved_cs_client */;
|
|
|
+ 98 |
|
|
|
+ 99 | --
|
|
|
+100 | -- Dumping data for table `category`
|
|
|
+101 | --
|
|
|
+102 |
|
|
|
+103 |
|
|
|
+104 | --
|
|
|
+105 | -- Table structure for table `city`
|
|
|
+106 | --
|
|
|
+107 |
|
|
|
+108 | DROP TABLE IF EXISTS `city`;
|
|
|
+109 | /*!40101 SET @saved_cs_client = @@character_set_client */;
|
|
|
+110 | /*!50503 SET character_set_client = utf8mb4 */;
|
|
|
+111 | CREATE TABLE `city` (
|
|
|
+112 | `id` bigint DEFAULT NULL COMMENT '地区id',
|
|
|
+113 | `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '地区名称',
|
|
|
+114 | `level` int DEFAULT '0' COMMENT '层级省市区县1,2,3,4',
|
|
|
+115 | `parent_id` bigint DEFAULT '0' COMMENT '上级id',
|
|
|
+116 | `state` int DEFAULT '1' COMMENT '状态1可用',
|
|
|
+117 | `sort` int DEFAULT '0' COMMENT '排序数值越大越靠前'
|
|
|
+118 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=COMPACT COMMENT='省、市、区、街道';
|
|
|
+119 | /*!40101 SET character_set_client = @saved_cs_client */;
|
|
|
+120 |
|
|
|
+121 | --
|
|
|
+122 | -- Dumping data for table `city`
|
|
|
+123 | --
|
|
|
+124 |
|
|
|
+125 | --
|
|
|
+126 | -- Table structure for table `config`
|
|
|
+127 | --
|
|
|
+128 |
|
|
|
+129 | DROP TABLE IF EXISTS `config`;
|
|
|
+130 | /*!40101 SET @saved_cs_client = @@character_set_client */;
|
|
|
+131 | /*!50503 SET character_set_client = utf8mb4 */;
|
|
|
+132 | CREATE TABLE `config` (
|
|
|
+133 | `id` int unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
|
|
|
+134 | `key` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '名称',
|
|
|
+135 | `value` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '值',
|
|
|
+136 | `state` int DEFAULT '2' COMMENT '状态 1可用 2禁用',
|
|
|
+137 | PRIMARY KEY (`id`),
|
|
|
+138 | UNIQUE KEY `key_state` (`key`,`state`) USING BTREE COMMENT 'key_state唯一'
|
|
|
+139 | ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
|
|
+140 | /*!40101 SET character_set_client = @saved_cs_client */;
|
|
|
+141 |
|
|
|
+142 | --
|
|
|
+143 | -- Dumping data for table `config`
|
|
|
+144 | --
|
|
|
+145 |
|
|
|
+146 |
|
|
|
+147 | --
|
|
|
+148 | -- Table structure for table `delivery_address`
|
|
|
+149 | --
|
|
|
+150 |
|
|
|
+151 | DROP TABLE IF EXISTS `delivery_address`;
|
|
|
+152 | /*!40101 SET @saved_cs_client = @@character_set_client */;
|
|
|
+153 | /*!50503 SET character_set_client = utf8mb4 */;
|
|
|
+154 | CREATE TABLE `delivery_address` (
|
|
|
+155 | `id` int NOT NULL AUTO_INCREMENT COMMENT '收货地址id',
|
|
|
+156 | `user_id` int DEFAULT '0' COMMENT '用户id',
|
|
|
+157 | `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '姓名',
|
|
|
+158 | `phone` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '手机号',
|
|
|
+159 | `address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '详细地址',
|
|
|
+160 | `receiver_province` bigint DEFAULT '0' COMMENT '省',
|
|
|
+161 | `receiver_city` bigint DEFAULT '0' COMMENT '市',
|
|
|
+162 | `receiver_district` bigint DEFAULT '0' COMMENT '区',
|
|
|
+163 | `receiver_town` bigint DEFAULT '0' COMMENT '街道',
|
|
|
+164 | `state` int DEFAULT '1' COMMENT '是否可用1正常2禁用3删除(不显示)',
|
|
|
+165 | `is_default` int DEFAULT '0' COMMENT '是否常用1是 2否',
|
|
|
+166 | PRIMARY KEY (`id`) USING BTREE
|
|
|
+167 | ) ENGINE=InnoDB AUTO_INCREMENT=36 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC COMMENT='用户收货地址表';
|
|
|
+168 | /*!40101 SET character_set_client = @saved_cs_client */;
|
|
|
+169 |
|
|
|
+170 | --
|
|
|
+171 | -- Dumping data for table `delivery_address`
|
|
|
+172 | --
|
|
|
+173 |
|
|
|
+174 |
|
|
|
+175 |
|
|
|
+176 | --
|
|
|
+177 | -- Table structure for table `express_company`
|
|
|
+178 | --
|
|
|
+179 |
|
|
|
+180 | DROP TABLE IF EXISTS `express_company`;
|
|
|
+181 | /*!40101 SET @saved_cs_client = @@character_set_client */;
|
|
|
+182 | /*!50503 SET character_set_client = utf8mb4 */;
|
|
|
+183 | CREATE TABLE `express_company` (
|
|
|
+184 | `id` int NOT NULL AUTO_INCREMENT COMMENT '表序号',
|
|
|
+185 | `name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '物流公司名称',
|
|
|
+186 | `code` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '物流编号',
|
|
|
+187 | `state` int NOT NULL DEFAULT '1' COMMENT '使用状态 1可用 2禁用',
|
|
|
+188 | `sort` int DEFAULT NULL COMMENT '优先级 值越大越优先',
|
|
|
+189 | PRIMARY KEY (`id`) USING BTREE
|
|
|
+190 | ) ENGINE=InnoDB AUTO_INCREMENT=45 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci AVG_ROW_LENGTH=420 ROW_FORMAT=COMPACT COMMENT='物流公司';
|
|
|
+191 | /*!40101 SET character_set_client = @saved_cs_client */;
|
|
|
+192 |
|
|
|
+193 | --
|
|
|
+194 | -- Dumping data for table `express_company`
|
|
|
+195 | --
|
|
|
+196 |
|
|
|
+197 |
|
|
|
+198 | --
|
|
|
+199 | -- Table structure for table `goods`
|
|
|
+200 | --
|
|
|
+201 |
|
|
|
+202 | DROP TABLE IF EXISTS `goods`;
|
|
|
+203 | /*!40101 SET @saved_cs_client = @@character_set_client */;
|
|
|
+204 | /*!50503 SET character_set_client = utf8mb4 */;
|
|
|
+205 | CREATE TABLE `goods` (
|
|
|
+206 | `id` int NOT NULL AUTO_INCREMENT,
|
|
|
+207 | `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '商品名称',
|
|
|
+208 | `price` decimal(10,2) DEFAULT '0.00' COMMENT '售卖价',
|
|
|
+209 | `cost_price` decimal(10,2) DEFAULT '0.00' COMMENT '成本价',
|
|
|
+210 | `sales_num` bigint DEFAULT '0' COMMENT '销售数量',
|
|
|
+211 | `click_num` bigint DEFAULT '0' COMMENT '点击次数',
|
|
|
+212 | `category_id1` int DEFAULT '0' COMMENT '一级类别id',
|
|
|
+213 | `category_id2` int DEFAULT '0' COMMENT '二级类别id',
|
|
|
+214 | `category_id3` int DEFAULT '0' COMMENT '三级类别id',
|
|
|
+215 | `goods_type` int DEFAULT '1' COMMENT '订单类型 1实物产品 2虚拟产品',
|
|
|
+216 | `supplier_id` int DEFAULT NULL COMMENT '所属供应商id',
|
|
|
+217 | `image` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '商品主图',
|
|
|
+218 | `slide_image` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '商品轮播(多个用,隔开)',
|
|
|
+219 | `detail` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT '商品详情',
|
|
|
+220 | `instructions` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '简介',
|
|
|
+221 | `sort` int DEFAULT '0' COMMENT '排序',
|
|
|
+222 | `state` int DEFAULT '1' COMMENT '状态1可用2不可用',
|
|
|
+223 | `stock` bigint DEFAULT '0' COMMENT '库存',
|
|
|
+224 | `spu_id` int DEFAULT '0' COMMENT '主商品ID',
|
|
|
+225 | `spu_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '主商品名称',
|
|
|
+226 | `lowest_buy` int DEFAULT '1' COMMENT '最小起购量',
|
|
|
+227 | `create_time` int DEFAULT '0' COMMENT '创建时间',
|
|
|
+228 | `update_time` int DEFAULT '0' COMMENT '修改时间',
|
|
|
+229 | PRIMARY KEY (`id`) USING BTREE
|
|
|
+230 | ) ENGINE=InnoDB AUTO_INCREMENT=10007 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC COMMENT='商品表';
|
|
|
+231 | /*!40101 SET character_set_client = @saved_cs_client */;
|
|
|
+232 |
|
|
|
+233 | --
|
|
|
+234 | -- Dumping data for table `goods`
|
|
|
+235 | --
|
|
|
+236 |
|
|
|
+237 |
|
|
|
+238 |
|
|
|
+239 | --
|
|
|
+240 | -- Table structure for table `merchant`
|
|
|
+241 | --
|
|
|
+242 |
|
|
|
+243 | DROP TABLE IF EXISTS `merchant`;
|
|
|
+244 | /*!40101 SET @saved_cs_client = @@character_set_client */;
|
|
|
+245 | /*!50503 SET character_set_client = utf8mb4 */;
|
|
|
+246 | CREATE TABLE `merchant` (
|
|
|
+247 | `id` int unsigned NOT NULL AUTO_INCREMENT,
|
|
|
+248 | `number` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '编号',
|
|
|
+249 | `name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '名称',
|
|
|
+250 | `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '密码',
|
|
|
+251 | `salt` char(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '随机码',
|
|
|
+252 | `login_num` int DEFAULT '0' COMMENT '登录次数',
|
|
|
+253 | `login_time` int unsigned NOT NULL DEFAULT '0' COMMENT '登录时间',
|
|
|
+254 | `login_ip` varchar(15) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '登录ip',
|
|
|
+255 | `last_login_time` int unsigned NOT NULL DEFAULT '0' COMMENT '上次登录时间',
|
|
|
+256 | `last_login_ip` varchar(15) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '上次登录ip',
|
|
|
+257 | `rsa_public_key` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '公钥',
|
|
|
+258 | `aes_key` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 'aes秘钥',
|
|
|
+259 | `create_time` int unsigned DEFAULT NULL COMMENT '创建时间',
|
|
|
+260 | `update_time` int unsigned DEFAULT '0' COMMENT '修改时间',
|
|
|
+261 | `state` int DEFAULT NULL COMMENT '状态 1可用 2禁用',
|
|
|
+262 | PRIMARY KEY (`id`) USING BTREE,
|
|
|
+263 | UNIQUE KEY `number` (`number`) USING BTREE
|
|
|
+264 | ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=COMPACT COMMENT='商户';
|
|
|
+265 | /*!40101 SET character_set_client = @saved_cs_client */;
|
|
|
+266 |
|
|
|
+267 | --
|
|
|
+268 | -- Dumping data for table `merchant`
|
|
|
+269 | --
|
|
|
+270 |
|
|
|
+271 |
|
|
|
+272 |
|
|
|
+273 | --
|
|
|
+274 | -- Table structure for table `orders`
|
|
|
+275 | --
|
|
|
+276 |
|
|
|
+277 | DROP TABLE IF EXISTS `orders`;
|
|
|
+278 | /*!40101 SET @saved_cs_client = @@character_set_client */;
|
|
|
+279 | /*!50503 SET character_set_client = utf8mb4 */;
|
|
|
+280 | CREATE TABLE `orders` (
|
|
|
+281 | `id` int NOT NULL AUTO_INCREMENT COMMENT '订单id',
|
|
|
+282 | `order_no` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '订单号',
|
|
|
+283 | `user_id` int DEFAULT '0' COMMENT '用户ID',
|
|
|
+284 | `auth_code` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '付款码',
|
|
|
+285 | `card_no` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '卡号',
|
|
|
+286 | `sjt_card_no` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '盛京通卡号',
|
|
|
+287 | `amount` decimal(10,2) DEFAULT '0.00' COMMENT '订单金额',
|
|
|
+288 | `cost_amount` decimal(10,2) DEFAULT '0.00' COMMENT '成本金额',
|
|
|
+289 | `freight_amount` decimal(10,2) DEFAULT '0.00' COMMENT '运费',
|
|
|
+290 | `discount_amount` decimal(10,2) DEFAULT '0.00' COMMENT '优惠金额',
|
|
|
+291 | `pay_amount` decimal(10,2) DEFAULT '0.00' COMMENT '实际支付金额',
|
|
|
+292 | `device_no` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '设备编号',
|
|
|
+293 | `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '订单描述',
|
|
|
+294 | `goods_detail` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '订单详情 json',
|
|
|
+295 | `goods_tag` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '订单优惠标记',
|
|
|
+296 | `address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '地址',
|
|
|
+297 | `order_type` int DEFAULT '1' COMMENT '订单类型 1实物订单 2虚拟订单',
|
|
|
+298 | `pay_type` int DEFAULT '0' COMMENT '支付类型1积分2礼券',
|
|
|
+299 | `pay_state` int DEFAULT '0' COMMENT '0未支付1支付中2支付成功3已退款4支付失败5订单关闭',
|
|
|
+300 | `state` int DEFAULT '0' COMMENT '订单状态0未发货1已发货2收货成功3已退货',
|
|
|
+301 | `user_phone` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '用户手机号',
|
|
|
+302 | `merchant_id` int DEFAULT '0' COMMENT '商户id',
|
|
|
+303 | `merchant_no` int DEFAULT NULL COMMENT '商户号',
|
|
|
+304 | `supplier_id` int DEFAULT '0' COMMENT '供货商id',
|
|
|
+305 | `address_id` int DEFAULT '0' COMMENT '地址id',
|
|
|
+306 | `receiver_mobile` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '收货人手机号',
|
|
|
+307 | `recevier_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '收货人姓名',
|
|
|
+308 | `recevier_province` bigint DEFAULT '0' COMMENT '收货人所在省',
|
|
|
+309 | `recevier_city` bigint DEFAULT '0' COMMENT '收货人所在市',
|
|
|
+310 | `recevier_district` bigint DEFAULT '0' COMMENT '收货人所在区',
|
|
|
+311 | `recevier_town` bigint DEFAULT '0' COMMENT '收货人所在街道',
|
|
|
+312 | `create_time` int DEFAULT '0' COMMENT '创建时间',
|
|
|
+313 | `update_time` int DEFAULT '0' COMMENT '更新时间',
|
|
|
+314 | `refund_time` int DEFAULT '0' COMMENT '退款时间',
|
|
|
+315 | `close_time` int DEFAULT '0' COMMENT '订单关闭时间',
|
|
|
+316 | `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '管理员备注信息',
|
|
|
+317 | PRIMARY KEY (`id`) USING BTREE,
|
|
|
+318 | UNIQUE KEY `order_no` (`order_no`) USING BTREE COMMENT '订单号唯一'
|
|
|
+319 | ) ENGINE=InnoDB AUTO_INCREMENT=114 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC COMMENT='订单表';
|
|
|
+320 | /*!40101 SET character_set_client = @saved_cs_client */;
|
|
|
+321 |
|
|
|
+322 | --
|
|
|
+323 | -- Dumping data for table `orders`
|
|
|
+324 | --
|
|
|
+325 |
|
|
|
+326 |
|
|
|
+327 |
|
|
|
+328 | --
|
|
|
+329 | -- Table structure for table `orders_goods`
|
|
|
+330 | --
|
|
|
+331 |
|
|
|
+332 | DROP TABLE IF EXISTS `orders_goods`;
|
|
|
+333 | /*!40101 SET @saved_cs_client = @@character_set_client */;
|
|
|
+334 | /*!50503 SET character_set_client = utf8mb4 */;
|
|
|
+335 | CREATE TABLE `orders_goods` (
|
|
|
+336 | `id` int NOT NULL AUTO_INCREMENT COMMENT '订单商品表id',
|
|
|
+337 | `order_id` int DEFAULT '0' COMMENT '订单表id',
|
|
|
+338 | `order_no` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '订单号',
|
|
|
+339 | `goods_id` int DEFAULT '0' COMMENT '商品id',
|
|
|
+340 | `goods_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '商品名称',
|
|
|
+341 | `goods_image` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '商品图片',
|
|
|
+342 | `goods_type` int DEFAULT '1' COMMENT '1实物产品2虚拟订单',
|
|
|
+343 | `supplier_id` int DEFAULT '0' COMMENT '供货商id',
|
|
|
+344 | `cost_price` decimal(10,2) DEFAULT '0.00' COMMENT '成本价',
|
|
|
+345 | `price` decimal(10,2) DEFAULT '0.00' COMMENT '售价',
|
|
|
+346 | `num` int DEFAULT '0' COMMENT '数量',
|
|
|
+347 | `freight_amount` decimal(10,2) DEFAULT '0.00' COMMENT '运费',
|
|
|
+348 | `state` int DEFAULT '0' COMMENT '状态(0未发货、1已发货)',
|
|
|
+349 | `express_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '快递名称',
|
|
|
+350 | `express_no` int DEFAULT NULL COMMENT '单号',
|
|
|
+351 | `create_time` int DEFAULT '0' COMMENT '创建时间',
|
|
|
+352 | `update_time` int DEFAULT '0' COMMENT '修改时间',
|
|
|
+353 | PRIMARY KEY (`id`) USING BTREE
|
|
|
+354 | ) ENGINE=InnoDB AUTO_INCREMENT=97 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC COMMENT='订单商品表';
|
|
|
+355 | /*!40101 SET character_set_client = @saved_cs_client */;
|
|
|
+356 |
|
|
|
+357 | --
|
|
|
+358 | -- Dumping data for table `orders_goods`
|
|
|
+359 | --
|
|
|
+360 |
|
|
|
+361 |
|
|
|
+362 |
|
|
|
+363 | --
|
|
|
+364 | -- Table structure for table `orders_refund`
|
|
|
+365 | --
|
|
|
+366 |
|
|
|
+367 | DROP TABLE IF EXISTS `orders_refund`;
|
|
|
+368 | /*!40101 SET @saved_cs_client = @@character_set_client */;
|
|
|
+369 | /*!50503 SET character_set_client = utf8mb4 */;
|
|
|
+370 | CREATE TABLE `orders_refund` (
|
|
|
+371 | `id` int NOT NULL COMMENT 'id',
|
|
|
+372 | `order_no` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '订单号',
|
|
|
+373 | `refund_order_no` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '退款订单号',
|
|
|
+374 | `refund_amount` decimal(10,2) DEFAULT NULL COMMENT '退款金额',
|
|
|
+375 | `create_time` int DEFAULT NULL COMMENT '退款时间',
|
|
|
+376 | `update_time` int DEFAULT NULL COMMENT '更新时间',
|
|
|
+377 | `state` int DEFAULT NULL COMMENT '0未退款1退款中2退款成功3退款失败',
|
|
|
+378 | PRIMARY KEY (`id`) USING BTREE,
|
|
|
+379 | UNIQUE KEY `refund_order_no` (`refund_order_no`) USING BTREE COMMENT 'refund_order_no'
|
|
|
+380 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=COMPACT COMMENT='退款';
|
|
|
+381 | /*!40101 SET character_set_client = @saved_cs_client */;
|
|
|
+382 |
|
|
|
+383 | --
|
|
|
+384 | -- Dumping data for table `orders_refund`
|
|
|
+385 | --
|
|
|
+386 |
|
|
|
+387 |
|
|
|
+388 | --
|
|
|
+389 | -- Table structure for table `organization`
|
|
|
+390 | --
|
|
|
+391 |
|
|
|
+392 | DROP TABLE IF EXISTS `organization`;
|
|
|
+393 | /*!40101 SET @saved_cs_client = @@character_set_client */;
|
|
|
+394 | /*!50503 SET character_set_client = utf8mb4 */;
|
|
|
+395 | CREATE TABLE `organization` (
|
|
|
+396 | `id` int NOT NULL AUTO_INCREMENT COMMENT '分行网点id',
|
|
|
+397 | `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '分行网点名称',
|
|
|
+398 | `parent_id` int DEFAULT '0' COMMENT '上级id',
|
|
|
+399 | `level` int DEFAULT '4' COMMENT '层级',
|
|
|
+400 | `create_time` int DEFAULT '0' COMMENT '床渐渐时间',
|
|
|
+401 | `update_time` int DEFAULT '0' COMMENT '修改时间',
|
|
|
+402 | `state` int DEFAULT '1' COMMENT '状态1可用2不可用',
|
|
|
+403 | PRIMARY KEY (`id`) USING BTREE
|
|
|
+404 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC COMMENT='组织架构表';
|
|
|
+405 | /*!40101 SET character_set_client = @saved_cs_client */;
|
|
|
+406 |
|
|
|
+407 | --
|
|
|
+408 | -- Dumping data for table `organization`
|
|
|
+409 | --
|
|
|
+410 |
|
|
|
+411 |
|
|
|
+412 | --
|
|
|
+413 | -- Table structure for table `supplier`
|
|
|
+414 | --
|
|
|
+415 |
|
|
|
+416 | DROP TABLE IF EXISTS `supplier`;
|
|
|
+417 | /*!40101 SET @saved_cs_client = @@character_set_client */;
|
|
|
+418 | /*!50503 SET character_set_client = utf8mb4 */;
|
|
|
+419 | CREATE TABLE `supplier` (
|
|
|
+420 | `id` int unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
|
|
|
+421 | `name` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '供货商名称',
|
|
|
+422 | `username` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '用户名',
|
|
|
+423 | `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '密码',
|
|
|
+424 | `salt` char(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '随机码',
|
|
|
+425 | `phone` char(11) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '手机号码',
|
|
|
+426 | `realname` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '姓名',
|
|
|
+427 | `login_num` int DEFAULT '0' COMMENT '登录次数',
|
|
|
+428 | `login_time` int unsigned NOT NULL DEFAULT '0' COMMENT '登录时间',
|
|
|
+429 | `login_ip` varchar(15) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '登录ip',
|
|
|
+430 | `last_login_time` int unsigned NOT NULL DEFAULT '0' COMMENT '上次登录时间',
|
|
|
+431 | `last_login_ip` varchar(15) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '上次登录ip',
|
|
|
+432 | `create_time` int unsigned NOT NULL COMMENT '创建时间',
|
|
|
+433 | `update_time` int unsigned NOT NULL DEFAULT '0' COMMENT '修改时间',
|
|
|
+434 | `state` tinyint unsigned DEFAULT '2' COMMENT '1 启用 2 禁用',
|
|
|
+435 | PRIMARY KEY (`id`) USING BTREE,
|
|
|
+436 | UNIQUE KEY `username` (`username`) USING BTREE
|
|
|
+437 | ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=COMPACT COMMENT='管理员';
|
|
|
+438 | /*!40101 SET character_set_client = @saved_cs_client */;
|
|
|
+439 |
|
|
|
+440 | --
|
|
|
+441 | -- Dumping data for table `supplier`
|
|
|
+442 | --
|
|
|
+443 |
|
|
|
+444 | --
|
|
|
+445 | -- Table structure for table `user`
|
|
|
+446 | --
|
|
|
+447 |
|
|
|
+448 |
|
|
|
+449 | -- Dumping data for table `user`
|
|
|
+450 | --
|
|
|
+451 |
|
|
|
+452 |
|
|
|
+453 | --
|
|
|
+454 | -- Table structure for table `user_card`
|
|
|
+455 | --
|
|
|
+456 |
|
|
|
+457 | DROP TABLE IF EXISTS `user_card`;
|
|
|
+458 | /*!40101 SET @saved_cs_client = @@character_set_client */;
|
|
|
+459 | /*!50503 SET character_set_client = utf8mb4 */;
|
|
|
+460 | CREATE TABLE `user_card` (
|
|
|
+461 | `id` int unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
|
|
|
+462 | `user_id` int unsigned NOT NULL COMMENT '用户id',
|
|
|
+463 | `agent_id` int DEFAULT NULL COMMENT '代理商',
|
|
|
+464 | `card_no` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '卡号',
|
|
|
+465 | `sjt_card_no` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '盛京通卡卡号',
|
|
|
+466 | `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '密码',
|
|
|
+467 | `auth_code` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '付款码70_75开头16位随机数',
|
|
|
+468 | `create_time` int unsigned NOT NULL DEFAULT '0' COMMENT '创建时间',
|
|
|
+469 | `update_time` int unsigned NOT NULL DEFAULT '0' COMMENT '修改时间',
|
|
|
+470 | `state` int unsigned NOT NULL DEFAULT '1' COMMENT '状态 1绑定 2解绑 通用联名电子卡不可解绑',
|
|
|
+471 | `balance` decimal(10,2) unsigned NOT NULL DEFAULT '0.00' COMMENT '余额',
|
|
|
+472 | `is_default` int DEFAULT '2' COMMENT '默认 1 是 2否',
|
|
|
+473 | PRIMARY KEY (`id`) USING BTREE
|
|
|
+474 | ) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=COMPACT COMMENT='用户卡';
|
|
|
+475 | /*!40101 SET character_set_client = @saved_cs_client */;
|
|
|
+476 |
|
|
|
+477 | --
|
|
|
+478 | -- Dumping data for table `user_card`
|
|
|
+479 | --
|
|
|
+480 |
|
|
|
+481 | --
|
|
|
+482 | -- Table structure for table `user_card_balance_record`
|
|
|
+483 | --
|
|
|
+484 |
|
|
|
+485 | DROP TABLE IF EXISTS `user_card_balance_record`;
|
|
|
+486 | /*!40101 SET @saved_cs_client = @@character_set_client */;
|
|
|
+487 | /*!50503 SET character_set_client = utf8mb4 */;
|
|
|
+488 | CREATE TABLE `user_card_balance_record` (
|
|
|
+489 | `id` int unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
|
|
|
+490 | `user_id` int unsigned NOT NULL COMMENT '用户id',
|
|
|
+491 | `card_no` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '卡号',
|
|
|
+492 | `amount` decimal(10,2) unsigned NOT NULL DEFAULT '0.00' COMMENT '变动金额',
|
|
|
+493 | `amount_before` decimal(10,2) unsigned NOT NULL DEFAULT '0.00' COMMENT '变动前金额',
|
|
|
+494 | `amount_after` decimal(10,2) unsigned NOT NULL DEFAULT '0.00' COMMENT '变动后金额',
|
|
|
+495 | `order_no` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '订单号',
|
|
|
+496 | `type` int NOT NULL COMMENT '类型 1消费 2退款',
|
|
|
+497 | `remark` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '备注',
|
|
|
+498 | `create_time` int unsigned NOT NULL COMMENT '创建时间',
|
|
|
+499 | `update_time` int unsigned NOT NULL DEFAULT '0' COMMENT '修改时间',
|
|
|
+500 | PRIMARY KEY (`id`) USING BTREE
|
|
|
+501 | ) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=COMPACT COMMENT='卡余额变动';
|
|
|
+502 | /*!40101 SET character_set_client = @saved_cs_client */;
|
|
|
+503 |
|
|
|
+504 | --
|
|
|
+505 | -- Dumping data for table `user_card_balance_record`
|
|
|
+506 | --
|
|
|
+507 |
|
|
|
+508 | --
|
|
|
+509 | -- Table structure for table `xt_orders`
|
|
|
+510 | --
|
|
|
+511 |
|
|
|
+512 | DROP TABLE IF EXISTS `xt_orders`;
|
|
|
+513 | /*!40101 SET @saved_cs_client = @@character_set_client */;
|
|
|
+514 | /*!50503 SET character_set_client = utf8mb4 */;
|
|
|
+515 | CREATE TABLE `xt_orders` (
|
|
|
+516 | `id` int NOT NULL COMMENT 'id',
|
|
|
+517 | `order_no` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '订单号',
|
|
|
+518 | `order_no_sort` varchar(34) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '子订单号',
|
|
|
+519 | `card_no` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '卡号',
|
|
|
+520 | `amount` decimal(10,2) DEFAULT NULL COMMENT '金额',
|
|
|
+521 | `create_time` int DEFAULT NULL COMMENT '创建时间',
|
|
|
+522 | `update_time` int DEFAULT NULL COMMENT '更新时间',
|
|
|
+523 | `state` int DEFAULT NULL COMMENT '支付状态 1待处理 2处理中 3支付成功 4支付失败',
|
|
|
+524 | `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '备注',
|
|
|
+525 | PRIMARY KEY (`id`) USING BTREE
|
|
|
+526 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=COMPACT COMMENT='新天订单';
|
|
|
+527 | /*!40101 SET character_set_client = @saved_cs_client */;
|
|
|
+528 |
|
|
|
+</content>
|
|
|
+</file>
|
|
|
+</files>
|
|
|
+<environment_details>
|
|
|
+# VSCode Visible Files
|
|
|
+docs/旧数据表.sql
|
|
|
+
|
|
|
+# VSCode Open Tabs
|
|
|
+docs/旧数据表.sql
|
|
|
+
|
|
|
+# Current Time
|
|
|
+Current time in ISO 8601 UTC format: 2025-08-13T03:09:21.910Z
|
|
|
+User time zone: UTC, UTC+0:00
|
|
|
+
|
|
|
+# Current Cost
|
|
|
+$0.29
|
|
|
+
|
|
|
+# Current Mode
|
|
|
+<slug>code</slug>
|
|
|
+<name>💻 代码</name>
|
|
|
+<model>d8d-ai-model</model>
|
|
|
+You have not created a todo list yet. Create one with `update_todo_list` if your task is complicated or involves multiple steps.
|
|
|
+</environment_details>
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+**Assistant:**
|
|
|
+
|
|
|
+我需要分析旧数据表结构,并基于通用CRUD规范创建相应的实体和API。让我创建一个todo列表来系统性地完成这个任务。
|
|
|
+
|
|
|
+<update_todo_list>
|
|
|
+<todos>
|
|
|
+[x] 分析旧数据表结构
|
|
|
+[ ] 创建商品实体 (goods)
|
|
|
+[ ] 创建商品分类实体 (category)
|
|
|
+[ ] 创建订单实体 (orders)
|
|
|
+[ ] 创建订单商品实体 (orders_goods)
|
|
|
+[ ] 创建商户实体 (merchant)
|
|
|
+[ ] 创建供应商实体 (supplier)
|
|
|
+[ ] 创建用户卡实体 (user_card)
|
|
|
+[ ] 创建卡实体 (card)
|
|
|
+[ ] 创建收货地址实体 (delivery_address)
|
|
|
+[ ] 创建物流公司实体 (express_company)
|
|
|
+[ ] 创建配置实体 (config)
|
|
|
+[ ] 注册所有实体到数据源
|
|
|
+[ ] 创建所有实体的通用CRUD路由
|
|
|
+[ ] 注册所有路由到API
|
|
|
+[ ] 创建管理后台页面
|
|
|
+[ ] 注册路由和菜单
|
|
|
+</todos>
|
|
|
+</update_todo_list>
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+**User:**
|
|
|
+
|
|
|
+[update_todo_list] Result:
|
|
|
+Todo list updated successfully.
|
|
|
+<environment_details>
|
|
|
+# VSCode Visible Files
|
|
|
+docs/旧数据表.sql
|
|
|
+
|
|
|
+# VSCode Open Tabs
|
|
|
+docs/旧数据表.sql
|
|
|
+
|
|
|
+# Current Time
|
|
|
+Current time in ISO 8601 UTC format: 2025-08-13T03:09:48.483Z
|
|
|
+User time zone: UTC, UTC+0:00
|
|
|
+
|
|
|
+# Current Cost
|
|
|
+$0.64
|
|
|
+
|
|
|
+# Current Mode
|
|
|
+<slug>code</slug>
|
|
|
+<name>💻 代码</name>
|
|
|
+<model>d8d-ai-model</model>
|
|
|
+====
|
|
|
+
|
|
|
+REMINDERS
|
|
|
+
|
|
|
+Below is your current list of reminders for this task. Keep them updated as you progress.
|
|
|
+
|
|
|
+| # | Content | Status |
|
|
|
+|---|---------|--------|
|
|
|
+| 1 | 分析旧数据表结构 | Completed |
|
|
|
+| 2 | 创建商品实体 (goods) | Pending |
|
|
|
+| 3 | 创建商品分类实体 (category) | Pending |
|
|
|
+| 4 | 创建订单实体 (orders) | Pending |
|
|
|
+| 5 | 创建订单商品实体 (orders_goods) | Pending |
|
|
|
+| 6 | 创建商户实体 (merchant) | Pending |
|
|
|
+| 7 | 创建供应商实体 (supplier) | Pending |
|
|
|
+| 8 | 创建用户卡实体 (user_card) | Pending |
|
|
|
+| 9 | 创建卡实体 (card) | Pending |
|
|
|
+| 10 | 创建收货地址实体 (delivery_address) | Pending |
|
|
|
+| 11 | 创建物流公司实体 (express_company) | Pending |
|
|
|
+| 12 | 创建配置实体 (config) | Pending |
|
|
|
+| 13 | 注册所有实体到数据源 | Pending |
|
|
|
+| 14 | 创建所有实体的通用CRUD路由 | Pending |
|
|
|
+| 15 | 注册所有路由到API | Pending |
|
|
|
+| 16 | 创建管理后台页面 | Pending |
|
|
|
+| 17 | 注册路由和菜单 | Pending |
|
|
|
+
|
|
|
+
|
|
|
+IMPORTANT: When task status changes, remember to call the `update_todo_list` tool to update your progress.
|
|
|
+
|
|
|
+</environment_details>
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+**Assistant:**
|
|
|
+
|
|
|
+现在开始创建商品实体。让我从商品实体开始,按照通用CRUD规范创建。
|
|
|
+
|
|
|
+<write_to_file>
|
|
|
+<path>src/server/modules/products/goods.entity.ts</path>
|
|
|
+<content>import { Entity, PrimaryGeneratedColumn, Column, ManyToOne, JoinColumn } from 'typeorm';
|
|
|
+import { File } from '@/server/modules/files/file.entity';
|
|
|
+
|
|
|
+@Entity('goods')
|
|
|
+export class Goods {
|
|
|
+ @PrimaryGeneratedColumn({ unsigned: true })
|
|
|
+ id!: number;
|
|
|
+
|
|
|
+ @Column({ name: 'name', type: 'varchar', length: 255, comment: '商品名称' })
|
|
|
+ name!: string;
|
|
|
+
|
|
|
+ @Column({ name: 'price', type: 'decimal', precision: 10, scale: 2, default: 0.00, comment: '售卖价' })
|
|
|
+ price!: number;
|
|
|
+
|
|
|
+ @Column({ name: 'cost_price', type: 'decimal', precision: 10, scale: 2, default: 0.00, comment: '成本价' })
|
|
|
+ costPrice!: number;
|
|
|
+
|
|
|
+ @Column({ name: 'sales_num', type: 'bigint', default: 0, comment: '销售数量' })
|
|
|
+ salesNum!: number;
|
|
|
+
|
|
|
+ @Column({ name: 'click_num', type: 'bigint', default: 0, comment: '点击次数' })
|
|
|
+ clickNum!: number;
|
|
|
+
|
|
|
+ @Column({ name: 'category_id1', type: 'int', default: 0, comment: '一级类别id' })
|
|
|
+ categoryId1!: number;
|
|
|
+
|
|
|
+ @Column({ name: 'category_id2', type: 'int', default: 0, comment: '二级类别id' })
|
|
|
+ categoryId2!: number;
|
|
|
+
|
|
|
+ @Column({ name: 'category_id3', type: 'int', default: 0, comment: '三级类别id' })
|
|
|
+ categoryId3!: number;
|
|
|
+
|
|
|
+ @Column({ name: 'goods_type', type: 'int', default: 1, comment: '订单类型 1实物产品 2虚拟产品' })
|
|
|
+ goodsType!: number;
|
|
|
+
|
|
|
+ @Column({ name: 'supplier_id', type: 'int', nullable: true, comment: '所属供应商id' })
|
|
|
+ supplierId!: number | null;
|
|
|
+
|
|
|
+ @Column({ name: 'image', type: 'varchar', length: 255, nullable: true, comment: '商品主图' })
|
|
|
+ image!: string | null;
|
|
|
+
|
|
|
+ @Column({ name: 'slide_image', type: 'varchar', length: 2000, nullable: true, comment: '商品轮播(多个用,隔开)' })
|
|
|
+ slideImage!: string | null;
|
|
|
+
|
|
|
+ @Column({ name: 'detail', type: 'text', nullable: true, comment: '商品详情' })
|
|
|
+ detail!: string | null;
|
|
|
+
|
|
|
+ @Column({ name: 'instructions', type: 'varchar', length: 255, nullable: true, comment: '简介' })
|
|
|
+ instructions!: string | null;
|
|
|
+
|
|
|
+ @Column({ name: 'sort', type: 'int', default: 0, comment: '排序' })
|
|
|
+ sort!: number;
|
|
|
+
|
|
|
+ @Column({ name: 'state', type: 'int', default: 1, comment: '状态1可用2不可用' })
|
|
|
+ state!: number;
|
|
|
+
|
|
|
+ @Column({ name: 'stock', type: 'bigint', default: 0, comment: '库存' })
|
|
|
+ stock!: number;
|
|
|
+
|
|
|
+ @Column({ name: 'spu_id', type: 'int', default: 0, comment: '主商品ID' })
|
|
|
+ spuId!: number;
|
|
|
+
|
|
|
+ @Column({ name: 'spu_name', type: 'varchar', length: 255, nullable: true, comment: '主商品名称' })
|
|
|
+ spuName!: string | null;
|
|
|
+
|
|
|
+ @Column({ name: 'lowest_buy', type: 'int', default: 1, comment: '最小起购量' })
|
|
|
+ lowestBuy!: number;
|
|
|
+
|
|
|
+ @Column({ name: 'image_file_id', type: 'int', unsigned: true, nullable: true, comment: '商品主图文件ID' })
|
|
|
+ imageFileId!: number | null;
|
|
|
+
|
|
|
+ @ManyToOne(() => File, { nullable: true })
|
|
|
+ @JoinColumn({ name: 'image_file_id', referencedColumnName: 'id' })
|
|
|
+ imageFile!: File | null;
|
|
|
+
|
|
|
+ @Column({ name: 'created_at', type: 'timestamp', default: () => 'CURRENT_TIMESTAMP', comment: '创建时间' })
|
|
|
+ createdAt!: Date;
|
|
|
+
|
|
|
+ @Column({ name: 'updated_at', type: 'timestamp', default: () => 'CURRENT_TIMESTAMP', onUpdate: 'CURRENT_TIMESTAMP', comment: '更新时间' })
|
|
|
+ updatedAt!: Date;
|
|
|
+}
|
|
|
+</content>
|
|
|
+<line_count>82</line_count>
|
|
|
+</write_to_file>
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+**User:**
|
|
|
+
|
|
|
+[write_to_file for 'src/server/modules/products/goods.entity.ts'] Result:
|
|
|
+<file_write_result>
|
|
|
+<path>src/server/modules/products/goods.entity.ts</path>
|
|
|
+<operation>created</operation>
|
|
|
+<notice>
|
|
|
+<i>You do not need to re-read the file, as you have seen all changes</i>
|
|
|
+<i>Proceed with the task using these changes as the new baseline.</i>
|
|
|
+</notice>
|
|
|
+</file_write_result>
|
|
|
+
|
|
|
+<environment_details>
|
|
|
+# VSCode Visible Files
|
|
|
+docs/旧数据表.sql
|
|
|
+
|
|
|
+# VSCode Open Tabs
|
|
|
+docs/旧数据表.sql
|
|
|
+
|
|
|
+# Current Time
|
|
|
+Current time in ISO 8601 UTC format: 2025-08-13T03:11:17.432Z
|
|
|
+User time zone: UTC, UTC+0:00
|
|
|
+
|
|
|
+# Current Cost
|
|
|
+$1.02
|
|
|
+
|
|
|
+# Current Mode
|
|
|
+<slug>code</slug>
|
|
|
+<name>💻 代码</name>
|
|
|
+<model>d8d-ai-model</model>
|
|
|
+====
|
|
|
+
|
|
|
+REMINDERS
|
|
|
+
|
|
|
+Below is your current list of reminders for this task. Keep them updated as you progress.
|
|
|
+
|
|
|
+| # | Content | Status |
|
|
|
+|---|---------|--------|
|
|
|
+| 1 | 分析旧数据表结构 | Completed |
|
|
|
+| 2 | 创建商品实体 (goods) | Pending |
|
|
|
+| 3 | 创建商品分类实体 (category) | Pending |
|
|
|
+| 4 | 创建订单实体 (orders) | Pending |
|
|
|
+| 5 | 创建订单商品实体 (orders_goods) | Pending |
|
|
|
+| 6 | 创建商户实体 (merchant) | Pending |
|
|
|
+| 7 | 创建供应商实体 (supplier) | Pending |
|
|
|
+| 8 | 创建用户卡实体 (user_card) | Pending |
|
|
|
+| 9 | 创建卡实体 (card) | Pending |
|
|
|
+| 10 | 创建收货地址实体 (delivery_address) | Pending |
|
|
|
+| 11 | 创建物流公司实体 (express_company) | Pending |
|
|
|
+| 12 | 创建配置实体 (config) | Pending |
|
|
|
+| 13 | 注册所有实体到数据源 | Pending |
|
|
|
+| 14 | 创建所有实体的通用CRUD路由 | Pending |
|
|
|
+| 15 | 注册所有路由到API | Pending |
|
|
|
+| 16 | 创建管理后台页面 | Pending |
|
|
|
+| 17 | 注册路由和菜单 | Pending |
|
|
|
+
|
|
|
+
|
|
|
+IMPORTANT: When task status changes, remember to call the `update_todo_list` tool to update your progress.
|
|
|
+
|
|
|
+</environment_details>
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+**Assistant:**
|
|
|
+
|
|
|
+现在创建商品实体的Zod Schema定义:
|
|
|
+
|
|
|
+<write_to_file>
|
|
|
+<path>src/server/modules/products/goods.schema.ts</path>
|
|
|
+<content>import { z } from '@hono/zod-openapi';
|
|
|
+
|
|
|
+// 商品信息Schema
|
|
|
+export const GoodsSchema = z.object({
|
|
|
+ id: z.number().int().positive().openapi({
|
|
|
+ description: '商品ID',
|
|
|
+ example: 1
|
|
|
+ }),
|
|
|
+ name: z.string().max(255).openapi({
|
|
|
+ description: '商品名称',
|
|
|
+ example: '精美商品'
|
|
|
+ }),
|
|
|
+ price: z.number().multipleOf(0.01).openapi({
|
|
|
+ description: '售卖价',
|
|
|
+ example: 99.99
|
|
|
+ }),
|
|
|
+ costPrice: z.number().multipleOf(0.01).openapi({
|
|
|
+ description: '成本价',
|
|
|
+ example: 50.00
|
|
|
+ }),
|
|
|
+ salesNum: z.number().int().min(0).openapi({
|
|
|
+ description: '销售数量',
|
|
|
+ example: 100
|
|
|
+ }),
|
|
|
+ clickNum: z.number().int().min(0).openapi({
|
|
|
+ description: '点击次数',
|
|
|
+ example: 1000
|
|
|
+ }),
|
|
|
+ categoryId1: z.number().int().min(0).openapi({
|
|
|
+ description: '一级类别id',
|
|
|
+ example: 1
|
|
|
+ }),
|
|
|
+ categoryId2: z.number().int().min(0).openapi({
|
|
|
+ description: '二级类别id',
|
|
|
+ example: 2
|
|
|
+ }),
|
|
|
+ categoryId3: z.number().int().min(0).openapi({
|
|
|
+ description: '三级类别id',
|
|
|
+ example: 3
|
|
|
+ }),
|
|
|
+ goodsType: z.number().int().min(1).max(2).openapi({
|
|
|
+ description: '订单类型 1实物产品 2虚拟产品',
|
|
|
+ example: 1
|
|
|
+ }),
|
|
|
+ supplierId: z.number().int().positive().nullable().openapi({
|
|
|
+ description: '所属供应商id',
|
|
|
+ example: 1
|
|
|
+ }),
|
|
|
+ image: z.string().max(255).nullable().openapi({
|
|
|
+ description: '商品主图',
|
|
|
+ example: 'https://example.com/image.jpg'
|
|
|
+ }),
|
|
|
+ slideImage: z.string().max(2000).nullable().openapi({
|
|
|
+ description: '商品轮播图(多个用,隔开)',
|
|
|
+ example: 'image1.jpg,image2.jpg,image3.jpg'
|
|
|
+ }),
|
|
|
+ detail: z.string().nullable().openapi({
|
|
|
+ description: '商品详情',
|
|
|
+ example: '<p>商品详细描述</p>'
|
|
|
+ }),
|
|
|
+ instructions: z.string().max(255).nullable().openapi({
|
|
|
+ description: '简介',
|
|
|
+ example: '优质商品,值得信赖'
|
|
|
+ }),
|
|
|
+ sort: z.number().int().min(0).openapi({
|
|
|
+ description: '排序',
|
|
|
+ example: 0
|
|
|
+ }),
|
|
|
+ state: z.number().int().min(1).max(2).openapi({
|
|
|
+ description: '状态1可用2不可用',
|
|
|
+ example: 1
|
|
|
+ }),
|
|
|
+ stock: z.number().int().min(0).openapi({
|
|
|
+ description: '库存',
|
|
|
+ example: 100
|
|
|
+ }),
|
|
|
+ spuId: z.number().int().min(0).openapi({
|
|
|
+ description: '主商品ID',
|
|
|
+ example: 0
|
|
|
+ }),
|
|
|
+ spuName: z.string().max(255).nullable().openapi({
|
|
|
+ description: '主商品名称',
|
|
|
+ example: null
|
|
|
+ }),
|
|
|
+ lowestBuy: z.number().int().min(1).openapi({
|
|
|
+ description: '最小起购量',
|
|
|
+ example: 1
|
|
|
+ }),
|
|
|
+ imageFileId: z.number().int().positive().nullable().openapi({
|
|
|
+ description: '商品主图文件ID',
|
|
|
+ example: 1
|
|
|
+ }),
|
|
|
+ imageFile: z.object({
|
|
|
+ id: z.number().int().positive().openapi({ description: '文件ID' }),
|
|
|
+ name: z.string().max(255).openapi({ description: '文件名', example: 'product.jpg' }),
|
|
|
+ fullUrl: z.string().openapi({ description: '文件完整URL', example: 'https://example.com/product.jpg' }),
|
|
|
+ type: z.string().nullable().openapi({ description: '文件类型', example: 'image/jpeg' }),
|
|
|
+ size: z.number().nullable().openapi({ description: '文件大小(字节)', example: 102400 })
|
|
|
+ }).nullable().optional().openapi({
|
|
|
+ description: '商品主图文件信息'
|
|
|
+ }),
|
|
|
+ createdAt: z.date().openapi({
|
|
|
+ description: '创建时间',
|
|
|
+ example: '2024-01-01T00:00:00Z'
|
|
|
+ }),
|
|
|
+ updatedAt: z.date().openapi({
|
|
|
+ description: '更新时间',
|
|
|
+ example: '2024-01-01T00:00:00Z'
|
|
|
+ })
|
|
|
+});
|
|
|
+
|
|
|
+// 创建商品DTO
|
|
|
+export const CreateGoodsDto = z.object({
|
|
|
+ name: z.string().max(255).openapi({
|
|
|
+ description: '商品名称',
|
|
|
+ example: '精美商品'
|
|
|
+ }),
|
|
|
+ price: z.coerce.number().multipleOf(0.01).openapi({
|
|
|
+ description: '售卖价',
|
|
|
+ example: 99.99
|
|
|
+ }),
|
|
|
+ costPrice: z.coerce.number().multipleOf(0.01).openapi({
|
|
|
+ description: '成本价',
|
|
|
+ example: 50.00
|
|
|
+ }),
|
|
|
+ categoryId1: z.coerce.number().int().min(0).openapi({
|
|
|
+ description: '一级类别id',
|
|
|
+ example: 1
|
|
|
+ }),
|
|
|
+ categoryId2: z.coerce.number().int().min(0).optional().openapi({
|
|
|
+ description: '二级类别id',
|
|
|
+ example: 2
|
|
|
+ }),
|
|
|
+ categoryId3: z.coerce.number().int().min(0).optional().openapi({
|
|
|
+ description: '三级类别id',
|
|
|
+ example: 3
|
|
|
+ }),
|
|
|
+ goodsType: z.coerce.number().int().min(1).max(2).default(1).openapi({
|
|
|
+ description: '订单类型 1实物产品 2虚拟产品',
|
|
|
+ example: 1
|
|
|
+ }),
|
|
|
+ supplierId: z.coerce.number().int().positive().optional().openapi({
|
|
|
+ description: '所属供应商id',
|
|
|
+ example: 1
|
|
|
+ }),
|
|
|
+ image: z.string().max(255).optional().openapi({
|
|
|
+ description: '商品主图',
|
|
|
+ example: 'https://example.com/image.jpg'
|
|
|
+ }),
|
|
|
+ slideImage: z.string().max(2000).optional().openapi({
|
|
|
+ description: '商品轮播图(多个用,隔开)',
|
|
|
+ example: 'image1.jpg,image2.jpg,image3.jpg'
|
|
|
+ }),
|
|
|
+ detail: z.string().optional().openapi({
|
|
|
+ description: '商品详情',
|
|
|
+ example: '<p>商品详细描述</p>'
|
|
|
+ }),
|
|
|
+ instructions: z.string().max(255).optional().openapi({
|
|
|
+ description: '简介',
|
|
|
+ example: '优质商品,值得信赖'
|
|
|
+ }),
|
|
|
+ sort: z.coerce.number().int().min(0).default(0).openapi({
|
|
|
+ description: '排序',
|
|
|
+ example: 0
|
|
|
+ }),
|
|
|
+ state: z.coerce.number().int().min(1).max(2).default(1).openapi({
|
|
|
+ description: '状态1可用2不可用',
|
|
|
+ example: 1
|
|
|
+ }),
|
|
|
+ stock: z.coerce.number().int().min(0).default(0).openapi({
|
|
|
+ description: '库存',
|
|
|
+ example: 100
|
|
|
+ }),
|
|
|
+ spuId: z.coerce.number().int().min(0).default(0).openapi({
|
|
|
+ description: '主商品ID',
|
|
|
+ example: 0
|
|
|
+ }),
|
|
|
+ spuName: z.string().max(255).optional().openapi({
|
|
|
+ description: '主商品名称',
|
|
|
+ example: null
|
|
|
+ }),
|
|
|
+ lowestBuy: z.coerce.number().int().min(1).default(1).openapi({
|
|
|
+ description: '最小起购量',
|
|
|
+ example: 1
|
|
|
+ }),
|
|
|
+ imageFileId: z.coerce.number().int().positive().optional().openapi({
|
|
|
+ description: '商品主图文件ID',
|
|
|
+ example: 1
|
|
|
+ })
|
|
|
+});
|
|
|
+
|
|
|
+// 更新商品DTO
|
|
|
+export const UpdateGoodsDto = z.object({
|
|
|
+ name: z.string().max(255).optional().openapi({
|
|
|
+ description: '商品名称',
|
|
|
+ example: '精美商品'
|
|
|
+ }),
|
|
|
+ price: z.coerce.number().multipleOf(0.01).optional().openapi({
|
|
|
+ description: '售卖价',
|
|
|
+ example: 99.99
|
|
|
+ }),
|
|
|
+ costPrice: z.coerce.number().multipleOf(0.01).optional().openapi({
|
|
|
+ description: '成本价',
|
|
|
+ example: 50.00
|
|
|
+ }),
|
|
|
+ categoryId1: z.coerce.number().int().min(0).optional().openapi({
|
|
|
+ description: '一级类别id',
|
|
|
+ example: 1
|
|
|
+ }),
|
|
|
+ categoryId2: z.coerce.number().int().min(0).optional().openapi({
|
|
|
+ description: '二级类别id',
|
|
|
+ example: 2
|
|
|
+ }),
|
|
|
+ categoryId3: z.coerce.number().int().min(0).optional().openapi({
|
|
|
+ description: '三级类别id',
|
|
|
+ example: 3
|
|
|
+ }),
|
|
|
+ goodsType: z.coerce.number().int().min(1).max(2).optional().openapi({
|
|
|
+ description: '订单类型 1实物产品 2虚拟产品',
|
|
|
+ example: 1
|
|
|
+ }),
|
|
|
+ supplierId: z.coerce.number().int().positive().optional().openapi({
|
|
|
+ description: '所属供应商id',
|
|
|
+ example: 1
|
|
|
+ }),
|
|
|
+ image: z.string().max(255).optional().openapi({
|
|
|
+ description: '商品主图',
|
|
|
+ example: 'https://example.com/image.jpg'
|
|
|
+ }),
|
|
|
+ slideImage: z.string().max(2000).optional().openapi({
|
|
|
+ description: '商品轮播图(多个用,隔开)',
|
|
|
+ example: 'image1.jpg,image2.jpg,image3.jpg'
|
|
|
+ }),
|
|
|
+ detail: z.string().optional().openapi({
|
|
|
+ description: '商品详情',
|
|
|
+ example: '<p>商品详细描述</p>'
|
|
|
+ }),
|
|
|
+ instructions: z.string().max(255).optional().openapi({
|
|
|
+ description: '简介',
|
|
|
+ example: '优质商品,值得信赖'
|
|
|
+ }),
|
|
|
+ sort: z.coerce.number().int().min(0).optional().openapi({
|
|
|
+ description: '排序',
|
|
|
+ example: 0
|
|
|
+ }),
|
|
|
+ state: z.coerce.number().int().min(1).max(2).optional().openapi({
|
|
|
+ description: '状态1可用2不可用',
|
|
|
+ example: 1
|
|
|
+ }),
|
|
|
+ stock: z.coerce.number().int().min(0).optional().openapi({
|
|
|
+ description: '库存',
|
|
|
+ example: 100
|
|
|
+ }),
|
|
|
+ spuId: z.coerce.number().int().min(0).optional().openapi({
|
|
|
+ description: '主商品ID',
|
|
|
+ example: 0
|
|
|
+ }),
|
|
|
+ spuName: z.string().max(255).optional().openapi({
|
|
|
+ description: '主商品名称',
|
|
|
+ example: null
|
|
|
+ }),
|
|
|
+ lowestBuy: z.coerce.number().int().min(1).optional().openapi({
|
|
|
+ description: '最小起购量',
|
|
|
+ example: 1
|
|
|
+ }),
|
|
|
+ imageFileId: z.coerce.number().int().positive().optional().openapi({
|
|
|
+ description: '商品主图文件ID',
|
|
|
+ example: 1
|
|
|
+ })
|
|
|
+});
|
|
|
+</content>
|
|
|
+<line_count>150</line_count>
|
|
|
+</write_to_file>
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+**User:**
|
|
|
+
|
|
|
+[write_to_file for 'src/server/modules/products/goods.schema.ts'] Result:
|
|
|
+<file_write_result>
|
|
|
+<path>src/server/modules/products/goods.schema.ts</path>
|
|
|
+<operation>created</operation>
|
|
|
+<notice>
|
|
|
+<i>You do not need to re-read the file, as you have seen all changes</i>
|
|
|
+<i>Proceed with the task using these changes as the new baseline.</i>
|
|
|
+</notice>
|
|
|
+</file_write_result>
|
|
|
+
|
|
|
+<environment_details>
|
|
|
+# VSCode Visible Files
|
|
|
+docs/旧数据表.sql
|
|
|
+
|
|
|
+# VSCode Open Tabs
|
|
|
+docs/旧数据表.sql
|
|
|
+
|
|
|
+# Current Time
|
|
|
+Current time in ISO 8601 UTC format: 2025-08-13T03:13:52.757Z
|
|
|
+User time zone: UTC, UTC+0:00
|
|
|
+
|
|
|
+# Current Cost
|
|
|
+$1.46
|
|
|
+
|
|
|
+# Current Mode
|
|
|
+<slug>code</slug>
|
|
|
+<name>💻 代码</name>
|
|
|
+<model>d8d-ai-model</model>
|
|
|
+====
|
|
|
+
|
|
|
+REMINDERS
|
|
|
+
|
|
|
+Below is your current list of reminders for this task. Keep them updated as you progress.
|
|
|
+
|
|
|
+| # | Content | Status |
|
|
|
+|---|---------|--------|
|
|
|
+| 1 | 分析旧数据表结构 | Completed |
|
|
|
+| 2 | 创建商品实体 (goods) | Pending |
|
|
|
+| 3 | 创建商品分类实体 (category) | Pending |
|
|
|
+| 4 | 创建订单实体 (orders) | Pending |
|
|
|
+| 5 | 创建订单商品实体 (orders_goods) | Pending |
|
|
|
+| 6 | 创建商户实体 (merchant) | Pending |
|
|
|
+| 7 | 创建供应商实体 (supplier) | Pending |
|
|
|
+| 8 | 创建用户卡实体 (user_card) | Pending |
|
|
|
+| 9 | 创建卡实体 (card) | Pending |
|
|
|
+| 10 | 创建收货地址实体 (delivery_address) | Pending |
|
|
|
+| 11 | 创建物流公司实体 (express_company) | Pending |
|
|
|
+| 12 | 创建配置实体 (config) | Pending |
|
|
|
+| 13 | 注册所有实体到数据源 | Pending |
|
|
|
+| 14 | 创建所有实体的通用CRUD路由 | Pending |
|
|
|
+| 15 | 注册所有路由到API | Pending |
|
|
|
+| 16 | 创建管理后台页面 | Pending |
|
|
|
+| 17 | 注册路由和菜单 | Pending |
|
|
|
+
|
|
|
+
|
|
|
+IMPORTANT: When task status changes, remember to call the `update_todo_list` tool to update your progress.
|
|
|
+
|
|
|
+</environment_details>
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+**Assistant:**
|
|
|
+
|
|
|
+<update_todo_list>
|
|
|
+<todos>
|
|
|
+[x] 分析旧数据表结构
|
|
|
+[x] 创建商品实体 (goods)
|
|
|
+[ ] 创建商品分类实体 (category)
|
|
|
+[ ] 创建订单实体 (orders)
|
|
|
+[ ] 创建订单商品实体 (orders_goods)
|
|
|
+[ ] 创建商户实体 (merchant)
|
|
|
+[ ] 创建供应商实体 (supplier)
|
|
|
+[ ] 创建用户卡实体 (user_card)
|
|
|
+[ ] 创建卡实体 (card)
|
|
|
+[ ] 创建收货地址实体 (delivery_address)
|
|
|
+[ ] 创建物流公司实体 (express_company)
|
|
|
+[ ] 创建配置实体 (config)
|
|
|
+[ ] 注册所有实体到数据源
|
|
|
+[ ] 创建所有实体的通用CRUD路由
|
|
|
+[ ] 注册所有路由到API
|
|
|
+[ ] 创建管理后台页面
|
|
|
+[ ] 注册路由和菜单
|
|
|
+</todos>
|
|
|
+</update_todo_list>
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+**User:**
|
|
|
+
|
|
|
+[update_todo_list] Result:
|
|
|
+Todo list updated successfully.
|
|
|
+<environment_details>
|
|
|
+# VSCode Visible Files
|
|
|
+docs/旧数据表.sql
|
|
|
+
|
|
|
+# VSCode Open Tabs
|
|
|
+docs/旧数据表.sql
|
|
|
+
|
|
|
+# Current Time
|
|
|
+Current time in ISO 8601 UTC format: 2025-08-13T03:14:08.469Z
|
|
|
+User time zone: UTC, UTC+0:00
|
|
|
+
|
|
|
+# Current Cost
|
|
|
+$1.84
|
|
|
+
|
|
|
+# Current Mode
|
|
|
+<slug>code</slug>
|
|
|
+<name>💻 代码</name>
|
|
|
+<model>d8d-ai-model</model>
|
|
|
+====
|
|
|
+
|
|
|
+REMINDERS
|
|
|
+
|
|
|
+Below is your current list of reminders for this task. Keep them updated as you progress.
|
|
|
+
|
|
|
+| # | Content | Status |
|
|
|
+|---|---------|--------|
|
|
|
+| 1 | 分析旧数据表结构 | Completed |
|
|
|
+| 2 | 创建商品实体 (goods) | Completed |
|
|
|
+| 3 | 创建商品分类实体 (category) | Pending |
|
|
|
+| 4 | 创建订单实体 (orders) | Pending |
|
|
|
+| 5 | 创建订单商品实体 (orders_goods) | Pending |
|
|
|
+| 6 | 创建商户实体 (merchant) | Pending |
|
|
|
+| 7 | 创建供应商实体 (supplier) | Pending |
|
|
|
+| 8 | 创建用户卡实体 (user_card) | Pending |
|
|
|
+| 9 | 创建卡实体 (card) | Pending |
|
|
|
+| 10 | 创建收货地址实体 (delivery_address) | Pending |
|
|
|
+| 11 | 创建物流公司实体 (express_company) | Pending |
|
|
|
+| 12 | 创建配置实体 (config) | Pending |
|
|
|
+| 13 | 注册所有实体到数据源 | Pending |
|
|
|
+| 14 | 创建所有实体的通用CRUD路由 | Pending |
|
|
|
+| 15 | 注册所有路由到API | Pending |
|
|
|
+| 16 | 创建管理后台页面 | Pending |
|
|
|
+| 17 | 注册路由和菜单 | Pending |
|
|
|
+
|
|
|
+
|
|
|
+IMPORTANT: When task status changes, remember to call the `update_todo_list` tool to update your progress.
|
|
|
+
|
|
|
+</environment_details>
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+**Assistant:**
|
|
|
+
|
|
|
+现在创建商品分类实体:
|
|
|
+
|
|
|
+<write_to_file>
|
|
|
+<path>src/server/modules/products/category.entity.ts</path>
|
|
|
+<content>import { Entity, PrimaryGeneratedColumn, Column, ManyToOne, JoinColumn } from 'typeorm';
|
|
|
+import { File } from '@/server/modules/files/file.entity';
|
|
|
+
|
|
|
+@Entity('category')
|
|
|
+export class Category {
|
|
|
+ @PrimaryGeneratedColumn({ unsigned: true })
|
|
|
+ id!: number;
|
|
|
+
|
|
|
+ @Column({ name: 'name', type: 'varchar', length: 255, comment: '类别名称' })
|
|
|
+ name!: string;
|
|
|
+
|
|
|
+ @Column({ name: 'parent_id', type: 'int', default: 0, comment: '上级id' })
|
|
|
+ parentId!: number;
|
|
|
+
|
|
|
+ @Column({ name: 'level', type: 'int', default: 0, comment: '层级' })
|
|
|
+ level!: number;
|
|
|
+
|
|
|
+ @Column({ name: 'state', type: 'int', default: 1, comment: '状态1可用2不可用' })
|
|
|
+ state!: number;
|
|
|
+
|
|
|
+ @Column({ name: 'image', type: 'varchar', length: 255, nullable: true, comment: '分类图片' })
|
|
|
+ image!: string | null;
|
|
|
+
|
|
|
+ @Column({ name: 'image_file_id', type: 'int', unsigned: true, nullable: true, comment: '分类图片文件ID' })
|
|
|
+ imageFileId!: number | null;
|
|
|
+
|
|
|
+ @ManyToOne(() => File, { nullable: true })
|
|
|
+ @JoinColumn({ name: 'image_file_id', referencedColumnName: 'id' })
|
|
|
+ imageFile!: File | null;
|
|
|
+
|
|
|
+ @Column({ name: 'created_at', type: 'timestamp', default: () => 'CURRENT_TIMESTAMP', comment: '创建时间' })
|
|
|
+ createdAt!: Date;
|
|
|
+
|
|
|
+ @Column({ name: 'updated_at', type: 'timestamp', default: () => 'CURRENT_TIMESTAMP', onUpdate: 'CURRENT_TIMESTAMP', comment: '更新时间' })
|
|
|
+ updatedAt!: Date;
|
|
|
+}
|
|
|
+</content>
|
|
|
+<line_count>33</line_count>
|
|
|
+</write_to_file>
|
|
|
+
|