|
@@ -1,831 +0,0 @@
|
|
|
----
|
|
|
-category: schema
|
|
|
-title: YSS项目Parse Server数据范式 - 统一空间管理
|
|
|
-subtitle: 映三色设计师项目管理系统完整数据表结构(统一空间管理版本)
|
|
|
-name: 'yss-schemas-unified-space'
|
|
|
-label: database
|
|
|
----
|
|
|
-
|
|
|
-# Parse Server 数据范式 - 映三色项目管理系统(统一空间管理)
|
|
|
-
|
|
|
-## 概述
|
|
|
-
|
|
|
-本文档定义了映三色(YSS)设计师项目管理系统的完整Parse Server数据范式。系统采用**多租户架构**,以Company为核心,支持客服、设计师、组长等多角色协作的全流程项目管理。
|
|
|
-
|
|
|
-**核心特性**:
|
|
|
-- 🏢 多租户架构,以Company为核心租户隔离
|
|
|
-- 👥 统一员工表(Profile)和客户表(ContactInfo)
|
|
|
-- 📋 项目与群聊灵活关联(Project ←→ GroupChat)
|
|
|
-- 🏠 **统一空间项目管理**:通过单一ProjectSpace表解决多空间项目管理问题
|
|
|
-- 🎨 设计师项目全生命周期管理
|
|
|
-- 💰 财务报价与结算流程
|
|
|
-- 📊 质量控制与客户反馈
|
|
|
-
|
|
|
-**空间管理优化**:
|
|
|
-- 🔄 **统一空间表**:ProjectSpace表统一管理所有空间相关功能
|
|
|
-- 💰 **空间报价**:通过`.quotation`字段管理空间级别的报价
|
|
|
-- 📁 **空间文件**:ProjectFile通过`.space`字段关联到具体空间
|
|
|
-- 👥 **空间团队**:通过`.assignedTeam`字段管理空间团队成员
|
|
|
-- 🎯 **空间需求**:通过`.requirements`字段管理空间详细需求
|
|
|
-- 📸 **空间全景**:通过`.panorama`字段管理空间全景图信息
|
|
|
-- ⭐ **空间评价**:通过`.reviews`字段管理空间评价和反馈
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-## 数据表关系图
|
|
|
-
|
|
|
-
|
|
|
-- Department 项目组(部门)
|
|
|
- - name String 项目组名称
|
|
|
- - type "project" 项目组
|
|
|
- - leader Pointer<Profile> 组长
|
|
|
- - company Pointer<Company> 指向当前帐套
|
|
|
-
|
|
|
-```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)
|
|
|
-}
|
|
|
-
|
|
|
-' ============ 统一空间项目管理 ============
|
|
|
-TABLE(ProjectSpace, "ProjectSpace\n统一项目空间表") {
|
|
|
- FIELD(objectId, String)
|
|
|
- FIELD(project, Pointer→Project)
|
|
|
- FIELD(name, String)
|
|
|
- FIELD(type, String)
|
|
|
- FIELD(area, Number)
|
|
|
- FIELD(priority, Number)
|
|
|
- FIELD(status, String)
|
|
|
- FIELD(complexity, String)
|
|
|
- FIELD(metadata, Object)
|
|
|
- FIELD(quotation, Object)
|
|
|
- FIELD(panorama, Object)
|
|
|
- FIELD(assignedTeam, Array)
|
|
|
- FIELD(deliveryFiles, Array)
|
|
|
- FIELD(dependencies, Array)
|
|
|
- FIELD(requirements, Object)
|
|
|
- FIELD(reviews, Array)
|
|
|
- FIELD(estimatedBudget, Number)
|
|
|
- FIELD(estimatedDuration, Number)
|
|
|
- FIELD(order, Number)
|
|
|
- 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(Product, "Product\n产品即交付物表") {
|
|
|
- FIELD(objectId, String)
|
|
|
- FIELD(project, Pointer→Project)
|
|
|
- FIELD(company, Pointer→Company)
|
|
|
- FIELD(stage, String)
|
|
|
- FIELD(processType, String)
|
|
|
- FIELD(space, Pointer→ProjectSpace)
|
|
|
- FIELD(fileUrl, String)
|
|
|
- FIELD(reviewStatus, String)
|
|
|
- FIELD(data, Object)
|
|
|
- FIELD(isDeleted, Boolean)
|
|
|
-}
|
|
|
-
|
|
|
-' NovaFile.id为Attachment.objectId
|
|
|
-TABLE(ProjectFile, "ProjectFile\n项目文件表") {
|
|
|
- FIELD(objectId, String)
|
|
|
- FIELD(project, Pointer→Project)
|
|
|
- FIELD(space, Pointer→ProjectSpace)
|
|
|
- FIELD(attach, Attachment)
|
|
|
- FIELD(uploadedBy, Pointer→Profile)
|
|
|
- FIELD(fileType, String)
|
|
|
- FIELD(fileUrl, String)
|
|
|
- FIELD(fileName, String)
|
|
|
- FIELD(fileSize, Number)
|
|
|
- FIELD(stage, String)
|
|
|
- FIELD(data, Object)
|
|
|
- FIELD(isDeleted, Boolean)
|
|
|
-}
|
|
|
-
|
|
|
-' ============ 财务模块 ============
|
|
|
-TABLE(ProjectSettlement, "ProjectSettlement\n结算记录表") {
|
|
|
- FIELD(objectId, String)
|
|
|
- FIELD(project, Pointer→Project)
|
|
|
- FIELD(company, Pointer→Company)
|
|
|
- FIELD(stage, String)
|
|
|
- FIELD(amount, Number)
|
|
|
- FIELD(percentage, Number)
|
|
|
- FIELD(status, String)
|
|
|
- FIELD(dueDate, Date)
|
|
|
- FIELD(settledAt, Date)
|
|
|
- FIELD(data, Object)
|
|
|
- FIELD(isDeleted, Boolean)
|
|
|
-}
|
|
|
-
|
|
|
-TABLE(ProjectVoucher, "ProjectVoucher\n付款凭证表") {
|
|
|
- FIELD(objectId, String)
|
|
|
- FIELD(settlement, Pointer→ProjectSettlement)
|
|
|
- FIELD(project, Pointer→Project)
|
|
|
- FIELD(amount, Number)
|
|
|
- FIELD(voucherUrl, String)
|
|
|
- FIELD(recognizedInfo, Object)
|
|
|
- FIELD(verifiedBy, Pointer→Profile)
|
|
|
- FIELD(data, Object)
|
|
|
- FIELD(isDeleted, Boolean)
|
|
|
-}
|
|
|
-
|
|
|
-' ============ 质量与反馈 ============
|
|
|
-TABLE(ProjectFeedback, "ProjectFeedback\n客户反馈表") {
|
|
|
- FIELD(objectId, String)
|
|
|
- FIELD(project, Pointer→Project)
|
|
|
- FIELD(customer, Pointer→ContactInfo)
|
|
|
- FIELD(stage, String)
|
|
|
- FIELD(feedbackType, String)
|
|
|
- FIELD(content, String)
|
|
|
- FIELD(rating, Number)
|
|
|
- FIELD(status, String)
|
|
|
- FIELD(data, Object)
|
|
|
- FIELD(isDeleted, Boolean)
|
|
|
-}
|
|
|
-
|
|
|
-TABLE(ProductCheck, "ProductCheck\n产品质量检查表") {
|
|
|
- FIELD(objectId, String)
|
|
|
- FIELD(project, Pointer→Project)
|
|
|
- FIELD(checkType, String)
|
|
|
- FIELD(checkedBy, Pointer→Profile)
|
|
|
- FIELD(checkedAt, Date)
|
|
|
- FIELD(isPassed, Boolean)
|
|
|
- FIELD(items, Array)
|
|
|
- FIELD(data, Object)
|
|
|
- FIELD(isDeleted, Boolean)
|
|
|
-}
|
|
|
-
|
|
|
-TABLE(ProjectIssue, "ProjectIssue\n异常记录表") {
|
|
|
- FIELD(objectId, String)
|
|
|
- FIELD(project, Pointer→Project)
|
|
|
- FIELD(reportedBy, Pointer→Profile)
|
|
|
- FIELD(exceptionType, String)
|
|
|
- FIELD(severity, String)
|
|
|
- FIELD(description, String)
|
|
|
- FIELD(status, String)
|
|
|
- FIELD(resolution, String)
|
|
|
- FIELD(data, Object)
|
|
|
- FIELD(isDeleted, Boolean)
|
|
|
-}
|
|
|
-
|
|
|
-' ============ 跟进记录 ============
|
|
|
-TABLE(ContactFollow, "ContactFollow\n跟进记录表") {
|
|
|
- FIELD(objectId, String)
|
|
|
- FIELD(project, Pointer→Project)
|
|
|
- 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 : 项目团队
|
|
|
-
|
|
|
-' 统一空间项目管理关系
|
|
|
-Project "1" --> "n" ProjectSpace : 项目空间
|
|
|
-ProjectSpace "1" --> "n" Product : 空间交付物
|
|
|
-ProjectSpace "1" --> "n" ProjectFile : 空间文件
|
|
|
-
|
|
|
-' 交付与财务
|
|
|
-Project "1" --> "n" Product : 交付物
|
|
|
-Project "1" --> "n" ProjectFile : 项目文件
|
|
|
-Project "1" --> "n" ProjectSettlement : 结算记录
|
|
|
-ProjectSettlement "1" --> "n" ProjectVoucher : 付款凭证
|
|
|
-
|
|
|
-' 质量与沟通
|
|
|
-Project "1" --> "n" ProjectFeedback : 客户反馈
|
|
|
-Project "1" --> "n" ProductCheck : 质量检查
|
|
|
-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. ProjectSpace(统一项目空间表)⭐
|
|
|
-
|
|
|
-**功能描述**: 统一管理项目空间的所有相关信息,包含报价、全景图、团队分配、需求等全生命周期数据。
|
|
|
-
|
|
|
-**字段说明**:
|
|
|
-| 字段名 | 类型 | 必填 | 说明 | 示例值 |
|
|
|
-|--------|------|------|------|--------|
|
|
|
-| objectId | String | 是 | 主键ID | "space001" |
|
|
|
-| project | Pointer | 是 | 所属项目 | → Project |
|
|
|
-| name | String | 是 | 空间名称 | "主卧" |
|
|
|
-| type | String | 是 | 空间类型 | "bedroom" |
|
|
|
-| area | Number | 否 | 面积(平方米) | 18.5 |
|
|
|
-| priority | Number | 否 | 优先级(1-10) | 8 |
|
|
|
-| status | String | 否 | 状态 | "in_progress" |
|
|
|
-| complexity | String | 否 | 复杂度 | "medium" |
|
|
|
-| metadata | Object | 否 | 空间元数据 | {dimensions, features} |
|
|
|
-| **quotation** | **Object** | **否** | **空间报价信息** | **{price, breakdown}** |
|
|
|
-| **panorama** | **Object** | **否** | **全景图信息** | **{url, hotspots}** |
|
|
|
-| **assignedTeam** | **Array** | **否** | **分配团队** | **[{profile, role}]** |
|
|
|
-| **deliveryFiles** | **Array** | **否** | **交付文件列表** | **[{fileId, type}]** |
|
|
|
-| **dependencies** | **Array** | **否** | **空间依赖关系** | **[{fromSpace, type}]** |
|
|
|
-| **requirements** | **Object** | **否** | **空间详细需求** | **{color, material}** |
|
|
|
-| **reviews** | **Array** | **否** | **空间评价列表** | **[{rating, comments}]** |
|
|
|
-| estimatedBudget | Number | 否 | 预估预算 | 35000 |
|
|
|
-| estimatedDuration | Number | 否 | 预估工期(天) | 7 |
|
|
|
-| order | Number | 否 | 排序顺序 | 2 |
|
|
|
-| isDeleted | Boolean | 否 | 是否删除 | false |
|
|
|
-
|
|
|
-**type 枚举值**:
|
|
|
-- `living_room`: 客厅
|
|
|
-- `bedroom`: 卧室
|
|
|
-- `kitchen`: 厨房
|
|
|
-- `bathroom`: 卫生间
|
|
|
-- `dining_room`: 餐厅
|
|
|
-- `study`: 书房
|
|
|
-- `balcony`: 阳台
|
|
|
-- `corridor`: 走廊
|
|
|
-- `storage`: 储物间
|
|
|
-- `entrance`: 玄关
|
|
|
-- `other`: 其他
|
|
|
-
|
|
|
-**status 枚举值**:
|
|
|
-- `not_started`: 未开始
|
|
|
-- `in_progress`: 进行中
|
|
|
-- `awaiting_review`: 待审核
|
|
|
-- `completed`: 已完成
|
|
|
-- `blocked`: 已阻塞
|
|
|
-- `delayed`: 已延期
|
|
|
-
|
|
|
-**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"
|
|
|
-}
|
|
|
-```
|
|
|
-
|
|
|
-**panorama 字段结构示例**:
|
|
|
-```json
|
|
|
-{
|
|
|
- "url": "https://...",
|
|
|
- "thumbnailUrl": "https://...",
|
|
|
- "previewImages": ["https://...", "https://..."],
|
|
|
- "hotspots": [
|
|
|
- {
|
|
|
- "id": "hotspot001",
|
|
|
- "position": {"x": 0.5, "y": 0.3},
|
|
|
- "type": "info",
|
|
|
- "title": "定制衣柜",
|
|
|
- "description": "实木定制衣柜,内部空间合理布局"
|
|
|
- }
|
|
|
- ],
|
|
|
- "resolution": {"width": 8192, "height": 4096},
|
|
|
- "fileSize": 15728640,
|
|
|
- "renderTime": 1800,
|
|
|
- "status": "completed"
|
|
|
-}
|
|
|
-```
|
|
|
-
|
|
|
-**assignedTeam 字段结构示例**:
|
|
|
-```json
|
|
|
-[
|
|
|
- {
|
|
|
- "profile": {"__type": "Pointer", "className": "Profile", "objectId": "prof001"},
|
|
|
- "profileName": "张设计师",
|
|
|
- "role": "primary_designer",
|
|
|
- "workload": 0.6,
|
|
|
- "assignedAt": "2024-10-01T10:00:00.000Z",
|
|
|
- "assignedBy": {"__type": "Pointer", "className": "Profile", "objectId": "prof002"},
|
|
|
- "status": "active",
|
|
|
- "notes": "主要负责空间整体设计"
|
|
|
- },
|
|
|
- {
|
|
|
- "profile": {"__type": "Pointer", "className": "Profile", "objectId": "prof003"},
|
|
|
- "profileName": "李建模师",
|
|
|
- "role": "modeling_designer",
|
|
|
- "workload": 0.4,
|
|
|
- "assignedAt": "2024-10-02T09:00:00.000Z",
|
|
|
- "status": "active"
|
|
|
- }
|
|
|
-]
|
|
|
-```
|
|
|
-
|
|
|
-**deliveryFiles 字段结构示例**:
|
|
|
-```json
|
|
|
-[
|
|
|
- {
|
|
|
- "fileId": {"__type": "Pointer", "className": "ProjectFile", "objectId": "file001"},
|
|
|
- "fileName": "主卧效果图v2.jpg",
|
|
|
- "fileType": "rendering",
|
|
|
- "stage": "rendering",
|
|
|
- "uploadedAt": "2024-10-15T14:30:00.000Z",
|
|
|
- "uploadedBy": {"__type": "Pointer", "className": "Profile", "objectId": "prof001"},
|
|
|
- "reviewStatus": "approved"
|
|
|
- }
|
|
|
-]
|
|
|
-```
|
|
|
-
|
|
|
-**dependencies 字段结构示例**:
|
|
|
-```json
|
|
|
-[
|
|
|
- {
|
|
|
- "fromSpace": {"__type": "Pointer", "className": "ProjectSpace", "objectId": "space002"},
|
|
|
- "fromSpaceName": "客厅",
|
|
|
- "type": "style_reference",
|
|
|
- "description": "需要与客厅风格保持一致",
|
|
|
- "priority": "high",
|
|
|
- "status": "active"
|
|
|
- }
|
|
|
-]
|
|
|
-```
|
|
|
-
|
|
|
-**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": "暖白",
|
|
|
- "lightIntensity": "中等",
|
|
|
- "specialRequirements": ["床头阅读灯", "氛围灯"]
|
|
|
- },
|
|
|
- "specificRequirements": [
|
|
|
- "需要大储物空间",
|
|
|
- "独立卫浴",
|
|
|
- "飘窗设计"
|
|
|
- ],
|
|
|
- "referenceImages": ["https://...", "https://..."],
|
|
|
- "referenceFiles": ["file002", "file003"]
|
|
|
-}
|
|
|
-```
|
|
|
-
|
|
|
-**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 ProjectSpace = Parse.Object.extend("ProjectSpace");
|
|
|
-const space = new ProjectSpace();
|
|
|
-space.set("project", project.toPointer());
|
|
|
-space.set("name", "主卧");
|
|
|
-space.set("type", "bedroom");
|
|
|
-space.set("area", 18.5);
|
|
|
-
|
|
|
-// 设置空间报价
|
|
|
-space.set("quotation", {
|
|
|
- price: 35000,
|
|
|
- currency: "CNY",
|
|
|
- breakdown: { design: 15000, modeling: 10000, rendering: 8000, softDecor: 2000 },
|
|
|
- status: "pending"
|
|
|
-});
|
|
|
-
|
|
|
-// 设置空间团队
|
|
|
-space.set("assignedTeam", [
|
|
|
- {
|
|
|
- profile: designer.toPointer(),
|
|
|
- profileName: designer.get("name"),
|
|
|
- role: "primary_designer",
|
|
|
- workload: 0.8,
|
|
|
- assignedAt: new Date()
|
|
|
- }
|
|
|
-]);
|
|
|
-
|
|
|
-await space.save();
|
|
|
-
|
|
|
-// 查询项目的所有空间
|
|
|
-const spaceQuery = new Parse.Query("ProjectSpace");
|
|
|
-spaceQuery.equalTo("project", projectId);
|
|
|
-spaceQuery.notEqualTo("isDeleted", true);
|
|
|
-spaceQuery.ascending("order");
|
|
|
-const spaces = await spaceQuery.find();
|
|
|
-
|
|
|
-// 查询设计师负责的空间
|
|
|
-const designerSpaceQuery = new Parse.Query("ProjectSpace");
|
|
|
-designerSpaceQuery.equalTo("project", projectId);
|
|
|
-designerSpaceQuery.equalTo("assignedTeam.profile", designerId);
|
|
|
-designerSpaceQuery.equalTo("assignedTeam.status", "active");
|
|
|
-```
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-### 6. Product(交付物表)
|
|
|
-
|
|
|
-**用途**: 记录项目各阶段的交付物,如效果图、施工图等。**已更新支持空间关联**。
|
|
|
-
|
|
|
-| 字段名 | 类型 | 必填 | 说明 | 示例值 |
|
|
|
-|--------|------|------|------|--------|
|
|
|
-| objectId | String | 是 | 主键ID | "deliv001" |
|
|
|
-| project | Pointer | 是 | 所属项目 | → Project |
|
|
|
-| company | Pointer | 是 | 所属企业 | → Company |
|
|
|
-| stage | String | 是 | 所属阶段 | "建模" / "渲染" / "后期" |
|
|
|
-| processType | String | 否 | 工序类型 | "modeling" / "rendering" |
|
|
|
-| **space** | **Pointer** | **否** | **所属空间** | **→ ProjectSpace** |
|
|
|
-| fileUrl | String | 是 | 文件URL | "https://..." |
|
|
|
-| reviewStatus | String | 是 | 审核状态 | "pending" / "approved" |
|
|
|
-| data | Object | 否 | 扩展数据 | { thumbnailUrl, version, ... } |
|
|
|
-| isDeleted | Boolean | 否 | 软删除标记 | false |
|
|
|
-| createdAt | Date | 自动 | 创建时间 | 2024-01-01T00:00:00.000Z |
|
|
|
-| updatedAt | Date | 自动 | 更新时间 | 2024-01-01T00:00:00.000Z |
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-### 7. ProjectFile(项目文件表)
|
|
|
-
|
|
|
-**用途**: 存储项目相关的所有文件,如CAD图纸、参考图等。**已更新支持空间关联**。
|
|
|
-
|
|
|
-| 字段名 | 类型 | 必填 | 说明 | 示例值 |
|
|
|
-|--------|------|------|------|--------|
|
|
|
-| objectId | String | 是 | 主键ID | "file001" |
|
|
|
-| project | Pointer | 是 | 所属项目 | → Project |
|
|
|
-| **space** | **Pointer** | **否** | **所属空间** | **→ ProjectSpace** |
|
|
|
-| attach | Pointer | 是 | 附件 | → Attachment |
|
|
|
-| uploadedBy | Pointer | 是 | 上传人 | → Profile |
|
|
|
-| fileType | String | 是 | 文件类型 | "cad" / "reference" / "document" |
|
|
|
-| fileUrl | String | 是 | 文件URL | "https://..." |
|
|
|
-| fileName | String | 是 | 文件名 | "户型图.dwg" |
|
|
|
-| fileSize | Number | 否 | 文件大小(字节) | 1024000 |
|
|
|
-| stage | String | 否 | 关联阶段 | "需求沟通" |
|
|
|
-| data | Object | 否 | 扩展数据 | { thumbnailUrl, ... } |
|
|
|
-| isDeleted | Boolean | 否 | 软删除标记 | false |
|
|
|
-| createdAt | Date | 自动 | 创建时间 | 2024-01-01T00:00:00.000Z |
|
|
|
-| updatedAt | Date | 自动 | 更新时间 | 2024-01-01T00:00:00.000Z |
|
|
|
-
|
|
|
-**使用场景示例**:
|
|
|
-```typescript
|
|
|
-// 上传空间相关文件
|
|
|
-const ProjectFile = Parse.Object.extend("ProjectFile");
|
|
|
-const file = new ProjectFile();
|
|
|
-file.set("project", project.toPointer());
|
|
|
-file.set("space", space.toPointer()); // 关联到具体空间
|
|
|
-file.set("fileName", "主卧参考图.jpg");
|
|
|
-file.set("fileType", "reference");
|
|
|
-file.set("uploadedBy", profile.toPointer());
|
|
|
-await file.save();
|
|
|
-
|
|
|
-// 查询空间的所有文件
|
|
|
-const fileQuery = new Parse.Query("ProjectFile");
|
|
|
-fileQuery.equalTo("space", spaceId);
|
|
|
-fileQuery.notEqualTo("isDeleted", true);
|
|
|
-const spaceFiles = await fileQuery.find();
|
|
|
-```
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-## 统一空间管理的优势
|
|
|
-
|
|
|
-### 1. 数据结构简化
|
|
|
-- **减少表数量**: 从15个空间相关表简化为1个统一表
|
|
|
-- **降低复杂度**: 消除复杂的表间关联关系
|
|
|
-- **提高性能**: 减少JOIN查询操作
|
|
|
-
|
|
|
-### 2. 功能完整性
|
|
|
-- **空间报价**: 通过`.quotation`字段实现空间级报价管理
|
|
|
-- **空间全景**: 通过`.panorama`字段管理全景图和热点信息
|
|
|
-- **团队协作**: 通过`.assignedTeam`字段管理空间团队成员
|
|
|
-- **文件管理**: 通过`.deliveryFiles`字段管理空间交付物
|
|
|
-- **需求跟踪**: 通过`.requirements`字段管理详细需求
|
|
|
-- **评价反馈**: 通过`.reviews`字段管理空间评价
|
|
|
-
|
|
|
-### 3. 使用便利性
|
|
|
-- **一次查询**: 获取空间所有相关信息
|
|
|
-- **原子操作**: 空间信息可原子性更新
|
|
|
-- **数据一致性**: 避免分布式数据一致性问题
|
|
|
-- **扩展灵活**: Object字段支持灵活扩展
|
|
|
-
|
|
|
-### 4. 实现示例对比
|
|
|
-
|
|
|
-**原有方式(多表操作)**:
|
|
|
-```typescript
|
|
|
-// 需要多次查询
|
|
|
-const space = await spaceQuery.get(spaceId);
|
|
|
-const quotation = await quotationQuery.equalTo("space", spaceId).first();
|
|
|
-const team = await teamQuery.equalTo("space", spaceId).find();
|
|
|
-const files = await fileQuery.equalTo("space", spaceId).find();
|
|
|
-const reviews = await reviewQuery.equalTo("space", spaceId).find();
|
|
|
-```
|
|
|
-
|
|
|
-**统一方式(单表操作)**:
|
|
|
-```typescript
|
|
|
-// 一次查询获取所有信息
|
|
|
-const space = await spaceQuery.get(spaceId);
|
|
|
-const quotation = space.get("quotation");
|
|
|
-const team = space.get("assignedTeam");
|
|
|
-const files = space.get("deliveryFiles");
|
|
|
-const reviews = space.get("reviews");
|
|
|
-```
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-## 数据迁移指南
|
|
|
-
|
|
|
-### 从多表结构迁移到统一ProjectSpace
|
|
|
-
|
|
|
-```typescript
|
|
|
-// 1. 迁移空间报价数据
|
|
|
-const oldQuotations = await new Parse.Query("SpaceQuotation").find();
|
|
|
-for (const quotation of oldQuotations) {
|
|
|
- const space = await quotation.get("space");
|
|
|
- space.set("quotation", {
|
|
|
- price: quotation.get("totalAmount"),
|
|
|
- currency: "CNY",
|
|
|
- breakdown: quotation.get("priceBreakdown"),
|
|
|
- status: "migrated"
|
|
|
- });
|
|
|
- await space.save();
|
|
|
-}
|
|
|
-
|
|
|
-// 2. 迁移空间团队数据
|
|
|
-const oldAssignments = await new Parse.Query("SpaceAssignment").find();
|
|
|
-for (const assignment of oldAssignments) {
|
|
|
- const space = await assignment.get("space");
|
|
|
- const team = space.get("assignedTeam") || [];
|
|
|
- team.push({
|
|
|
- profile: assignment.get("assigneeId"),
|
|
|
- profileName: assignment.get("assigneeName"),
|
|
|
- role: assignment.get("role"),
|
|
|
- workload: assignment.get("workload"),
|
|
|
- assignedAt: assignment.get("assignedAt"),
|
|
|
- assignedBy: assignment.get("assignedBy"),
|
|
|
- status: "migrated"
|
|
|
- });
|
|
|
- space.set("assignedTeam", team);
|
|
|
- await space.save();
|
|
|
-}
|
|
|
-
|
|
|
-// 3. 迁移空间需求
|
|
|
-const oldRequirements = await new Parse.Query("SpaceRequirement").find();
|
|
|
-for (const requirement of oldRequirements) {
|
|
|
- const space = await requirement.get("space");
|
|
|
- space.set("requirements", {
|
|
|
- colorRequirement: requirement.get("colorRequirement"),
|
|
|
- materialRequirement: requirement.get("materialRequirement"),
|
|
|
- lightingRequirement: requirement.get("lightingRequirement"),
|
|
|
- specificRequirements: requirement.get("specificRequirements"),
|
|
|
- constraints: requirement.get("constraints"),
|
|
|
- referenceImages: requirement.get("referenceImages"),
|
|
|
- referenceFiles: requirement.get("referenceFiles")
|
|
|
- });
|
|
|
- await space.save();
|
|
|
-}
|
|
|
-```
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-## 总结
|
|
|
-
|
|
|
-通过统一空间管理的重构,YSS项目管理系统实现了:
|
|
|
-
|
|
|
-✅ **架构简化**: 从15个空间相关表简化为1个ProjectSpace表
|
|
|
-✅ **功能完整**: 保留所有空间管理功能,无缝迁移
|
|
|
-✅ **性能提升**: 减少查询复杂度,提高响应速度
|
|
|
-✅ **维护便利**: 降低数据模型维护成本
|
|
|
-✅ **扩展灵活**: Object字段支持未来功能扩展
|
|
|
-✅ **数据一致**: 避免多表数据一致性问题
|
|
|
-
|
|
|
-这个统一的空间管理方案解决了多空间项目管理的复杂性,通过单一ProjectSpace表实现了报价、全景图、团队协作、文件管理、需求跟踪、评价反馈等全生命周期管理,大大简化了系统架构并提高了开发效率。
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-**文档版本**: v2.0(统一空间管理)
|
|
|
-**最后更新**: 2025-10-20
|
|
|
-**维护者**: YSS Development Team
|