浏览代码

feat:new schema docs

0225266 1 天之前
父节点
当前提交
d3c96ab3cb
共有 5 个文件被更改,包括 373 次插入81 次删除
  1. 3 0
      .vscode/settings.json
  2. 90 0
      docs/info-map.md
  3. 198 1
      docs/schema.md
  4. 16 14
      myapp/src/app/tab1/tab1.module.ts
  5. 66 66
      myapp/src/app/tab1/tab1.page.scss

+ 3 - 0
.vscode/settings.json

@@ -0,0 +1,3 @@
+{
+    "plantuml.server":"http://www.plantuml.com/plantuml"
+}

+ 90 - 0
docs/info-map.md

@@ -0,0 +1,90 @@
+# 智能旅游数据库设计
+
+## 表结构
+
+### _User (Parse内置表)
+- objectId: String
+- username: String
+- email: String
+- createdAt: Date
+- updatedAt: Date
+- phone: String
+- profilePic: File
+- emergencyContact: String
+
+### TouristResource (旅游资源)
+- objectId: String
+- createdAt: Date
+- updatedAt: Date
+- name: String
+- type: String `景点/酒店/餐厅`
+- description: String
+- location: GeoPoint
+- openingHours: String
+- priceRange: String
+- images: File[]
+- rating: Number
+- capacity: Number `承载量`
+
+### Itinerary (行程提醒)
+- objectId: String
+- createdAt: Date
+- updatedAt: Date
+- title: String
+- startTime: Date
+- endTime: Date
+- reminderType: String `时间/位置`
+- location: GeoPoint `位置提醒`
+- notes: String
+- alertLevel: String `高/中/低`
+- isCompleted: Bool
+
+### TravelJournal (旅行日志)
+- objectId: String
+- createdAt: Date
+- updatedAt: Date
+- title: String
+- content: String
+- photos: File[]
+- location: GeoPoint
+- weatherData: Object `温度/湿度`
+- moodRating: Number
+
+### RealTimeData (实时监测)
+- objectId: String
+- createdAt: Date
+- updatedAt: Date
+- dataType: String `客流/天气/交通`
+- value: Object `动态JSON`
+- location: GeoPoint
+- source: String `官方/传感器`
+- validity: Date `有效期`
+
+### SafetyWarning (安全预警)
+- objectId: String
+- createdAt: Date
+- updatedAt: Date
+- title: String
+- description: String
+- severity: String `紧急/高/中`
+- affectedArea: GeoPoint
+- validUntil: Date
+- relatedHazards: String[] `自然灾害/事故`
+
+## 表关系
+- 用户 → 行程
+  - 1个用户创建N个行程
+- 用户 → 日志
+  - 1个用户记录N个日志
+- 行程 → 资源
+  - N个行程关联1个资源
+- 日志 → 资源
+  - N个日志提及1个资源
+- 监测 → 资源
+  - N个监测数据对应1个资源
+- 预警 → 资源
+  - N个预警影响N个资源 (多对多)
+- 监测 → 预警
+  - 1个监测数据触发1个预警
+- 行程 → 预警
+  - 1个行程关联1个预警

+ 198 - 1
docs/schema.md

@@ -28,7 +28,7 @@ GeoPoint => {latitude: 40.0, longitude: -30.0}
 请您帮我用markmap格式表示上面的信息结构图
 
 >输出结果(SQL语句)
-请您帮我用sql格式给我建表语句和测试数据插入语句
+请您帮我用sql格式给我建表语句和测试数据插入语句,注意字段请使用小驼峰用""引起来。
 
 # UML类图
 ```plantuml
@@ -137,4 +137,201 @@ Itinerary "1" -- "1" SafetyWarning : "关联预警"
 
 @enduml
 ```
+
+# SQL语句
+
+-- 创建扩展(用于PostGIS空间函数)
+CREATE EXTENSION IF NOT EXISTS postgis;
+
+-------------------------
+-- 1. 用户表扩展 (Parse内置)
+-------------------------
+ALTER TABLE "_User" ADD COLUMN IF NOT EXISTS "phone" VARCHAR(20);
+ALTER TABLE "_User" ADD COLUMN IF NOT EXISTS "profilePic" TEXT;
+ALTER TABLE "_User" ADD COLUMN IF NOT EXISTS "emergencyContact" VARCHAR(100);
+
+-------------------------
+-- 2. 旅游资源表
+-------------------------
+CREATE TABLE IF NOT EXISTS "TouristResource" (
+    "objectId" VARCHAR(36) PRIMARY KEY,
+    "createdAt" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    "updatedAt" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    "name" VARCHAR(255) NOT NULL,
+    "type" VARCHAR(50) NOT NULL CHECK ("type" IN ('景点', '酒店', '餐厅')),
+    "description" TEXT,
+    "latitude" DOUBLE PRECISION NOT NULL,
+    "longitude" DOUBLE PRECISION NOT NULL,
+    "openingHours" VARCHAR(100),
+    "priceRange" VARCHAR(50),
+    "images" JSONB,
+    "rating" NUMERIC(3,1),
+    "capacity" INTEGER
+);
+
+-- 空间索引
+CREATE INDEX IF NOT EXISTS "idx_tourist_resource_location" 
+ON "TouristResource" USING GIST (ST_MakePoint("longitude", "latitude"));
+
+-------------------------
+-- 3. 行程提醒表
+-------------------------
+CREATE TABLE IF NOT EXISTS "Itinerary" (
+    "objectId" VARCHAR(36) PRIMARY KEY,
+    "createdAt" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    "updatedAt" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    "title" VARCHAR(255) NOT NULL,
+    "startTime" TIMESTAMP NOT NULL,
+    "endTime" TIMESTAMP NOT NULL,
+    "reminderType" VARCHAR(20) NOT NULL CHECK ("reminderType" IN ('时间', '位置')),
+    "latitude" DOUBLE PRECISION,
+    "longitude" DOUBLE PRECISION,
+    "notes" TEXT,
+    "alertLevel" VARCHAR(10) CHECK ("alertLevel" IN ('高', '中', '低')),
+    "isCompleted" BOOLEAN DEFAULT false,
+    "userId" VARCHAR(36) REFERENCES "_User"("objectId") ON DELETE CASCADE,
+    "resourceId" VARCHAR(36) REFERENCES "TouristResource"("objectId") ON DELETE SET NULL
+);
+
+-------------------------
+-- 4. 旅行日志表
+-------------------------
+CREATE TABLE IF NOT EXISTS "TravelJournal" (
+    "objectId" VARCHAR(36) PRIMARY KEY,
+    "createdAt" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    "updatedAt" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    "title" VARCHAR(255) NOT NULL,
+    "content" TEXT NOT NULL,
+    "photos" JSONB,
+    "latitude" DOUBLE PRECISION,
+    "longitude" DOUBLE PRECISION,
+    "weatherData" JSONB,
+    "moodRating" INTEGER CHECK ("moodRating" BETWEEN 1 AND 5),
+    "userId" VARCHAR(36) REFERENCES "_User"("objectId") ON DELETE CASCADE,
+    "resourceId" VARCHAR(36) REFERENCES "TouristResource"("objectId") ON DELETE SET NULL
+);
+
+-------------------------
+-- 5. 实时监测数据表
+-------------------------
+CREATE TABLE IF NOT EXISTS "RealTimeData" (
+    "objectId" VARCHAR(36) PRIMARY KEY,
+    "createdAt" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    "updatedAt" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    "dataType" VARCHAR(20) NOT NULL CHECK ("dataType" IN ('客流', '天气', '交通')),
+    "value" JSONB NOT NULL,
+    "latitude" DOUBLE PRECISION NOT NULL,
+    "longitude" DOUBLE PRECISION NOT NULL,
+    "source" VARCHAR(50) NOT NULL,
+    "validity" TIMESTAMP NOT NULL,
+    "resourceId" VARCHAR(36) REFERENCES "TouristResource"("objectId") ON DELETE CASCADE
+);
+
+-------------------------
+-- 6. 安全预警表
+-------------------------
+CREATE TABLE IF NOT EXISTS "SafetyWarning" (
+    "objectId" VARCHAR(36) PRIMARY KEY,
+    "createdAt" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    "updatedAt" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    "title" VARCHAR(255) NOT NULL,
+    "description" TEXT NOT NULL,
+    "severity" VARCHAR(10) NOT NULL CHECK ("severity" IN ('紧急', '高', '中')),
+    "latitude" DOUBLE PRECISION NOT NULL,
+    "longitude" DOUBLE PRECISION NOT NULL,
+    "validUntil" TIMESTAMP NOT NULL,
+    "relatedHazards" JSONB
+);
+
+-- 安全预警与旅游资源关联表
+CREATE TABLE IF NOT EXISTS "SafetyWarningResource" (
+    "warningId" VARCHAR(36) REFERENCES "SafetyWarning"("objectId") ON DELETE CASCADE,
+    "resourceId" VARCHAR(36) REFERENCES "TouristResource"("objectId") ON DELETE CASCADE,
+    PRIMARY KEY ("warningId", "resourceId")
+);
+
+-------------------------
+-- 测试数据插入
+-------------------------
+
+-- 用户数据
+UPDATE "_User" SET 
+    "phone" = '13800138000',
+    "profilePic" = 'https://example.com/users/1.jpg',
+    "emergencyContact" = '张女士 13900139000'
+WHERE "objectId" = 'user001';
+
+-- 旅游资源数据
+INSERT INTO "TouristResource" (
+    "objectId", "name", "type", "description", "latitude", "longitude", 
+    "openingHours", "priceRange", "images", "rating", "capacity"
+) VALUES
+('res001', '故宫博物院', '景点', '中国明清两代的皇家宫殿', 39.916345, 116.397155, 
+ '08:30-17:00', '60元', 
+ '["https://example.com/res/res001_1.jpg", "https://example.com/res/res001_2.jpg"]', 
+ 4.8, 80000),
+('res002', '长城酒店', '酒店', '五星级豪华酒店', 40.002345, 116.487155, 
+ '全天', '800-2000元', 
+ '["https://example.com/res/res002_1.jpg"]', 
+ 4.5, 300),
+('res003', '老北京烤鸭店', '餐厅', '传统北京烤鸭', 39.906345, 116.407155, 
+ '10:00-22:00', '100-300元', 
+ '["https://example.com/res/res003_1.jpg", "https://example.com/res/res003_2.jpg"]', 
+ 4.7, 200);
+
+-- 行程数据
+INSERT INTO "Itinerary" (
+    "objectId", "title", "startTime", "endTime", "reminderType", 
+    "latitude", "longitude", "notes", "alertLevel", "isCompleted", 
+    "userId", "resourceId"
+) VALUES
+('itn001', '参观故宫', '2023-10-01 09:00:00', '2023-10-01 12:00:00', '时间', 
+ 39.916345, 116.397155, '提前预约门票', '中', false, 
+ 'user001', 'res001'),
+('itn002', '长城酒店入住', '2023-10-01 15:00:00', '2023-10-01 16:00:00', '位置', 
+ 40.002345, 116.487155, '带身份证办理', '低', true, 
+ 'user001', 'res002');
+
+-- 旅行日志数据
+INSERT INTO "TravelJournal" (
+    "objectId", "title", "content", "photos", 
+    "latitude", "longitude", "weatherData", "moodRating", 
+    "userId", "resourceId"
+) VALUES
+('log001', '故宫初体验', '宏伟的古代建筑群令人震撼', 
+ '["https://example.com/logs/log001_1.jpg"]', 
+ 39.916345, 116.397155, '{"temperature": 25, "humidity": 60}', 5, 
+ 'user001', 'res001'),
+('log002', '美味烤鸭', '皮脆肉嫩,正宗北京味', 
+ '["https://example.com/logs/log002_1.jpg", "https://example.com/logs/log002_2.jpg"]', 
+ 39.906345, 116.407155, '{"temperature": 22, "humidity": 65}', 4, 
+ 'user001', 'res003');
+
+-- 实时监测数据
+INSERT INTO "RealTimeData" (
+    "objectId", "dataType", "value", 
+    "latitude", "longitude", "source", "validity", "resourceId"
+) VALUES
+('rtd001', '客流', '{"count": 3500, "density": "中等"}', 
+ 39.916345, 116.397155, '官方', '2023-10-01 14:00:00', 'res001'),
+('rtd002', '天气', '{"temperature": 24, "condition": "晴朗", "aqi": 45}', 
+ 39.916345, 116.397155, '传感器', '2023-10-01 13:00:00', 'res001'),
+('rtd003', '交通', '{"status": "拥堵", "speed": 15}', 
+ 40.002345, 116.487155, '官方', '2023-10-01 14:30:00', 'res002');
+
+-- 安全预警数据
+INSERT INTO "SafetyWarning" (
+    "objectId", "title", "description", "severity", 
+    "latitude", "longitude", "validUntil", "relatedHazards"
+) VALUES
+('warn001', '大风黄色预警', '预计未来3小时有8级以上大风', '高', 
+ 39.916345, 116.397155, '2023-10-02 18:00:00', '["自然灾害"]'),
+('warn002', '道路施工通知', '东华门周边道路施工,请绕行', '中', 
+ 39.916345, 116.397155, '2023-10-05 23:00:00', '["事故"]');
+
+-- 预警资源关联
+INSERT INTO "SafetyWarningResource" ("warningId", "resourceId") VALUES
+('warn001', 'res001'),
+('warn001', 'res003'),
+('warn002', 'res001');
                                                     

+ 16 - 14
myapp/src/app/tab1/tab1.module.ts

@@ -1,21 +1,23 @@
-import { IonicModule } from '@ionic/angular';
 import { NgModule } from '@angular/core';
 import { CommonModule } from '@angular/common';
+import { IonicModule } from '@ionic/angular';
 import { FormsModule } from '@angular/forms';
-import { Tab1Page } from './tab1.page';
-import { ExploreContainerComponentModule } from '../explore-container/explore-container.module';
+import { RouterModule } from '@angular/router';
 
-import { Tab1PageRoutingModule } from './tab1-routing.module';
+import { Tab1Page } from './tab1.page';
 
 @NgModule({
-  imports: [
-    IonicModule,
-    CommonModule,
-    FormsModule,
-    ExploreContainerComponentModule,
-    Tab1PageRoutingModule
-  ],
-  declarations: [Tab1Page],
-  exports: [Tab1Page]
+  imports: [
+    CommonModule,
+    FormsModule,
+    IonicModule,
+    RouterModule.forChild([
+      {
+        path: '',
+        component: Tab1Page,
+      },
+    ]),
+  ],
+  declarations: [Tab1Page],
 })
-export class Tab1PageModule {}
+export class Tab1PageModule {}

+ 66 - 66
myapp/src/app/tab1/tab1.page.scss

@@ -1,75 +1,75 @@
 ion-content {
-    --background: #f8f9fa;
-  
-    // 动态仪表盘样式
-    .dashboard-card {
-      margin: 16px;
-      border-radius: 16px;
-  
-      .stats-grid {
-        padding: 16px;
-  
-        .stat-card {
-          --background: rgba(38, 90, 129, 0.05);
-          text-align: center;
-  
-          .stat-value {
-            font-size: 2.5rem;
-            font-weight: bold;
-            color: var(--ion-color-primary);
-          }
-  
-          .stat-label {
-            color: #666;
-            font-size: 0.9rem;
-          }
+  --background: #f8f9fa;
+
+  // 动态仪表盘样式
+  .dashboard-card {
+    margin: 16px;
+    border-radius: 16px;
+
+    .stats-grid {
+      padding: 16px;
+
+      .stat-card {
+        --background: rgba(38, 90, 129, 0.05);
+        text-align: center;
+
+        .stat-value {
+          font-size: 2.5rem;
+          font-weight: bold;
+          color: var(--ion-color-primary);
         }
-      }
-    }
-  
-    // 智能推荐卡片
-    .recommendation-card {
-      margin: 16px;
-  
-      ion-fab-button {
-        --background: var(--ion-color-primary);
-        --box-shadow: 0 4px 8px rgba(38, 90, 129, 0.3);
-      }
-    }
-  
-    // 社交动态墙
-    .social-wall {
-      margin: 16px;
-  
-      .engagement-counts {
-        display: flex;
-        justify-content: flex-end;
-        gap: 16px;
-        margin-top: 8px;
-  
-        ion-icon {
-          font-size: 1.2em;
-          margin-right: 4px;
+
+        .stat-label {
+          color: #666;
+          font-size: 0.9rem;
         }
       }
     }
-  
-    // 暗色模式适配
-    .dark-mode {
-      --ion-color-primary: #488aff;
-      --background: #1a1a1a;
-  
-      .stat-value {
-        color: #8ab4f8;
+  }
+
+  // 智能推荐卡片
+  .recommendation-card {
+    margin: 16px;
+
+    ion-fab-button {
+      --background: var(--ion-color-primary);
+      --box-shadow: 0 4px 8px rgba(38, 90, 129, 0.3);
+    }
+  }
+
+  // 社交动态墙
+  .social-wall {
+    margin: 16px;
+
+    .engagement-counts {
+      display: flex;
+      justify-content: flex-end;
+      gap: 16px;
+      margin-top: 8px;
+
+      ion-icon {
+        font-size: 1.2em;
+        margin-right: 4px;
       }
     }
   }
-  
-  // 微交互动画
-  .stat-card.interactive {
-    transition: transform 0.2s ease;
-  
-    &:hover {
-      transform: translateY(-4px);
+
+  // 暗色模式适配
+  .dark-mode {
+    --ion-color-primary: #488aff;
+    --background: #1a1a1a;
+
+    .stat-value {
+      color: #8ab4f8;
     }
-  }
+  }
+}
+
+// 微交互动画
+.stat-card.interactive {
+  transition: transform 0.2s ease;
+
+  &:hover {
+    transform: translateY(-4px);
+  }
+}