| docs/功能测试报告/功能测试报告_审核界面交互与问题话术导出_2026-09-09.md | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| docs/工作日结/工作日结_2026-09-09.md | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| traffic-audit-server/src/main/java/com/trafficaudit/auditengine/service/AuditEngineService.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| traffic-audit-web/src/views/AuditResult.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| traffic-audit-web/src/views/DataView.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| traffic-audit-web/src/views/ReportExport.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
docs/¹¦ÄܲâÊÔ±¨¸æ/¹¦ÄܲâÊÔ±¨¸æ_ÉóºË½çÃæ½»»¥ÓëÎÊÌâ»°Êõµ¼³ö_2026-09-09.md
New file @@ -0,0 +1,38 @@ # åè½æµè¯æ¥åï¼å®¡æ ¸ç»æçé¢äº¤äºä¼åä¸å¯¼åºé®é¢è¯æ¯è½å° æ¥æï¼2026-09-09ãæ¨¡åï¼å®¡æ ¸ç»æ / æ°æ®æ¥ç / æ¥è¡¨çæï¼å端ï¼+ å®¡æ ¸ç»æå¯¼åºä¸æ¥è¯¢ï¼å端ï¼ãæµè¯äººï¼Codexï¼ä¸å¡ç¹éªåè¡¥å ï¼ ## ä¸ãåè½è¯´æ 1. å®¡æ ¸ç»æé¡µæä¸å¡å馿¶æäº¤äºè¯ä¹ï¼é®é¢èå´ä¸¤ä¸ªé项æ¹ä¸ºãä» éæ ¸å® / 嫿éåãå¹¶é说æãæéåä» æç¤ºååãä¸éå¤çï¼å¯¼åºé»è®¤ä¸å«ãï¼è§å¾é»è®¤ãæä¼ä¸åå¹¶ãï¼åæ¶ä¿çãææ¡æç»ãï¼çéåºæ¹ä¸ºæµ ç°å¡çæ ï¼å¹¶å±ç¤ºãå½åçé N æ¡ / M å®¶ä¼ä¸ã宿¶å½ä¸æ°ï¼é¡¶é¨çº¢/é»/å¾ å¤ç/å·²å¤çç»è®¡å¡æ¹ä¸ºè·éå½åçéç»æèå¨ã 2. 导åºãä¼ä¸åå¹¶ãSheet çé®é¢åè¯æ¯æç¨æ·ç»å® 4 æ¡ä¾ææ ¼å¼çæï¼å ¶ä½è§åç»ä¸ä¸ºãæ ¸å®å¼å¸¸/å·®å¼è¯´æï¼å«å ³é®æ°å¼ï¼ï¼è¯·æ ¸å®ã飿 ¼ï¼queryResults æ¹ä¸ºææ¥è¡¨ç±»åå åè§åãåå该æç»æï¼é¿å å ¨è¡¨è§åæ¯å¯¹ã 3. æ°æ®æ¥çé¡µå·¥å ·æ æ´ç为ä¸å¯¼å ¥é¡µä¸è´çãåç»æ¨¡åï¼ç±»å䏿ãï¼æ¥è¡¨æ/å ³é®å/æ¥è¯¢/å ¨å±å¹¶æäºä¸è¡ï¼åºé¨æç¤ºæ¹ä¸ºãå ± N æ¡è®°å½ï¼å·²å è½½ N æ¡ãã 4. æ¥è¡¨çæé¡µãéè·¯è¿è¾éæ±æ»è¡¨ï¼æ´æ¬ï¼ãé¢è§æ¹ä¸ºåç»è¡¨æ ¼ï¼é路货è¿/åå¸å®¢è¿/ä¸å£å¾ Ã å½æ/累计/忝ï¼ï¼åæ¯ç¼ºä¸å¹´åºææ¶é项ç»ãâãä¸æç¤ºã ## äºãæµè¯ç¯å¢ - å端 8090ï¼2026-09-09 15:45 ä»¥ææ°ä»£ç éå¯å°±ç»ªï¼ï¼å端 8080ï¼dev ç¼è¯æåãHMR çæï¼ã - æ°æ®åºï¼æ¬æº traffic_auditï¼2026-08 è´§è¿/æ 客/å ¬äº¤/åºç§æ°æ®åå¨åºï¼ã ## ä¸ãç¨ä¾ä¸ç»æ | ç¼å· | ç¨ä¾ | è¾å ¥ | 颿 | å®é | ç»è®º | |---|---|---|---|---|---| | 1 | 2026-08 è´§è¿æ¥è¯¢ä¸è½¬å | 页é¢é 2026-08ï¼è´§è¿ææ¥âæ¥è¯¢ç»æ | æ°ç§å è¿å并忢 loading | 约 2~3s è¿å 487 æ¡ / 403 å®¶ï¼æ å¡è½¬å | éè¿ | | 2 | é®é¢èå´æé®å³æ¶ååº | ç¹å»ã嫿éåãåç¹ãä» éæ ¸å®ã | é䏿ä¸å½ä¸æ°å³æ¶ååï¼æ ééæ°æ¥è¯¢ | é䏿ç§åï¼ä» éæ ¸å®ä¸èªå¨åé¤ RULE_004 æéåï¼487â474 æ¡ï¼ | éè¿ | | 3 | è§å¾é»è®¤ä¸åæ¢ | è¿å ¥é¡µé¢âè§å¾åé | é»è®¤ãæä¼ä¸åå¹¶ãï¼å¯åãææ¡æç»ã | é»è®¤æä¼ä¸åå¹¶ï¼AX é䏿 Value=1ï¼ï¼ææ¡æç»å¯æ£å¸¸åæ¢ä¸º 10 åéæ¡è¡¨ | éè¿ | | 4 | ææ¥æ°æ®å¼¹çªï¼æ°æ®ï¼æ¥å£ | /api/data/list?type=h2032/cityBus/h2031&period=2026-08 | å¿«éè¿å该ä¼ä¸è¯¥æå¡«æ¥ | 23~561ms è¿åï¼h2032 å ³é®åå½ä¸ 1 æ¡ãcityBus 10 æ¡ãh2031 50 æ¡/æ»æ°119ï¼ | éè¿ | | 5 | H2031 导åºé®é¢åä¸ç¨æ· 4 æ¡æ¨¡æ¿ä¸è´ | /api/audit/export 2026-08 H2031 | 1)~4) è¯æ¯ä¸ç¨æ·æä¾æ ¼å¼å®å ¨ä¸è´ | 宿µ G7ï¼â 客è¿éç¯æ¯=0æ ¸å®å¼å¸¸ï¼ä¸æå®¢è¿é=3784ï¼æ¬æå 车客è¿é=3784ï¼è¯·æ ¸å® â¡æ 客å¨è½¬éç¯æ¯=0æ ¸å®å¼å¸¸ï¼â¦ï¼è¯·æ ¸å® â¢å 车平åè¿è·çäºä¸æï¼ä¸æè¿è·=25.9ï¼æ¬æè¿è·=25.9ï¼è¯·æ ¸å®ä¼ä¸æ¯å¦æ¯åºå®çº¿è·¯æ 游æè éå¤ä¸å¡ï¼G10 ç线为ãâ¦ç¯æ¯è¶ ±20%â¦ï¼ä¸ç±»ç线平åè¿è·=0ï¼ä¸æ=17.6ï¼ç¯æ¯100%ï¼â¦è¯·æ ¸å®ã | éè¿ | | 6 | H2032 导åºé®é¢åå«æç» | åä¸ H2032 | æ¯ç±»æ ¸å®æè§å¸¦å ³é®æ°å¼ | 宿µãä¼ä¸ä¸æ¥è½¦è¾/å¨ä½ä¸è¿æ¿æ°æ®å¯¹æ¯åå¨å·®å¼ï¼æ´è½¦å¨ä½ï¼ä¸æ¥=â¦ï¼è¿æ¿=â¦ï¼å·®â¦ï¼é50 å¨ï¼ï¼æ»å¨ä½ï¼â¦ï¼è¯·æ ¸å®ãã䏿¥å¨è½¬éä¸è½¨è¿¹æµç®å¨è½¬é差弿æ¾ï¼ä¸æ¥å¨è½¬é=â¦ï¼è½¨è¿¹æµç®=â¦ï¼è¯·åèè½¨è¿¹æ ¸å®ä¼ä¸å¨è½¬éãç | éè¿ | | 7 | å®¡æ ¸ç»æå¯¼åºç»æä¸åå¹¶åº | openpyxl æå¼ä¸¤ä»½å¯¼åº | å SheetãB/G è·¨è¡åå¹¶ãé®é¢åç¼å· 1ã2ã3⦠| H2031 84 è¡ãH2032 475 è¡ï¼ä¼ä¸åå¹¶ Bï¼ä¼ä¸ï¼/Gï¼é®é¢ï¼åå¹¶åæ | éè¿ | | 8 | æ´æ¬é¢è§ 2026-08 åç»è¡¨é®å | /api/report/preview?period=2026-08&types=summaryWorkbook | summary é®å䏿°åç»è¡¨æ ¼åå¼ä¸è´ | è¿åé®å«ãå ¨çè´§ç©å¨è½¬é·累计 / Â·ç´¯è®¡åæ¯ããåå¸å®¢è¿é/å¨è½¬éÂ·å½æÂ·ç´¯è®¡ããä¸å£å¾å®¢è¿é/å¨è½¬éÂ·å½æÂ·ç´¯è®¡ãçï¼å端 wbRows åç»å¯åæ°ï¼ç¼ºå½ææºæ°æ®ä¸ä¸å¹´åºæçè¡æ¾ç¤ºãâãå¹¶ç»æç¤º | éè¿ | | 9 | ç¼è¯ä¸è¿è¡ | mvn compileï¼å端 dev | æ ç¼è¯é误ã页é¢å¯äº¤äº | å端 15:45 é坿åï¼Started ⦠port 8090ï¼ï¼å端 15:42 ç¼è¯æåï¼é¡µé¢å®æµç¹å»/忢/æ¥è¯¢åæ£å¸¸ | éè¿ | ## åãåç°é®é¢ä¸å¤ç½® - åãæ ¸å®å/å ¨é¨ãææ¡è¯ä¹ä¸æ¸ 导è´ç¨æ·å°æ â æ¹ä¸ºãä» éæ ¸å®/嫿éåãï¼å¹¶å ç°è²è¯´ææåï¼åãææ¡æç»ãé»è®¤è§å¾ â æ¹ä¸ºé»è®¤ãæä¼ä¸åå¹¶ãï¼ä¸æ¥å¸¸æä¼ä¸ä¸åæ ¸å¯¹ç工使µä¸è´ï¼ã - ç¨æ·åé¦âé 8 æè´§è¿/åå¸å ¬äº¤ä¸ç´è½¬åâï¼å¤æµ 2026-08 åç±»åç»ææ¥è¯¢å <1sã/data/list å¼¹çªæ°æ® <600msï¼æªå¤ç°è½¬åï¼å¤å®ä¸ºæ§çæé®ä» æ´æ°éæ©ç¶æä¸å·æ°å表æè´ï¼ç°å·²æ¹ä¸ºå端ååºå¼è¿æ»¤ï¼åèå´/ç¶æå³æ¶çæï¼ï¼æ éæ´é¡µéæ°è¯·æ±ã - 导åºé®é¢å H2032 æ§è¯æ¯åªåâå¼å¸¸ï¼å®é /åºå/åå·®ï¼âè¾æ¦æ¶© â æè§åè¡¥é½å ³é®æ°å¼ä¸ä¸å¡å£å¾ï¼è¿æ¿å项ã轨迹ãéè£ ç®±ãæ´è½¦å¨ä½çï¼ï¼è´§è¿/客è¿ä¸¤ç±»è¯æ¯åå·²ææ°æ ¼å¼å®æµæ ¸å¯¹ã ## äºãå¾ ä¸å¡ç¹éª / éç - 请ä¸å¡å¨æµè§å¨ç¹éªï¼é®é¢èå´/è§å¾/ç¶æä¸ä¸ªæ§ä»¶åæ¢ãè¡å ãæ°æ®ãå¼¹çªãå¯¼åº Excel æå¼åä¸ docs/å®¡æ ¸çé¢ææ¥æ¨¡æ¿/模æ¿_å®¡æ ¸ç»æ.xlsx å忡便鿡æ¯å¯¹ã - 䏿¢æéçä¸è´ï¼æ±æ»å¤§è¡¨ 8 æèªå¨å¡«å¼ï¼M2/M3 SummaryFillerï¼æªå¯å¨ï¼8 æç¼º freight_turnover_import çæºæ°æ®è¡ï¼å¯¼å ¥å¼¹çª UI ä¸ RULE_001 éå¼ï¼5 å°/50 å¨ï¼å¾ ä¸å¡ç¡®è®¤ã ## å ãç»è®º æ¬è½®çé¢äº¤äºæ¶æã导åºé®é¢è¯æ¯è½å°ä¸é¢è§è¡¨æ ¼ååéè¿æ¥å£çº§ä¸é¡µé¢çº§éªè¯ï¼æªåç°é»å¡æ§é®é¢ï¼å¯é代ç ä¸å¹¶äº¤ä»ï¼çå¾ ä¸å¡ç»éªã docs/¹¤×÷ÈÕ½á/¹¤×÷ÈÕ½á_2026-09-09.md
@@ -38,3 +38,24 @@ - /api/audit/export 2026-08 H2032ï¼å®¡æ ¸ç»æ 475 è¡ 10 å + ä¼ä¸åå¹¶ 150 ç»ï¼B/G åå¹¶ï¼ï¼ä» æ ¸å®åï¼status=pending/handled è¿æ»¤çæã - /api/report/preview summaryWorkbookï¼2026-07 æ¾ç¤ºå ¨çè´§è¿é 16285.71 ä¸å¨/累计 113423.13ï¼å¨è½¬é彿/累计+忝ï¼åå¸å®¢è¿é彿 30612.85 ä¸äººæ¬¡çï¼åæ¯ç¼º 2025-07 åºææ°æ®çä¸é¡¹åææç¡®æç¤ºã - æ°æ®æ¥çåç»ææ ¸å¯¹ï¼æå¡ç«¯å« enterpriseCode/unifiedCreditCode/reportUnit ä¸åï¼å端éèçæï¼ã --- ## ä¸å第ä¸è½®ï¼2026-09-09 16:xxï¼çé¢è¯ä¹æ¶æ / 导åºé®é¢è¯æ¯ / é¢è§è¡¨æ ¼åï¼å·²å¨æ¬å°å¤éªï¼ ### 宿å 容 - å®¡æ ¸ç»æé¡µï¼è§å¾æ¹ä¸ºé»è®¤ãæä¼ä¸åå¹¶ãï¼ä¿çãææ¡æç»ãï¼ï¼ãé®é¢èå´ãæ¹ææ¡ãä» éæ ¸å®/嫿éåãå¹¶é说æãæéåä» æç¤ºååãä¸éå¤çï¼å¯¼åºé»è®¤ä¸å«ãï¼çéåºå¡çåï¼ç»è®¡å¡ä¸ãå½åçé N æ¡/M å®¶ä¼ä¸ãéçé宿¶èå¨ï¼åæ¢ä¸åéè¦éæ°æ¥è¯¢ï¼ã - å®¡æ ¸ç»æå¯¼åºï¼ä¼ä¸åå¹¶ãé®é¢ãåæç¨æ· 4 æ¡ä¾ææ ¼å¼è½å°ï¼RULE_P003/04 客è¿éãæ å®¢å¨è½¬éç¯æ¯=0 æ ¸å®å¼å¸¸ï¼ä¸æâ¦=â¦ï¼æ¬æâ¦=â¦ï¼è¯·æ ¸å®ï¼RULE_P005 ç线平åè¿è·ç¯æ¯è¶ ééä¸ä¸æä¸ç¯æ¯ï¼RULE_P006 å 车平åè¿è·çäºä¸æï¼ä¸æè¿è·=â¦ï¼æ¬æè¿è·=â¦ï¼è¯·æ ¸å®æ¯å¦åºå®çº¿è·¯æ 游æéå¤ï¼ï¼H2032 è´§è¿è¯æ¯è¡¥å项æç»ï¼è½¦è¾/å¨ä½è¿æ¿å·®ã轨迹å¨è½¬éãéè£ ç®±ãæ´è½¦å¨ä½èå´çï¼ãå端 queryResults æ¹ä¸ºå ææ¥è¡¨ç±»ååè§ååæ¥è¯¥æç»æã - æ°æ®æ¥çï¼é¡¶é¨å·¥å ·æ æ´çï¼åç»æ¨¡å+ç±»å䏿/æ¥è¡¨æ/å ³é®å/æ¥è¯¢/å ¨å±ä¸è¡åï¼ï¼åºé¨è®¡æ°æ¹ãå ± N æ¡ï¼å·²å è½½ N æ¡ãã - æ¥è¡¨çæï¼æ±æ»å¤§è¡¨ï¼æ´æ¬ï¼é¢è§æ¹ä¸ºåç»è¡¨ï¼é路货è¿/åå¸å®¢è¿/ä¸å£å¾ Ã å½æ/累计/忝ï¼ï¼ç¼º 2025 åºææå½ææºæ°æ®æ¶ç»ãâãä¸æç¤ºã ### æµè¯ç»ææè¦ - 页é¢å®æµï¼8080ï¼ï¼2026-08 è´§è¿æ¥è¯¢ 2~3s è¿å 487 æ¡/403 å®¶æ 转åï¼ãä» éæ ¸å®/嫿éåãç¹å»å³æ¶çæï¼487â474 æ¡èªå¨åé¤ RULE_004ï¼ï¼è§å¾é»è®¤æä¼ä¸åå¹¶å¯åæç»ï¼è¡å ãæ°æ®ãæ¥å£ 23~561ms è¿åã - 导åºå®æµï¼H2031 2026-08 é®é¢åä¸ 4 æ¡ä¾æé忝坹ä¸è´ï¼H2032 2026-08 å Sheet 475 è¡ãB/G åå¹¶æ£å¸¸ã - å端 dev ç¼è¯æåï¼15:42ï¼ï¼å端 15:45 éå¯å°±ç»ªï¼ä¸¤ä¸ªè¿ç«¯ï¼gitea main / 个人 gitee masterï¼åæ æ°æäº¤ã - æµè¯æ¥åï¼docs/åè½æµè¯æ¥å/åè½æµè¯æ¥å_å®¡æ ¸çé¢äº¤äºä¸é®é¢è¯æ¯å¯¼åº_2026-09-09.mdã ### éçé®é¢ä¸å¾ åï¼ä¸ä¸åä¸è´ï¼ - æ±æ»å¤§è¡¨ 8 æèªå¨å¡«å¼ï¼M2/M3 SummaryFillerï¼æªå¯å¨ï¼8 æç¼º freight_turnover_importãscale_split_transportãpassenger_individual_monthlyãwyc_total/order æºæ°æ®ã - å¾ ä¸å¡ç»éªï¼é®é¢èå´/è§å¾/ç¶ææ§ä»¶ãè¡å æ°æ®å¼¹çªãå¯¼åº Excel 䏿¨¡æ¿/åæ¡ä¾æéæ¡æ ¸å¯¹ï¼å¯¼å ¥å¼¹çª UIãRULE_001 éå¼ï¼5 å°/50 å¨ï¼æ¯å¦ç¬¦åä¸å¡é¢æã traffic-audit-server/src/main/java/com/trafficaudit/auditengine/service/AuditEngineService.java
@@ -1259,19 +1259,17 @@ public List<AuditResult> queryResults(String reportPeriod, String reportType) { String type = reportType == null || reportType.trim().isEmpty() ? "H2032" : reportType.trim(); List<AuditRule> rules = ruleMapper.selectList(new LambdaQueryWrapper<AuditRule>() .eq(AuditRule::getReportType, type)); if (rules.isEmpty()) return new java.util.ArrayList<>(); List<Long> ruleIds = new ArrayList<>(); for (AuditRule rule : rules) ruleIds.add(rule.getId()); List<AuditResult> results = resultMapper.selectList(new LambdaQueryWrapper<AuditResult>() .eq(AuditResult::getReportPeriod, reportPeriod) .in(AuditResult::getRuleId, ruleIds) .orderByAsc(AuditResult::getId)); List<Long> ruleIds = new ArrayList<>(); for (AuditRule rule : ruleMapper.selectList(null)) { if (type.equals(rule.getReportType())) ruleIds.add(rule.getId()); } List<AuditResult> filtered = new ArrayList<>(); for (AuditResult result : results) { if (ruleIds.contains(result.getRuleId())) filtered.add(result); } attachInfo(filtered); return filtered; attachInfo(results, type, reportPeriod); return results; } public void reviewResult(Long id, String status, String comment) { @@ -1283,46 +1281,56 @@ resultMapper.updateById(result); } private void attachInfo(List<AuditResult> results) { private void attachInfo(List<AuditResult> results, String type, String period) { if (results.isEmpty()) return; Map<Long, AuditRule> ruleMap = new HashMap<>(); for (AuditRule rule : ruleMapper.selectList(null)) ruleMap.put(rule.getId(), rule); Map<Long, String> h2032Name = new HashMap<>(); Map<Long, String> h2032Explain = new HashMap<>(); Map<Long, String> passengerName = new HashMap<>(); Map<Long, String> passengerExplain = new HashMap<>(); Map<Long, String> energyName = new HashMap<>(); Map<Long, String> investName = new HashMap<>(); Map<Long, String> busName = new HashMap<>(); Map<Long, String> busExplain = new HashMap<>(); Map<Long, String> taxiName = new HashMap<>(); Map<Long, String> taxiExplain = new HashMap<>(); for (H2032EnterpriseMonthly r : h2032Mapper.selectList(null)) { h2032Name.putIfAbsent(r.getId(), r.getEnterpriseName()); h2032Explain.putIfAbsent(r.getId(), r.getVerifyExplanation()); for (AuditRule rule : ruleMapper.selectList(new LambdaQueryWrapper<AuditRule>() .eq(AuditRule::getReportType, type))) { ruleMap.put(rule.getId(), rule); } for (PassengerEnterpriseMonthly r : passengerMapper.selectList(null)) { passengerName.putIfAbsent(r.getId(), r.getEnterpriseName()); passengerExplain.putIfAbsent(r.getId(), r.getVerifyExplanation()); } for (EnergyVehicleQuarterly r : energyMapper.selectList(null)) { energyName.putIfAbsent(r.getId(), r.getEnterpriseName()); } for (CityBusMonthly r : cityBusMapper.selectList(null)) { busName.putIfAbsent(r.getId(), r.getEnterpriseName()); busExplain.putIfAbsent(r.getId(), r.getVerifyExplanation()); } for (CityTaxiMonthly r : cityTaxiMapper.selectList(null)) { taxiName.putIfAbsent(r.getId(), r.getCity()); taxiExplain.putIfAbsent(r.getId(), r.getVerifyExplanation()); } Map<Long, Long> investProjectId = new HashMap<>(); for (InvestmentMonthly r : investMonthlyMapper.selectList(null)) { investProjectId.putIfAbsent(r.getId(), r.getProjectId()); } for (InvestmentProject p : investProjectMapper.selectList(null)) { for (Map.Entry<Long, Long> e : investProjectId.entrySet()) { if (e.getValue().equals(p.getId())) investName.putIfAbsent(e.getKey(), p.getProjectName()); Map<Long, String> nameMap = new HashMap<>(); Map<Long, String> explainMap = new HashMap<>(); if ("INVEST".equals(type)) { Map<Long, Long> monthlyProject = new HashMap<>(); for (InvestmentMonthly m : investMonthlyMapper.selectList(new LambdaQueryWrapper<InvestmentMonthly>() .eq(InvestmentMonthly::getReportPeriod, period))) { monthlyProject.put(m.getId(), m.getProjectId()); } for (InvestmentProject p : investProjectMapper.selectList(null)) { for (Map.Entry<Long, Long> e : monthlyProject.entrySet()) { if (e.getValue() != null && e.getValue().equals(p.getId())) { nameMap.putIfAbsent(e.getKey(), p.getProjectName()); } } } } else if ("H204".equals(type)) { for (EnergyVehicleQuarterly m : energyMapper.selectList(new LambdaQueryWrapper<EnergyVehicleQuarterly>() .eq(EnergyVehicleQuarterly::getReportPeriod, period))) { nameMap.putIfAbsent(m.getId(), m.getEnterpriseName()); } } else if ("H2031".equals(type)) { for (PassengerEnterpriseMonthly m : passengerMapper.selectList(new LambdaQueryWrapper<PassengerEnterpriseMonthly>() .eq(PassengerEnterpriseMonthly::getReportPeriod, period))) { nameMap.putIfAbsent(m.getId(), m.getEnterpriseName()); explainMap.putIfAbsent(m.getId(), m.getVerifyExplanation()); } } else if ("CITY_BUS".equals(type)) { for (CityBusMonthly m : cityBusMapper.selectList(new LambdaQueryWrapper<CityBusMonthly>() .eq(CityBusMonthly::getReportPeriod, period))) { nameMap.putIfAbsent(m.getId(), m.getEnterpriseName()); explainMap.putIfAbsent(m.getId(), m.getVerifyExplanation()); } } else if ("CITY_TAXI".equals(type)) { for (CityTaxiMonthly m : cityTaxiMapper.selectList(new LambdaQueryWrapper<CityTaxiMonthly>() .eq(CityTaxiMonthly::getReportPeriod, period))) { nameMap.putIfAbsent(m.getId(), m.getCity()); explainMap.putIfAbsent(m.getId(), m.getVerifyExplanation()); } } else { for (H2032EnterpriseMonthly m : h2032Mapper.selectList(new LambdaQueryWrapper<H2032EnterpriseMonthly>() .eq(H2032EnterpriseMonthly::getReportPeriod, period))) { nameMap.putIfAbsent(m.getId(), m.getEnterpriseName()); explainMap.putIfAbsent(m.getId(), m.getVerifyExplanation()); } } for (AuditResult result : results) { @@ -1332,69 +1340,49 @@ result.setRuleCode(rule.getRuleCode()); result.setAlertLevel(rule.getAlertLevel()); } // åæ¥è¡¨è¡¨ id åèªç¬ç«èªå¢ï¼éæè§åæå±æ¥è¡¨ç±»åå表åå¡«ä¼ä¸åç§° String type = rule == null ? null : rule.getReportType(); Map<Long, String> nameMap = "INVEST".equals(type) ? investName : "H204".equals(type) ? energyName : "H2031".equals(type) ? passengerName : "CITY_BUS".equals(type) ? busName : "CITY_TAXI".equals(type) ? taxiName : h2032Name; Map<Long, String> explainMap = "H2031".equals(type) ? passengerExplain : "CITY_BUS".equals(type) ? busExplain : "CITY_TAXI".equals(type) ? taxiExplain : h2032Explain; String enterpriseName = nameMap.get(result.getReportId()); if (enterpriseName == null) { // 䏿¥æ°æ®è¢«éæ°å¯¼å ¥åæ§å®¡æ ¸ç»æå·²å¤±æï¼ç»åºæç¤ºèéç©ºç½ enterpriseName = "\uFF08\u539F\u6570\u636E\u5DF2\u91CD\u65B0\u5BFC\u5165\uFF0C\u8BF7\u91CD\u65B0\u6267\u884C\u5BA1\u6838\uFF09"; enterpriseName = "ï¼åæ°æ®å·²éæ°å¯¼å ¥ï¼è¯·éæ°æ§è¡å®¡æ ¸ï¼"; } result.setEnterpriseName(enterpriseName); result.setVerifyExplanation(explainMap.get(result.getReportId())); } } /** æè¿ææ°æ®çæ¥è¡¨æï¼ç¨äºå端é»è®¤éä¸ï¼ */ public String latestPeriod(String reportType) { String type = reportType == null || reportType.trim().isEmpty() ? "H2032" : reportType.trim(); String max = null; switch (type) { case "H2031": for (PassengerEnterpriseMonthly m : passengerMapper.selectList( new LambdaQueryWrapper<PassengerEnterpriseMonthly>().select(PassengerEnterpriseMonthly::getReportPeriod))) { max = maxPeriod(max, m.getReportPeriod()); } break; return firstOf(passengerMapper.selectObjs(new LambdaQueryWrapper<PassengerEnterpriseMonthly>() .select(PassengerEnterpriseMonthly::getReportPeriod) .orderByDesc(PassengerEnterpriseMonthly::getReportPeriod).last("LIMIT 1"))); case "H204": for (EnergyVehicleQuarterly m : energyMapper.selectList( new LambdaQueryWrapper<EnergyVehicleQuarterly>().select(EnergyVehicleQuarterly::getReportPeriod))) { max = maxPeriod(max, m.getReportPeriod()); } break; return firstOf(energyMapper.selectObjs(new LambdaQueryWrapper<EnergyVehicleQuarterly>() .select(EnergyVehicleQuarterly::getReportPeriod) .orderByDesc(EnergyVehicleQuarterly::getReportPeriod).last("LIMIT 1"))); case "INVEST": for (InvestmentMonthly m : investMonthlyMapper.selectList( new LambdaQueryWrapper<InvestmentMonthly>().select(InvestmentMonthly::getReportPeriod))) { max = maxPeriod(max, m.getReportPeriod()); } break; return firstOf(investMonthlyMapper.selectObjs(new LambdaQueryWrapper<InvestmentMonthly>() .select(InvestmentMonthly::getReportPeriod) .orderByDesc(InvestmentMonthly::getReportPeriod).last("LIMIT 1"))); case "CITY_BUS": for (CityBusMonthly m : cityBusMapper.selectList( new LambdaQueryWrapper<CityBusMonthly>().select(CityBusMonthly::getReportPeriod))) { max = maxPeriod(max, m.getReportPeriod()); } break; return firstOf(cityBusMapper.selectObjs(new LambdaQueryWrapper<CityBusMonthly>() .select(CityBusMonthly::getReportPeriod) .orderByDesc(CityBusMonthly::getReportPeriod).last("LIMIT 1"))); case "CITY_TAXI": for (CityTaxiMonthly m : cityTaxiMapper.selectList( new LambdaQueryWrapper<CityTaxiMonthly>().select(CityTaxiMonthly::getReportPeriod))) { max = maxPeriod(max, m.getReportPeriod()); } break; return firstOf(cityTaxiMapper.selectObjs(new LambdaQueryWrapper<CityTaxiMonthly>() .select(CityTaxiMonthly::getReportPeriod) .orderByDesc(CityTaxiMonthly::getReportPeriod).last("LIMIT 1"))); default: for (H2032EnterpriseMonthly m : h2032Mapper.selectList( new LambdaQueryWrapper<H2032EnterpriseMonthly>().select(H2032EnterpriseMonthly::getReportPeriod))) { max = maxPeriod(max, m.getReportPeriod()); } break; return firstOf(h2032Mapper.selectObjs(new LambdaQueryWrapper<H2032EnterpriseMonthly>() .select(H2032EnterpriseMonthly::getReportPeriod) .orderByDesc(H2032EnterpriseMonthly::getReportPeriod).last("LIMIT 1"))); } return max; } private String firstOf(List<Object> objs) { if (objs == null || objs.isEmpty() || objs.get(0) == null) return null; String v = String.valueOf(objs.get(0)); return v.trim().isEmpty() ? null : v.trim(); } private String maxPeriod(String a, String b) { @@ -1512,25 +1500,84 @@ /** ä¼ä¸åå¹¶âé®é¢âåè¯æ¯ï¼æè§åç±»åçæå¯è¯»çæ ¸å®æè§ */ private String issueSentence(AuditResult res) { String code = res.getRuleCode(); String dev = valueOf(res.getDeviation()); String name = valueOf(res.getRuleName()); String act = valueOf(res.getActualValue()); String thr = valueOf(res.getThresholdValue()); if ("RULE_001".equals(code) || "RULE_002".equals(code)) { return "ä¼ä¸ä¸æ¥è½¦è¾/å¨ä½ä¸è¿æ¿æ°æ®å¯¹æ¯åå¨å·®å¼ï¼" + dev + "ï¼ï¼è¯·æ ¸å®"; return "ä¼ä¸ä¸æ¥è½¦è¾/å¨ä½ä¸è¿æ¿æ°æ®å¯¹æ¯åå¨å·®å¼ï¼" + act + "ï¼ï¼è¯·æ ¸å®"; } if ("RULE_003".equals(code)) { return "䏿¥å¨è½¬éä¸è½¨è¿¹æµç®å¨è½¬é差弿æ¾ï¼" + dev + "ï¼ï¼è¯·åèè½¨è¿¹æ ¸å®ä¼ä¸å¨è½¬é"; return "䏿¥å¨è½¬éä¸è½¨è¿¹æµç®å¨è½¬é差弿æ¾ï¼" + act + "ï¼ï¼è¯·åèè½¨è¿¹æ ¸å®ä¼ä¸å¨è½¬é"; } if ("RULE_004".equals(code)) { return "è´§è¿ç±»åç¯æ¯åçååï¼è¯·æ ¸å®"; return "è´§è¿ç±»åç¯æ¯åçåå" + (act.isEmpty() ? "" : "ï¼" + act + "ï¼") + "ï¼è¯·å ³æ³¨æ¯å¦å¡«æ¥æ£å¸¸"; } if ("RULE_005".equals(code)) { return "æ éè£ ç®±è½¦ä½åå¨éè£ ç®±è´§è¿éï¼è¯·æ ¸å®è½¦è¾ç±»åä¸è´§è¿éå¡«æ¥"; return "æ éè£ ç®±è½¦ä½åå¨éè£ ç®±è´§è¿éï¼" + act + "ï¼ï¼è¯·æ ¸å®è½¦è¾ç±»åä¸è´§è¿éå¡«æ¥"; } if ("RULE_006".equals(code)) { return "æ´è½¦å¨ä½è¶ åº 4~40 å¨åçèå´ï¼è¯·æ ¸å®å¹³åå¨ä½å¡«æ¥"; return "æ´è½¦å¹³åå¨ä½è¶ åºåçèå´ï¼" + act + "ï¼ï¼è¯·æ ¸å®å¹³åå¨ä½å¡«æ¥"; } return valueOf(res.getRuleName()) + "å¼å¸¸ï¼å®é ï¼" + act + "ï¼åºåï¼" + thr + "ï¼" + dev + "ï¼ï¼è¯·æ ¸å®"; if (code != null && code.startsWith("RULE_P")) { String special = passengerIssueSentence(res); if (special != null) return special; } return name + "å¼å¸¸ï¼" + act + "ï¼ï¼è¯·æ ¸å®"; } /** 客è¿ï¼H2031ï¼è§åé®é¢è¯æ¯ï¼è´´å模æ¿ç¤ºä¾âæ ¸å®å¼å¸¸ï¼ä¸æææ =ï¼æ¬æææ =ï¼è¯·æ ¸å®â */ private String passengerIssueSentence(AuditResult res) { String code = res.getRuleCode(); String act = valueOf(res.getActualValue()); if ("RULE_P003".equals(code) || "RULE_P004".equals(code)) { boolean turnover = "RULE_P004".equals(code); String inner = act; if (inner.startsWith("æ¬æä¸ä¸æç¸å: ")) { inner = inner.substring("æ¬æä¸ä¸æç¸å: ".length()); } java.util.List<String> clauses = new java.util.ArrayList<>(); for (String item : inner.split("ã")) { int eq = item.indexOf('='); if (eq <= 0) { clauses.add(item); continue; } String label = item.substring(0, eq).trim(); String v = item.substring(eq + 1).trim(); clauses.add("䏿" + (turnover ? "å¨è½¬é" : "客è¿é") + "=" + v + "ï¼æ¬æ" + label + "=" + v); } return valueOf(res.getRuleName()) + "å¼å¸¸ï¼" + String.join("ï¼", clauses) + "ï¼è¯·æ ¸å®"; } if ("RULE_P005".equals(code)) { String pct = extractPct(valueOf(res.getThresholdValue())); String prefix = pct.isEmpty() ? "ç线平åè¿è·ç¯æ¯è¶ é" : "ç线平åè¿è·ç¯æ¯è¶ ±" + pct + "%"; return prefix + "ï¼æ£å¸¸ç线è¿è·å¨çº¿è·¯æªåçé大åååè¾ä¸ºç¨³å®ï¼" + act + "ï¼ï¼è¯·æ ¸å®"; } if ("RULE_P006".equals(code)) { String inner = act; if (inner.startsWith("çäºä¸æ: ")) { inner = inner.substring("çäºä¸æ: ".length()); } java.util.List<String> clauses = new java.util.ArrayList<>(); for (String item : inner.split("ã")) { int eq = item.indexOf('='); if (eq <= 0) { clauses.add(item); continue; } String v = item.substring(eq + 1).trim(); clauses.add("䏿è¿è·=" + v + "ï¼æ¬æè¿è·=" + v); } return "å 车平åè¿è·çäºä¸æï¼" + String.join("ï¼", clauses) + "ï¼è¯·æ ¸å®ä¼ä¸æ¯å¦æ¯åºå®çº¿è·¯æ 游æè éå¤ä¸å¡"; } return null; } private String extractPct(String thresholdText) { if (thresholdText == null || thresholdText.isEmpty()) return ""; int idx = thresholdText.indexOf('\u00b1'); if (idx < 0) return ""; StringBuilder num = new StringBuilder(); for (int i = idx + 1; i < thresholdText.length(); i++) { char c = thresholdText.charAt(i); if (Character.isDigit(c) || c == '.') num.append(c); else if (!Character.isWhitespace(c)) break; } return num.toString(); } private String auditStatusCn(String status) { traffic-audit-web/src/views/AuditResult.vue
@@ -50,7 +50,9 @@ <div class="sev-card sev-pending"><b>{{ severityStats.pending }}</b> å¾ å¤ç</div> <div class="sev-card sev-done"><b>{{ severityStats.done }}</b> å·²å¤ç</div> </div> <el-form v-if="!focusMode" :inline="true" style="margin-top:8px;flex:none"> <div v-if="!focusMode" class="audit-filter-bar"> <el-form :inline="true"> <el-form-item label="çé"></el-form-item> <el-form-item label="ä¼ä¸åç§°"> <el-input v-model="enterpriseFilter" placeholder="è¾å ¥ä¼ä¸åç§°å ³é®å" clearable style="width:200px" @keyup.enter.native="queryResults"></el-input> </el-form-item> @@ -59,11 +61,12 @@ <el-option v-for="rn in ruleOptions" :key="rn" :label="rn" :value="rn"></el-option> </el-select> </el-form-item> <el-form-item label="é®é¢ç±»å"> <el-form-item label="é®é¢èå´"> <el-radio-group v-model="issueScope" size="small" @change="updateBatchSelection"> <el-radio-button label="verify">æ ¸å®å</el-radio-button> <el-radio-button label="all">å ¨é¨</el-radio-button> <el-radio-button label="verify">ä» éæ ¸å®</el-radio-button> <el-radio-button label="all">嫿éå</el-radio-button> </el-radio-group> <span class="hint">æéåä» æç¤ºååãä¸éå¤çï¼å¯¼åºé»è®¤ä¸å«</span> </el-form-item> <el-form-item label="ç¶æ"> <el-select v-model="statusScope" style="width:110px" @change="updateBatchSelection"> @@ -87,9 +90,11 @@ <el-button size="small" plain @click="statsCollapsed = !statsCollapsed">{{ statsCollapsed ? 'å±å¼' : 'æ¶èµ·' }}è§åç»è®¡</el-button> </el-form-item> <el-form-item> <span style="color:#909399;font-size:12px">å ± {{ results.length }} æ¡é®é¢ï¼{{ mergedResults.length }} å®¶ä¼ä¸</span> <span style="color:#303133;font-size:13px;font-weight:600">å½åçé {{ filteredResults.length }} æ¡ / {{ mergedResults.length }} å®¶ä¼ä¸</span> <span style="color:#909399;font-size:12px;margin-left:8px">ï¼å ± {{ results.length }} æ¡é®é¢ï¼</span> </el-form-item> </el-form> </div> <div v-if="ruleStats.length && !statsCollapsed && !focusMode" class="rule-stats" style="flex:none"> <div class="stats-cards"> <div v-for="rs in sortedRuleStats" :key="rs.ruleId" class="stat-card" @@ -354,7 +359,7 @@ data() { return { period: '', reportType: 'H2032', loading: false, marking: false, results: [], ruleStats: [], statsCollapsed: false, enterpriseFilter: '', ruleFilter: '', viewMode: 'detail', issueScope: 'verify', statusScope: 'all', batchSelection: [], focusMode: false, enterpriseFilter: '', ruleFilter: '', viewMode: 'merged', issueScope: 'verify', statusScope: 'all', batchSelection: [], focusMode: false, explainDrafts: {}, savingExplainId: null, expandedExplain: null, monthVisible: false, monthLoading: false, monthType: '', monthPeriod: '', monthKeyword: '', monthRecords: [], monthColumns: [] } @@ -367,7 +372,7 @@ }, severityStats() { const s = { red: 0, yellow: 0, pending: 0, done: 0 } this.results.forEach(r => { this.filteredResults.forEach(r => { if (r.alertLevel === 'RED') s.red++ else if (r.alertLevel === 'YELLOW') s.yellow++ if (r.status === 'PENDING') s.pending++ @@ -769,4 +774,9 @@ .mr-sec-tab th { background: #F5F7FA; font-weight: 600; } .mr-note { margin: 6px 12px 12px; background: #FDF6EC; border: 1px solid #FAECD8; border-radius: 4px; padding: 8px 10px; font-size: 12px; color: #8a6d3b; white-space: pre-wrap; word-break: break-all; } .mr-note-line { margin: 2px 0; } .audit-filter-bar { background:#FAFAFA; border:1px solid #EBEEF5; border-radius:8px; padding:2px 12px 0; margin-top:8px; flex:none; } .audit-filter-bar .el-form-item { margin-bottom:6px; } .audit-filter-bar .el-form-item__label { color:#606266; font-weight:600; } .hint { color:#909399; font-size:12px; margin-left:6px; white-space:nowrap; } </style> traffic-audit-web/src/views/DataView.vue
@@ -16,32 +16,23 @@ </el-aside> <el-main> <h3>å¯¼å ¥æ°æ®æ¥ç</h3> <div class="type-row"> <span class="type-label">æ°æ®ç±»å</span> <div class="toolbar"> <span class="toolbar-label">æ°æ®ç±»å</span> <el-radio-group v-model="activeModule" size="small" @change="onModuleChange"> <el-radio-button v-for="g in modules" :key="g.key" :label="g.key">{{ g.name }}</el-radio-button> </el-radio-group> <el-select v-model="type" size="small" style="width:300px" placeholder="éæ©æ°æ®ç±»å" @change="onTypeSelect"> <el-select v-model="type" size="small" style="width:250px" placeholder="éæ©æ°æ®ç±»å" @change="onTypeSelect"> <el-option-group :label="activeTypes.name"> <el-option v-for="t in activeTypes.types" :key="t.value" :label="t.label" :value="t.value"></el-option> </el-option-group> </el-select> <span class="toolbar-sep"></span> <el-date-picker v-model="period" type="month" placeholder="æ¥è¡¨æï¼å ¨é¨ï¼" value-format="yyyy-MM" clearable style="width:150px" @change="doQuery"></el-date-picker> <el-input v-model="keyword" placeholder="ä¼ä¸/å¸å·åç§°" clearable style="width:180px" @keyup.enter.native="doQuery"></el-input> <el-button type="primary" size="small" @click="doQuery">æ¥è¯¢</el-button> <el-button size="small" icon="el-icon-full-screen" @click="toggleFullscreen">å ¨å±æ¥ç</el-button> </div> <el-form :inline="true" class="filter-row"> <el-form-item label="æ¥è¡¨æ"> <el-date-picker v-model="period" type="month" placeholder="å ¨é¨" value-format="yyyy-MM" clearable style="width:140px" @change="loadData"></el-date-picker> </el-form-item> <el-form-item label="å ³é®å"> <el-input v-model="keyword" placeholder="ä¼ä¸/å¸å·åç§°" clearable style="width:200px" @keyup.enter.native="loadData"></el-input> </el-form-item> <el-form-item> <el-button type="primary" @click="loadData">æ¥è¯¢</el-button> <el-button type="success" icon="el-icon-full-screen" @click="toggleFullscreen">å ¨å±æ¥ç</el-button> </el-form-item> </el-form> <div style="color:#909399;font-size:12px;margin-bottom:6px"> å ± {{ total }} æ¡è®°å½ï¼å½å第 {{ page }} 页 </div> <div class="load-hint">å ± {{ total }} æ¡è®°å½ï¼å·²å è½½ {{ records.length }} æ¡</div> <div class="table-wrap" ref="tableWrap"> <div class="table-area"> <el-table :data="records" border v-loading="loading" size="small" style="width:100%" height="100%"> @@ -52,12 +43,8 @@ </el-table-column> </el-table> </div> <el-pagination style="margin-top:15px;text-align:right" background layout="total, prev, pager, next, sizes" :total="total" :current-page.sync="page" :page-size.sync="size" :page-sizes="[20, 50, 100]" @current-change="loadData" @size-change="loadData"> </el-pagination> </div> </el-main> </el-container> </el-container> @@ -99,7 +86,7 @@ period: '', keyword: '', page: 1, size: 20, size: 50, total: 0, records: [], columns: [], @@ -126,9 +113,14 @@ if (!g.types.some(t => t.value === this.type)) { this.type = g.types[0].value } this.doQuery() }, onTypeSelect() { this.doQuery() }, doQuery() { this.page = 1 this.records = [] this.loadData() }, onTypeSelect() { this.loadData() }, loadData() { this.loading = true this.loadingMore = false @@ -262,43 +254,14 @@ .type-row { margin-bottom: 10px; display: flex; align-items: center; gap: 10px; flex-wrap: wrap; } .type-label { color: #606266; font-weight: 600; } .filter-row { margin-bottom: 4px; } #app .table-wrap { display: flex; flex-direction: column; height: calc(100vh - 330px); min-height: 300px; } #app .table-area { flex: 1 1 auto; min-height: 0; overflow: hidden; } #app .table-area .el-table { width: 100%; height: 100%; } #app .table-wrap .el-pagination { flex: none; margin-top: 8px; } #app .table-area:fullscreen { padding: 20px; background: #fff; overflow: auto; } #app .table-wrap:fullscreen { padding: 20px; background: #fff; overflow: auto; display: flex; flex-direction: column; height: 100vh; } #app .table-wrap:fullscreen .table-area { flex: 1 1 auto; min-height: 0; } #app .table-wrap:fullscreen .el-pagination { flex: none; } #app .toolbar { display:flex; align-items:center; gap:10px; flex-wrap:wrap; padding:8px 12px; background:#FAFAFA; border:1px solid #EBEEF5; border-radius:8px; margin-bottom:8px; } #app .toolbar-label { color:#606266; font-weight:600; white-space:nowrap; } #app .toolbar-sep { width:1px; height:22px; background:#DCDFE6; margin:0 2px; } #app .load-hint { color:#909399; font-size:12px; margin-bottom:6px; } #app .table-wrap { display:flex; flex-direction:column; height:calc(100vh - 250px); min-height:300px; } #app .table-area { flex:1 1 auto; min-height:0; overflow:hidden; } #app .table-area .el-table { width:100%; height:100%; } #app .table-area:fullscreen { padding:20px; background:#fff; overflow:auto; } #app .table-wrap:fullscreen { padding:20px; background:#fff; overflow:auto; display:flex; flex-direction:column; height:100vh; } #app .table-wrap:fullscreen .table-area { flex:1 1 auto; min-height:0; } </style> traffic-audit-web/src/views/ReportExport.vue
@@ -112,7 +112,25 @@ <span v-if="!it.ready" class="cov-bad" style="margin-left:10px">{{ it.note }}</span> <span v-if="it.ready && it.audited === false" class="cov-bad" style="margin-left:10px">æªå®¡æ ¸</span> </div> <table class="preview-summary" v-if="it.summary && it.summary.length"> <table class="preview-summary wb-table" v-if="it.key === 'summaryWorkbook' && it.summary && it.summary.length"> <thead> <tr><th style="width:44%">ææ </th><th style="width:30%">æ°æ®</th><th>忝</th></tr> </thead> <tbody> <template v-for="(sec, si) in wbRows(it.summary)"> <tr v-for="(row, ri) in sec.rows" :key="si + '-' + ri"> <td v-if="ri === 0" :rowspan="sec.rows.length" class="wb-sec">{{ sec.name }}</td> <td class="wb-label">{{ row.label }}</td> <td class="wb-value">{{ row.value === null ? 'â' : fmtVal(row.value) }}</td> <td class="wb-yoy" :class="{ 'yoy-empty': row.yoy === null }">{{ row.yoy === null ? 'â' : row.yoy }}</td> </tr> </template> </tbody> </table> <div v-if="it.key === 'summaryWorkbook' && wbMissing(it.summary)" class="wb-note"> é¨åææ ç¼ºå°ä¸å¹´åæï¼{{ wbPrevYear() }}ï¼åºææ°æ®ï¼åæ¯ææªè®¡ç® </div> <table class="preview-summary" v-else-if="it.summary && it.summary.length"> <tbody> <tr v-for="(s, i) in it.summary" :key="i"> <td>{{ s.label }}</td> @@ -380,6 +398,65 @@ } return String(v) }, wbRows(summary) { const get = (key) => { const hit = (summary || []).find(x => x.label === key) return hit && hit.value !== null && hit.value !== undefined && hit.value !== '' ? hit.value : null } const pct = (key) => { const v = get(key) return v === null ? null : this.fmtVal(v) + '%' } const mk = (defs) => defs.map(d => ({ label: d[0], value: get(d[1]), yoy: d[2] ? pct(d[2]) : null })) return [ { name: 'é路货è¿', rows: mk([ ['å½æè´§è¿é(ä¸å¨)', 'å ¨çè´§è¿éÂ·å½æ'], ['å½æè´§ç©å¨è½¬é(ä¸å¨)', 'å ¨çè´§ç©å¨è½¬éÂ·å½æ', 'å ¨çè´§ç©å¨è½¬éÂ·å½æåæ¯'], ['累计货è¿é(ä¸å¨)', 'å ¨çè´§è¿é·累计'], ['累计货ç©å¨è½¬é(ä¸å¨å ¬é)', 'å ¨çè´§ç©å¨è½¬é·累计', 'å ¨çè´§ç©å¨è½¬éÂ·ç´¯è®¡åæ¯'] ]) }, { name: 'åå¸å®¢è¿', rows: mk([ ['彿åå¸å®¢è¿é:', 'åå¸å®¢è¿éÂ·å½æ'], ['彿åå¸å®¢è¿å¨è½¬é', 'åå¸å®¢è¿å¨è½¬éÂ·å½æ'], ['累计åå¸å®¢è¿é:', 'åå¸å®¢è¿é·累计'], ['累计åå¸å®¢è¿å¨è½¬é', 'åå¸å®¢è¿å¨è½¬é·累计'] ]) }, { name: 'ä¸å£å¾', rows: mk([ ['彿ä¸å£å¾å®¢è¿é', 'ä¸å£å¾å®¢è¿éÂ·å½æ'], ['彿ä¸å£å¾å¨è½¬é', 'ä¸å£å¾å¨è½¬éÂ·å½æ'], ['累计ä¸å£å¾å®¢è¿é', 'ä¸å£å¾å®¢è¿é·累计'], ['累计ä¸å£å¾å¨è½¬é', 'ä¸å£å¾å¨è½¬é·累计'] ]) } ] }, wbMissing(summary) { let total = 0 let have = 0 ;(summary || []).forEach(x => { if (String(x.label).indexOf('忝') >= 0) return total++ if (x.value !== null && x.value !== undefined && x.value !== '') have++ }) return total > 0 && have < total }, wbPrevYear() { const m = /^(\d{4})-(\d{2})$/.exec(this.previewPeriod || '') if (!m) return 'ä¸å¹´åæ' return (Number(m[1]) - 1) + '-' + m[2] }, coverageText(it) { const cov = it.monthCoverage || [] if (!cov.length) return 'æ æ°æ®' @@ -494,4 +571,11 @@ @media (max-width: 900px) { .panel-head { flex-direction: column; align-items: flex-start; } } .wb-table th { background:#f5f7fa; } .wb-sec { background:#F7F9FC; font-weight:600; text-align:center; color:#303133; } .wb-label { color:#303133; } .wb-value { text-align:right; font-variant-numeric: tabular-nums; } .wb-yoy { text-align:right; color:#606266; } .wb-yoy.yoy-empty { color:#C0C4CC; } .wb-note { color:#E6A23C; font-size:12px; margin:2px 0 8px; } </style>