XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

EARSystem

【ASP】耳间,网页端的情绪智能推荐系统

公开
关注 0 Fork 0 Star 0
UTF-8

架构与数据设计

应用结构

单体应用通过 MVC 渲染页面,Fetch 调用同源 JSON。Web 负责登录、输入校验、防伪和用户边界;Core 保持画像与评分逻辑可测试;Infrastructure 负责持久化、供应商接入和体验聚合。

flowchart LR
    Browser["Razor / 本地 Bootstrap / Chart.js"] --> Web["EARSystem.Web / MVC / Identity"]
    Web --> Core["EARSystem.Core / 画像与目标 / 六项匹配"]
    Web --> Infra["EARSystem.Infrastructure / 体验事务 / 周报数据"]
    Core --> Provider["IPlaceProvider"]
    Provider --> Catalog["独立目录 / Demo 与 Collected 分区"]
    Provider --> AMap["高德实时地点服务"]
    Browser --> Proxy["/_AMapService 受限安全代理"]
    Proxy --> JS["高德 JS API 2.0"]
    Infra --> SQL["SQL Server / EF Core"]
    Catalog --> SQL

交互闭环

flowchart TD
    Login["注册 / 登录 / 开发演示登录"] --> Mood["自评心情、精力、压力与想法"]
    Mood --> Hint["可选文字规则提示"]
    Hint --> Confirm["用户确认候选标签"]
    Confirm --> Save["保存私密日记"]
    Save --> Profile["最近 7 天按日取最后一条形成画像"]
    Profile --> Goal["自动目标;允许本次覆盖"]
    Goal --> Location["授权定位 / 地址搜索 / 手动选点"]
    Location --> Recall["明确选择在线或演示;召回至多 100 个"]
    Recall --> Filter["范围、屏蔽、预算、类别、营业筛选"]
    Filter --> Rank["六项评分 / 类别多样性 / 前 10 项"]
    Rank --> Detail["查看原因、来源、氛围及详情"]
    Detail --> Favorite["收藏独立目录地点"]
    Favorite --> Experience["私密到访体验"]
    Experience --> Consent["可选贡献结构化氛围 / 同步日记"]
    Consent --> Review["趋势、日历、周报"]
    Consent --> Feedback["下一次推荐读取最新个人体验与匿名统计"]
    Feedback --> Rank

ER 图

Identity 的用户、角色与用户角色表由框架维护;以下包含关键业务关联。MoodEntry.ExperienceId 是应用管理的可选关联:取消同步或删除体验会解除它,日记仍保留。

erDiagram
    ApplicationUser ||--o{ MoodEntry : records
    ApplicationUser ||--o| UserPreference : configures
    ApplicationUser ||--o{ Experience : owns
    ApplicationUser ||--o{ Favorite : saves
    ApplicationUser ||--o{ RecommendationRecord : requests
    Place ||--o| PlaceAtmosphere : has_baseline
    Place ||--o{ Experience : receives
    Place ||--o{ Favorite : referenced
    Experience o|--o| MoodEntry : optional_sync
    ApplicationUser {
        string Id PK
        string Email
        string DisplayName
        bool IsDemo
    }
    MoodEntry {
        guid Id PK
        string UserId FK
        int Mood
        int Energy
        int Stress
        string TagsJson
        string Thoughts
        long RecordedAt
        guid Version
        guid ExperienceId
    }
    UserPreference {
        string UserId PK
        string FavoriteCategoriesJson
        string BlockedCategoriesJson
        string BlockedPlacesJson
        decimal Budget
        int RadiusMeters
    }
    Place {
        guid Id PK
        string Name
        string Address
        int Category
        int Source
        double Longitude
        double Latitude
        decimal Price
        double Rating
        int OpenHour
        int CloseHour
    }
    PlaceAtmosphere {
        guid PlaceId PK
        double Quiet
        double Comfort
        double Nature
        double Liveliness
        double Social
        double Focus
        int BaselineCount
        string Evidence
    }
    Experience {
        guid Id PK
        string UserId FK
        guid PlaceId FK
        long VisitedAt
        int VisitDay
        int Satisfaction
        int MoodBefore
        int MoodAfter
        string Thoughts
        bool Contribute
        guid Version
    }
    Favorite {
        string UserId PK
        guid PlaceId PK
        long CreatedAt
    }
    RecommendationRecord {
        guid Id PK
        string UserId FK
        int Goal
        int Mode
        string AlgorithmVersion
        string ResultsJson
        double DurationMs
    }
    RuleConfiguration {
        int Id PK
        string Version
        string WeightsJson
        guid ConcurrencyStamp
        datetimeoffset DemoSeededAt
    }

Experience 还含六个 1–5 氛围评分。PlaceAtmosphere 保存独立采集或演示的基线;用户贡献保持在 Experience 中,读取时聚合,不覆盖基线。有效人数为基线样本数加去重后的贡献人数;同一人多次体验取其最新同意贡献的记录。

约束与边界

对象 约束
MoodEntry UserId+RecordedAt 索引、正文最多 5,000 字、Version 并发令牌
Experience UserId+PlaceId+VisitDay 唯一、UserId+VisitedAt 及 PlaceId+Contribute 索引、Version 并发令牌
Favorite UserId+PlaceId 复合主键;“去过”由当前有效体验推导
Place Source+Category 索引;有收藏/体验时不能删除;已存在地点不可更换数据来源
RuleConfiguration 单一规则配置、权重总和校验、版本号、ConcurrencyStamp
个人内容 会话获取 UserId,所有个人查询/变更同时匹配本人;管理员页面无私人正文入口
第三方地点 在线响应临时用于匹配,不入地点表;持久体验引用独立目录

JSON 接口

所有接口需要 Cookie 登录。POST/PUT/DELETE 需要 X-CSRF-TOKEN,可从布局的防伪隐藏字段读取。身份不接受请求中的 userId。

方法与路径 行为
GET /api/moods?date=YYYY-MM-DD 或 ?days=30 本人的时间范围记录
POST /api/moods 创建自评
PUT /api/moods/ 编辑,body.version 必须匹配
DELETE /api/moods/?version= 删除并发校验
POST /api/emotion-tags/preview 提示标签与触发短语,不持久化
POST /api/recommendations 位置、坐标系、模式、筛选和本次目标
GET/POST /api/experiences 本人体验列表与创建
PUT /api/experiences/ 修改体验,校验 version
DELETE /api/experiences/?version= 删除并重算贡献;关联日记保留
GET/POST /api/favorites 收藏列表与创建
DELETE /api/favorites/ 取消本人收藏
GET/PUT /api/preferences 偏好、预算、距离与屏蔽
GET /api/reports/trend?days=7或30 每日最后记录,缺失为 null
GET /api/reports/weekly?week=YYYY-MM-DD 自动对齐周一至周日
POST /api/map/geocode 在线地址搜索,body.text

枚举用字符串:Demo/Online、Relax/Explore/Social/Focus、Dining/Cafe/Park/Bookstore/Gallery/Entertainment。坐标系为 WGS84 或 GCJ02。

推荐响应包含 goal、goalName、basis、profile、mode、algorithmVersion、candidateCount、suggestExpand、items 和转换后的 location。每项含 place、distanceMeters、score、parts、confidence、reasons。分项和精确位置只随响应返回,不写入推荐历史。

401 表示未登录,403 权限不足,400 输入无效,404 本人记录不存在,409 并发/唯一约束冲突,429 限流,503 地图失败或超时。前端显示错误并保留编辑输入。