This commit is contained in:
dubingyan666 2025-11-25 21:46:59 +08:00
parent d4b2c801f4
commit b1f02e6b7a
26 changed files with 34 additions and 1524 deletions

View File

@ -1,59 +0,0 @@
## 输出目标
- 以 `admin`(后台)与 `app`(用户端)两大类重组全部现有 `v1` API。
- 统一每个接口的文档格式:路径、方法、版本、功能说明、公开/认证、admin权限要求、请求参数与格式、响应结构、错误代码。
- 版本标注统一为 `v1`(前缀 `"/api/v1"`)。
## 分类规则
- `admin`:在 `app/api/v1/__init__.py:33-38,45-51` 通过 `dependencies=[DependAuth, DependPermission]` 绑定的模块及其接口:`user/role/menu/api/dept/auditlog/valuations/invoice/transactions/third_party_api`,以及 `base`(后台登录与个人信息)。
- `app`:面向终端用户的模块:`app-user``app-valuations``sms`(登录与验证码相关)、`upload`
- 管理功能但当前公开(未绑定后台依赖):`industry/index/policy/esg`,归入 `admin公开`,在文档中明确“公开接口”。
## 文档结构
- 顶层两章:
- `app用户端`:模块分组(用户认证与账户、用户资料与仪表盘、用户端估值、短信验证码、上传)
- `admin后台`模块分组用户管理、角色管理、菜单管理、API 权限管理、部门管理、审计日志、估值评估、发票管理、交易管理、第三方内置接口、内容管理:行业/指数/政策/ESG、基础登录/个人信息)
- 接口条目统一字段:
- 路径:`/api/v1/<module>/<subpath>`
- 方法:`GET/POST/PUT/DELETE`
- 版本:`v1`
- 功能说明:一句话摘要
- 公开/认证:`公开``需认证``admin` 另标注“需权限校验”)
- 权限要求admin是否受 `DependPermission` 控制(匹配 `(method, path)`
- 请求参数Query/Path/BodyBody 引用 `pydantic` 模型名)
- 响应结构:统一 `{code,msg,data}` 或分页 `{code,msg,data,total,page,page_size}`(引用响应模型)
- 错误代码200/400/401/403/404/422/500依据全局异常与业务抛出
## 信息来源与标注依据
- 路由与版本:`app/api/v1/__init__.py:28-52`(前缀与模块挂载)。
- 认证与权限:
- `admin` 统一:`DependAuth``DependPermission``app/api/v1/__init__.py:33-38,45-51`;依赖定义于 `app/core/dependency.py`)。
- `app` 认证:`Depends(get_current_app_user)`/`Depends(get_current_app_user_id)``app/utils/app_user_jwt.py:51,71-72`)。
- 单接口特例:`sms``/send-report` 需后台认证(`app/api/v1/sms/sms.py:68`)。
- 请求/响应模型:端点签名与 `response_model`(来源 `app/schemas/*`)。
- 错误码与统一响应:`app/core/init_app.py:56-59`(注册),`app/core/exceptions.py:15,23,31`(处理器)。
## 示例格式(两条)
- `appPOST /api/v1/sms/send-code`v1
- 功能:发送登录验证码到手机号
- 公开/认证:公开
- 请求参数Body`SendCodeRequest`
- 响应结构:`SendResponse``{code,msg,data}`
- 错误码:`400/422/500`
- 代码参照:`app/api/v1/sms/sms.py:68`
- `adminGET /api/v1/user/list`v1
- 功能:分页查询后台用户
- 公开/认证:需认证;需权限校验
- 请求参数Query分页与过滤
- 响应结构:`SuccessExtra``{code,msg,data,total,page,page_size}`
- 错误码:`401/403/422/500`
- 代码参照:`app/api/v1/__init__.py:33`
## 交付内容
- 生成统一的 Markdown 文档(建议 `docs/api-v1.md`),按 `app``admin` 两章、功能模块分组列出全部接口,逐条填充统一字段。
- 附“错误码说明”与“认证/权限机制”章节,提供关键代码路径引用,便于后续维护与审计。
## 验证与维护
- 通过聚合路由与端点扫描确认无遗漏;如有新接口,按相同格式追加。
- 校验每条接口的认证与权限标注是否与代码一致;抽样比对响应结构、错误码与异常处理一致性。
请确认上述按 `admin``app` 分类的计划;确认后我将开始生成完整文档并交付。

View File

@ -1,184 +0,0 @@
## 现状速览
* 后端框架FastAPIORMTortoise权限`DependAuth` + `DependPermission` 挂载在 admin 路由(`app/api/v1/__init__.py:33-37`)。
* 用户端估值评估路由:`/api/v1/app-valuations``app/api/v1/app_valuations/app_valuations.py`),控制器分层清晰(`app/controllers/user_valuation.py``app/controllers/valuation.py`)。
* 上传目前仅支持图片(`app/controllers/upload.py:12-52``app/api/v1/upload/upload.py:7-14`)。
* 发票与抬头能力完善(`app/api/v1/invoice/invoice.py``app/controllers/invoice.py`)。
* Web 管理端用户列表当前使用 Mock 数据展示“剩余体验次数”(`web/src/views/user-management/user-list/index.vue:115-122``web/src/api/index.js:279-352`)。
## 目标改造概览
* 交易管理新增“邮件发送”接口,支持正文与附件,完备校验与日志。
* 用户管理新增“剩余估值次数”字段与管理员调额能力,提供操作日志(前/后值、类型、备注)。
* 估值表新增“报告/证书”URL 字段与多格式上传能力,生成可下载链接。
* 估值表新增“统一社会信用代码/身份证号”与“业务/传承介绍”,前后端同步与校验。
* 全量权限控制、API 文档补充、数据库变更记录与单元测试覆盖。
## 数据库与模型变更
* ValuationAssessment`app/models/valuation.py`)新增:
* `report_url: CharField(512)``certificate_url: CharField(512)` 用于管理员上传的报告/证书下载地址。
* `credit_code_or_id: CharField(64)` 用于统一社会信用代码或身份证号。
* `biz_intro: TextField` 业务/传承介绍。
* 用户配额与日志:
* AppUser`app/models/user.py`)新增 `remaining_quota: IntField(default=0)`
* 新增操作日志模型(建议放入 `app/models/invoice.py` 同模块管理,或新建 `app/models/transaction.py``AppUserQuotaLog` 字段:`app_user_id``operator_id``operator_name``before_count``after_count``op_type`(如:付费估值)、`remark``created_at`
* 邮件发送日志模型:`EmailSendLog` 字段:`email``subject``body` 摘要(前 N 字符)、`file_name`/`file_url``status`OK/FAIL`error`(可空)、`sent_at`
* 迁移:使用 Aerich 生成并升级(保持兼容,所有新增字段均可空或有安全默认值)。
## 接口设计与权限控制
* 交易管理新增:`POST /api/v1/transactions/send-email`
* Bodymultipart 或 JSON
* `email`(必填,邮箱校验)
* `subject`(可选,默认“估值服务通知”)
* `body`(必填,文案内容,长度与危险字符校验)
* `file`(可选,`UploadFile`,或 `file_url` 字符串二选一)
* 行为:使用标准库 `smtplib` + `email` 组合发送;支持 TLS/SSL发送后落库 `EmailSendLog`;返回发送状态与日志 ID。
* 权限:挂载于 `transactions_router`(已带 `DependAuth``DependPermission``app/api/v1/__init__.py:52`)。
* 用户管理新增:
* `GET /api/v1/user/list` 返回结构新增 `remaining_quota` 字段。
* `POST /api/v1/user/quota`(管理员)调整用户剩余估值次数:
* Body`user_id``target_count``delta``op_type``remark`
* 行为:读取当前值,计算前后值,更新 `AppUser.remaining_quota`,记录 `AppUserQuotaLog`
* `GET /api/v1/user/{id}/quota-logs` 返回日志列表(分页、类型筛选)。
* 发票抬头查看:
* 复用现有接口 `GET /api/v1/invoice/headers?app_user_id=...``app/api/v1/invoice/invoice.py:118-124`)。
* 估值评估新增字段对外:
* 管理端与用户端输出 Schema 同步包含 `report_url``certificate_url``credit_code_or_id``biz_intro`
## 上传能力扩展
* 控制器:新增 `upload_file(file: UploadFile)` 支持 `pdf/docx/xlsx/zip` 等白名单;存储到 `app/static/files`;生成可下载链接 `settings.BASE_URL + /static/files/{name}`
* 路由:`POST /api/v1/upload/file`(保留图片接口不变)。
* 校验:
* MIME 白名单与大小限制;文件名清洗与去重;异常返回 4xx/5xx。
## Schema 与后端校验
* 估值 Schema`app/schemas/valuation.py`)新增并校验:
* `credit_code_or_id`:正则校验(统一社会信用代码/18位身份证格式二选一
* `report_url``certificate_url`URL 格式校验。
* 用户配额:新增 `AppUserQuotaUpdateSchema``AppUserQuotaLogOutSchema`
* 邮件发送:`SendEmailRequest` 支持两种附件输入;返回 `SendEmailResponse`
<br />
## 发送逻辑实现要点
* 设置:在 `app/settings/config.py` 增加 SMTP 相关配置:`SMTP_HOST``SMTP_PORT``SMTP_USERNAME``SMTP_PASSWORD``SMTP_TLS``SMTP_FROM`(默认 None走环境变量注入
* 发送器:`app/services/email_client.py`(或 `app/controllers/transactions.py` 内部封装),使用 `smtplib.SMTP_SSL`/`SMTP.starttls()`,构造 `MIMEText``MIMEBase`,附件从 `UploadFile` 或远程 `file_url` 下载后附加。
* 错误处理:
* 参数校验失败返回 422SMTP 异常记录 `EmailSendLog.error` 并返回 500长正文截断日志摘要防止超长存储。
* 日志:统一 `loguru` 记录关键事件(如 `transactions.email_send_start/ok/fail`)。
## 权限控制与 API 权限表
* 新增接口在 `Api` 表登记(路径+方法+标签),使用现有刷新接口 `POST /api/v1/api/refresh` 扫描路由自动入库。
* 路由均落于已挂载依赖的 admin 模块App 端路由继续独立(`app/api/v1/__init__.py:28-33`)。
## API 文档与变更记录
* 为所有新增接口与控制器方法补充函数级注释(功能、参数、返回值),满足用户规范。
* 通过 FastAPI 自动生成的 OpenAPI 展示补充接口示例与错误码说明Docstring
* 数据库变更记录:在迁移文件中含新增字段/表说明;在说明文档中列出字段语义与默认值(本次提交提供变更概要)。
## 单元测试计划
* 邮件发送:
* 伪造 `FakeEmailClient`,覆盖成功/失败/附件两种输入;比照 `tests/api/v1/test_sms.py` 的 monkeypatch 风格。
* 用户配额:
* 调额接口:前后值正确、日志记录正确、权限检查(需登录管理员)。
* 估值字段:
* 创建/更新时包含新字段URL 与正则校验失败用例;上传文件生成链接断言。
* 上传:
* 非法 MIME 与超限大小拒绝;合法文件成功返回 URL。
## 兼容性与回滚策略
* 所有新增字段均为可空或安全默认,旧数据不受影响。
* 新增接口均为新增路由,不改动原有行为;前端逐步切换数据源,保留 Mock 作为回退。
* 迁移脚本按标准生成;如需回滚 aerich 支持 `downgrade`
## 实施步骤
1. 模型与 Schema 更新;生成 Aerich 迁移;本地升级并验证。
2. 上传控制器扩展与新路由;估值控制器/输出字段同步。
3. 交易管理发送接口(含 SMTP 封装、日志落库、异常处理)。
4. 用户配额接口与日志模型/路由admin 列表与详情改造。
5. 权限入库与刷新;为接口添加函数级注释。
6. 单元测试编写与通过OpenAPI 检视;交付 API/DB 变更说明。
## 关键代码定位参考
* 路由注册:`app/api/v1/__init__.py:28-52`
* 用户端估值入口:`app/api/v1/app_valuations/app_valuations.py:233-318`
* 估值控制器:`app/controllers/valuation.py:73-100``app/controllers/user_valuation.py:21-42`
* 上传控制器:`app/controllers/upload.py:12-52`
* 发票抬头接口:`app/api/v1/invoice/invoice.py:118-144`
* 管理端用户列表(前端):`web/src/views/user-management/user-list/index.vue:69-166`
* Mock 数据与 API`web/src/api/index.js:279-352, 433-479`
——请确认方案后,我将按上述步骤开始落地实现、编写迁移与测试。

View File

@ -1,133 +0,0 @@
## 目标概述
* 加强“交易管理-发票附件与发送邮箱”能力,完善数据记录与事务保障。
* 改进“开票弹窗附件上传”支持多文件上传(后端存储结构)。
* 优化“用户管理备注与操作记录”,区分备注维度并完善日志。
* 覆盖单元/集成测试、数据库迁移、API文档与审计日志。
## 数据库与模型变更
* EmailSendLog
* 新增:`extra: JSONField(null=True)` 完整记录发送邮箱的请求数据(收件人、主题、正文、附件列表、重试信息等)。
* Invoice或与开票弹窗相关的业务模型
* 新增:`attachments: JSONField(null=True)` 支持多个附件URL与弹窗上传对应
<br />
* <br />
* 迁移脚本:创建/修改上述字段;保留历史数据不丢失。
## 事务与原子性
* 发送邮箱流程(交易管理)
* 封装在 `tortoise.transactions.in_transaction()`邮件发送、EmailSendLog写入含attachments/extra原子提交失败回滚。
* extra写入内容完整`SendEmailRequest`收件人、主题、正文、附件URL/文件名、重试次数、客户端UA等
* 多文件上传至发票附件(开票弹窗)
* 更新发票的 `attachments` 字段在同一事务内写入如任一URL校验失败则回滚。
## 后端接口改造
* 上传组件(后端)
* 新增:`POST /api/v1/upload/files` 接收 `files: List[UploadFile]`,统一返回 `urls: string[]`;保留现有单文件接口向后兼容。
* 交易管理(管理员)
* `POST /api/v1/transactions/send-email` 扩展:
* 入参支持 `file_urls: string[]`(与/或单文件),服务端聚合附件;
* 在事务中记录 EmailSendLog含attachments与extra返回log\_id与状态
* 回显接口(详情/列表)新增 `extra` 字段完整展示发送记录。
* 开票弹窗附件(管理员/或对应端)
* 新增/改造:`PUT /api/v1/invoice/{id}/attachments` 入参 `urls: string[]`,更新发票 `attachments`
* 列表/详情回显 `attachments: string[]`
* 用户管理备注优化(管理员端)
* 新接口:`PUT /api/v1/app-user-admin/{user_id}/notes`
* 入参:`system_notes?: string``user_notes?: string`(可选择性更新)
* 逻辑:仅更新提供的字段;不影响其他字段。
* 修复:`POST /api/v1/app-user-admin/quota` 仅调整次数,不再自动写入 `user.notes`
* 操作日志:在调整配额、更新备注、停用启用等操作时写入 `AppUserOperationLog`
## 前端改造(要点)
* 多文件上传组件
* 改为多选/拖拽支持;对每个文件显示上传进度与失败重试;
* 成功后收集URL数组写入发票 `attachments` 或作为邮件附件来源;
* 兼容旧接口若后端仅返回单URL前端仍正常显示降级为单文件模式
* 开票弹窗
* 支持附件列表预览与移除;提交时调用 `PUT /invoice/{id}/attachments`
* 邮件发送弹窗
* 选择附件来源(已上传的附件/本地文件再上传);提交后在详情页面完整回显 `extra`(含附件清单与正文等)。
## 审计与日志
* 关键操作:邮件发送、发票附件更新、用户备注更新、配额调整
* 统一调用审计记录(路由中间件已存在,补充结构化日志:`logger.info()` + DB审计表/操作日志表写入)。
## 测试方案
* 单元测试
* Email发送控制器事务成功/失败回滚(模拟抛错)
* 多文件上传文件类型校验、URL数组返回、尾随空白处理
* 备注更新:选择性字段更新、不影响其他字段
* 集成测试FastAPI + httpx.AsyncClient
* 发送邮箱请求→持久化校验attachments/extra→回显接口校验
* 附件上传:批量上传、更新发票、列表/详情回显
* 用户备注接口调用→DB值校验→操作日志存在
## 迁移与兼容
* 使用现有迁移工具如Aerich生成并应用迁移新增JSON/Text字段
* 前端保留旧接口兼容若上传仍走单文件后端返回数组长度1
* API文档OpenAPI
* 补充/更新以上端点的schema说明、示例请求/响应、错误码约定;
## 实施步骤与交付
1. 数据模型与迁移脚本编写与应用EmailSendLog、Invoice、AppUser/OperationLog
2. 后端接口改造与事务封装(邮件发送、多文件上传、发票附件更新、备注接口)。
3. 前端组件与弹窗改造多文件上传、进度与错误处理、回显extra
4. 审计日志与结构化日志补充。
5. 单元与集成测试编写,覆盖核心路径。
6. 更新接口文档与部署回归验证。

View File

@ -1,71 +0,0 @@
## 目标与范围
- 针对“估值二期”需求(用户端、管理端)设计完整 API去除 Webhook 回调。
- 对齐现有约定:认证 `POST /api/v1/base/access_token`app/api/v1/base/base.py:19-38`token` 请求头web/src/utils/http/interceptors.js:11-14响应 `Success/SuccessExtra/Fail`app/schemas/base.py成功码 `code===200`web/src/utils/http/interceptors.js:23-33估值域已有 `/api/v1/valuations`app/api/v1/valuations/valuations.py:21-191
## 核心流程
- 用户端:登录→评估提交→个人中心(汇款凭证、抬头选择、类型选择、发票列表/详情)→估值记录(下载证书/报告、分享、历史结果、剩余次数)。
- 管理端:交易管理(查看/核验/邮件/开票/状态)→用户管理(信息/操作/修改/审核/投诉/短信文案/证书与报告)→审核列表(上传证书/下载/重传)。
## 实体与关系
- AppUser ⇄ Valuation(1..n)、Invoice(1..n)、InvoiceHeader(n)
- Valuation ⇄ ValuationCalculationStep(1..n) ⇄ Certificate/Report
- Invoice ⇄ InvoiceHeader/PaymentReceipt/Transaction
- Complaint、SMSMessage 与用户/估值/发票按需关联
## 端点设计(与前端映射保持一致)
- 认证与用户
- POST `/api/v1/base/access_token` 登录app/api/v1/base/base.py:19-38
- GET `/api/v1/base/userinfo` 用户信息app/api/v1/base/base.py:40-46
- GET `/api/v1/app-user/profile` 当前用户画像与剩余估值次数
- GET `/api/v1/app-user/list`、GET `/api/v1/app-user/get`、POST `/api/v1/app-user/register|update`、DELETE `/api/v1/app-user/delete`(对齐 web/src/api/index.js:433-503
- 估值评估(沿用并扩展)
- POST `/api/v1/valuations/`、GET `/api/v1/valuations/`、GET `/api/v1/valuations/{id}`(已存在)
- GET `/api/v1/valuations/{id}/steps`(已存在,用于过程展示)
- GET `/api/v1/valuations/{id}/certificate`(新增:证书下载)
- GET `/api/v1/valuations/{id}/report`(新增:报告下载)
- POST `/api/v1/valuations/{id}/share`(新增:生成分享链接/小程序码,异步)
- POST `/api/v1/valuations/batch/delete`(已存在)
- 发票与交易(保留现有路径)
- GET `/api/v1/invoice/list`、GET `/api/v1/invoice/detail`、POST `/api/v1/invoice/create|update|send|remind|refund`、DELETE `/api/v1/invoice/delete`、POST `/api/v1/invoice/update-status`(对齐 web/src/api/index.js:504-725
- POST `/api/v1/invoice/{id}/receipt`(新增:上传付款凭证)
- GET `/api/v1/invoice/headers`、GET `/api/v1/invoice/headers/{id}`、POST `/api/v1/invoice/headers`(新增:抬头管理)
- POST `/api/v1/invoice/{id}/issue`(新增:开票,异步 Job
- 审核与证书
- GET `/api/v1/review/valuations` 审核列表(新增)
- POST `/api/v1/review/valuations/{id}/approve|reject`复用估值审核app/api/v1/valuations/valuations.py:167-183
- POST `/api/v1/review/valuations/{id}/certificate` 上传证书(新增)
- PUT `/api/v1/review/valuations/{id}/report` 重传报告(新增)
- 投诉与短信
- GET `/api/v1/complaints`、GET `/api/v1/complaints/{id}`、PUT `/api/v1/complaints/{id}`(新增)
- GET `/api/v1/sms/templates`、POST `/api/v1/sms/templates`、POST `/api/v1/sms/send`(新增)
## 请求/响应格式与认证
- 统一 JSON请求头 `token` 必填(除登录与公共资源)。
- 成功:`{code:200,data:...,msg:"success"}`;失败:`{code:4xx/5xx,msg:"错误"}`
## 字段与校验(示例)
- ValuationCreate`asset_name(1-64)`, `institution(1-128)`, `industry(1-64)`, `heritage_level?`, `inputs(object)`, `attachments?[url[]]`
- InvoiceCreate`ticket_type(electronic|paper)`, `invoice_type(special|normal)`, `phone`, `email`, `company_name`, `tax_number`, `register_address`, `register_phone`, `bank_name`, `bank_account`
- PaymentReceipt`url`, `uploaded_at`, `verified`
- ShareRequest`channel(miniprogram|link)`, `expire(<=604800)`
- 规则:邮箱/手机号/税号格式;枚举校验;附件数量与大小限制。
## 错误码
- 200 成功400 参数错误401 未认证前端自动登出web/src/utils/http/interceptors.js:45-53403 无权限404 不存在409 冲突422 校验失败429 频率限制500 内部错误。
## 批量与异步(无 Webhook
- 批量:发票批量开具、邮件批量发送(`POST /api/v1/invoice/batch/issue|send`)。
- 异步 Job开票/报告/分享生成返回 `job_id`;查询 `GET /api/v1/jobs/{id}``status: pending|running|success|failed`)。客户端采用轮询或前端提示重试。
## 性能目标
- 登录/用户信息 P95 ≤ 100ms列表分页 P95 ≤ 200ms单页 ≤ 100 条)。
- 异步任务完成 ≤ 5sQPS单实例读 200+/s、写 50+/s。
## 实施建议
1. 在 `app/api/v1/` 新增 invoices/reviews/complaints/sms 路由文件。
2. 在 `controllers/` 实现控制器,复用 `ValuationController` 的计算步骤记录app/controllers/valuation.py:24-53
3. 在 `schemas/` 新增/扩展 Pydantic 模型,严格校验。
4. 增加 Job 状态查询端点,统一返回结构;无 Webhook 的情况下采用客户端轮询。
5. 前端按 `web/src/api/index.js` 对齐接入,复用错误处理与 401 登出。
——请确认该无 Webhook 版本的 API 方案,确认后我将开始后端路由/控制器/模型实现并提供前端对接示例。

View File

@ -1,184 +0,0 @@
## 目标
* 完整设计并落实“估值计算步骤”API与落库机制保证
1. 用户提交估值后,所有中间计算步骤按规范写入数据库;
2. 管理端在详情中查看完整步骤链条与中间结果;
3. 统一数学公式、变量来源、步骤编号与展示结构。
## 现有能力与锚点
* 步骤模型:`ValuationCalculationStep`app/models/valuation.py:88-107
* 步骤写入:控制器提供创建/查询app/controllers/valuation.py:24-53, 37-53
* 管理端步骤查询:`GET /api/v1/valuations/{id}/steps`app/api/v1/valuations/valuations.py:50-56
* 已有示例记录风险调整B3模块内已演示步骤写入app/utils/calculation\_engine/risk\_adjustment\_b3/sub\_formulas/risk\_adjustment\_b3.py:195-237
* 用户端计算入口后台任务执行统一计算app/api/v1/app\_valuations/app\_valuations.py:210-299
## 公式总览与数学表达
1. 经济价值 B1economic\_value\_b1
* 基础价值 B11依据财务与法律/创新、普及度
* 示例表达:`B11 = w_f * f(three_year_income) + w_i * innovation_ratio + w_p * popularity_score + w_l * infringement_factor + w_pat * patent_score`
* 流量因子 B12`S = α * S1 + β * S2 + γ * S3`;其中 S1 搜索指数(百度/微信/微博S2 行业均值S3 社交传播(点赞/评论/分享)
* 政策乘数 B13`P = p_impl * implementation_stage_score + p_fund * funding_support_score`
* 汇总:`B1 = B11 * (1 + θ * S) * (1 + λ * P)`
1. 文化价值 B2cultural\_value\_b2
* 活态传承 B21`B21 = κ1 * inheritor_level_coefficient + κ2 * offline_sessions + κ3 * social_views`
* 纹样基因 B22`B22 = μ1 * historical_inheritance + μ2 * structure_complexity + μ3 * normalized_entropy`
* 汇总:`B2 = B21 + B22`
1. 风险调整 B3risk\_adjustment\_b3
* 风险评分总和:`R = 0.3 * market_risk + 0.4 * legal_risk + 0.3 * inheritance_risk`
* 风险调整系数:`B3 = 0.8 + 0.4 * R`app/utils/.../risk\_adjustment\_b3.py:33-45, 47-66
1. 市场价值 Cmarket\_value\_c
* 竞价 C1`C1 = weighted_average_price(transaction_data, manual_bids, expert_valuations)`
* 热度系数 C2`C2 = ψ1 * daily_browse_volume + ψ2 * collection_count`
* 稀缺性乘数 C3`C3 = φ(circulation)`(限量>稀缺性高)
* 时效性衰减 C4`C4 = decay(recent_market_activity)`
* 汇总:`C = C1 * (1 + C2) * C3 * C4`
1. 最终估值 ABfinal\_value\_ab
* 模型估值 B`B = B1 + B2`;再叠加风险调整:`B_adj = B * B3`
* 市场估值:`C`
* 最终:`Final = f(B_adj, C)`(例如加权平均或规则合成)
## 变量定义与来源映射
* 用户输入UserValuationCreateapp/schemas/valuation.py:144-147
* `three_year_income``annual_revenue``rd_investment``application_coverage``offline_activities``platform_accounts``sales_volume``link_views``circulation``last_market_activity``price_fluctuation``funding_status``implementation_stage``patent_application_no``historical_evidence``pattern_images``inheritor_level``inheritor_age_count`
* 系统/API来源
* 搜索指数S1、行业均值S2、社交传播S3app/api/v1/app\_valuations/app\_valuations.py:328-347, 333-343
* ESG分、行业系数、政策匹配度app/api/v1/app\_valuations/app\_valuations.py:47-80
* 侵权/专利校验app/api/v1/app\_valuations/app\_valuations.py:81-118
## 计算步骤落库设计
* 统一步骤结构app/schemas/valuation.py:239-259
* `step_order`:序号(含小数层级,如 1.11, 2.31
* `step_name`中文名称如“基础价值B11计算”
* `step_description`:公式与解释
* `input_params`:输入参数 JSON含变量与其来源
* `output_result`:中间结果(如每项得分,最终值)
* `status``in_progress|completed|failed`
* `error_message`:失败描述
* 步骤编号建议:
* 经济价值 B12.1xB11=2.11B12=2.12B13=2.13汇总B1=2.19
* 文化价值 B22.2xB21=2.21B22=2.22汇总B2=2.29
* 风险调整 B32.3x总评R=2.30B3=2.31
* 市场价值 C3.1xC1=3.11C2=3.12C3=3.13C4=3.14汇总C=3.19
* 最终估值 AB4.1xB组合=4.11B×B3=4.12Final=4.19
* 落库时机统一在后台任务中分模块记录app/api/v1/app\_valuations/app\_valuations.py:38-41, 142-171
* 写入方式:通过控制器 `create_calculation_step`app/controllers/valuation.py:24-36
* 已有范例风险调整B3模块先 `in_progress``completed`app/utils/.../risk\_adjustment\_b3.py:195-237
## 完整流程说明
1. 原始数据输入:`POST /api/v1/app-valuations/`app/api/v1/app\_valuations/app\_valuations.py:210-299
2. 后台任务提取参数B1/B2/B3/Capp/api/v1/app\_valuations/app\_valuations.py:302-567
3. 模块计算与步骤记录:按编号分别执行,逐步写入 `ValuationCalculationStep`
4. 汇总合成:计算 `model_value_b``market_value_c``final_value_ab``dynamic_pledge_rate` 并存入 `ValuationAssessment`
5. 管理端查看:
* 详情:`GET /api/v1/valuations/{id}`(返回序列化后的详情)
* 步骤:`GET /api/v1/valuations/{id}/steps`(返回序列化后的步骤数组)
## 示例计算过程(模拟数据)
* 输入(节选):
* `three_year_income=[400,450,500]``annual_revenue=500``rd_investment=50`(创新投入比=10%
* `application_coverage=全国覆盖`popularity\_score→由B11计算器给分`offline_activities=12`
* `platform_accounts.douyin.likes=1200`S3参数`price_fluctuation=[95,105]`(波动率)
* `inheritor_level=市级传承人`(转换为系数)、`inheritor_age_count=[45,60,75]`
* `historical_evidence={历史文献:3, 考古发现:2, 传承谱系:5}`
* 步骤样例:
* 2.11 基础价值B11`input_params={three_year_income, innovation_ratio, popularity_score, infringement_score, patent_score}``output_result={B11: 123.45}`
* 2.12 流量因子B12`input_params={S1,S2,S3}``output_result={S: 0.32}`
* 2.13 政策乘数B13`input_params={implementation_stage,funding_support}``output_result={P: 0.15}`
* 2.19 B1汇总`output_result={B1: 156.78}`
* 2.21 活态传承B21`input_params={inheritor_level_coefficient,offline_sessions, social_views}``output_result={B21: 10.2}`
* 2.22 纹样基因B22`input_params={historical_inheritance,structure_complexity,normalized_entropy}``output_result={B22: 8.9}`
* 2.30 风险总评R`input_params={market_risk,legal_risk,inheritance_risk}``output_result={R: 0.42}`
* 2.31 风险调整B3`output_result={B3: 0.97}`
* 3.11~~3.14 市场价值子项:分别写入 C1~~C4
* 3.19 市场价值C`output_result={C: 118.0}`
* 4.11/4.12/4.19 最终汇总:`output_result={B: 175.88, B_adj: 170.6, Final: 122.0}`
## 后台展示规范
* 列表返回序列化后的 Pydantic 对象,避免 JSONResponse 序列化错误(已在管理端端点处理)
* 步骤展示:按照 `step_order` 升序,逐条显示 `step_name``step_description``input_params``output_result``status`;失败步骤显示 `error_message`
## 实施项
1. 将 B1、B2、C 模块对齐 B3 的“步骤写入”模式:每个子公式在计算前记录 `in_progress`,完成后记录 `completed` 并带结果;异常时标记 `failed`
2. 在 `FinalValueACalculator` 合成阶段补充步骤记录B组合、B×B3、Final
3. 确保管理端详情与步骤返回统一进行 JSON 序列化(管理端端点已按 `model_dump_json()` 修复)。
## 交付
* 我将按上述规范逐步在计算引擎各子模块与统一计算入口中补充“步骤写入”,并确保管理端端点返回可序列化的数据结构;完成后会提供一份面向管理员的“估值步骤查看”前后端对接说明(端点与字段)。

View File

@ -1,98 +0,0 @@
## 背景与确认
* 备注为“用户维度”,按指示在 `app_user` 增加备注字段并贯通列表与配额调整流程。
* 操作记录需补充时间字段以便前端展示。
* 交易管理列表需支持“提交时间区间、状态、手机号、公司名称、公司税号”搜索。
* 上传接口从两个合并为一个,统一入参与返回结构。
## 改动总览
* 模型:为 `AppUser` 增加 `notes: CharField(256, null=True)`
* 接口:
* `admin-App用户管理`:列表返回 `notes`;配额调整将 `remark` 同步写入 `AppUser.notes`;配额日志返回 `created_at`
* `交易管理`:对公转账列表增加“提交时间区间”筛选。
* `上传`:新增统一上传接口 `/api/v1/upload/upload`(或 `/api/v1/upload`),老接口内部复用统一实现保留兼容。
* 迁移:使用现有 Aerich 流程生成并升级迁移。
## 详细实施
### 1. App 用户备注(用户维度)
* 文件:`app/models/user.py`
* 在 `AppUser` 增加字段 `notes = fields.CharField(max_length=256, null=True, description="备注")`
* 文件:`app/api/v1/app_users/admin_manage.py`
* `/list`:返回 `notes = u.notes or ""`
* `/quota`:接收 `remark` 后,除写入 `AppUserQuotaLog`
### 2. 操作记录时间字段
* 文件:`app/schemas/app_user.py`
* `AppUserQuotaLogOut` 增加 `created_at: str`
* 文件:`app/api/v1/app_users/admin_manage.py`
* `/ {user_id}/quota-logs`:为每条日志填充 `created_at = r.created_at.isoformat()` 返回。
### 3. 交易管理列表搜索增强
* 文件:`app/controllers/invoice.py`
* `list_receipts(...)`:增加对 `PaymentReceipt.created_at` 的区间筛选:
* 支持 `created_at`(数组,毫秒时间戳)或 `submitted_start/submitted_end`ISO 或毫秒)。
* 文件:`app/api/v1/transactions/transactions.py`
* `list_receipts`:路由签名增加上述可选查询参数并传入控制器。
### 4. 上传接口统一
* 文件:`app/controllers/upload.py`
* 新增 `upload_any(file: UploadFile)`
* `image/*` 保存到 `static/images`;其他受支持类型保存到 `static/files`。
* 返回 `{ url, filename, content_type }`
* 文件:`app/api/v1/upload/upload.py`
* 新增 `/upload`(或 `/upload/upload` 按路由前缀安排):统一入口;
* 旧 `/image``/file` 内部调用 `upload_any` 保持兼容。
* 文件:`app/schemas/upload.py`
* 若需要,补充统一响应模型,或复用 `FileUploadResponse`(包含 `content_type`)。
## 迁移与兼容
* Aerich`init_db` 已集成迁移流程,生成迁移后执行 `upgrade`,自动创建 `app_user.notes` 列。
* 旧接口兼容:上传旧路径保留;交易列表与日志返回仅新增字段,不影响既有消费逻辑。
## 验证与测试
* 备注更新:调用 `/app-user-admin/quota``remark`,再查 `/app-user-admin/list` 验证 `notes`;查 `/app-user-admin/{id}/quota-logs` 验证 `created_at` 存在。
* 交易筛选:造两条不同日期的凭证,分别用时间区间查询命中与不命中。
* 上传统一:上传 PNG 与 PDF 验证保存路径与返回结构;旧接口路由到统一实现成功。
## 交付
* 提交代码与迁移;更新接口文档的路由说明与字段变化;前端无需大改即可使用新返回的 `notes` 与日志 `created_at`,交易列表按“凭证时间”筛选可用。

View File

@ -1,23 +0,0 @@
## 问题
- 后台任务在提取B1参数时引用未定义函数calculate_popularity_score、calculate_patent_score导致计算中止步骤未入库。
## 修复方案
1) 移除未定义函数引用,在 `_extract_calculation_params_b1` 内实现本地计算:
- 普及地域分mapping {全球覆盖:10全国覆盖:7区域覆盖:4}默认7
- 专利分:按剩余年限近似 {>10年:105-10年:7<5年:3}用已有 `calculate_total_years(data_list)` 近似转换
- 保留创新投入比与搜索指数、行业均值等现有逻辑
- 增加logger输出popularity_score、innovation_ratio、patent_score
2) 确保步骤写入链路:
- 计算入口:先创建估值记录取 `valuation_id`;将 `valuation_id` 传入统一计算器;计算后用 `ValuationAssessmentUpdate` 更新记录
- 模型B汇总对经济B1、文化B2、风险B3的计算改为 `await` 并传 `valuation_id`
- 市场C与风险B3保持原有按 `valuation_id` 写入
3) 日志增强:
- 在步骤创建与更新时写入日志calcstep.create/update/list
- 在估值初始化与更新时写入日志valuation.init_created/updated
## 验证
- 重启服务、运行脚本查看服务日志应出现calcstep.create/update/list与valuation.updatedAdmin脚本打印“后台估值计算步骤”。
——确认后我将按以上方案进行代码调整并回填日志。

View File

@ -1,63 +0,0 @@
## 接口定位
- 用户端提交路径:`POST /v1/app-valuations/`(处理函数在 `app/api/v1/app_valuations/app_valuations.py:234`
- 后台计算任务:`_perform_valuation_calculation``app/api/v1/app_valuations/app_valuations.py:40`
- 计算输入映射:
- B1 提取:`_extract_calculation_params_b1``app/api/v1/app_valuations/app_valuations.py:325`
- B2 提取:`_extract_calculation_params_b2``app/api/v1/app_valuations/app_valuations.py:430`
- B3 提取:`_extract_calculation_params_b3``app/api/v1/app_valuations/app_valuations.py:517`
- C 提取:`_extract_calculation_params_c``app/api/v1/app_valuations/app_valuations.py:532`
- 请求体模型:`UserValuationCreate` 基于 `ValuationAssessmentBase``app/schemas/valuation.py:7``app/schemas/valuation.py:153`
## 必填/推荐字段
- 基础:`asset_name``institution``industry`
- 财务B1`three_year_income``rd_investment``annual_revenue``funding_status``application_coverage``implementation_stage``platform_accounts(douyin.likes/comments/shares)``sales_volume``link_views`
- 文化B2`inheritor_level``offline_activities``cooperation_depth``historical_evidence`
- 风险B3`price_fluctuation``inheritor_age_count`
- 市场C`scarcity_level``circulation``market_activity_time`
- 质押率辅助:`heritage_asset_level`(用于动态质押率)
## 字段规范化
- 数组字段统一为数值数组:`three_year_income``price_fluctuation`
- 金额/计数按模型定义传字符串(系统内有安全转换):`annual_revenue``rd_investment``sales_volume``link_views``offline_activities`
- 平台账号字段示例:`{"douyin": {"account": "...", "likes": "...", "comments": "...", "shares": "..."}}`
- 覆盖范围枚举:`全球覆盖/全国覆盖/区域覆盖`(未提供时默认全国覆盖,参见 `app/api/v1/app_valuations/app_valuations.py:343-347`
## 提交载荷示例(基于“马王堆”数据)
```json
{
"asset_name": "马王堆",
"institution": "成都文化产权交易所",
"industry": "文化艺术业",
"annual_revenue": "10000",
"rd_investment": "6000",
"three_year_income": [8000, 9000, 9500],
"funding_status": "省级资助",
"inheritor_level": "省级传承人",
"inheritor_age_count": [200, 68, 20],
"heritage_asset_level": "纳入《国家文化数字化战略清单》",
"historical_evidence": {"artifacts": 58, "ancient_literature": 789, "inheritor_testimony": 100},
"implementation_stage": "成熟应用",
"application_coverage": "全国覆盖",
"cooperation_depth": "0",
"offline_activities": "20",
"platform_accounts": {
"douyin": {"account": "成都文交所", "likes": "500000", "comments": "89222", "shares": "97412"}
},
"sales_volume": "60000",
"link_views": "350000",
"circulation": "3",
"scarcity_level": "流通:总发行份数 >1000份或二级市场流通率 ≥ 5%",
"market_activity_time": "近一周",
"monthly_transaction_amount": "月交易额100万500万",
"price_fluctuation": [402, 445]
}
```
## 验证步骤(确认后执行)
- 发送上述 JSON 到 `POST /v1/app-valuations/`,观察返回 `status``id`
- 通过 `GET /v1/app-valuations/{id}` 查看写入的 `calculation_input``model_value_b/market_value_c/final_value_ab/dynamic_pledge_rate`
- 若需批量提交,按相同字段规范为每条记录生成载荷并调用接口(可提供脚本)
## 可能的扩展
- 无抖音 `views` 字段时已用 `link_views`,如需更精确的 C 值,可补充 `views`(参见 `app/api/v1/app_valuations/app_valuations.py:566-585`
- `application_coverage` 为非枚举值时将按默认 7 分处理(见 `app/api/v1/app_valuations/app_valuations.py:343-347`

View File

@ -1,60 +0,0 @@
## 目标
- 创建若干“交易记录”(对公转账付款凭证)测试数据,并确保后台管理可以正常查看、筛选与分页。
- 全流程可回滚,严格隔离开发与生产数据。
## 关键假设
- 交易记录以 `PaymentReceipt`(关联 `Invoice`)为核心:后端模型位于 `app/models/invoice.py`
- 后端已提供发票与凭证相关 API
- 发票:`GET/POST /api/v1/invoice/*``app/api/v1/invoice/invoice.py`
- 凭证:`POST /api/v1/invoice/{id}/receipt`、列表 `GET /api/v1/transactions/receipts``app/api/v1/transactions/transactions.py`)。
- 现有后台页已覆盖发票列表 `web/src/views/transaction/invoice/index.vue`,尚无“凭证专属列表”页面。
## 数据建模与来源
- `Invoice`:发票记录(开票状态、类型、抬头信息、公司税号、银行账户等)。
- `PaymentReceipt`:对公转账付款凭证(字段含 `invoice_id``url``note``verified``created_at`)。
- 为保证后台可见,需同时插入可查询的 `Invoice` 与其关联的 `PaymentReceipt`
## 实施路径
### 方案 A通过现有 API 批量生成(零代码改动,首选)
- 步骤:
- 调用 `POST /api/v1/invoice/create` 批量创建 510 条覆盖不同类型/状态的发票(含公司名、税号、银行账户等)。
- 对每条发票调用 `POST /api/v1/invoice/{id}/receipt` 上传/登记 12 条付款凭证(`file_url``url``note``verified`)。
- 可选:通过 `POST /api/v1/transactions/send-email` 生成邮件日志,验证通知链路。
- 优势:不改动代码,快速、低风险;与现有权限和审计链路一致。
### 方案 B后端种子脚本仅开发环境便于重复初始化
- 在 `app/core/init_app.py` 新增 `init_demo_transactions()`
- 仅在开发环境执行(如 `ENV=dev`);避免污染生产。
- 批量创建 `Invoice` 测试数据,再为每条 `Invoice` 创建若干 `PaymentReceipt`
- 为可识别性,在 `note` 中加入 `DEMO` 标签或新增布尔字段(若允许)。
- 将该方法纳入现有 `init_data()` 的“开发模式”分支;保留一键清理逻辑(删除 `DEMO` 标记数据)。
## 前端后台展示
- 新增后台页“交易记录”:`web/src/views/transaction/receipts/index.vue`Naive UI
- 数据源:`GET /api/v1/transactions/receipts`;支持分页与筛选(手机号、公司名、税号、状态、类型等)。
- 列:凭证时间、公司名称、税号、转账备注(`note`)、审核状态(`verified`)、关联发票 ID/类型,查看详情。
- 行为:查看详情(`GET /api/v1/transactions/receipts/{id}`),跳转到发票详情。
- 菜单与权限:
- 在后端 `init_menus()` 增加“交易记录”菜单,并为管理员角色在 `init_roles()` 授权;在 `init_apis()` 注册 `receipts` 相关 API。
- 备选轻改:在 `invoice/index.vue` 增加“凭证数/链接”列与详情入口,先实现可见性,后续再拆分独立列表页。
## 验证步骤
- 数据验证:
- 通过 API 查询:`GET /api/v1/invoice/list``GET /api/v1/transactions/receipts`,确认条数、筛选与分页正确。
- 随机抽样验证 `PaymentReceipt` 与对应 `Invoice` 关联完整、字段齐备。
- 前端验证:
- 后台页加载正常、列渲染与筛选可用;详情跳转与状态标签正确。
- 安全验证:
- 在生产环境禁用种子逻辑;标记测试数据,提供清理。
## 回滚与清理
- 提供清理脚本/接口:按 `DEMO` 标记或 ID 范围批量删除测试发票与凭证。
- 菜单与权限变更可回退至原状态(移除菜单、撤销授权)。
## 交付物
- A一组 API 请求示例(可直接运行)生成测试交易与凭证。
- B可选开发环境种子函数与清理脚本。
- C前端“交易记录”后台页或在发票页增加凭证列的最小改动
## 备注
- 编码时为新增函数与接口补充函数级注释(功能、参数、返回值说明),遵循现有代码风格与安全规范。

View File

@ -1,29 +0,0 @@
## 目标
- 汇总所有前后端需求与 API 到一个文档,其他分散文档删除,仅保留总览,便于统一查看与维护。
## 操作与产物
- 新增单一文档:`docs/估值二期-需求与API总览.md`
- 内容包含:
1) 概述与约定(认证、响应包装、错误码、前缀)
2) 数据实体InvoiceHeader、PaymentReceipt、TransactionRecord、Valuation、AppUser、Complaint、SMSMessage与字段定义
3) 用户端流程与 API登录/首页摘要、评估提交/校验/状态、估值记录下载与分享、个人中心-对公转账、发票抬头/类型、发票列表与详情、剩余次数、投诉与短信、批量与异步Job
4) 管理端流程与 API交易管理记录列表/详情/状态/邮件/开票/批量;审核列表;用户管理)
5) 前端对接映射(`web/src/api/index.js` 现有与新增占位)
6) 请求/响应示例与字段校验(重点:抬头管理、对公转账、交易管理记录)
7) 性能与限制(分页、异步、频率)
- 删除分散文档:
- `web/docs/项目结构.md``web/docs/技术架构.md``web/docs/关键模块说明.md``web/docs/接口约定与预留.md`
- `app/docs/项目结构.md``app/docs/技术架构.md``app/docs/关键模块说明.md``app/docs/接口约定与预留.md`
## 你提出的新增明确项(将详列在文档中)
- 抬头管理字段(必填项标注):公司名称、公司税号、注册地址、注册电话、开户银行、银行账号、邮箱
- 对公转账(用户端):上传图片(付款凭证)+ 选择发票抬头 + 开票类型(电子/纸质、专票/普票)
- 交易管理记录(管理端):提交时间、付款凭证、手机号、微信号、公司名称、公司税号、注册地址、注册电话、开户银行、银行账号、接收邮箱、开票类型、状态
- 状态枚举pending/verified/issued/rejected 等
## 执行步骤
1. 创建总览文档并写入上述结构内容与端点清单
2. 迁移现有 app/web 文档中的有效信息到总览文档
3. 删除分散文档,仅保留总览
——请确认上述方案,确认后我将生成唯一的总览文档并删除分散文档。

View File

@ -1,26 +0,0 @@
## 问题
- 计算步骤创建时报 Pydantic 校验错误:`step_order` 期望整型,但代码使用层级小数(如 2.1、2.11)。这不是计算公式问题,而是“类型不匹配”导致步骤未入库。
## 修复原则
- 不改变任何计算公式或数值流程,仅调整“步骤顺序”的存储与校验类型,使其能接受层级小数。
## 具体改动
1) 模型字段修改(不涉公式):
- `app/models/valuation.py``ValuationCalculationStep.step_order: IntField → DecimalField(max_digits=8, decimal_places=3)`;保留 `ordering=["step_order"]`,确保排序正确。
2) Schema 修改(不涉公式):
- `ValuationCalculationStepCreate.step_order: int → Decimal`,添加前置校验,支持 int/float/str 自动转换为 Decimal`ValuationCalculationStepOut` 同步为 Decimal。
- 列表与详情端点已使用 `model_dump_json()``json.loads()`Decimal 会被正确序列化为 JSON 数字,无需改动。
3) 代码调用无需改(不涉公式):
- 由于 Schema 接受 float 并转换为 Decimal现有调用处传入 `2.1/2.11/...` 不需改。
4) 迁移与验证
- 启动时执行 Aerich 迁移更新列类型(项目已有初始化流程)。
- 跑脚本观测:`calcstep.create` 不再报错;`calcstep.list` 数量 > 0后台“估值计算步骤”返回完整数组。
## 影响范围与安全性
- 仅变更“步骤顺序”的字段类型与 Schema 校验,不触及任何计算逻辑或公式。
- 排序按照 Decimal 正常工作层级表达2.11 < 2.2保留
——确认后,我将按以上方案修改模型与 Schema并执行验证保证不改变计算逻辑仅解决类型不匹配问题。

View File

@ -1,17 +0,0 @@
## 目标
- 让每次用户估值的所有中间步骤写入 `valuation_calculation_steps` 并可关联该估值ID
- 测试脚本打印详细步骤链,包括 step_order、step_name、step_description、input_params、output_result、status
## 代码改动
1) 计算入口 `_perform_valuation_calculation`
- 先创建估值记录以拿到 `valuation_id`
- 传 `valuation_id``FinalValueACalculator.calculate_complete_final_value_a`
- 计算完成后用 `ValuationAssessmentUpdate` 将结果更新到该记录
2) 测试脚本:
- 在 AdminClient 增加 `valuation_steps(id)` 方法
- 打印步骤数组,包含名称、描述、输入与输出
## 验证
- 运行 `python run.py`
- 运行脚本并查看详细步骤输出

View File

@ -1,99 +0,0 @@
## 目标与范围
- 接入阿里云短信服务,封装发送客户端
- 提供两类发送接口:验证码通知、报告生成通知,供 App 调用
- 支持模板动态调用与验证码变量 `${code}` 的正确替换
- 记录发送日志并融入现有审计体系
- 实现同一手机号每分钟不超过 1 条的频率限制
- 安全存储 AccessKey 等敏感信息(环境变量/配置)
## 技术选型
- 后端框架FastAPI现有工程
- 短信 SDKAlibaba Cloud SMS Python SDKTea/OpenAPI V2`alibabacloud_dysmsapi20170525`
- 端点(中国站):`dysmsapi.aliyuncs.com`
- 关键请求字段:`PhoneNumbers``SignName``TemplateCode``TemplateParam`
- 日志:沿用 `app/log` 的 Loguru 与审计中间件
- 频率限制:服务内共享的内存限流(后续可升级为 Redis
- 安全通过环境变量注入凭证Pydantic Settings 读取
- 参考文档:
- Alibaba Cloud SDK V2Python示例SendSmshttps://www.alibabacloud.com/help/en/sdk/developer-reference/v2-python-integrated-sdk
- 短信服务 SendSms 接口2017-05-25https://help.aliyun.com/zh/sms/developer-reference/api-dysmsapi-2017-05-25-sendsms
## 代码改动
- 新增:`app/services/sms_client.py`
- 初始化 Dysms 客户端(读取 `ALIBABA_CLOUD_ACCESS_KEY_ID``ALIBABA_CLOUD_ACCESS_KEY_SECRET``ALIYUN_SMS_SIGN_NAME``ALIYUN_SMS_ENDPOINT`
- 方法:`send_by_template(phone, template_code, template_param_json)`
- 方法:`send_code(phone, code)`(模板:`SMS_498190229`
- 方法:`send_report(phone)`(模板:`SMS_498140213`
- 新增:`app/services/rate_limiter.py`
- 类:`PhoneRateLimiter`,键为手机号,值为最近一次发送时间戳;判定 60s 内拒绝
- 新增路由:`app/api/v1/sms/sms.py`
- `POST /api/v1/sms/send-code`(无鉴权,用于登录场景)
- `POST /api/v1/sms/send-report`(需要鉴权,防滥用)
- 统一返回结构:`{status, message, request_id}`
- 路由聚合:在 `app/api/v1/__init__.py` 注册 `sms_router(prefix="/sms", tags=["短信服务"])`
- 配置:扩展 `app/settings/config.py`Pydantic Settings增加短信相关字段并从环境读入
## 接口设计
- `POST /api/v1/sms/send-code`
- 请求体:`{ "phone": "1390000****", "code": "123456" }`
- 处理:限流校验 → 构造 `TemplateParam``{"code": "123456"}` → 调用 `SMS_498190229`
- 成功:`{ "status": "OK", "message": "sent", "request_id": "..." }`
- 失败:`{ "status": "ERROR", "message": "..." }`
- `POST /api/v1/sms/send-report`
- 请求体:`{ "phone": "1390000****" }`
- 处理:鉴权(`DependAuth`)→ 限流校验 → 调用 `SMS_498140213`
- 返回同上
- 校验:手机号格式(支持无前缀或 `+86``code` 为 48 位数字(可按需约束)
## 模板与变量替换
- 验证码模板:`SMS_498190229`
- `TemplateParam``{"code": "<动态验证码>"}``${code}` 正确对应
- 报告通知模板:`SMS_498140213`
- 不含变量,可传空对象 `{}` 或不传 `TemplateParam`
- 签名:`ALIYUN_SMS_SIGN_NAME` 读取为“成都文化产权交易所”且不在代码中硬编码
## 日志与审计
- 路由层:审计中间件自动记录请求/响应(`module=短信服务``summary=验证码发送/报告通知发送`
- 服务层:`from app.log import logger`
- 发送开始、Provider 请求入参(不含敏感信息)、返回码、`RequestId`、耗时、失败异常
- 敏感信息不入日志AccessKey、完整模板内容不打印
## 频率限制
- 策略:同一手机号在 60 秒内全模板合并限 1 次(共享窗口)
- 实现:进程内 `dict[phone]=last_ts`;进入路由先校验再发送;返回 429或业务错误码
- 进阶:如需多实例一致性,后续接入 Redis`sms:limit:{phone}` TTL=60s
## 安全与配置
- 环境变量:
- `ALIBABA_CLOUD_ACCESS_KEY_ID`
- `ALIBABA_CLOUD_ACCESS_KEY_SECRET`
- `ALIYUN_SMS_SIGN_NAME`
- `ALIYUN_SMS_ENDPOINT`(默认 `dysmsapi.aliyuncs.com`
- Pydantic Settings 统一读取,避免硬编码,并在 `/docs` 与审计中隐藏敏感字段
## 依赖与安装
- 在 `pyproject.toml` 添加:
- `alibabacloud_dysmsapi20170525`
- `alibabacloud_tea_openapi`
- `alibabacloud_tea_util`
- 与 `requirements.txt` 保持一致版本钉死策略Python 3.11 兼容性验证
## 测试与验证
- 单元测试:
- Mock SDK 客户端,校验 `TemplateCode``TemplateParam` 的正确构造
- 限流:同号 60s 内第二次返回限制错误
- 集成测试:
- 使用 `httpx.AsyncClient` 调用两个接口并断言响应结构
- 在预设测试手机号上进行真实发送,观察到达与模板内容正确
- 观测:
- 查看应用日志与审计表(`AuditLog`)记录
## 风险与回滚
- 进程内限流仅在单实例有效,多实例需 Redis后续迭代
- SDK 版本冲突,采用独立最小版本并逐项验证;必要时锁版本
- 若出现发送失败,保留错误码与 `RequestId`,按官方错误码表排查(见 SendSms 文档)
## 交付物
- 新增短信客户端与路由模块
- 两个可调用接口(验证码发送、报告通知发送)
- 限流与日志落地,配置基于环境变量

View File

@ -1,41 +0,0 @@
## 目标
- 编写一个一次性可运行的接口测试脚本,按照总览文档顺序执行:
1) App 用户注册 → 登录 → 用户相关接口
2) 提交估值(用户端)并轮询结果(列表/详情)
3) 管理端登录admin→ 查看估值数据(列表/详情)
- 输出结构化结果与关键字段校验,便于快速人工检查。
## 脚本位置与运行
- 路径:`scripts/api_smoke_test.py`
- 运行:`python scripts/api_smoke_test.py --base http://127.0.0.1:9991/api/v1`
- 基础:默认使用 `http://127.0.0.1:9991/api/v1`(根据 `run.py`),可通过参数覆盖。
## 步骤与端点
1. App 用户注册与登录
- POST `/app-user/register`(若手机号已存在则跳过)
- POST `/app-user/login` → 获取 `access_token`
- GET `/app-user/profile`、GET `/app-user/dashboard`、GET `/app-user/quota`
2. 用户端估值
- POST `/app-valuations/`(使用总览文档示例数据,最小必要字段)
- 轮询 GET `/app-valuations/`(分页)查看是否新增记录,捕获 `id`
- GET `/app-valuations/{id}` 详情
3. 管理端数据查看
- POST `/base/access_token`admin/123456获取后端 `token`
- GET `/valuations` 列表(后台视角)
- GET `/valuations/{id}` 详情(与用户端一致性对比)
## 输出与校验
- 每步打印:请求路径、状态码、关键字段(如 `access_token``user_id``latest_valuation``final_value_ab`
- 断言:登录成功、列表包含新记录、详情字段存在。
- 错误处理:捕获非 200 情况并打印 `code/msg`
## 技术细节
- 使用 `requests``Session` 维护 `token`;用户端与后台端各独立 `Session`
- 函数化:为每个步骤提供函数与函数级注释(描述、参数、返回值)。
- 兼容:对注册接口“手机号已存在”返回情况做兼容(脚本继续执行)。
## 交付
- 创建 `scripts/api_smoke_test.py` 并填充完整逻辑;默认数据内置,必要处留参数。
- 如你需要,我可在脚本创建后直接运行,输出结果供你检查。

View File

@ -1,25 +0,0 @@
## 目标
- 提供一个可在本机直接运行的 Shell 脚本,测试 `POST /api/v1/transactions/send-email`,支持本地文件上传与远程文件 URL两种模式均可验证。
## 实现方式
- 新增 `scripts/send_email_test.sh`
- 参数:
- `-t <token>` 后台 token必填
- `-e <email>` 收件人邮箱(必填)
- `-s <subject>` 邮件主题(可选)
- `-b <body>` 邮件正文(必填)
- `-f <file_path>` 本地附件路径(可选)
- `-u <file_url>` 远程附件 URL可选`-f` 互斥)
- `-a <base_api>` 基础地址,默认 `http://127.0.0.1:9999/api/v1`
- 逻辑:
- 若提供 `-f`,使用 `curl -F` 构造 `multipart/form-data` 表单项:`email/subject/body/file`
- 否则以 JSON 发送:`email/subject/body`,可选 `file_url`
- 输出:直接打印服务端返回的 JSON
## 验证
- 无附件:`./scripts/send_email_test.sh -t <token> -e zfc9393@163.com -s 测试 -b 测试代码`
- 本地附件:`./scripts/send_email_test.sh -t <token> -e zfc9393@163.com -s 测试 -b 测试代码 -f ./demo.pdf`
- 远程附件:`./scripts/send_email_test.sh -t <token> -e zfc9393@163.com -s 测试 -b 测试代码 -u https://example.com/demo.pdf`
## 安全
- 不写入任何敏感信息到仓库;脚本仅通过命令行参数接收 token 与内容。

View File

@ -1,20 +0,0 @@
## 目标
- 将 `scripts/api_smoke_test.py` 的示例负载替换为你提供的完整参数,保持后端现有计算逻辑不变。
## 具体改动
- 替换 `build_sample_payload()` 返回值为你提供的 JSON字段逐项对齐
- `asset_name``institution``industry``annual_revenue``rd_investment``three_year_income``funding_status``sales_volume``link_views``circulation``last_market_activity``monthly_transaction``price_fluctuation``application_maturity``application_coverage``cooperation_depth``offline_activities``inheritor_level``inheritor_age_count``inheritor_certificates``heritage_level``historical_evidence``patent_certificates``pattern_images``patent_application_no``heritage_asset_level``inheritor_ages``implementation_stage``coverage_area``collaboration_type``scarcity_level``market_activity_time``monthly_transaction_amount``platform_accounts`
- 保留 `platform_accounts`douyin作为后端期望的数据源`online_accounts`(数组)不参与当前计算,保留或忽略均可;默认保留以便后续扩展。
- `application_coverage`:后端当前使用该字段计算普及分;你的参数中同时有 `coverage_area`,将按优先 `application_coverage` 使用;若 `application_coverage` 为占位如“0”建议同步设置为“全球覆盖”或我在脚本中用 `coverage_area` 回填)。
- 其余数值以字符串提供,后端已通过 `safe_float` 做转换,无需脚本侧强制转数值。
## 兼容与注意
- 不改计算逻辑;仅更新脚本负载以贴合后端字段期望。
- 保持 `AdminClient` 输出“后台估值详情”和“后台估值计算步骤”打印,便于你核验。
## 验证
- 启动后端并确保迁移已执行(`step_order` 已支持 Decimal
- 运行脚本:`python scripts/api_smoke_test.py --base http://127.0.0.1:9991/api/v1 --phone 13800138001`
- 观察输出:用户侧成功提交,后台列表/详情显示完整数据,步骤列表非空。
——确认后我将直接更新脚本并提交。

View File

@ -1,48 +0,0 @@
## 目标
* 将“用户端”API补齐内容更新到现有文档便于你审阅。
## 更新范围
* 修改 `app/docs/接口约定与预留.md`:新增“用户端 API”章节覆盖登录/首页/评估/个人中心/估值记录/通知/批量与异步,与错误码和校验对齐。
* 修改 `web/docs/接口约定与预留.md`:新增“前端对接(用户端)”章节,列出与 `web/src/api/index.js` 的映射与新增端点占位,确保路径与请求方式一致。
## 文档结构变更
* `app/docs/接口约定与预留.md`
* 新增:
* “用户端 API 概览”
* “认证与首页”
* “评估提交与引导提示”
* “估值记录与分享”
* “个人中心:汇款凭证/发票抬头与类型/发票列表与详情”
* “剩余估值次数”
<br />
* `web/docs/接口约定与预留.md`
* 新增:
* “用户端对接路径”与现有 `invoice/*`、`valuation/*`、`app-user/*` 的映射
* 新增端点建议(如 `app-valuation/*`、`invoice/headers`、`invoice/{id}/receipt`、`jobs/{id}`)的前端占位说明
## 风格与格式
* 统一中文、RESTful端点风格示例以JSON格式。
* 保持与现有文档用语一致Success/Fail、token、code===200
## 交付
* 完成上述两处文档更新不新增新文档文件更新内容可直接在IDE中查看。

View File

@ -1,101 +0,0 @@
目标
* 在 `蜀锦估值计算流程核对.md` 中补充并修复:历史传承度 HI=18 的明确记录,以及由此引发的 B22、B2、模型估值 B、最终估值 A 的新数值与计算公式。保留现有内容同时在文末新增“修正HI=18 后的计算”分节,按“参数 | 步骤 | 计算结果 | 计算公式”的统一格式展示。
修改要点
* 新增分节:`## 修正:历史传承度 HI=18 后的计算`
* 插入子段落:
1. 历史传承度 HI参数/步骤/计算结果/计算公式)→ HI=18
2. 纹样基因 B22使用 SC=1.5, H=9, HI=18→ B22=810
3. 文化价值 B2B21=9.37804, B22=810→ B2=38.026824
4. 模型估值 BB1≈519.8, B2=38.026824, B3=0.92)→ B≈346.9 万元
5. 市场估值 C复核不变→ C=9452.0 万元
6. 最终估值 A使用新 B 与 C→ A≈3078.43 万元
* 每一段落严格附加“计算公式”行,确保审阅可落地。
输出格式与一致性
* 所有行使用中文标签与反引号包裹关键数值/公式。
* 不删除原有章节,仅在文末追加修正;与日志与现有参数保持一致。
执行后期望
* 文档清晰体现 HI 修正后的计算链路与结果,审阅时可直接对照参数与公式核验。
## 修正:历史传承度 HI=18 后的计算
**历史传承度 HI**
* 参数: `historical_evidence={"artifacts":2,"ancient_literature":5,"inheritor_testimony":5,"modern_research":6}`
* 步骤: 解析为对象→对各项做安全数值化→求和
* 计算结果: `HI=18`
* 计算公式: `HI = sum(safe_float(v) for v in historical_evidence)`
**纹样基因 B22文化 B2 子项)**
* 参数: `SC=1.5``H=9``HI=18`
* 步骤: 复杂度与熵线性合成×历史度×10
* 计算结果: `B22=810`
* 计算公式: `B22 = (SC×0.6 + H×0.4) × HI × 10``(1.5×0.6 + 9×0.4) × 18 × 10 = 4.5 × 18 × 10 = 810`
**文化价值 B2合成**
* 参数: `B21=9.37804``B22=810`
* 步骤: `B2 = B21×0.6 + (B22/10)×0.4`
* 计算结果: `B2=38.026824`
* 计算公式: `B2 = B21×0.6 + (B22/10)×0.4``9.37804×0.6 + (810/10)×0.4 = 5.626824 + 32.4 = 38.026824`
**模型估值 B**
* 参数: `B1≈519.8``B2=38.026824``B3=0.92`
* 步骤: 经济与文化加权后乘风险系数
* 计算结果: `B≈346.9` 万元
* 计算公式: `B = (B1×0.7 + B2×0.3) × B3``(519.8×0.7 + 38.026824×0.3) × 0.92 ≈ (363.86 + 11.408) × 0.92 ≈ 346.9`
**市场估值 C**
* 参数: `C1=2780``C2=2.0``C3=1.7``C4=1.0`
* 步骤: 乘法聚合 `C = C1 × C2 × C3 × C4`
* 计算结果: `C=9452.0` 万元
* 计算公式: `C = C1 × C2 × C3 × C4`
**C1 市场竞价平均交易价C 子项)**
* 参数: `bids=[3980,1580,2780]``weighted_average_price=None``expert_valuations=[]`
* 步骤: 平均价缺失→排序出价→取中位数
* 计算结果: `C1=2780`
* 计算公式: `C1 = median(bids)`;奇数 `n``sorted_bids[n//2]`;偶数 `n``(sorted_bids[n//2-1] + sorted_bids[n//2]) / 2`
**最终估值 A**
* 参数: `B≈346.9``C=9452.0`
* 步骤: 固定权重合成
* 计算结果: `A≈3078.43` 万元
* 计算公式: `A = 0.7×B + 0.3×C``0.7×346.9 + 0.3×9452 ≈ 242.83 + 2835.6 ≈ 3078.43`

View File

@ -1,23 +0,0 @@
## 目标
- 以简明清晰的中文给出发票状态pending、invoiced、rejected、refunded的标准释义。
- 重点补充“rejected已拒绝”的常见触发原因与处理建议便于运营与审核同口径使用。
## 来源与现状
- 状态字段来源:`app/models/invoice.py:32``pending|invoiced|rejected|refunded`)。
- 后台页面状态标签:`web/src/views/transaction/invoice/index.vue:82-91`
## 输出内容
- 提供四个状态的含义与可执行动作:
- pending未开票等待处理可进行开票或退款需核验资料。
- invoiced已开票发票已生成可查看重发邮件等不可再提交同笔开票。
- rejected已拒绝审核未通过说明常见拒绝原因与后续处理方式。
- refunded已退款已取消并完成退款如需再次开票需走新流程。
- “rejected”典型原因分类与处理建议
- 企业信息不一致/缺失;税号无效或格式不符;银行账户异常;发票类型不合规;重复或异常申请;付款凭证无法核验等。
- 建议:更正信息后重新提交;提供有效凭证;必要时走退款流程。
## 可选改进(待确认)
- 在后台页面增加“拒绝原因”提示(若未来增加原因字段),或在详情中补充统一口径的原因文案与建议。
## 交付方式
- 立即以文本形式给出状态释义与“rejected”原因说明便于直接使用。

View File

@ -1,70 +0,0 @@
## 目标
- 提升 Nginx 代理下的上传体积与超时解决大文件上传被限制的问题413/超时)。
## 现状
- 当前配置文件:`deploy/web.conf` 使用 `location ^~ /api/` 反向代理到后端 `http://127.0.0.1:9999`,未设置上传大小和超时。
## 修改内容
- 在 `server {}` 块中增加统一的体积限制。
- 在 `location ^~ /api/` 中增加长超时与关闭请求缓冲(提升大文件上传稳定性)。
## 具体改动(覆盖式替换关键片段)
- 在 `server_name localhost;` 后增加:
```
client_max_body_size 50m;
```
- 在 `location ^~ /api/ { ... }` 内追加:
```
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_read_timeout 300s;
proxy_send_timeout 300s;
proxy_request_buffering off;
```
## 变更后的完整结构示例
```
server {
listen 80;
server_name localhost;
client_max_body_size 50m;
location = /docs {
proxy_pass http://127.0.0.1:9999/docs;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location = /redoc {
proxy_pass http://127.0.0.1:9999/redoc;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location = /openapi.json {
proxy_pass http://127.0.0.1:9999/openapi.json;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location / {
root /opt/vue-fastapi-admin/web/dist;
index index.html index.htm;
try_files $uri /index.html;
}
location ^~ /api/ {
proxy_pass http://127.0.0.1:9999;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_read_timeout 300s;
proxy_send_timeout 300s;
proxy_request_buffering off;
}
}
```
## 发布与验证
- 检查配置:`nginx -t`
- 重新加载:`nginx -s reload`
- 测试上传:使用 3040MB 文件调用 `POST /api/v1/upload/file`,确认不再出现 413 或上传超时;同时测试 `POST /api/v1/upload/image` 大图。
## 备注
- 如需更大体积可将 `client_max_body_size` 调整为 `100m` 或更高;若上层云负载均衡也有限制,需要同步放宽。
- 后续可在应用层增加最大体积限制与提示,避免无界上传占用过多资源。

View File

@ -1,36 +0,0 @@
## 目标
- 配置并启用阿里企业邮箱 SMTP完成服务端发送邮件功能验证含附件/远程文件)。
## 所需配置
- 配置项位置:`app/settings/config.py:103-109``SMTP_HOST/SMTP_PORT/SMTP_USERNAME/SMTP_PASSWORD/SMTP_TLS/SMTP_FROM`
- 建议取值(不要写入仓库,使用环境变量注入):
- `SMTP_HOST=smtp.qiye.aliyun.com`
- `SMTP_PORT=465`SSL 直连)
- `SMTP_TLS=false`465 对应 SSL如用 587 则改为 `SMTP_TLS=true``SMTP_PORT=587`
- `SMTP_FROM=value@cdcee.net`
- `SMTP_USERNAME=value@cdcee.net`
- `SMTP_PASSWORD=<授权码>`(你提供的授权码)
- 安全要求:不将授权码写入代码或仓库;仅通过环境变量或部署系统秘密管理器设置。
## 实现检查
- 发送实现:`app/services/email_client.py:12-49`
- 当 `SMTP_TLS=false` 时使用 `SMTP_SSL(host, 465)`;为 `true` 时使用 `SMTP(host, 587).starttls()`
- 发送成功返回 `{status: 'OK'}`,失败返回 `{status: 'FAIL', error}`
- 接口:`POST /api/v1/transactions/send-email``app/api/v1/transactions/transactions.py:62-104`
- 支持直接上传附件(`file`)或通过 `file_url` 拉取远程文件,记录日志到 `email_send_log`
## 验证步骤
1. 获取后台 token`POST /api/v1/base/access_token`admin 账号)
2. 发送纯文本邮件(无附件):
- `POST /api/v1/transactions/send-email`JSON`{email, subject, body}`,携带 `token`
3. 发送带附件file_url
- JSON`{email, subject, body, file_url: 'https://...'}`;或使用 `multipart/form-data` 上传 `file`
4. 结果期望:返回 `{"status":"OK","log_id":...}`;失败时查看错误内容并修正配置。
## 可选增强
- 为 `email_client.send` 增加更明确的错误分类与超时提示(保留现有结构)。
- 提供健康检查端点:尝试建立 SMTP 连接并返回诊断信息(仅管理员角色可访问)。
## 回滚与安全
- 变更仅在环境变量层面,可随时回滚;不改代码,不提交授权码。
- 若切换至 587需同时改为 `SMTP_TLS=true` 并确保上游网络允许 STARTTLS。

View File

@ -1,103 +0,0 @@
## 工作范围与目标
- 范围:梳理 `web` 目录(排除 `web1`),形成结构与架构产物
- 目标:
- 生成完整项目结构文档(目录树、职责说明、关键路径)
- 制作技术架构示意图(前端分层、运行时链路、对后端的调用关系)
- 编写关键模块说明文档路由、状态、鉴权、HTTP、页面域
- 预留接口说明,支撑后续开发接入
## 技术栈识别
- 框架Vue 3`web/package.json:37`构建Vite`web/package.json:43``web/vite.config.js:1`
- 路由vue-router@4`web/package.json:39`);守卫统一注册(`web/src/router/guard/index.js:5-9`
- 状态Pinia`web/package.json:26``web/src/store/index.js:1-5`
- UI 与样式Naive UI`web/package.json:25`UnoCSS`web/package.json:30``web/src/main.js:3`),全局样式(`web/src/styles/global.scss`
- 国际化vue-i18n`web/package.json:38``web/src/main.js:22``web/i18n/index.js`
- 网络Axios`web/package.json:20`),自建请求封装(`web/src/utils/http/index.js:4-18`)与拦截器(`web/src/utils/http/interceptors.js:23-33,35-59`
- 运行环境:`.env.*` 配置,开发代理到后端 `127.0.0.1:9999``/api/v1``web/.env.development:8``web/build/constant.js:19-22``web/vite.config.js:31-35`
## 项目结构综述
- 顶层关键目录:
- `build/`Vite 定制化(定义、插件、脚本、代理)(`web/build/*`
- `i18n/`:国际化资源与实例(`web/i18n/index.js``web/i18n/messages/*`
- `settings/`:主题与全局设置(`web/settings/theme.json``web/settings/index.js`
- `public/`:静态资源与加载占位(`web/public/resource/*`
- `src/`:业务主目录(见下)
- `src/` 结构与职责:
- 入口与应用:`main.js`(应用装配,挂载插件)(`web/src/main.js:14-23``App.vue`
- 路由:`router/`(基本路由、动态路由、守卫、滚动)(`web/src/router/index.js:7-18,30-55`
- 状态:`store/`Pinia 注册与模块聚合)(`web/src/store/index.js:1-5``web/src/store/modules/index.js:1-4`
- 组件:`components/`(通用、表格、查询栏、图标、页面容器)
- 视图:`views/`(系统管理、估值评估、交易开票、登录、工作台等域)
- 工具:`utils/`鉴权、存储、HTTP、通用工具`web/src/utils/*`
- 指令:`directives/`(权限等自定义指令)
- 可复用逻辑:`composables/`(如 `useCRUD`
- 样式:`styles/`Reset、全局样式UnoCSS 原子类)
## 核心模块与功能点
- 鉴权与导航:
- 登录白名单与重定向(`web/src/router/guard/auth-guard.js:3-16`
- 动态路由注入、用户与权限联动(`web/src/router/index.js:30-55`
- 状态管理:
- 用户信息获取、登出流程(`web/src/store/modules/user/index.js:37-60`
- 标签、权限、应用模块聚合(`web/src/store/modules/index.js:1-4`
- 网络与错误处理:
- `request` 实例与 `baseURL` 环境绑定(`web/src/utils/http/index.js:17-19`
- 成功码约定 `code === 200`、统一错误提示(`web/src/utils/http/interceptors.js:23-33`
- 401 处理与自动登出(`web/src/utils/http/interceptors.js:45-53`
- 业务域:
- 系统管理(用户、角色、菜单、部门、审计日志)(`web/src/views/system/*`API 汇总:`web/src/api/index.js:393-431`
- 客户端用户管理、开票记录、估值评估(`web/src/views/user-management/*``web/src/views/transaction/invoice/*``web/src/views/valuation/*`;对应 API`web/src/api/index.js`
- UI 框架与布局:
- 布局与头部/侧栏/标签页组件(`web/src/layout/*`
- Naive UI 组件与 UnoCSS 原子化样式协同
## 技术架构示意图
```mermaid
graph TD
U[用户] --> A[Vue 应用]
A --> R[Router]
A --> S[Pinia]
A --> V[视图与组件]
V --> UI[Naive UI / UnoCSS]
A --> I18N[vue-i18n]
S --> H[HTTP 封装]
R --> G[路由守卫]
H --> X[Axios 拦截器]
X --> B[(后端 API /api/v1)]
subgraph 构建与运行
Vite[Vite Dev/Build]
end
A --> Vite
```
## 文档产出方案
- 目录与位置:在 `web/docs/` 下生成 4 个文档,统一中文、层级清晰、可落地
- `项目结构.md`:目录树 + 角色说明 + 入口与关键路径
- `技术架构.md`:架构分层 + 运行链路 + Mermaid 图
- `关键模块说明.md`路由、状态、HTTP、业务域的职责与协作
- `接口约定与预留.md`:环境、鉴权、响应约定、扩展接入指引
- 文档格式约定:
- 标题层级H1 总览H2 模块H3 文件与职责;统一术语与中文阐述
- 代码引用统一用内联反引号与文件定位(如 `web/src/router/index.js:30-55`
## 接口预留说明(用于后续开发)
- 基础约定:
- `baseURL``VITE_BASE_API`(默认 `/api/v1``web/.env.development:8`
- 认证头:`token`(由拦截器自动注入,`web/src/utils/http/interceptors.js:11-14`
- 成功响应:`{ code: 200, data, msg }``web/src/utils/http/interceptors.js:23-33`
- 接入方式:在 `web/src/api/index.js` 中以函数方式声明对应业务端点,统一走 `request`
- 错误处理:全局弹窗与 401 自动登出链路已就绪(`web/src/utils/http/interceptors.js:45-53`
## 执行步骤
1. 固化目录树与职责说明,输出《项目结构.md》
2. 绘制 Mermaid 架构图并输出《技术架构.md》
3. 编写《关键模块说明.md》覆盖路由、状态、HTTP、页面域
4. 编写《接口约定与预留.md》包含新增接口接入模板与约束
5. 交付文档后,等待新需求文档,启动开发
## 输出验收与规范
- 文档格式:统一中文,标题层级一致,引用路径与行号定位
- 风格一致:术语与代码片段与现有实现保持一致(如 `request``useUserStore`
- 可演进:接口文档预留扩展章节,支持后续模块按同规范接入
——请确认以上方案,确认后我将按该方案生成 4 个文档并提交供评审。

View File

@ -165,11 +165,12 @@ class FinalValueACalculator:
logger.info("final_value_a.calculating_model_value_b 开始计算模型估值B")
model_start_time = time.time()
model_result = await self.model_value_calculator.calculate_complete_model_value_b(
model_result_raw = await self.model_value_calculator.calculate_complete_model_value_b(
valuation_id,
input_data['model_data']
)
model_value_b = model_result if isinstance(model_result, (int, float)) else model_result.get('model_value_b')
model_result = model_result_raw if isinstance(model_result_raw, dict) else {"model_value_b": model_result_raw}
model_value_b = model_result.get('model_value_b')
model_duration = time.time() - model_start_time
logger.info("final_value_a.model_value_b_calculated 模型估值B计算完成: 模型估值B={}万元 耗时={}ms 返回字段={}",
@ -194,17 +195,18 @@ class FinalValueACalculator:
logger.info("final_value_a.calculating_market_value_c 开始计算市场估值C")
market_start_time = time.time()
market_result = await self.market_value_calculator.calculate_complete_market_value_c(
market_result_raw = await self.market_value_calculator.calculate_complete_market_value_c(
valuation_id,
input_data['market_data']
)
market_value_c = market_result if isinstance(market_result, (int, float)) else market_result.get('market_value_c')
market_result = market_result_raw if isinstance(market_result_raw, dict) else {"market_value_c": market_result_raw}
market_value_c = market_result.get('market_value_c')
market_duration = time.time() - market_start_time
logger.info("final_value_a.market_value_c_calculated 市场估值C计算完成: 市场估值C={}万元 耗时={}ms 返回字段={}",
logger.info("final_value_a.market_value_c_calculated 市场估值C计算完成: 市场估值C={}万元 耗时={}ms 请求字段={}",
market_value_c,
int(market_duration * 1000),
list(market_result.keys()))
input_data['market_data'])
await self.valuation_controller.create_calculation_step(
ValuationCalculationStepCreate(

View File

@ -51,7 +51,7 @@ class ModelValueBCalculator:
return model_value
async def calculate_complete_model_value_b(self, valuation_id: int, input_data: Dict) -> float:
async def calculate_complete_model_value_b(self, valuation_id: int, input_data: Dict) -> Dict[str, float]:
"""
计算完整的模型估值B并记录详细的计算步骤
@ -69,7 +69,7 @@ class ModelValueBCalculator:
}
Returns:
float: 计算得出的模型估值B
Dict[str, float]: 包含中间结果和最终模型估值B的字典
Raises:
Exception: 在计算过程中遇到的任何异常都会被捕获记录然后重新抛出
@ -87,8 +87,21 @@ class ModelValueBCalculator:
)
step_order += 1
current_stage = "初始化模型估值B参数"
try:
if not isinstance(input_data, dict):
raise TypeError(f"model_data必须为字典当前类型为{type(input_data).__name__}")
required_sections = ("economic_data", "cultural_data", "risky_data")
missing_sections = [
section for section in required_sections
if not isinstance(input_data.get(section), dict)
]
if missing_sections:
raise ValueError(f"model_data缺少必要字段: {', '.join(missing_sections)}")
# 计算经济价值B1传入估值ID并等待异步完成
current_stage = "经济价值B1计算"
economic_value_b1 = await self.economic_value_calculator.calculate_complete_economic_value_b1(
valuation_id,
input_data['economic_data']
@ -107,6 +120,7 @@ class ModelValueBCalculator:
step_order += 1
# 计算文化价值B2传入估值ID并等待异步完成
current_stage = "文化价值B2计算"
cultural_value_b2 = await self.cultural_value_calculator.calculate_complete_cultural_value_b2(
valuation_id,
input_data['cultural_data']
@ -125,6 +139,7 @@ class ModelValueBCalculator:
step_order += 1
# 计算风险调整系数B3传入估值ID并等待异步完成
current_stage = "风险调整系数B3计算"
risk_value_b3 = await self.risk_adjustment_calculator.calculate_complete_risky_value_b3(
valuation_id,
input_data['risky_data']
@ -143,6 +158,7 @@ class ModelValueBCalculator:
step_order += 1
# 计算模型估值B
current_stage = "模型估值B汇总"
model_value_b = self.calculate_model_value_b(
economic_value_b1,
cultural_value_b2,
@ -159,7 +175,12 @@ class ModelValueBCalculator:
status="completed"
)
)
return model_value_b
return {
"economic_value_b1": economic_value_b1,
"cultural_value_b2": cultural_value_b2,
"risk_value_b3": risk_value_b3,
"model_value_b": model_value_b,
}
except Exception as e:
await self.valuation_controller.create_calculation_step(
ValuationCalculationStepCreate(
@ -168,7 +189,7 @@ class ModelValueBCalculator:
step_name="计算失败",
step_description="计算过程中发生错误。",
status="failed",
error_message=str(e)
error_message=f"{current_stage}失败: {e}"
)
)
raise

View File

@ -101,7 +101,7 @@ class MarketValueCCalculator:
market_value = (market_bidding_c1 * heat_coefficient_c2 *
scarcity_multiplier_c3 * temporal_decay_c4)
return market_value
return market_value / 10000.0
async def calculate_complete_market_value_c(self, valuation_id: int, input_data: Dict) -> float:
"""

Binary file not shown.