Nav apraksta
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

mock-data.service.ts 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. import { Injectable } from '@angular/core';
  2. import { Observable, of } from 'rxjs';
  3. import { DocumentSession, DocumentType, createEmptyDocumentSessions } from '../models/document.model';
  4. @Injectable({
  5. providedIn: 'root'
  6. })
  7. export class MockDataService {
  8. // 模拟项目ID
  9. private mockProjectId = 'proj_mock_001';
  10. // 模拟文档会话数据
  11. private mockDocumentSessions: DocumentSession[] = [
  12. {
  13. id: DocumentType.UserRequirement,
  14. sessionId: 'session_user_req_001',
  15. title: '用户原始需求',
  16. content: `帮我建立自动补货:要求先按销售业绩进行店铺分组,商品按爆畅平滞分类,后,按照售罄率进行补货等等来编写sql代码,分步骤建立临时表保存过度数据,最后测试通过,发布。
  17. 具体要求:
  18. 1. 店铺分组:按最近30天销售额分为A、B、C三类店铺
  19. 2. 商品分类:按销售表现分为爆款、畅款、平款、滞销款
  20. 3. 补货逻辑:基于售罄率计算补货数量
  21. 4. 临时表:每个步骤建立临时表保存中间结果
  22. 5. 最终输出:完整的补货建议报告`,
  23. type: DocumentType.UserRequirement,
  24. lastUpdated: new Date('2025-02-13T10:00:00'),
  25. isLoading: false,
  26. hasContent: true
  27. },
  28. {
  29. id: DocumentType.Requirement,
  30. sessionId: 'session_req_002',
  31. title: '需求文档',
  32. content: `# 自动补货系统需求文档
  33. ## 1. 业务目标
  34. 建立智能补货系统,基于销售数据和库存情况自动生成补货建议。
  35. ## 2. 核心功能
  36. ### 2.1 店铺分级
  37. - 输入:店铺最近30天销售数据
  38. - 逻辑:按销售额排序,分为A(前30%)、B(中间40%)、C(后30%)
  39. - 输出:店铺分级表
  40. ### 2.2 商品分类
  41. - 输入:商品销售数据(销量、销售额、库存)
  42. - 逻辑:按销售表现分类:
  43. - 爆款:销量Top 20%,售罄率>80%
  44. - 畅款:销量中间60%,售罄率40-80%
  45. - 平款:销量较低但稳定
  46. - 滞销款:30天无销售或售罄率<20%
  47. - 输出:商品分类表
  48. ### 2.3 补货计算
  49. - 输入:商品分类、店铺分级、当前库存、销售预测
  50. - 逻辑:基于售罄率计算建议补货数量
  51. - 公式:建议补货量 = (销售预测 × 补货系数) - 当前库存
  52. - 输出:补货建议表
  53. ## 3. 数据流程
  54. 1. 原始销售数据 → 店铺分级
  55. 2. 商品销售数据 → 商品分类
  56. 3. 分级+分类+库存 → 补货计算
  57. 4. 输出补货建议报告`,
  58. type: DocumentType.Requirement,
  59. lastUpdated: new Date('2025-02-13T11:30:00'),
  60. isLoading: false,
  61. hasContent: true
  62. },
  63. {
  64. id: DocumentType.Technical,
  65. sessionId: 'session_tech_003',
  66. title: '技术文档',
  67. content: `# 自动补货系统技术方案
  68. ## 1. 系统架构
  69. ### 1.1 数据层
  70. - 数据源:销售事实表、店铺维度表、商品维度表
  71. - 存储:MySQL + Redis缓存
  72. - ETL:每日定时任务更新数据
  73. ### 1.2 计算层
  74. - 临时表设计:
  75. \`\`\`sql
  76. -- 临时表1:店铺分级
  77. CREATE TEMPORARY TABLE tmp_store_level AS
  78. SELECT
  79. store_id,
  80. sales_amount,
  81. CASE
  82. WHEN sales_percentile <= 0.3 THEN 'A'
  83. WHEN sales_percentile <= 0.7 THEN 'B'
  84. ELSE 'C'
  85. END AS store_level
  86. FROM (
  87. SELECT
  88. store_id,
  89. SUM(sales_amount) as sales_amount,
  90. PERCENT_RANK() OVER (ORDER BY SUM(sales_amount)) as sales_percentile
  91. FROM sales_fact
  92. WHERE sale_date >= DATE_SUB(CURDATE(), INTERVAL 30 DAY)
  93. GROUP BY store_id
  94. ) t;
  95. \`\`\`
  96. ### 1.3 业务层
  97. - 补货算法实现
  98. - 参数配置管理
  99. - 结果输出接口
  100. ## 2. 关键技术
  101. - SQL窗口函数(PERCENT_RANK)
  102. - 临时表管理
  103. - 参数化查询
  104. - 批量数据处理`,
  105. type: DocumentType.Technical,
  106. lastUpdated: new Date('2025-02-13T13:15:00'),
  107. isLoading: false,
  108. hasContent: true
  109. },
  110. {
  111. id: DocumentType.Implementation,
  112. sessionId: 'session_impl_004',
  113. title: '业务实现',
  114. content: `# 自动补货SQL实现代码
  115. ## 步骤1:店铺分级
  116. \`\`\`sql
  117. -- 创建店铺分级临时表
  118. DROP TEMPORARY TABLE IF EXISTS tmp_store_level;
  119. CREATE TEMPORARY TABLE tmp_store_level AS
  120. WITH store_sales AS (
  121. SELECT
  122. s.store_id,
  123. st.store_name,
  124. SUM(f.sales_amount) as total_sales,
  125. COUNT(DISTINCT f.sale_date) as sales_days,
  126. ROW_NUMBER() OVER (ORDER BY SUM(f.sales_amount) DESC) as rank,
  127. COUNT(*) OVER () as total_stores
  128. FROM sales_fact f
  129. JOIN store_dim s ON f.store_id = s.store_id
  130. WHERE f.sale_date >= DATE_SUB(CURDATE(), INTERVAL 30 DAY)
  131. GROUP BY s.store_id, st.store_name
  132. )
  133. SELECT
  134. store_id,
  135. store_name,
  136. total_sales,
  137. sales_days,
  138. CASE
  139. WHEN rank <= total_stores * 0.3 THEN 'A'
  140. WHEN rank <= total_stores * 0.7 THEN 'B'
  141. ELSE 'C'
  142. END as store_level
  143. FROM store_sales;
  144. \`\`\`
  145. ## 步骤2:商品分类
  146. \`\`\`sql
  147. -- 创建商品分类临时表
  148. DROP TEMPORARY TABLE IF EXISTS tmp_product_category;
  149. CREATE TEMPORARY TABLE tmp_product_category AS
  150. SELECT
  151. p.product_id,
  152. p.product_name,
  153. SUM(f.quantity) as total_sales_qty,
  154. SUM(f.sales_amount) as total_sales_amount,
  155. AVG(p.current_stock) as avg_stock,
  156. CASE
  157. WHEN SUM(f.quantity) > PERCENTILE_CONT(0.8) WITHIN GROUP (ORDER BY SUM(f.quantity)) OVER ()
  158. AND (SUM(f.quantity) / (AVG(p.current_stock) + SUM(f.quantity))) > 0.8
  159. THEN '爆款'
  160. WHEN SUM(f.quantity) > PERCENTILE_CONT(0.2) WITHIN GROUP (ORDER BY SUM(f.quantity)) OVER ()
  161. THEN '畅款'
  162. WHEN SUM(f.quantity) > 0 THEN '平款'
  163. ELSE '滞销款'
  164. END as product_category
  165. FROM sales_fact f
  166. JOIN product_dim p ON f.product_id = p.product_id
  167. WHERE f.sale_date >= DATE_SUB(CURDATE(), INTERVAL 30 DAY)
  168. GROUP BY p.product_id, p.product_name;
  169. \`\`\`
  170. ## 步骤3:补货计算
  171. \`\`\`sql
  172. -- 最终补货建议
  173. SELECT
  174. s.store_id,
  175. s.store_name,
  176. s.store_level,
  177. p.product_id,
  178. p.product_name,
  179. p.product_category,
  180. p.current_stock,
  181. f.avg_daily_sales,
  182. ROUND(f.avg_daily_sales * 7 - p.current_stock, 0) as suggested_replenishment
  183. FROM store_dim s
  184. CROSS JOIN product_dim p
  185. JOIN (
  186. SELECT
  187. store_id,
  188. product_id,
  189. AVG(quantity) as avg_daily_sales
  190. FROM sales_fact
  191. WHERE sale_date >= DATE_SUB(CURDATE(), INTERVAL 30 DAY)
  192. GROUP BY store_id, product_id
  193. ) f ON s.store_id = f.store_id AND p.product_id = f.product_id
  194. WHERE p.current_stock < f.avg_daily_sales * 3 -- 库存小于3天销量
  195. ORDER BY s.store_level, p.product_category, suggested_replenishment DESC;
  196. \`\`\``,
  197. type: DocumentType.Implementation,
  198. lastUpdated: new Date('2025-02-13T14:45:00'),
  199. isLoading: false,
  200. hasContent: true
  201. },
  202. {
  203. id: DocumentType.Test,
  204. sessionId: 'session_test_005',
  205. title: '测试文档',
  206. content: `# 自动补货系统测试方案
  207. ## 1. 测试数据准备
  208. ### 1.1 模拟数据
  209. \`\`\`sql
  210. -- 创建测试店铺数据
  211. INSERT INTO store_dim (store_id, store_name, region, create_time) VALUES
  212. ('S001', '测试店铺A', '华东', NOW()),
  213. ('S002', '测试店铺B', '华南', NOW()),
  214. ('S003', '测试店铺C', '华北', NOW());
  215. -- 创建测试商品数据
  216. INSERT INTO product_dim (product_id, product_name, category, current_stock, create_time) VALUES
  217. ('P001', '测试商品1', '服装', 100, NOW()),
  218. ('P002', '测试商品2', '鞋类', 50, NOW()),
  219. ('P003', '测试商品3', '配件', 200, NOW());
  220. -- 创建测试销售数据
  221. INSERT INTO sales_fact (sale_id, store_id, product_id, sale_date, quantity, sales_amount) VALUES
  222. (UUID(), 'S001', 'P001', DATE_SUB(CURDATE(), INTERVAL 1 DAY), 10, 1000),
  223. (UUID(), 'S001', 'P002', DATE_SUB(CURDATE(), INTERVAL 2 DAY), 5, 750),
  224. (UUID(), 'S002', 'P001', DATE_SUB(CURDATE(), INTERVAL 3 DAY), 8, 800);
  225. \`\`\`
  226. ## 2. 功能测试用例
  227. ### 2.1 店铺分级测试
  228. - 输入:30天销售数据
  229. - 预期:正确分为A、B、C三级
  230. - 验证:检查分级逻辑和比例
  231. ### 2.2 商品分类测试
  232. - 输入:商品销售数据
  233. - 预期:正确分为爆、畅、平、滞四类
  234. - 验证:检查分类算法准确性
  235. ### 2.3 补货计算测试
  236. - 输入:分级+分类+库存
  237. - 预期:合理的补货建议
  238. - 验证:检查计算公式和阈值
  239. ## 3. 性能测试
  240. - 数据量:1000店铺 × 10000商品
  241. - 响应时间:< 30秒
  242. - 内存使用:< 2GB
  243. ## 4. 集成测试
  244. - 数据流:源系统 → 临时表 → 结果表
  245. - 异常处理:空数据、异常值、连接中断
  246. - 恢复机制:失败重试、数据回滚`,
  247. type: DocumentType.Test,
  248. lastUpdated: new Date('2025-02-13T16:00:00'),
  249. isLoading: false,
  250. hasContent: true
  251. }
  252. ];
  253. constructor() { }
  254. /**
  255. * 获取项目文档会话数据
  256. */
  257. getProjectDocuments(projectId: string): Observable<DocumentSession[]> {
  258. if (projectId === this.mockProjectId) {
  259. return of(this.mockDocumentSessions);
  260. }
  261. // 其他项目返回空数据
  262. return of(createEmptyDocumentSessions(projectId));
  263. }
  264. /**
  265. * 获取项目文档会话映射
  266. */
  267. getProjectDocumentSessionIds(projectId: string): Observable<Record<DocumentType, string>> {
  268. const sessionIds: Record<DocumentType, string> = {
  269. [DocumentType.UserRequirement]: 'session_user_req_001',
  270. [DocumentType.Requirement]: 'session_req_002',
  271. [DocumentType.Technical]: 'session_tech_003',
  272. [DocumentType.Implementation]: 'session_impl_004',
  273. [DocumentType.Test]: 'session_test_005'
  274. };
  275. return of(sessionIds);
  276. }
  277. /**
  278. * 模拟SSE事件流
  279. * 在实际中将被真实的EventService替换
  280. */
  281. simulateSSEEvent(sessionId: string, content: string): Observable<string> {
  282. // 模拟打字机效果
  283. return new Observable<string>(observer => {
  284. let index = 0;
  285. const interval = setInterval(() => {
  286. if (index < content.length) {
  287. observer.next(content.charAt(index));
  288. index++;
  289. } else {
  290. clearInterval(interval);
  291. observer.complete();
  292. }
  293. }, 50);
  294. });
  295. }
  296. /**
  297. * 获取模拟AI回复
  298. */
  299. getMockAIResponse(): string {
  300. return `# 自动补货系统实现建议
  301. 我已经分析了您的需求,以下是完整的实现方案:
  302. ## 1. 架构设计
  303. 采用**分层临时表**策略,确保数据处理流程清晰:
  304. 1. **店铺分级表** (tmp_store_level)
  305. 2. **商品分类表** (tmp_product_category)
  306. 3. **销售预测表** (tmp_sales_forecast)
  307. 4. **补货建议表** (tmp_replenishment_suggestion)
  308. ## 2. 关键技术点
  309. ### 2.1 窗口函数应用
  310. \`\`\`sql
  311. -- 使用PERCENT_RANK进行店铺分级
  312. PERCENT_RANK() OVER (ORDER BY sales_amount) as sales_percentile
  313. \`\`\`
  314. ### 2.2 临时表管理
  315. \`\`\`sql
  316. -- 创建临时表保存中间结果
  317. CREATE TEMPORARY TABLE tmp_intermediate AS ...
  318. \`\`\`
  319. ### 2.3 性能优化
  320. - 索引优化:在store_id, product_id, sale_date上建立索引
  321. - 分区策略:按日期分区销售事实表
  322. - 批量处理:分批次处理大数据量
  323. ## 3. 完整实现代码
  324. [详见业务实现文档]
  325. ## 4. 测试建议
  326. 1. 单元测试:每个临时表独立测试
  327. 2. 集成测试:完整流程测试
  328. 3. 性能测试:大数据量压力测试
  329. ## 5. 部署建议
  330. 1. 生产环境:每日凌晨执行
  331. 2. 监控:执行时间、数据质量
  332. 3. 报警:异常情况及时通知`;
  333. }
  334. }