--- category: schema title: YSS项目Parse Server数据范式 - Product表统一空间管理 subtitle: 映三色设计师项目管理系统完整数据表结构(基于Product表的空间管理版本) name: 'yss-schemas-product-space' label: database --- # Parse Server 数据范式 - 映三色项目管理系统(Product表统一空间管理) ## 概述 本文档定义了映三色(YSS)设计师项目管理系统的完整Parse Server数据范式。系统采用**多租户架构**,以Company为核心,支持客服、设计师、组长等多角色协作的全流程项目管理。 **核心特性**: - 🏢 多租户架构,以Company为核心租户隔离 - 👥 统一员工表(Profile)和客户表(ContactInfo) - 📋 项目与群聊灵活关联(Project ←→ GroupChat) - 🏠 **Product表统一空间管理**:通过Product表实现多空间设计产品管理 - 🎨 设计师项目全生命周期管理 - 💰 财务报价与结算流程 - 📊 质量控制与客户反馈 **空间管理优化**: - 🎯 **Product即空间**:每个Product代表一个空间的设计产品 - 💰 **产品报价**:通过Product的`.quotation`字段管理空间级报价 - 📁 **文件分类**:ProjectFile通过`.category`区分panorama、delivery等类型 - 👥 **设计师分配**:通过Product的`.profile`字段直接关联负责设计师 - 🎯 **产品需求**:通过Product的`.requirements`字段管理空间需求 - ⭐ **产品评价**:通过Product的`.reviews`字段管理空间评价 --- ## 数据表关系图 - Department 项目组(部门) - name String 项目组名称 - type "project" 项目组 - leader Pointer 组长 - company Pointer 指向当前帐套 ```plantuml @startuml !define TABLE(name,desc) class name as "desc" << (T,#FFAAAA) >> !define FIELD(name,type) name : type skinparam classAttributeIconSize 0 skinparam class { BackgroundColor LightYellow BorderColor Black ArrowColor Black } ' ============ 核心租户与人员 ============ TABLE(Company, "Company\n企业表") { FIELD(objectId, String) FIELD(name, String) FIELD(corpId, String) FIELD(data, Object) FIELD(isDeleted, Boolean) } TABLE(Profile, "Profile\n员工档案表") { FIELD(objectId, String) FIELD(name, String) FIELD(mobile, String) FIELD(department, Pointer→Department) FIELD(company, Pointer→Company) FIELD(userId, String) FIELD(roleName, String) FIELD(data, Object) FIELD(isDeleted, Boolean) } TABLE(ContactInfo, "ContactInfo\n客户信息表") { FIELD(objectId, String) FIELD(name, String) FIELD(mobile, String) FIELD(company, Pointer→Company) FIELD(external_userid, String) FIELD(source, String) FIELD(data, Object) FIELD(isDeleted, Boolean) } ' ============ 企微集成 ============ TABLE(GroupChat, "GroupChat\n企微群聊表") { FIELD(objectId, String) FIELD(chat_id, String) FIELD(name, String) FIELD(company, Pointer→Company) FIELD(project, Pointer→Project) FIELD(member_list, Array) FIELD(joinUrl, String) FIELD(data, Object) FIELD(isDeleted, Boolean) } TABLE(ProjectGroup, "ProjectGroup\n项目群组关联表") { FIELD(objectId, String) FIELD(project, Pointer→Project) FIELD(groupChat, Pointer→GroupChat) FIELD(isPrimary, Boolean) FIELD(createdAt, Date) } ' ============ 项目模块 ============ TABLE(Project, "Project\n项目表") { FIELD(objectId, String) FIELD(title, String) FIELD(company, Pointer→Company) FIELD(customer, Pointer→ContactInfo) FIELD(assignee, Pointer→Profile) FIELD(status, String) FIELD(currentStage, String) FIELD(deadline, Date) FIELD(data, Object) FIELD(isDeleted, Boolean) } ' ============ 核心创新:Product表统一空间管理 ============ TABLE(Product, "Product\n空间设计产品表") { FIELD(objectId, String) FIELD(project, Pointer→Project) FIELD(company, Pointer→Company) FIELD(profile, Pointer→Profile) FIELD(stage, String) FIELD(processType, String) FIELD(productName, String) FIELD(productType, String) FIELD(status, String) FIELD(fileUrl, String) FIELD(reviewStatus, String) FIELD(space, Object) FIELD(quotation, Object) FIELD(requirements, Object) FIELD(reviews, Array) FIELD(estimatedBudget, Number) FIELD(estimatedDuration, Number) FIELD(order, Number) FIELD(data, Object) FIELD(isDeleted, Boolean) } TABLE(ProjectRequirement, "ProjectRequirement\n需求信息表") { FIELD(objectId, String) FIELD(project, Pointer→Project) FIELD(company, Pointer→Company) FIELD(spaces, Array) FIELD(designRequirements, Object) FIELD(materialAnalysis, Object) FIELD(data, Object) FIELD(isDeleted, Boolean) } TABLE(ProjectTeam, "ProjectTeam\n项目团队表") { FIELD(objectId, String) FIELD(project, Pointer→Project) FIELD(profile, Pointer→Profile) FIELD(role, String) FIELD(workload, Number) FIELD(isDeleted, Boolean) } ' ============ 文件管理(简化版) ============ TABLE(ProjectFile, "ProjectFile\n项目文件表") { FIELD(objectId, String) FIELD(project, Pointer→Project) FIELD(product, Pointer→Product) FIELD(attach, Pointer→Attachment) FIELD(uploadedBy, Pointer→Profile) FIELD(stage, String) FIELD(data, Object) FIELD(isDeleted, Boolean) } ' ============ 财务模块 ============ TABLE(ProjectPayment, "ProjectPayment\n项目付款表") { FIELD(objectId, String) FIELD(project, Pointer→Project) FIELD(company, Pointer→Company) FIELD(type, String) FIELD(stage, String) FIELD(method, String) FIELD(amount, Number) FIELD(currency, String) FIELD(percentage, Number) FIELD(paymentDate, Date) FIELD(dueDate, Date) FIELD(recordedDate, Date) FIELD(status, String) FIELD(voucherFile, Pointer→ProjectFile) FIELD(voucherUrl, String) FIELD(transactionId, String) FIELD(paymentReference, String) FIELD(paidBy, Pointer→ContactInfo) FIELD(recordedBy, Pointer→Profile) FIELD(verifiedBy, Pointer→Profile) FIELD(description, String) FIELD(notes, String) FIELD(relatedStage, String) FIELD(product, Pointer→Product) FIELD(autoReminderSent, Boolean) FIELD(reminderCount, Number) FIELD(data, Object) FIELD(isDeleted, Boolean) } ' ============ 质量与反馈 ============ TABLE(ProjectFeedback, "ProjectFeedback\n客户反馈表") { FIELD(objectId, String) FIELD(project, Pointer→Project) FIELD(customer, Pointer→ContactInfo) FIELD(product, Pointer→Product) FIELD(stage, String) FIELD(feedbackType, String) FIELD(content, String) FIELD(rating, Number) FIELD(status, String) FIELD(data, Object) FIELD(isDeleted, Boolean) } TABLE(ProjectIssue, "ProjectIssue\n项目问题追踪表") { FIELD(objectId, String) FIELD(project, Pointer→Project) FIELD(product, Pointer→Product) FIELD(creator, Pointer→Profile) // 创建人 FIELD(assignee, Pointer→Profile) // 责任人 FIELD(title, String) // 问题标题 FIELD(description, String) // 问题描述 FIELD(relatedSpace, String) // 相关空间 FIELD(relatedStage, String) // 相关阶段 FIELD(relatedContentType, String) // 相关内容类型 (白模/软装/渲染/后期) FIELD(relatedFiles, Array) // 相关项目文件 FIELD(priority, String) // 优先程度 (低/中/高/紧急) FIELD(issueType, String) // 问题类型 (投诉/建议/改图) FIELD(dueDate, Date) // 截止时间 FIELD(status, String) // 状态 (待处理/处理中/已解决/已关闭) FIELD(resolution, String) // 解决方案 FIELD(lastReminderAt, Date) // 最后催单时间 FIELD(reminderCount, Number) // 催单次数 FIELD(data, Object) // 扩展数据 FIELD(isDeleted, Boolean) } ' ============ 跟进记录 ============ TABLE(ContactFollow, "ContactFollow\n跟进记录表") { FIELD(objectId, String) FIELD(project, Pointer→Project) FIELD(product, Pointer→Product) FIELD(sender, Pointer→Profile/ContactInfo) FIELD(content, String) FIELD(type, String) FIELD(stage, String) FIELD(attachments, Array) FIELD(data, Object) FIELD(isDeleted, Boolean) } ' ============ 关系连线 ============ ' Company 一对多关系 Company "1" --> "n" Profile : 企业员工 Company "1" --> "n" ContactInfo : 企业客户 Company "1" --> "n" Project : 企业项目 Company "1" --> "n" GroupChat : 企业群聊 ' 项目核心关系 Project "n" --> "1" Company : 所属企业 Project "n" --> "1" ContactInfo : 客户 Project "n" --> "1" Profile : 负责人(assignee) Project "1" --> "1" ProjectRequirement : 需求信息 Project "1" <--> "n" GroupChat : ProjectGroup\n群聊关联 Project "1" --> "n" ProjectTeam : 项目团队 ' Product表统一空间管理关系 Project "1" --> "n" Product : 空间设计产品 Product "n" --> "1" Profile : 负责设计师 Product "1" --> "n" ProjectFile : 产品文件 Product "1" --> "n" ProjectFeedback : 产品反馈 Product "1" --> "n" ProjectIssue : 产品异常 Product "1" --> "n" ContactFollow : 产品跟进 ' 交付与财务 Project "1" --> "n" ProjectFile : 项目文件 Project "1" --> "n" ProjectPayment : 项目付款 ProjectPayment "1" --> "1" ProjectFile : 付款凭证 ProjectPayment "1" --> "1" ContactInfo : 付款人 ProjectPayment "1" --> "1" Profile : 记录人/验证人 Product "1" --> "n" ProjectPayment : 产品级付款 ' 质量与沟通 Project "1" --> "n" ProjectFeedback : 客户反馈 Project "1" --> "n" ProjectIssue : 异常记录 Project "1" --> "n" ContactFollow : 跟进记录 ' 群聊关系 GroupChat "n" --> "1" Company : 所属企业 GroupChat "n" --> "1" Project : 关联项目(可选) @enduml ``` --- ## 核心数据表详解 ### 1. Company(企业表) **用途**: 多租户系统的核心,所有数据通过 company 字段进行租户隔离。 | 字段名 | 类型 | 必填 | 说明 | 示例值 | |--------|------|------|------|--------| | objectId | String | 是 | 主键ID | "cDL6R1hgSi" | | name | String | 是 | 企业名称 | "映三色设计" | | corpId | String | 否 | 企业微信CorpID | "ww1234567890" | | data | Object | 否 | 扩展数据 | { settings: {...}, modules: [...] } | | isDeleted | Boolean | 否 | 软删除标记 | false | | createdAt | Date | 自动 | 创建时间 | 2024-01-01T00:00:00.000Z | | updatedAt | Date | 自动 | 更新时间 | 2024-01-01T00:00:00.000Z | --- ### 2. Profile(员工档案表) **用途**: 存储企业员工档案信息,统一管理客服、设计师、组长等所有角色。 | 字段名 | 类型 | 必填 | 说明 | 示例值 | |--------|------|------|------|--------| | objectId | String | 是 | 主键ID | "prof001" | | name | String | 是 | 员工姓名 | "张三" | | mobile | String | 否 | 手机号 | "13800138000" | | department | Pointer | 是 | 所属小组 | → Department | | company | Pointer | 是 | 所属企业 | → Company | | userId | String | 否 | 企微UserID | "zhangsan" | | roleName | String | 是 | 员工角色 | "客服" / "组员" / "组长" | | data | Object | 否 | 扩展数据 | { avatar, department, skills, ... } | | isDeleted | Boolean | 否 | 软删除标记 | false | | createdAt | Date | 自动 | 创建时间 | 2024-01-01T00:00:00.000Z | | updatedAt | Date | 自动 | 更新时间 | 2024-01-01T00:00:00.000Z | **role 枚举值**: - `客服`: 客户服务人员,负责接单、跟进 - `组员`: 设计师,负责具体设计工作 - `组长`: 团队负责人,负责审核、分配 - `财务`: 财务人员 - `人事`: 人事人员 - `管理员`: 系统管理员 --- ### 3. ContactInfo(客户信息表) **用途**: 统一管理所有客户信息,支持企微外部联系人同步。 | 字段名 | 类型 | 必填 | 说明 | 示例值 | |--------|------|------|------|--------| | objectId | String | 是 | 主键ID | "contact001" | | name | String | 是 | 客户姓名 | "李四" | | mobile | String | 否 | 手机号 | "13900139000" | | company | Pointer | 是 | 所属企业 | → Company | | external_userid | String | 否 | 企微外部联系人ID | "wmxxx" | | source | String | 否 | 来源渠道 | "朋友圈" / "信息流" / "转介绍" | | data | Object | 否 | 扩展数据 | { avatar, wechat, tags, ... } | | isDeleted | Boolean | 否 | 软删除标记 | false | | createdAt | Date | 自动 | 创建时间 | 2024-01-01T00:00:00.000Z | | updatedAt | Date | 自动 | 更新时间 | 2024-01-01T00:00:00.000Z | --- ### 4. Project(项目表) **用途**: 项目管理的核心表,记录设计项目的全生命周期信息。 | 字段名 | 类型 | 必填 | 说明 | 示例值 | |--------|------|------|------|--------| | objectId | String | 是 | 主键ID | "proj001" | | title | String | 是 | 项目标题 | "李总现代简约全案" | | company | Pointer | 是 | 所属企业 | → Company | | customer | Pointer | 是 | 客户 | → ContactInfo | | assignee | Pointer | 否 | 负责设计师 | → Profile | | status | String | 是 | 项目状态 | "进行中" | | currentStage | String | 是 | 当前阶段 | "建模" | | deadline | Date | 否 | 截止时间 | 2024-12-31T00:00:00.000Z | | data | Object | 否 | 扩展数据 | { requirements, stageHistory, ... } | | isDeleted | Boolean | 否 | 软删除标记 | false | | createdAt | Date | 自动 | 创建时间 | 2024-01-01T00:00:00.000Z | | updatedAt | Date | 自动 | 更新时间 | 2024-01-01T00:00:00.000Z | --- ### 5. Product(空间设计产品表)⭐ **功能描述**: **核心创新** - 统一管理空间设计产品,每个Product代表一个空间的设计产品(如"李总主卧设计"、"王总客厅设计"),包含空间信息、报价、需求、评价等全生命周期数据。 **字段说明**: | 字段名 | 类型 | 必填 | 说明 | 示例值 | |--------|------|------|------|--------| | objectId | String | 是 | 主键ID | "prod001" | | project | Pointer | 是 | 所属项目 | → Project | | company | Pointer | 是 | 所属企业 | → Company | | **profile** | **Pointer** | **是** | **负责设计师** | **→ Profile** | | stage | String | 是 | 设计阶段 | "建模" / "渲染" / "后期" | | processType | String | 否 | 工序类型 | "modeling" / "rendering" | | **productName** | **String** | **是** | **产品名称** | **"李总主卧设计"** | | **productType** | **String** | **是** | **空间类型** | **"bedroom"** | | status | String | 是 | 产品状态 | "进行中" | | fileUrl | String | 否 | 主要效果图URL | "https://..." | | reviewStatus | String | 是 | 审核状态 | "pending" / "approved" | | **space** | **Object** | **否** | **空间信息** | **{name, area, dimensions}** | | **quotation** | **Object** | **否** | **产品报价** | **{price, breakdown}** | | **requirements** | **Object** | **否** | **设计需求** | **{color, material}** | | **reviews** | **Array** | **否** | **产品评价** | **[{rating, comments}]** | | estimatedBudget | Number | 否 | 预估预算 | 35000 | | estimatedDuration | Number | 否 | 预估工期(天) | 7 | | order | Number | 否 | 排序顺序 | 1 | | data | Object | 否 | 扩展数据 | { version, progress, ... } | | isDeleted | Boolean | 否 | 软删除标记 | false | **productType 枚举值**: - `living_room`: 客厅 - `bedroom`: 卧室 - `kitchen`: 厨房 - `bathroom`: 卫生间 - `dining_room`: 餐厅 - `study`: 书房 - `balcony`: 阳台 - `corridor`: 走廊 - `storage`: 储物间 - `entrance`: 玄关 - `other`: 其他 **status 枚举值**: - `not_started`: 未开始 - `in_progress`: 进行中 - `awaiting_review`: 待审核 - `completed`: 已完成 - `blocked`: 已阻塞 - `delayed`: 已延期 **space 字段结构示例**: ```json { "spaceName": "主卧", "area": 18.5, "dimensions": { "length": 4.5, "width": 4.1, "height": 2.8 }, "features": ["朝南", "飘窗", "独立卫浴"], "constraints": ["承重墙不可动"], "priority": "high", "complexity": "medium" } ``` **quotation 字段结构示例**: ```json { "price": 35000, "currency": "CNY", "breakdown": { "design": 15000, "modeling": 10000, "rendering": 8000, "softDecor": 2000 }, "unitPrice": 1891, "estimatedDays": 7, "status": "approved", "approvedBy": {"__type": "Pointer", "className": "Profile", "objectId": "prof001"}, "validUntil": "2024-12-31T00:00:00.000Z" } ``` **requirements 字段结构示例**: ```json { "colorRequirement": { "primaryHue": 180, "saturation": 45, "temperature": "暖色调", "colorDistribution": [ {"hex": "#F5F5DC", "percentage": 40, "name": "米白色"}, {"hex": "#8B4513", "percentage": 30, "name": "原木色"} ] }, "materialRequirement": { "preferred": ["实木", "环保材料"], "avoid": ["塑料", "合成材料"], "budget": { "min": 20000, "max": 40000 } }, "lightingRequirement": { "naturalLight": "充足", "lightColor": "暖白", "specialRequirements": ["床头阅读灯", "氛围灯"] }, "specificRequirements": [ "需要大储物空间", "独立卫浴", "飘窗设计" ], "referenceImages": ["https://...", "https://..."] } ``` **reviews 字段结构示例**: ```json [ { "reviewId": "review001", "satisfactionScore": 4.5, "spaceSpecificRatings": { "design": 5, "functionality": 4, "material": 4, "lighting": 5 }, "usageFeedback": { "positive": ["储物空间充足", "光线舒适"], "improvements": ["可以增加插座数量"] }, "comments": "整体设计很满意,储物功能强大", "afterPhotos": ["https://...", "https://..."], "submittedAt": "2024-11-15T10:00:00.000Z", "submittedBy": {"__type": "Pointer", "className": "ContactInfo", "objectId": "contact001"} } ] ``` **使用场景示例**: ```typescript // 创建空间设计产品 const Product = Parse.Object.extend("Product"); const product = new Product(); product.set("project", project.toPointer()); product.set("profile", designer.toPointer()); product.set("productName", "李总主卧设计"); product.set("productType", "bedroom"); product.set("stage", "modeling"); // 设置空间信息 product.set("space", { spaceName: "主卧", area: 18.5, dimensions: { length: 4.5, width: 4.1, height: 2.8 }, features: ["朝南", "飘窗", "独立卫浴"] }); // 设置产品报价 product.set("quotation", { price: 35000, currency: "CNY", breakdown: { design: 15000, modeling: 10000, rendering: 8000, softDecor: 2000 }, status: "pending" }); await product.save(); // 查询项目的所有空间设计产品 const productQuery = new Parse.Query("Product"); productQuery.equalTo("project", projectId); productQuery.notEqualTo("isDeleted", true); productQuery.ascending("order"); const products = await productQuery.find(); // 查询设计师负责的空间产品 const designerProductQuery = new Parse.Query("Product"); designerProductQuery.equalTo("profile", designerId); designerProductQuery.equalTo("status", "in_progress"); const designerProducts = await designerProductQuery.find(); ``` --- ### 6. ProjectFile(项目文件表) **用途**: 存储项目相关的所有文件,**简化设计**,通过 `.category` 字段区分文件类型。 | 字段名 | 类型 | 必填 | 说明 | 示例值 | |--------|------|------|------|--------| | objectId | String | 是 | 主键ID | "file001" | | project | Pointer | 是 | 所属项目 | → Project | | **product** | **Pointer** | **否** | **关联空间产品** | **→ Product** | | attach | Pointer | 是 | 附件 | → Attachment | NovaFile.id为Attachment.objectId| | uploadedBy | Pointer | 是 | 上传人 | → Profile | | stage | String | 否 | 关联阶段 | "需求沟通" | | category | String | 否 | 关联阶段 | "需求沟通" | | data | Object | 否 | 扩展数据 | { thumbnailUrl, ... } | | analysis | Object | 否 | 分析结果 | 详见下方 `analysis.color` 结构 | | isDeleted | Boolean | 否 | 软删除标记 | false | | createdAt | Date | 自动 | 创建时间 | 2024-01-01T00:00:00.000Z | | updatedAt | Date | 自动 | 更新时间 | 2024-01-01T00:00:00.000Z | **stage 枚举值** - `订单分配`: 'order' - `方案深化`: 'requirements' - `交付执行`: 'delivery' - `售后归档`: 'aftercare' **category 枚举值**: - `quotation`: 财务凭据 - `panorama`: 全景素材 - `delivery`: 交付文件 - `reference`: 参考文件 - `requirement`: 需求文件 **analysis.color - 色彩分析结果结构** 用于存放“色彩分析插件(color-get)”生成的分析报告,并支持重新分析覆盖。该结构与组件内 `ColorAnalysisReport` 对齐,并补充元信息。 ```json { "version": "1.0", // 结构版本,便于未来演进 "source": "color-get", // 生成来源(组件/脚本/服务) "pixelSize": 100, // 马赛克像素块大小(用于重现) "createdAt": "2025-10-20T12:00:00.000Z", // 生成时间 "palette": [ // 主色卡(按占比降序,最多20) { "rgb": { "r": 240, "g": 200, "b": 160 }, "hex": "#F0C8A0", "percentage": 28.5 } ], "mosaicUrl": "data:image/png;base64,....", // 马赛克图(可选,dataURL 或存储链接) "metrics": { "warmCoolBalance": 12.0, // 冷暖平衡:-100(冷) 到 100(暖) "averageBrightness": 56.0, // 平均亮度:0-100 "averageSaturation": 42.5, // 平均饱和度:0-100 "diversity": 18 // 色彩多样度(主色数量) }, "histogram": { "brightnessBins": [0, 1, 3, 5, 8, 12, 9, 6, 3, 1], "saturationBins": [0, 0, 2, 4, 7, 10, 9, 5, 2, 1] }, "splitPoints": [ // 色彩拆分散点(冷暖/明暗/占比/色值) { "temp": 14.2, "brightness": 62.1, "size": 3.5, "color": "#F0C8A0" } ] } ``` **读写约定** - 写入:将以上对象保存至 `ProjectFile.analysis.color`。 - 读取:若存在 `analysis.color`,组件直接使用并渲染(无需重复计算)。 - 重新分析:覆盖同一字段,保留 `version`、`source`、`pixelSize` 与 `createdAt` 更新。 - 存储位置:优先内嵌对象;如需持久化图像(大体积 `mosaicUrl`),可改为文件存储链接,并在此字段写入其URL。 **fileType 枚举值**: - `cad`: CAD图纸 - `reference`: 参考图片 - `document`: 文档资料 - `contract`: 合同文件 - `voucher`: 付款凭证 - `other`: 其他 **使用场景示例**: ```typescript // 上传空间产品相关的全景图文件 const ProjectFile = Parse.Object.extend("ProjectFile"); const file = new ProjectFile(); file.set("project", project.toPointer()); file.set("product", product.toPointer()); // 关联到具体空间产品 file.set("category", "panorama"); // 标记为全景图文件 file.set("fileName", "主卧720全景图.jpg"); file.set("uploadedBy", profile.toPointer()); await file.save(); // 查询空间产品的所有全景图文件 const panoramaQuery = new Parse.Query("ProjectFile"); panoramaQuery.equalTo("product", productId); panoramaQuery.equalTo("category", "panorama"); panoramaQuery.notEqualTo("isDeleted", true); const panoramaFiles = await panoramaQuery.find(); // 查询空间产品的所有报价文件 const quotationQuery = new Parse.Query("ProjectFile"); quotationQuery.equalTo("product", productId); quotationQuery.equalTo("category", "quotation"); const quotationFiles = await quotationQuery.find(); ``` --- ### 7. ProjectPayment(项目付款表)⭐ **功能描述**: **统一的项目付款管理表**,整合了原有的 ProjectSettlement 和 ProjectVoucher 两张表的功能。每条记录代表一次具体的付款行为,包含付款类型、金额、方式、凭证等完整信息,支持项目级和产品级付款管理。 **字段说明**: | 字段名 | 类型 | 必填 | 说明 | 示例值 | |--------|------|------|------|--------| | objectId | String | 是 | 主键ID | "payment001" | | project | Pointer | 是 | 所属项目 | → Project | | company | Pointer | 是 | 所属企业 | → Company | | **type** | **String** | **是** | **付款类型** | **"advance" / "milestone" / "final" / "refund"** | | **stage** | **String** | **是** | **付款阶段** | **"order" / "requirements" / "delivery" / "aftercare"** | | **method** | **String** | **是** | **支付方式** | **"cash" / "bank_transfer" / "alipay" / "wechat"** | | **amount** | **Number** | **是** | **付款金额** | **35000** | | **currency** | **String** | **是** | **货币类型** | **"CNY"** | | **percentage** | **Number** | **否** | **占总价百分比** | **30** | | **paymentDate** | **Date** | **否** | **实际付款时间** | **2024-12-01T10:00:00.000Z** | | **dueDate** | **Date** | **是** | **应付款时间** | **2024-12-01T00:00:00.000Z** | | **recordedDate** | **Date** | **自动** | **记录时间** | **2024-11-30T15:30:00.000Z** | | **status** | **String** | **是** | **付款状态** | **"pending" / "paid" / "overdue" / "cancelled"** | | **voucherFile** | **Pointer** | **否** | **付款凭证文件** | **→ ProjectFile** | | **voucherUrl** | **String** | **否** | **凭证URL** | **"https://..."** | | **transactionId** | **String** | **否** | **第三方交易ID** | **"wx_123456789"** | | **paymentReference** | **String** | **否** | **付款参考号/发票号** | **"INV-2024-001"** | | **paidBy** | **Pointer** | **是** | **付款人** | **→ ContactInfo** | | **recordedBy** | **Pointer** | **是** | **记录人** | **→ Profile** | | **verifiedBy** | **Pointer** | **否** | **验证人** | **→ Profile** | | **description** | **String** | **否** | **付款描述** | **"首期款"** | | **notes** | **String** | **否** | **备注信息** | **"客户通过银行转账付款"** | | **relatedStage** | **String** | **否** | **关联执行阶段** | **"modeling"** | | **product** | **Pointer** | **否** | **关联产品** | **→ Product** | | **autoReminderSent** | **Boolean** | **否** | **是否已发送提醒** | **false** | | **reminderCount** | **Number** | **否** | **提醒次数** | **0** | | **data** | **Object** | **否** | **扩展数据** | **{bankInfo, approvalFlow}** | | **isDeleted** | **Boolean** | **否** | **软删除标记** | **false** | **type 枚举值**: - `advance`: 预付款/定金 - `milestone`: 里程碑付款 - `final`: 尾款/结算款 - `refund`: 退款 **stage 枚举值**: - `order`: 订单分配阶段 - `requirements`: 方案深化阶段 - `delivery`: 交付执行阶段 - `aftercare`: 售后归档阶段 **method 枚举值**: - `cash`: 现金 - `bank_transfer`: 银行转账 - `alipay`: 支付宝 - `wechat`: 微信支付 - `credit_card`: 信用卡 - `other`: 其他 **status 枚举值**: - `pending`: 待付款 - `paid`: 已付款 - `overdue`: 逾期 - `cancelled`: 已取消 - `refunded`: 已退款 **data 字段结构示例**: ```json { "bankInfo": { "bankName": "中国工商银行", "accountNumber": "****1234", "accountName": "李四" }, "approvalFlow": { "requestedBy": "客服小王", "approvedBy": "财务张三", "approvedAt": "2024-11-30T16:00:00.000Z", "comments": "款项已确认到账" }, "automaticPayment": { "provider": "alipay", "gateway": "alipay_scan", "qrCodeUrl": "https://..." } } ``` **使用场景示例**: ```typescript // 创建项目付款记录 const ProjectPayment = Parse.Object.extend("ProjectPayment"); const payment = new ProjectPayment(); payment.set("project", project.toPointer()); payment.set("company", company.toPointer()); payment.set("type", "advance"); payment.set("stage", "order"); payment.set("method", "bank_transfer"); payment.set("amount", 35000); payment.set("currency", "CNY"); payment.set("percentage", 30); payment.set("dueDate", new Date("2024-12-01")); payment.set("paidBy", customer.toPointer()); payment.set("recordedBy", profile.toPointer()); payment.set("status", "pending"); payment.set("description", "项目首期款"); await payment.save(); // 上传付款凭证并关联 const voucherFile = await uploadVoucherFile(file); payment.set("voucherFile", voucherFile.toPointer()); payment.set("status", "paid"); payment.set("paymentDate", new Date()); await payment.save(); // 查询项目的所有付款记录 const paymentQuery = new Parse.Query("ProjectPayment"); paymentQuery.equalTo("project", projectId); paymentQuery.include("voucherFile"); paymentQuery.include("paidBy"); paymentQuery.include("recordedBy"); paymentQuery.descending("paymentDate"); const payments = await paymentQuery.find(); // 查询某个产品的付款记录 const productPaymentQuery = new Parse.Query("ProjectPayment"); productPaymentQuery.equalTo("product", { __type: "Pointer", className: "Product", objectId: productId }); productPaymentQuery.equalTo("status", "paid"); const productPayments = await productPaymentQuery.find(); // 计算项目总付款金额 const totalPaid = payments.reduce((sum, payment) => { return sum + (payment.get("status") === "paid" ? payment.get("amount") : 0); }, 0); ``` --- ### 8. ProjectFeedback(客户反馈表) **用途**: 记录客户在各阶段的反馈和评价。**已更新支持产品关联**。 | 字段名 | 类型 | 必填 | 说明 | 示例值 | |--------|------|------|------|--------| | objectId | String | 是 | 主键ID | "feedback001" | | project | Pointer | 是 | 所属项目 | → Project | | **product** | **Pointer** | **否** | **关联空间产品** | **→ Product** | | customer | Pointer | 是 | 反馈客户 | → ContactInfo | | stage | String | 是 | 反馈阶段 | "建模" / "渲染" | | feedbackType | String | 是 | 反馈类型 | "suggestion" / "complaint" | | content | String | 是 | 反馈内容 | "客厅颜色希望再暖一些" | | rating | Number | 否 | 评分(1-5) | 4 | | status | String | 是 | 处理状态 | "待处理" / "已解决" | | data | Object | 否 | 扩展数据 | { response, attachments, ... } | | isDeleted | Boolean | 否 | 软删除标记 | false | | createdAt | Date | 自动 | 创建时间 | 2024-01-01T00:00:00.000Z | | updatedAt | Date | 自动 | 更新时间 | 2024-01-01T00:00:00.000Z | --- ## Product表统一空间管理的优势 ### 1. 行业语义清晰 - **Product即空间设计产品**:符合家装设计行业的业务理解 - **产品化管理**:每个空间都是一个独立的设计产品 - **商业逻辑一致**:报价、交付、评价都围绕产品展开 ### 2. 数据结构极简 - **单表多能**:Product表承载空间管理的所有核心功能 - **文件分类管理**:通过ProjectFile.category区分不同类型文件 - **设计师直连**:通过Product.profile直接关联负责设计师 ### 3. 使用场景优化 - **产品清单**:通过Product表直接获得项目的空间设计产品清单 - **交付物管理**:通过Product.fileUrl和ProjectFile管理交付物 - **报价管理**:通过Product.quotation管理产品级报价 ### 4. 实现示例对比 **原有方式(多表操作)**: ```typescript // 需要查询多个表 const spaces = await spaceQuery.equalTo("project", projectId).find(); const quotations = await quotationQuery.equalTo("project", projectId).find(); const panoramas = await panoramaQuery.equalTo("project", projectId).find(); const deliveries = await deliveryQuery.equalTo("project", projectId).find(); ``` **Product表方式(单表操作)**: ```typescript // 一次查询获得所有空间设计产品 const products = await productQuery.equalTo("project", projectId).find(); // 每个product包含完整的space、quotation、requirements信息 // 文件通过ProjectFile按category分类查询 ```