project.service.ts 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884
  1. import { Injectable } from '@angular/core';
  2. import { Observable, of } from 'rxjs';
  3. import {
  4. Project,
  5. Task,
  6. RenderProgress,
  7. CustomerFeedback,
  8. DesignerChange,
  9. Settlement,
  10. SkillTag,
  11. PerformanceData,
  12. MatchingOrder,
  13. ProjectStage
  14. } from '../models/project.model';
  15. // 材料统计数据接口
  16. interface MaterialStatistics {
  17. monthlyAdded: number;
  18. totalCostSaved: number;
  19. personalDownloads: number;
  20. }
  21. // 材料项接口
  22. interface MaterialItem {
  23. id: string;
  24. name: string;
  25. type: string;
  26. style: string;
  27. price: number;
  28. thumbnailUrl: string;
  29. downloadCount: number;
  30. tags: string[];
  31. costSaved: number;
  32. isNew: boolean;
  33. uploadTime: Date;
  34. }
  35. // 材料列表响应接口
  36. interface MaterialsResponse {
  37. materials: MaterialItem[];
  38. total: number;
  39. }
  40. // 异常历史记录接口
  41. interface ExceptionHistory {
  42. id: string;
  43. type: 'failed' | 'stuck' | 'quality' | 'other';
  44. description: string;
  45. submitTime: Date;
  46. status: '待处理' | '处理中' | '已解决';
  47. response?: string;
  48. }
  49. @Injectable({
  50. providedIn: 'root'
  51. })
  52. export class ProjectService {
  53. // 模拟数据 - 实际应用中应从API获取
  54. private projects: Project[] = [
  55. {
  56. id: 'proj-001',
  57. name: '现代风格客厅设计',
  58. customerName: '张三',
  59. customerTags: [
  60. { source: '朋友圈', needType: '硬装', preference: '现代', colorAtmosphere: '简约明亮' }
  61. ],
  62. highPriorityNeeds: ['需家具购买建议'],
  63. status: '进行中',
  64. currentStage: '需求沟通',
  65. stage: '需求沟通',
  66. createdAt: new Date('2025-09-01'),
  67. deadline: new Date('2025-09-15'),
  68. assigneeId: 'designer1',
  69. assigneeName: '设计师A',
  70. skillsRequired: ['现代风格', '硬装']
  71. },
  72. {
  73. id: '2',
  74. name: '宋式风格卧室设计',
  75. customerName: '李四',
  76. customerTags: [
  77. { source: '信息流', needType: '软装', preference: '宋式', colorAtmosphere: '典雅古朴' }
  78. ],
  79. highPriorityNeeds: [],
  80. status: '进行中',
  81. currentStage: '渲染',
  82. stage: '渲染',
  83. createdAt: new Date('2025-09-02'),
  84. deadline: new Date('2025-09-20'),
  85. assigneeId: 'designer1',
  86. assigneeName: '设计师A',
  87. skillsRequired: ['宋式风格', '软装']
  88. },
  89. {
  90. id: '3',
  91. name: '欧式风格厨房设计',
  92. customerName: '王五',
  93. customerTags: [
  94. { source: '朋友圈', needType: '硬装', preference: '欧式', colorAtmosphere: '豪华温馨' }
  95. ],
  96. highPriorityNeeds: ['需快速交付'],
  97. status: '已完成',
  98. currentStage: '投诉处理',
  99. stage: '投诉处理',
  100. createdAt: new Date('2025-08-20'),
  101. deadline: new Date('2025-09-05'),
  102. assigneeId: 'designer1',
  103. assigneeName: '设计师A',
  104. skillsRequired: ['欧式风格', '硬装']
  105. }
  106. ];
  107. private tasks: Task[] = [
  108. {
  109. id: 't1',
  110. projectId: '1',
  111. projectName: '现代风格客厅设计',
  112. title: '完成客厅建模',
  113. stage: '建模',
  114. deadline: new Date('2025-09-10'),
  115. isOverdue: false,
  116. isCompleted: false,
  117. priority: 'high',
  118. assignee: '设计师A',
  119. description: '根据客户需求完成客厅3D模型构建'
  120. },
  121. {
  122. id: 't2',
  123. projectId: '2',
  124. projectName: '宋式风格卧室设计',
  125. title: '确认渲染结果',
  126. stage: '渲染',
  127. deadline: new Date('2025-09-12'),
  128. isOverdue: false,
  129. isCompleted: false,
  130. priority: 'medium',
  131. assignee: '设计师B',
  132. description: '审核渲染效果并与客户确认'
  133. },
  134. {
  135. id: 't3',
  136. projectId: '1',
  137. projectName: '现代风格客厅设计',
  138. title: '处理客户反馈',
  139. stage: '渲染',
  140. deadline: new Date('2025-09-08'),
  141. isOverdue: true,
  142. isCompleted: false,
  143. priority: 'high',
  144. assignee: '客服',
  145. description: '整理客户反馈意见并传达给设计团队'
  146. }
  147. ];
  148. private renderProgresses: RenderProgress[] = [
  149. {
  150. id: 'rp1',
  151. projectId: '2',
  152. completionRate: 60,
  153. estimatedTimeRemaining: 1,
  154. status: '进行中',
  155. updatedAt: new Date()
  156. }
  157. ];
  158. private feedbacks: CustomerFeedback[] = [
  159. {
  160. id: 'f1',
  161. projectId: '1',
  162. content: '客厅设计不太满意,沙发的颜色和整体风格不太搭配',
  163. isSatisfied: false,
  164. problemLocation: '沙发区域',
  165. expectedEffect: '更宽敞舒适',
  166. referenceCase: '提供了参考图片',
  167. status: '待处理',
  168. createdAt: new Date('2025-09-07'),
  169. customerName: '张女士',
  170. rating: 2
  171. },
  172. {
  173. id: 'f2',
  174. projectId: '1',
  175. content: '整体设计很满意,特别是厨房的布局很合理,使用起来很方便',
  176. isSatisfied: true,
  177. problemLocation: '',
  178. expectedEffect: '',
  179. referenceCase: '',
  180. status: '已解决',
  181. createdAt: new Date('2025-09-05'),
  182. updatedAt: new Date('2025-09-06'),
  183. customerName: '张女士',
  184. rating: 5,
  185. response: '感谢您的认可,我们会继续努力为您提供更好的设计服务。'
  186. },
  187. {
  188. id: 'f3',
  189. projectId: '1',
  190. content: '卧室的灯光设计有些暗,希望能增加一些辅助照明',
  191. isSatisfied: false,
  192. problemLocation: '主卧室',
  193. expectedEffect: '更明亮温馨',
  194. referenceCase: '希望参考北欧风格的照明设计',
  195. status: '处理中',
  196. createdAt: new Date('2025-09-06'),
  197. customerName: '张女士',
  198. rating: 3
  199. },
  200. {
  201. id: 'f4',
  202. projectId: '2',
  203. content: '餐厅的家具选择很棒,质感和颜色都很满意',
  204. isSatisfied: true,
  205. problemLocation: '',
  206. expectedEffect: '',
  207. referenceCase: '',
  208. status: '已解决',
  209. createdAt: new Date('2025-09-04'),
  210. updatedAt: new Date('2025-09-05'),
  211. customerName: '李先生',
  212. rating: 4,
  213. response: '谢谢您的好评,我们精心挑选的家具能得到您的认可很开心。'
  214. },
  215. {
  216. id: 'f5',
  217. projectId: '2',
  218. content: '阳台的设计需要调整,现在的布局不太实用',
  219. isSatisfied: false,
  220. problemLocation: '阳台区域',
  221. expectedEffect: '更实用的储物和休闲空间',
  222. referenceCase: '希望有更多储物柜',
  223. status: '待处理',
  224. createdAt: new Date('2025-09-08'),
  225. customerName: '李先生',
  226. rating: 2
  227. },
  228. {
  229. id: 'f6',
  230. projectId: '3',
  231. content: '书房的设计非常棒,工作环境很舒适,书柜的设计也很实用',
  232. isSatisfied: true,
  233. problemLocation: '',
  234. expectedEffect: '',
  235. referenceCase: '',
  236. status: '已解决',
  237. createdAt: new Date('2025-09-03'),
  238. updatedAt: new Date('2025-09-04'),
  239. customerName: '王女士',
  240. rating: 5,
  241. response: '很高兴书房设计能满足您的工作需求,实用性一直是我们设计的重点。'
  242. },
  243. {
  244. id: 'f7',
  245. projectId: '3',
  246. content: '客厅的材质选择有些问题,地板的纹理和墙面不太协调',
  247. isSatisfied: false,
  248. problemLocation: '客厅地面',
  249. expectedEffect: '更协调的材质搭配',
  250. referenceCase: '希望参考现代简约风格',
  251. status: '处理中',
  252. createdAt: new Date('2025-09-07'),
  253. customerName: '王女士',
  254. rating: 3
  255. },
  256. {
  257. id: 'f8',
  258. projectId: '1',
  259. content: '儿童房的设计很用心,孩子很喜欢,安全性也考虑得很周到',
  260. isSatisfied: true,
  261. problemLocation: '',
  262. expectedEffect: '',
  263. referenceCase: '',
  264. status: '已解决',
  265. createdAt: new Date('2025-09-02'),
  266. updatedAt: new Date('2025-09-03'),
  267. customerName: '张女士',
  268. rating: 5,
  269. response: '孩子的安全和喜好是我们设计儿童房的首要考虑,很开心能得到小朋友的认可。'
  270. },
  271. {
  272. id: 'f9',
  273. projectId: '2',
  274. content: '厨房的收纳设计很实用,但是操作台的高度需要调整',
  275. isSatisfied: false,
  276. problemLocation: '厨房操作台',
  277. expectedEffect: '更符合人体工学的高度',
  278. referenceCase: '希望按照我的身高定制',
  279. status: '待处理',
  280. createdAt: new Date('2025-09-09'),
  281. customerName: '李先生',
  282. rating: 3
  283. },
  284. {
  285. id: 'f10',
  286. projectId: '3',
  287. content: '整体效果超出预期,设计师很专业,沟通也很顺畅',
  288. isSatisfied: true,
  289. problemLocation: '',
  290. expectedEffect: '',
  291. referenceCase: '',
  292. status: '已解决',
  293. createdAt: new Date('2025-09-01'),
  294. updatedAt: new Date('2025-09-02'),
  295. customerName: '王女士',
  296. rating: 5,
  297. response: '感谢您对我们团队的认可,专业和沟通是我们一直坚持的服务标准。'
  298. }
  299. ];
  300. private settlements: Settlement[] = [
  301. // 项目3的结算记录
  302. {
  303. id: 's1',
  304. projectId: '3',
  305. projectName: '欧式风格厨房设计',
  306. stage: '建模',
  307. amount: 3000,
  308. percentage: 30,
  309. status: '已结算',
  310. createdAt: new Date('2025-08-25'),
  311. settledAt: new Date('2025-09-01')
  312. },
  313. {
  314. id: 's2',
  315. projectId: '3',
  316. projectName: '欧式风格厨房设计',
  317. stage: '渲染',
  318. amount: 5000,
  319. percentage: 50,
  320. status: '已结算',
  321. createdAt: new Date('2025-08-28'),
  322. settledAt: new Date('2025-09-01')
  323. },
  324. {
  325. id: 's3',
  326. projectId: '3',
  327. projectName: '欧式风格厨房设计',
  328. stage: '渲染',
  329. amount: 2000,
  330. percentage: 20,
  331. status: '已结算',
  332. createdAt: new Date('2025-09-02'),
  333. settledAt: new Date('2025-09-05')
  334. },
  335. // 项目1的结算记录(当前项目)
  336. {
  337. id: 's4',
  338. projectId: 'proj-001',
  339. projectName: '现代风格客厅设计',
  340. stage: '建模',
  341. amount: 4500,
  342. percentage: 30,
  343. status: '已结算',
  344. createdAt: new Date('2025-09-01'),
  345. settledAt: new Date('2025-09-03')
  346. },
  347. {
  348. id: 's5',
  349. projectId: 'proj-001',
  350. projectName: '现代风格客厅设计',
  351. stage: '软装',
  352. amount: 3500,
  353. percentage: 25,
  354. status: '已结算',
  355. createdAt: new Date('2025-09-05'),
  356. settledAt: new Date('2025-09-08')
  357. },
  358. {
  359. id: 's6',
  360. projectId: 'proj-001',
  361. projectName: '现代风格客厅设计',
  362. stage: '渲染',
  363. amount: 4000,
  364. percentage: 30,
  365. status: '待结算',
  366. createdAt: new Date('2025-09-10')
  367. },
  368. {
  369. id: 's7',
  370. projectId: 'proj-001',
  371. projectName: '现代风格客厅设计',
  372. stage: '渲染',
  373. amount: 2000,
  374. percentage: 15,
  375. status: '待结算',
  376. createdAt: new Date('2025-09-12')
  377. },
  378. // 添加一些逾期的结算项
  379. {
  380. id: 's8',
  381. projectId: 'proj-001',
  382. projectName: '现代风格客厅设计',
  383. stage: '尾款结算',
  384. amount: 6000,
  385. percentage: 40,
  386. status: '待结算',
  387. createdAt: new Date('2025-08-15') // 超过30天,算作逾期
  388. },
  389. {
  390. id: 's9',
  391. projectId: 'proj-001',
  392. projectName: '现代风格客厅设计',
  393. stage: '方案确认',
  394. amount: 1500,
  395. percentage: 10,
  396. status: '待结算',
  397. createdAt: new Date('2025-08-20') // 逾期项目
  398. },
  399. // 项目2的结算记录
  400. {
  401. id: 's10',
  402. projectId: '2',
  403. projectName: '宋式风格卧室设计',
  404. stage: '建模',
  405. amount: 3200,
  406. percentage: 30,
  407. status: '已结算',
  408. createdAt: new Date('2025-09-03'),
  409. settledAt: new Date('2025-09-05')
  410. },
  411. {
  412. id: 's11',
  413. projectId: '2',
  414. projectName: '宋式风格卧室设计',
  415. stage: '软装',
  416. amount: 2800,
  417. percentage: 25,
  418. status: '待结算',
  419. createdAt: new Date('2025-09-08')
  420. },
  421. // 客服项目的尾款结算记录
  422. {
  423. id: 's12',
  424. projectId: '1', // 对应客服项目PRJ-2024-001
  425. projectName: '企业官网设计开发',
  426. stage: '尾款结算',
  427. amount: 50000,
  428. percentage: 100,
  429. status: '待结算',
  430. createdAt: new Date('2024-01-15'),
  431. dueDate: new Date('2024-02-15')
  432. },
  433. {
  434. id: 's13',
  435. projectId: '2', // 对应客服项目PRJ-2024-002
  436. projectName: '移动端APP开发',
  437. stage: '尾款结算',
  438. amount: 80000,
  439. percentage: 100,
  440. status: '逾期',
  441. createdAt: new Date('2024-01-10'),
  442. dueDate: new Date('2024-02-10')
  443. },
  444. {
  445. id: 's14',
  446. projectId: '3', // 对应客服项目PRJ-2024-003
  447. projectName: '电商平台升级',
  448. stage: '尾款结算',
  449. amount: 120000,
  450. percentage: 100,
  451. status: '已结算',
  452. createdAt: new Date('2024-01-08'),
  453. settledAt: new Date('2024-01-22'),
  454. dueDate: new Date('2024-02-08')
  455. },
  456. // 添加更多不同项目的尾款结算记录
  457. {
  458. id: 's15',
  459. projectId: '4',
  460. projectName: '品牌VI设计',
  461. stage: '尾款结算',
  462. amount: 35000,
  463. percentage: 100,
  464. status: '待结算',
  465. createdAt: new Date('2024-12-01'),
  466. dueDate: new Date('2024-12-31')
  467. },
  468. {
  469. id: 's16',
  470. projectId: '5',
  471. projectName: '小程序开发',
  472. stage: '尾款结算',
  473. amount: 45000,
  474. percentage: 100,
  475. status: '逾期',
  476. createdAt: new Date('2024-11-15'),
  477. dueDate: new Date('2024-12-15')
  478. },
  479. {
  480. id: 's17',
  481. projectId: '6',
  482. projectName: '网站重构项目',
  483. stage: '尾款结算',
  484. amount: 28000,
  485. percentage: 100,
  486. status: '已结算',
  487. createdAt: new Date('2024-12-10'),
  488. settledAt: new Date('2024-12-20'),
  489. dueDate: new Date('2025-01-10')
  490. },
  491. {
  492. id: 's18',
  493. projectId: '7',
  494. projectName: '数据可视化系统',
  495. stage: '尾款结算',
  496. amount: 95000,
  497. percentage: 100,
  498. status: '待结算',
  499. createdAt: new Date('2024-12-20'),
  500. dueDate: new Date('2025-01-20')
  501. },
  502. {
  503. id: 's19',
  504. projectId: '8',
  505. projectName: '智能家居控制系统',
  506. stage: '尾款结算',
  507. amount: 68000,
  508. percentage: 100,
  509. status: '逾期',
  510. createdAt: new Date('2024-10-30'),
  511. dueDate: new Date('2024-11-30')
  512. },
  513. {
  514. id: 's20',
  515. projectId: '9',
  516. projectName: '在线教育平台',
  517. stage: '尾款结算',
  518. amount: 150000,
  519. percentage: 100,
  520. status: '已结算',
  521. createdAt: new Date('2024-11-25'),
  522. settledAt: new Date('2024-12-15'),
  523. dueDate: new Date('2024-12-25')
  524. }
  525. ];
  526. private skillTags: SkillTag[] = [
  527. { id: 'sk1', name: '现代风格', level: 5, count: 10 },
  528. { id: 'sk2', name: '宋式风格', level: 3, count: 5 },
  529. { id: 'sk3', name: '硬装', level: 5, count: 8 },
  530. { id: 'sk4', name: '软装', level: 3, count: 4 }
  531. ];
  532. private performanceData: PerformanceData[] = [
  533. { month: '2025-08', projectCompletionRate: 90, customerSatisfaction: 95, deliveryOnTimeRate: 85 },
  534. { month: '2025-09', projectCompletionRate: 85, customerSatisfaction: 90, deliveryOnTimeRate: 90 },
  535. { month: '2025-10', projectCompletionRate: 95, customerSatisfaction: 92, deliveryOnTimeRate: 88 }
  536. ];
  537. private matchingOrders: MatchingOrder[] = [
  538. {
  539. id: 'mo1',
  540. projectName: '新中式风格书房设计',
  541. requiredSkills: ['宋式风格', '硬装'],
  542. matchRate: 90,
  543. customerLevel: '优质'
  544. },
  545. {
  546. id: 'mo2',
  547. projectName: '北欧风格餐厅设计',
  548. requiredSkills: ['现代风格', '软装'],
  549. matchRate: 80,
  550. customerLevel: '普通'
  551. }
  552. ];
  553. // 获取当前设计师的项目列表
  554. getProjects(): Observable<Project[]> {
  555. return of(this.projects);
  556. }
  557. // 获取项目详情
  558. getProjectById(id: string): Observable<Project | undefined> {
  559. // 尝试从Parse查询真实数据
  560. return new Observable(observer => {
  561. this.getProjectFromParse(id).then(project => {
  562. if (project) {
  563. observer.next(project);
  564. } else {
  565. // 降级:使用模拟数据
  566. observer.next(this.projects.find(project => project.id === id));
  567. }
  568. observer.complete();
  569. }).catch(error => {
  570. console.error('查询项目失败,使用模拟数据:', error);
  571. observer.next(this.projects.find(project => project.id === id));
  572. observer.complete();
  573. });
  574. });
  575. }
  576. /**
  577. * 从Parse查询项目
  578. */
  579. private async getProjectFromParse(id: string): Promise<Project | undefined> {
  580. try {
  581. const { FmodeParse } = await import('fmode-ng/parse');
  582. const Parse = FmodeParse.with('nova');
  583. const query = new Parse.Query('Project');
  584. query.include('customer', 'assignee');
  585. const project = await query.get(id);
  586. if (!project) {
  587. return undefined;
  588. }
  589. // 转换为前端Project格式
  590. const customer = project.get('customer');
  591. const assignee = project.get('assignee');
  592. const data = project.get('data') || {};
  593. return {
  594. id: project.id,
  595. name: project.get('title') || '未命名项目',
  596. customerName: customer?.get('name') || '未知客户',
  597. customerTags: [],
  598. highPriorityNeeds: data.highPriorityNeeds || [],
  599. status: project.get('status') || '待分配',
  600. currentStage: project.get('currentStage') || '订单分配',
  601. stage: project.get('currentStage') || '订单分配',
  602. createdAt: project.get('createdAt') || new Date(),
  603. deadline: project.get('deadline') || new Date(),
  604. assigneeId: assignee?.id || '',
  605. assigneeName: assignee?.get('name') || '未分配',
  606. skillsRequired: data.skillsRequired || []
  607. };
  608. } catch (error) {
  609. console.error('Parse查询失败:', error);
  610. return undefined;
  611. }
  612. }
  613. // 获取待办任务
  614. getTasks(mockSize?: number): Observable<Task[]> {
  615. if (typeof mockSize === 'number' && mockSize > 0) {
  616. const now = new Date(this.projects[0]?.deadline || new Date());
  617. const year = now.getFullYear();
  618. const month = now.getMonth();
  619. const pool = ['设计师A','设计师B','设计师C','设计师D','设计师E'];
  620. const prios: Array<'high'|'medium'|'low'> = ['high','medium','low'];
  621. const gen: Task[] = [];
  622. const daysInMonth = new Date(year, month + 1, 0).getDate();
  623. for (let i = 0; i < mockSize; i++) {
  624. const day = (i % daysInMonth) + 1;
  625. const deadline = new Date(year, month, day);
  626. gen.push({
  627. id: `m${i}`,
  628. projectId: String((i % this.projects.length) + 1),
  629. projectName: this.projects[i % this.projects.length].name,
  630. title: `Mock任务${i}`,
  631. stage: '建模',
  632. deadline,
  633. isOverdue: deadline < new Date(),
  634. isCompleted: false,
  635. priority: prios[i % prios.length],
  636. assignee: pool[i % pool.length],
  637. description: '性能压测生成'
  638. });
  639. }
  640. return of(gen);
  641. }
  642. return of(this.tasks);
  643. }
  644. // 标记任务完成
  645. markTaskAsCompleted(taskId: string): Observable<Task> {
  646. const task = this.tasks.find(t => t.id === taskId);
  647. if (task) {
  648. task.isCompleted = true;
  649. task.completedDate = new Date();
  650. }
  651. return of(task as Task);
  652. }
  653. // 获取渲染进度
  654. getRenderProgress(projectId: string): Observable<RenderProgress | undefined> {
  655. return of(this.renderProgresses.find(rp => rp.projectId === projectId));
  656. }
  657. // 获取客户反馈
  658. getCustomerFeedbacks(): Observable<CustomerFeedback[]> {
  659. return of(this.feedbacks);
  660. }
  661. // 更新反馈状态
  662. updateFeedbackStatus(feedbackId: string, status: '处理中' | '已解决'): Observable<CustomerFeedback> {
  663. const feedback = this.feedbacks.find(f => f.id === feedbackId);
  664. if (feedback) {
  665. feedback.status = status;
  666. feedback.updatedAt = new Date();
  667. }
  668. return of(feedback as CustomerFeedback);
  669. }
  670. // 获取结算记录
  671. getSettlements(): Observable<Settlement[]> {
  672. return of(this.settlements);
  673. }
  674. // 新增:创建结算记录(用于自动发起尾款结算申请)
  675. addSettlement(settlement: Settlement): Observable<void> {
  676. this.settlements.push(settlement);
  677. return of(void 0);
  678. }
  679. // 获取技能标签
  680. getSkillTags(): Observable<SkillTag[]> {
  681. return of(this.skillTags);
  682. }
  683. // 获取绩效数据
  684. getPerformanceData(): Observable<PerformanceData[]> {
  685. return of(this.performanceData);
  686. }
  687. // 获取匹配订单
  688. getMatchingOrders(): Observable<MatchingOrder[]> {
  689. return of(this.matchingOrders);
  690. }
  691. // 生成需求确认清单
  692. generateRequirementChecklist(projectId: string): Observable<string[]> {
  693. return of([
  694. '个性化需求已确认',
  695. '色彩氛围已确认',
  696. '硬装/软装范围已确认',
  697. '资料提交截止时间已确认'
  698. ]);
  699. }
  700. // 生成提醒话术
  701. generateReminderMessage(type: 'overdue' | 'stagnation'): Observable<string> {
  702. if (type === 'overdue') {
  703. return of('当前处于对图期,需1小时内回复,若您需时间梳理需求,可约定XX时间沟通');
  704. } else {
  705. return of('接下来将推进新项目,若需修改请提前1天预约');
  706. }
  707. }
  708. // 更新项目阶段
  709. updateProjectStage(projectId: string, stage: ProjectStage): Observable<Project | undefined> {
  710. const project = this.projects.find(p => p.id === projectId);
  711. if (project) {
  712. project.currentStage = stage;
  713. // 如果是投诉处理阶段,则将项目状态设置为已完成
  714. if (stage === '投诉处理') {
  715. project.status = '已完成';
  716. }
  717. }
  718. return of(project);
  719. }
  720. // 获取材料统计数据
  721. getMaterialStatistics(): Observable<MaterialStatistics> {
  722. return of({
  723. monthlyAdded: 15,
  724. totalCostSaved: 2800,
  725. personalDownloads: 42
  726. });
  727. }
  728. // 获取异常历史记录
  729. getExceptionHistories(projectId: string): Observable<ExceptionHistory[]> {
  730. return of([
  731. {
  732. id: 'eh1',
  733. type: 'quality',
  734. description: '光线效果不符合预期',
  735. submitTime: new Date('2025-09-05'),
  736. status: '已解决',
  737. response: '已调整灯光参数'
  738. },
  739. {
  740. id: 'eh2',
  741. type: 'stuck',
  742. description: '沙发尺寸需要调整',
  743. submitTime: new Date('2025-09-07'),
  744. status: '待处理'
  745. }
  746. ]);
  747. }
  748. // 更新收藏材料状态
  749. updateFavoriteMaterial(materialId: string, isFavorite: boolean): Observable<void> {
  750. // 模拟API调用
  751. console.log(`${isFavorite ? '添加' : '取消'}材料收藏:`, materialId);
  752. return of(void 0);
  753. }
  754. // 获取收藏材料列表
  755. getFavoriteMaterials(): Observable<string[]> {
  756. // 模拟返回收藏的材料ID列表
  757. return of(['mat1', 'mat3', 'mat5']);
  758. }
  759. // 获取材料列表
  760. getMaterials(
  761. searchQuery: string = '',
  762. filterType: string = '',
  763. filterStyle: string = '',
  764. filterPrice: string = '',
  765. page: number = 1,
  766. pageSize: number = 10
  767. ): Observable<MaterialsResponse> {
  768. // 模拟材料数据
  769. const mockMaterials: MaterialItem[] = [
  770. { id: 'mat1', name: '现代风格沙发', type: '家具', style: '现代', price: 2800, thumbnailUrl: 'https://picsum.photos/200/150', downloadCount: 120, tags: ['现代', '舒适', '客厅', '布艺'], costSaved: 500, isNew: false, uploadTime: new Date('2025-08-15') },
  771. { id: 'mat2', name: '宋式风格茶几', type: '家具', style: '宋式', price: 1500, thumbnailUrl: 'https://picsum.photos/200/151', downloadCount: 85, tags: ['宋式', '古典', '实木', '客厅'], costSaved: 300, isNew: true, uploadTime: new Date('2025-09-07') },
  772. { id: 'mat3', name: '欧式吊灯', type: '灯具', style: '欧式', price: 2200, thumbnailUrl: 'https://picsum.photos/200/152', downloadCount: 150, tags: ['欧式', '奢华', '客厅', '水晶'], costSaved: 450, isNew: false, uploadTime: new Date('2025-08-20') },
  773. { id: 'mat4', name: '中式地毯', type: '纺织品', style: '中式', price: 1800, thumbnailUrl: 'https://picsum.photos/200/153', downloadCount: 95, tags: ['中式', '传统', '卧室', '羊毛'], costSaved: 350, isNew: false, uploadTime: new Date('2025-08-25') },
  774. { id: 'mat5', name: '北欧风格窗帘', type: '纺织品', style: '北欧', price: 1200, thumbnailUrl: 'https://picsum.photos/200/154', downloadCount: 130, tags: ['北欧', '简约', '卧室', '亚麻'], costSaved: 250, isNew: true, uploadTime: new Date('2025-09-05') }
  775. ];
  776. // 简单的搜索和过滤逻辑
  777. let filtered = [...mockMaterials];
  778. if (searchQuery) {
  779. filtered = filtered.filter(m => m.name.toLowerCase().includes(searchQuery.toLowerCase()));
  780. }
  781. if (filterType) {
  782. filtered = filtered.filter(m => m.type === filterType);
  783. }
  784. if (filterStyle) {
  785. filtered = filtered.filter(m => m.style === filterStyle);
  786. }
  787. // 分页
  788. const startIndex = (page - 1) * pageSize;
  789. const paginated = filtered.slice(startIndex, startIndex + pageSize);
  790. return of({ materials: paginated, total: filtered.length });
  791. }
  792. // 记录材料下载
  793. recordMaterialDownload(materialId: string): Observable<void> {
  794. // 模拟下载记录
  795. console.log('记录材料下载:', materialId);
  796. return of(void 0);
  797. }
  798. // 创建项目
  799. createProject(projectData: {
  800. customerId: string;
  801. customerName: string;
  802. requirement: any;
  803. referenceCases: any[];
  804. tags: {
  805. demandType?: string;
  806. preferenceTags?: string[];
  807. followUpStatus?: string;
  808. };
  809. // 可选扩展字段:报价与指派信息
  810. quotation?: any;
  811. assignment?: any;
  812. orderAmount?: number;
  813. }): Observable<{ success: boolean; projectId: string }> {
  814. // 模拟API调用
  815. console.log('创建项目:', projectData);
  816. // 模拟返回创建的项目ID
  817. return of({ success: true, projectId: 'new-project-' + Date.now() });
  818. }
  819. // 创建项目群
  820. createProjectGroup(groupData: {
  821. customerId: string;
  822. customerName: string;
  823. tags?: {
  824. demandType?: string;
  825. preferenceTags?: string[];
  826. followUpStatus?: string;
  827. };
  828. }): Observable<{ success: boolean; groupId: string }> {
  829. // 模拟API调用
  830. console.log('创建项目群:', groupData);
  831. // 模拟返回创建的群组ID
  832. return of({ success: true, groupId: 'new-group-' + Date.now() });
  833. }
  834. }