| docs/功能测试报告/功能测试报告_导入清空按类型与按钮防误触_2026-09-10.md | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| docs/工作日结/工作日结_2026-09-10.md | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| traffic-audit-server/src/main/java/com/trafficaudit/dataimport/controller/DataImportController.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| traffic-audit-server/src/main/java/com/trafficaudit/dataimport/service/DataImportService.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| traffic-audit-web/src/views/DataImport.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
docs/¹¦ÄܲâÊÔ±¨¸æ/¹¦ÄܲâÊÔ±¨¸æ_µ¼ÈëÇå¿Õ°´ÀàÐÍÓë°´Å¥·ÀÎó´¥_2026-09-10.md
New file @@ -0,0 +1,42 @@ # åè½æµè¯æ¥åï¼æ°æ®å¯¼å ¥é¡µâæ¸ ç©ºæ°æ®âå¢å¼ºï¼æç±»åæ¸ ç©º + æé®ç§»åºå·æ°è¡é²è¯¯è§¦ï¼ 2026-09-10 ## åè½è¯´æ - æ°æ®å¯¼å ¥é¡µå³ä¾§âå¯¼å ¥è¿åº¦âä¾§æ å¨åâå·æ°âæå»æâæ¸ ç©ºâï¼æ¹ä¸ºå¨ä¾§æ æ é¢è¡ä¸æ¹æ°å¢ç¬ç«å±é©æä½åºï¼æµ çº¢åº + è¾¹æ¡ï¼ï¼å å« `el-button type="danger" plain` çâæ¸ ç©ºæ°æ®â¦âæé®ä¸è¯´æâææ¥è¡¨ææ¸ åºï¼ç¨äºæ´æé导âï¼ä¸âå·æ°âç©çåå¼ï¼éä½è¯¯è§¦ã - æ°å¢æ¸ 空弹çªï¼æ¾ç¤ºå½åæ¥è¡¨æï¼éæ©âæ¸ ç©ºè¯¥æ¥è¡¨æå ¨é¨å·²å¯¼å ¥æ°æ®âæâåªæ¸ 空æå®ç±»åâï¼éç±»åæ¶ç¨ `el-select multiple filterable`ï¼æåç»ååºå¯éç±»åå¹¶æ æ³¨âï¼å·²å¯¼å ¥ N è¡/æªå¯¼å ¥ï¼âï¼åºé¨çº¢è²è¦ç¤ºè¯è¯´æä¼åæ¥å é¤å®¡æ ¸ç»æãå·²å®¡æ ¸æ è®°ä¸å¯¼å ¥æ¹æ¬¡ï¼æèµé¡¹ç®ä¸»æ¡£ä¿çï¼ä¸ä¸å¯æ¤éã - å端 `POST /api/import/clear` å¢å å¯éåæ° `types`ï¼éå·åéï¼ï¼ä¸ºç©º = æ¸ ç©ºè¯¥æ¥è¡¨æå ¨é¨ç±»åï¼åè¡ä¸ºä¸åï¼ï¼é空 = åªæ¸ 空æå®æ°æ®ç±»åï¼å¹¶åæ¥æ¸ çå ¶å ³èç audit_result / audit_run / import_batchã ## æ¶åæ¹å¨ - å端 `DataImportService`ï¼`clearPeriod(period, types)` éè½½ï¼æ°å¢éææ å° `CLEAR_TYPE_TO_OP`ï¼ç±»åâæ°æ®è¡¨æä½é®ï¼å表å½å¹¶å»éï¼ã`CLEAR_TYPE_TO_AUDIT`ï¼ç±»åâå®¡æ ¸è§åç±»åï¼ã`CLEAR_TYPE_TO_BATCH`ï¼ç±»åâimportTypeï¼ï¼æ°å¢ `clearTypeData(op, period)` åæ´¾ä¸ `deleteInvestmentMonthly(period, category)`ï¼æèµæåº¦æé¡¹ç®ç±»å«è¿æ»¤ï¼ä» å æ¬ææç»ï¼æèµä¸»æ¡£ä¿çï¼ãè¿å弿°å¢ `scope` ä¸ `types`ï¼ä¾¿äºå端æç¤ºæ¸ 空èå´ã - å端 `DataImportController`ï¼`clearData` å¢å `types` åæ°è§£æï¼ç©ºä¸²/空项忽ç¥ï¼ã - å端 `DataImport.vue`ï¼ç§»é¤ `.side-head-btns` 䏿§ `clearPeriodData()`ï¼æ°å¢ `.side-danger` å±é©æä½åºãæ¸ ç©ºå¼¹çªã`openClearDialog()/clearableGroups()/confirmClear()` ä¸ `clearDialog/clearScope/clearTypes` ç¶æï¼ç¡®è®¤ååèµ°ä¸æ¬¡ `$confirm` äºæ¬¡ç¡®è®¤ï¼æåæç¤ºå¸¦å é¤è¡æ°ã ## æµè¯ç¯å¢ - å端ï¼traffic-audit-server 8090ï¼å«æ¬æ¬¡æ¹å¨ï¼`start-dev.ps1` å¯å¨ï¼PID 21884ï¼å¯å¨æ¶é´ 2026-09-10 08:54:02ï¼å è½½ `target/classes` ææ°ç¼è¯äº§ç©ï¼ã - å端ï¼traffic-audit-web 8080 devï¼`frontend.log` æè¿ä¸æ¬¡ `Compiled successfully in 347ms`ï¼08:53:29ï¼ï¼çæ´æ°å·²çæã - æ°æ®åºï¼æ¬æº MySQL `localhost:3308/traffic_audit`ï¼mysql CLI ç´æ¥æ ¸å¯¹ï¼ç»å½è´¦å· `admin/123456`ã - æµè¯æ°æ®ï¼ä¸æ¬¡æ§æµè¯æ `2099-01 / 2099-02`ï¼ä½¿ç¨ `docs/è´§è¿éå¯¼å ¥çæ°æ®/è´§è¿/2026å¹´1-7ææ¥/é路货ç©è¿è¾æåº¦ç产æ åµï¼2026å¹´6æï¼.xls`ï¼636 è¡ï¼ä¸ 2026-07 åå¸å ¬äº¤æ ·æ¬ï¼çå®æä»½ä» ååå½å¯¹æ¯ï¼ä¸è¢«åå ¥æå é¤ã ## ç¨ä¾è¡¨ | # | ç¨ä¾ | è¾å ¥ | 颿 | å®é | ç»è®º | |---|---|---|---|---|---| | 1 | ç¼è¯ | `mvn -o -q compile` | éè¿ | æ æ¥é | éè¿ | | 2 | æ£å-æç±»åæ¸ ç©º | `POST /import/clear?period=2099-01&types=h2032` | åªå h2032 åå ¶ H2032 å®¡æ ¸ç»æ/æ¹æ¬¡ | dataRows=636ãauditRows=31ãauditRunRows=1ãbatchRows=1ï¼DB æ ¸å¯¹ h2032=0ãH2032 è§åå®¡æ ¸ç»æ=0ãaudit_run(H2032)=0ãæ¹æ¬¡(H2032)=0 | éè¿ | | 3 | é离æ§-å ¶å®ç±»åä¸åå½±å | åä¸ï¼æ¸ h2032 忥 cityBus | cityBus æ°æ®ä¸å®¡æ ¸/æ¹æ¬¡ä¿ç | cityBus ä¸å¡ 142 è¡ãCITY_BUS å®¡æ ¸ 53 è¡ãaudit_run(CITY_BUS)=1ãæ¹æ¬¡(CITY_BUS)=1 åä¿ç | éè¿ | | 4 | é离æ§-å ¶å®æ¥è¡¨æä¸åå½±å | åä¸ï¼æ¥ 2099-02 | 2099-02 æ°æ®ä¸åå½±å | 2099-02 æ°æ®å®å¥½ | éè¿ | | 5 | è´å-éæ³ç±»å | `types=notAType` | æç»å¹¶æç¤º | HTTP 500ï¼`æ¸ ç©ºå¤±è´¥: æªæå®ææçæ°æ®ç±»å` | éè¿ | | 6 | è¾¹ç-ææ+æªç¥æ··å | `types=cityBus,notAType` | å¿½ç¥æªç¥ãæææç±»åæ§è¡ | æåï¼è¿å `scope=types, types=[cityBus,notAType]`ï¼å é¤ 0 è¡ï¼è¯¥ææ æ°æ®ï¼ | éè¿ | | 7 | è¾¹ç-空类åå表 | ä¸ä¼ `types` | æå ¨é¨ç±»åæ¸ ç©ºï¼åè¡ä¸ºï¼ | æåï¼`scope=all` | éè¿ | | 8 | æèµæç±»å« | æå ¥ 2099-01 客è¿ç«åº/ç©æµååºæµè¯è¡åå嫿¸ 空 | åªå 对åºç±»å«ï¼æèµä¸»æ¡£ä¿ç | `types=investment` åªå 客è¿ç«åºã`types=investmentLogistics` åªå ç©æµååºï¼`investment_project` 主档ä¿ç | éè¿ | | 9 | UI-æé®ä½ç½® | æå¼æ°æ®å¯¼å ¥é¡µï¼å±å¼âå¯¼å ¥è¿åº¦â | âå·æ°âææ æ¸ ç©ºï¼æ¸ 空æé®å¨ç¬ç«çº¢è²å±é©åº | ä¸é¢æä¸è´ï¼å¯è®¿é®æ§æ å¯è¯»å°âæ¸ ç©ºæ°æ®â¦âæé®ä¸æç¤ºææ¡ï¼ | éè¿ | | 10 | UI-å¼¹çªé项 | ç¹âæ¸ ç©ºæ°æ®â¦â | å¼¹çªå«æ¥è¡¨æãå ¨é¨/æå®ç±»ååéãç±»åä¸æå¸¦å¯¼å ¥ç¶æ | éä¸âé路货ç©è¿è¾æåº¦ç产æ åµï¼å·²å¯¼å ¥ 636 è¡ï¼âï¼é项æ ç¾ä¸ç¶æä¸è´ | éè¿ | | 11 | UI-ç¡®è®¤æ¸ ç©º | éä¸ h2032 åç¹âç¡®è®¤æ¸ ç©ºâ | äºæ¬¡ç¡®è®¤ â æåæç¤ºå«è¡æ°ãè¿åº¦åâæªå¯¼å ¥â | æç¤ºâå·²æ¸ ç©º 2099-01 æ°æ®ï¼ä¸å¡æ°æ® 636 è¡ãå®¡æ ¸ç»æ 0 è¡ãå¯¼å ¥æ¹æ¬¡ 1 æ¡ï¼å¯ä»¥éæ°å¯¼å ¥âï¼è¿åº¦åâæªå¯¼å ¥â | éè¿ | | 12 | åå½-ç宿份 | æ¸ ç©ºååå¯¹æ¯ | æ åå | 2099-01 æ®ç=0ï¼2026-09=636ã2026-07=636ã2025-07=664 æªåï¼ç宿¹æ¬¡æ»æ° 239 æªå | éè¿ | ## åç°çé®é¢ä¸å¤ç½® - æ åè½æ§ç¼ºé·ãæµè¯ææ°æ®å¨éªè¯ç»æåå·²å ¨é¨æ¸ é¤ï¼æªæ®çã - 说æï¼ä¿çç¹æ§ï¼ï¼ä¸æ¬¡æ¸ 空ä¼å é¤è¯¥æ¥è¡¨æâå ¨é¨ç±»åâçä¸å¡æ°æ®åå®¡æ ¸ç»æ/å·²å®¡æ ¸æ è®°/å¯¼å ¥æ¹æ¬¡ï¼å¼¹çªå·²ç¨çº¢è²ææ¡æç¤ºä¸å¯æ¤éï¼åªæ³æ¸ åä¸ç±»åæ¶ä½¿ç¨âåªæ¸ 空æå®ç±»åâï¼æªå¯¼å ¥çç±»åä»å¯å¾éä½ä¸äº§çå é¤ã - ç¯å¢å¤æ³¨ï¼æ¬æºåº `admin` å¯ç 为 `123456`ï¼`admin123` 卿¬æºä¸å¹é ï¼ã ## ç»è®º - éè¿ãâæ¸ ç©ºæ°æ®â¦âå·²ä»âå·æ°âæç§»åºå¹¶åè§è§é离ï¼å¼¹çªæ¯æææ´æææç±»åæ¸ ç©ºï¼æ¥å£æèå´ç²¾ç¡®å é¤ä¸å¡æ°æ®ãå®¡æ ¸ç»æãå·²å®¡æ ¸æ è®°ä¸å¯¼å ¥æ¹æ¬¡ï¼ä¸å¯¹å ¶å®ç±»åãå ¶å®æ¥è¡¨æä¸ç宿份é¶å½±åã - å¾ ç¨æ·å¨èªå·±æµè§å¨éªæ¶ä¸æ¬¡æé®ä½ç½®ä¸å¼¹çªææ¡ã docs/¹¤×÷ÈÕ½á/¹¤×÷ÈÕ½á_2026-09-10.md
@@ -19,5 +19,25 @@ - å¾ ç¨æ·å®é æµè§å¨éªæ¶âæ¸ ç©ºâæé®ï¼å»ºè®®å 确认æéæ¥è¡¨æä¸å¤ä»½ï¼ï¼å¦éåªæ¸ æä¸æ°æ®ç±»åï¼å¯åç»åâæç±»åæ¸ ç©ºâã - æ²¿ç¨æ¨æ¥æªå¨å¾ åï¼æ±æ»å¤§è¡¨ M3ï¼ç½çº¦è½¦å°è´¦åæ°ãè´§è¿é¡µ FreightCalc è§ä¸/è§ä¸ãåå¸å®¢è¿/ä¸å£å¾åæé¡µï¼ä¸â9 æ+æ æ¯çèªå¨æ©åâï¼8 æä»ç¼º 4 ç±»æºæ°æ®è¡¨è¡ï¼freight_turnover_importãscale_split_transportãpassenger_individual_monthlyãç½çº¦è½¦æåè¾å ¥ï¼ã ## ä¸åï¼2026-09-10ï¼æ¸ 空åè½å¢å¼ºï¼æ¯ææç±»åæ¸ ç©º + æ¸ ç©ºæé®ç§»åºâå·æ°âé²è¯¯è§¦ ### 宿å 容 - ç¨æ·åé¦âæ¸ ç©ºæ¾å¨å·æ°æè¾¹æè¯¯è§¦âï¼ä¸éè¦è½åªæ¸ æä¸æ°æ®ç±»åï¼ææ¸ ç©ºä»ä¾§æ æ é¢è¡ï¼å·æ°æï¼ç§»é¤ï¼æ¹å°æ é¢è¡ä¸æ¹ç¬ç«çº¢è²å±é©æä½åºï¼æµ çº¢åº + è¾¹æ¡ï¼âæ¸ ç©ºæ°æ®â¦âæé® + æç¤ºâææ¥è¡¨ææ¸ åºï¼ç¨äºæ´æé导âï¼ï¼ä¸å·æ°ç©çéå¼ã - æ°å¢æ¸ 空弹çªï¼åéâæ¸ ç©ºå ¨é¨ / åªæ¸ 空æå®ç±»åâï¼æå®ç±»åç¨å¤é䏿并æåç»ååºãæ ç¾å¸¦âï¼å·²å¯¼å ¥ N è¡/æªå¯¼å ¥ï¼âï¼åºé¨çº¢è²è¦ç¤ºè¯´æä¼åæ¥å å®¡æ ¸ç»æãå·²å®¡æ ¸æ è®°ãå¯¼å ¥æ¹æ¬¡ï¼æèµé¡¹ç®ä¸»æ¡£ä¿çï¼ä¸ä¸å¯æ¤éï¼ç¡®è®¤ååèµ°ä¸æ¬¡äºæ¬¡ç¡®è®¤ã - å端 `POST /api/import/clear` å¢å å¯é `types`ï¼éå·åéï¼ï¼ç©º=æ´æå ¨æ¸ ï¼åè¡ä¸ºä¸åï¼ï¼é空=åªæ¸ æå®ç±»åï¼å¹¶åæ¥æ¸ çå ³è audit_result/audit_run/import_batchï¼è¿åå¼å¢å `scope` ä¸ `types`ãæ°å¢ç±»åâ表/å®¡æ ¸ç±»å/æ¹æ¬¡ç±»åä¸å¼ éææ å°ä¸ `clearTypeData` åæ´¾ï¼æèµæåº¦æé¡¹ç®ç±»å«è¿æ»¤ï¼ä¸»æ¡£ä¿çï¼ã ### æµè¯ç»ææè¦ - ç¨ä¸æ¬¡æ§æµè¯æ 2099-01/2099-02 éªè¯ï¼æ¸ h2032 â dataRows=636ãauditRows=31ãauditRunRows=1ãbatchRows=1ï¼DB æ ¸å¯¹å表对åºè®°å½å ¨ 0ï¼åæç cityBus ä¸å¡ 142 è¡ãCITY_BUS å®¡æ ¸ 53 è¡ãaudit_run 䏿¹æ¬¡åä¿çï¼2099-02 æ°æ®ä¸åå½±åã - è´åï¼`types=notAType` â 500âæªæå®ææçæ°æ®ç±»åâï¼ææ+æªç¥æ··å â å¿½ç¥æªç¥ææææ§è¡ï¼ä¸ä¼ types â æ´æå ¨æ¸ ã - æèµç±»å«ï¼`types=investment` åªå 客è¿ç«åºã`types=investmentLogistics` åªå ç©æµååºï¼æèµä¸»æ¡£ä¿çã - UI 宿µï¼åºç¨å æµè§å¨ï¼admin ç»å½ï¼ï¼âå·æ°âæå·²æ æ¸ ç©ºï¼æ°å±é©åºæé®ä¸å¼¹çªææ¡æ£å¸¸ï¼éä¸âé路货ç©è¿è¾æåº¦ç产æ åµï¼å·²å¯¼å ¥ 636 è¡ï¼â确认åæç¤ºâå·²æ¸ ç©º 2099-01 æ°æ®ï¼ä¸å¡æ°æ® 636 è¡ãå®¡æ ¸ç»æ 0 è¡ãå¯¼å ¥æ¹æ¬¡ 1 æ¡ï¼å¯ä»¥éæ°å¯¼å ¥âï¼è¿åº¦åâæªå¯¼å ¥âã - åå½ï¼æµè¯ææ æ®çï¼ç宿份 2026-09=636ã2026-07=636ã2025-07=664 ä¸ç宿¹æ¬¡æ»æ° 239 åæªåã - å端 `mvn -o -q compile` éè¿ï¼æå¡å·²éå¯ï¼PID 21884ï¼08:54 å¯å¨ï¼ï¼å端 dev `Compiled successfully`ã - æµè¯æ¥åï¼docs/åè½æµè¯æ¥å/åè½æµè¯æ¥å_å¯¼å ¥æ¸ ç©ºæç±»å䏿é®é²è¯¯è§¦_2026-09-10.mdã ### éçé®é¢ä¸å¾ å - å¾ ç¨æ·å¨èªå·±æµè§å¨éªæ¶æ°æé®ä½ç½®ä¸å¼¹çªææ¡ï¼å¦ä»è§å¾å±é©åºå¤ªæ¾ç¼å¯åæ¶è¿âæ´å¤æä½âæå ã - æ²¿ç¨æªå¨å¾ åï¼æ±æ»å¤§è¡¨ M3ï¼ç½çº¦è½¦å°è´¦åæ°ãè´§è¿é¡µ FreightCalc è§ä¸/è§ä¸ãåå¸å®¢è¿/ä¸å£å¾åæé¡µï¼ä¸â9 æ+æ æ¯çèªå¨æ©åâï¼8 æä»ç¼º 4 ç±»æºæ°æ®è¡¨è¡ï¼freight_turnover_importãscale_split_transportãpassenger_individual_monthlyãç½çº¦è½¦æåè¾å ¥ï¼ã ## éï¼æäº¤ - æ¬æ¬¡æ¹å¨ 3 ä¸ªä»£ç æä»¶ + æ¬æ¥å䏿¥ç»ï¼æè§èå `git fetch gitea/origin` 对æ¯åå¹¶ï¼å commit å¹¶å端æ¨éï¼gitea mainã个人 gitee masterï¼ã - æ¬æ¬¡æ¹å¨ 3 ä¸ªä»£ç æä»¶ + åè½æµè¯æ¥å䏿¥ç»ï¼æè§èå `git fetch gitea/origin` 对æ¯åå¹¶ï¼å commit å¹¶å端æ¨éï¼gitea mainã个人 gitee masterï¼ã traffic-audit-server/src/main/java/com/trafficaudit/dataimport/controller/DataImportController.java
@@ -443,14 +443,25 @@ return Result.ok(result); } /** æ¸ ç©ºæå®æ¥è¡¨æå ¨é¨å·²å¯¼å ¥æ°æ®ä¸å®¡æ ¸ç»æï¼æ°æ®å¯¼å ¥é¡µ"æ¸ ç©º"æé®è°ç¨ï¼ï¼ä¾¿äºæ´æéæ°å¯¼å ¥ */ /** * æ¸ ç©ºæå®æ¥è¡¨æå·²å¯¼å ¥æ°æ®ä¸å®¡æ ¸ç»æï¼æ°æ®å¯¼å ¥é¡µ"æ¸ ç©ºæ°æ®"å ¥å£è°ç¨ï¼ï¼ä¾¿äºæ´æéæ°å¯¼å ¥ã * types ä¸ºç©ºè¡¨ç¤ºæ¸ ç©ºè¯¥æ¥è¡¨æå ¨é¨ç±»åï¼å¦ååªæ¸ 空æå®æ°æ®ç±»åï¼éå·åéï¼å¦ h2032,cityBusï¼ã */ @PostMapping("/clear") public Result<Map<String, Object>> clearData(@RequestParam("period") String period) { public Result<Map<String, Object>> clearData(@RequestParam("period") String period, @RequestParam(value = "types", required = false) String types) { try { Map<String, Object> stats = importService.clearPeriod(period); List<String> typeList = new java.util.ArrayList<>(); if (types != null) { for (String t : types.split(",")) { String s = t.trim(); if (!s.isEmpty()) typeList.add(s); } } Map<String, Object> stats = importService.clearPeriod(period, typeList); return Result.ok(stats); } catch (Exception e) { log.error("clear period {} error", period, e); log.error("clear period {} types {} error", period, types, e); return Result.error("æ¸ ç©ºå¤±è´¥: " + e.getMessage()); } } traffic-audit-server/src/main/java/com/trafficaudit/dataimport/service/DataImportService.java
@@ -1317,13 +1317,100 @@ } } /** æ¸ ç©ºæå®æ¥è¡¨æå ¨é¨å·²å¯¼å ¥æ°æ®ä¸å®¡æ ¸ç»æï¼å«å¯¼å ¥æ¹æ¬¡ãå®¡æ ¸éè¿æ è®°ï¼ï¼ç¨äºæ´æéå¯¼ï¼æèµé¡¹ç®ä¸»æ¡£ä¿ç */ /** æ¯æâæç±»åæ¸ ç©ºâçæ°æ®ç±»å -> æ°æ®è¡¨æä½é®ï¼å表åç±»å«å½å¹¶ï¼é¿å éå¤å é¤ï¼ */ private static final Map<String, String> CLEAR_TYPE_TO_OP = new LinkedHashMap<>(); /** æ°æ®ç±»å -> å ³èå®¡æ ¸è§åç±»åï¼åæ¥æ¸ é¤å®¡æ ¸ç»æä¸å·²å®¡æ ¸æ è®°ï¼ */ private static final Map<String, String[]> CLEAR_TYPE_TO_AUDIT = new HashMap<>(); /** æ°æ®ç±»å -> å ³èå¯¼å ¥æ¹æ¬¡ importTypeï¼åæ¥æ¸ é¤å¯¼å ¥æ¹æ¬¡è®°å½ï¼ */ private static final Map<String, String[]> CLEAR_TYPE_TO_BATCH = new HashMap<>(); static { CLEAR_TYPE_TO_OP.put("h2032", "H2032"); CLEAR_TYPE_TO_OP.put("transportAuth", "TRANSPORT_AUTH"); CLEAR_TYPE_TO_OP.put("trackMileage", "TRACK_MILEAGE"); CLEAR_TYPE_TO_OP.put("scaleSplit", "SCALE_SPLIT"); CLEAR_TYPE_TO_OP.put("freightTurnover", "FREIGHT_TURNOVER"); CLEAR_TYPE_TO_OP.put("passengerMonthly", "H2031"); CLEAR_TYPE_TO_OP.put("passengerAuth", "PASSENGER_AUTH"); CLEAR_TYPE_TO_OP.put("passengerIndividual", "PASSENGER_INDIVIDUAL"); CLEAR_TYPE_TO_OP.put("energyMonthly", "H204"); CLEAR_TYPE_TO_OP.put("energyAuth", "ENERGY_AUTH"); CLEAR_TYPE_TO_OP.put("investment", "INVEST_MONTHLY_PASSENGER"); CLEAR_TYPE_TO_OP.put("investCityPassenger", "INVEST_MONTHLY_PASSENGER"); CLEAR_TYPE_TO_OP.put("investmentLogistics", "INVEST_MONTHLY_LOGISTICS"); CLEAR_TYPE_TO_OP.put("investCityLogistics", "INVEST_MONTHLY_LOGISTICS"); CLEAR_TYPE_TO_OP.put("investmentSystem", "INVEST_SYSTEM"); CLEAR_TYPE_TO_OP.put("cityBus", "CITY_BUS"); CLEAR_TYPE_TO_OP.put("cityTaxi", "CITY_TAXI"); CLEAR_TYPE_TO_OP.put("cityTaxiAuth", "CITY_TAXI_AUTH"); CLEAR_TYPE_TO_OP.put("wycTotal", "WYC_TOTAL"); CLEAR_TYPE_TO_OP.put("wycOrder", "WYC_ORDER"); CLEAR_TYPE_TO_AUDIT.put("h2032", new String[]{"H2032"}); CLEAR_TYPE_TO_AUDIT.put("transportAuth", new String[]{"H2032"}); CLEAR_TYPE_TO_AUDIT.put("trackMileage", new String[]{"H2032"}); CLEAR_TYPE_TO_AUDIT.put("scaleSplit", new String[]{"H2032"}); CLEAR_TYPE_TO_AUDIT.put("freightTurnover", new String[]{"H2032"}); CLEAR_TYPE_TO_AUDIT.put("passengerMonthly", new String[]{"H2031"}); CLEAR_TYPE_TO_AUDIT.put("passengerAuth", new String[]{"H2031"}); CLEAR_TYPE_TO_AUDIT.put("passengerIndividual", new String[]{"H2031"}); CLEAR_TYPE_TO_AUDIT.put("energyMonthly", new String[]{"H204"}); CLEAR_TYPE_TO_AUDIT.put("energyAuth", new String[]{"H204"}); CLEAR_TYPE_TO_AUDIT.put("investment", new String[]{"INVEST"}); CLEAR_TYPE_TO_AUDIT.put("investmentLogistics", new String[]{"INVEST"}); CLEAR_TYPE_TO_AUDIT.put("investCityPassenger", new String[]{"INVEST"}); CLEAR_TYPE_TO_AUDIT.put("investCityLogistics", new String[]{"INVEST"}); CLEAR_TYPE_TO_AUDIT.put("investmentSystem", new String[]{"INVEST"}); CLEAR_TYPE_TO_AUDIT.put("cityBus", new String[]{"CITY_BUS"}); CLEAR_TYPE_TO_AUDIT.put("cityTaxi", new String[]{"CITY_TAXI"}); CLEAR_TYPE_TO_AUDIT.put("cityTaxiAuth", new String[]{"CITY_TAXI"}); String[] investPassengerBatch = {"INVEST_客è¿ç«åº", "INVEST_客è¿ç«åº_CITY"}; String[] investLogisticsBatch = {"INVEST_ç©æµååº", "INVEST_ç©æµååº_CITY"}; CLEAR_TYPE_TO_BATCH.put("h2032", new String[]{"H2032"}); CLEAR_TYPE_TO_BATCH.put("transportAuth", new String[]{"TRANSPORT_AUTH"}); CLEAR_TYPE_TO_BATCH.put("trackMileage", new String[]{"TRACK_MILEAGE"}); CLEAR_TYPE_TO_BATCH.put("scaleSplit", new String[]{"SCALE_SPLIT"}); CLEAR_TYPE_TO_BATCH.put("freightTurnover", new String[]{"FREIGHT_TURNOVER"}); CLEAR_TYPE_TO_BATCH.put("passengerMonthly", new String[]{"H2031"}); CLEAR_TYPE_TO_BATCH.put("passengerAuth", new String[]{"PASSENGER_AUTH"}); CLEAR_TYPE_TO_BATCH.put("passengerIndividual", new String[]{"PASSENGER_INDIVIDUAL"}); CLEAR_TYPE_TO_BATCH.put("energyMonthly", new String[]{"H204"}); CLEAR_TYPE_TO_BATCH.put("energyAuth", new String[]{"ENERGY_AUTH"}); CLEAR_TYPE_TO_BATCH.put("investment", investPassengerBatch); CLEAR_TYPE_TO_BATCH.put("investCityPassenger", investPassengerBatch); CLEAR_TYPE_TO_BATCH.put("investmentLogistics", investLogisticsBatch); CLEAR_TYPE_TO_BATCH.put("investCityLogistics", investLogisticsBatch); CLEAR_TYPE_TO_BATCH.put("investmentSystem", new String[]{"INVEST_SYSTEM"}); CLEAR_TYPE_TO_BATCH.put("cityBus", new String[]{"CITY_BUS"}); CLEAR_TYPE_TO_BATCH.put("cityTaxi", new String[]{"CITY_TAXI"}); CLEAR_TYPE_TO_BATCH.put("cityTaxiAuth", new String[]{"CITY_TAXI_AUTH"}); CLEAR_TYPE_TO_BATCH.put("wycTotal", new String[]{"WYC_TOTAL"}); CLEAR_TYPE_TO_BATCH.put("wycOrder", new String[]{"WYC_ORDER"}); } /** * æ¸ ç©ºæå®æ¥è¡¨æå·²å¯¼å ¥æ°æ®ä¸å®¡æ ¸ç»æï¼ç¨äºæ´æéå¯¼ï¼æèµé¡¹ç®ä¸»æ¡£ä¿çã * * @param types 鿏 ç©ºçæ°æ®ç±»åï¼å端类åé®ï¼å¦ h2032/cityBusï¼ï¼ä¸ºç©ºåæ¸ ç©ºè¯¥æ¥è¡¨æå ¨é¨ç±»å */ @Transactional(rollbackFor = Exception.class) public Map<String, Object> clearPeriod(String period) { public Map<String, Object> clearPeriod(String period, List<String> types) { if (period == null || !period.matches("\\d{4}-\\d{2}")) { throw new IllegalArgumentException("æ¥è¡¨ææ ¼å¼ä¸æ£ç¡®ï¼åºä¸º yyyy-MM"); } Set<String> selected = new LinkedHashSet<>(); if (types != null) { for (String t : types) { if (t != null && !t.trim().isEmpty()) selected.add(t.trim()); } } boolean clearAll = selected.isEmpty(); int dataRows = 0; int auditRows = 0; int auditRunRows = 0; int batchRows = 0; if (clearAll) { dataRows += h2032Mapper.delete(new LambdaQueryWrapper<H2032EnterpriseMonthly>() .eq(H2032EnterpriseMonthly::getReportPeriod, period)); dataRows += transportAuthMapper.delete(new LambdaQueryWrapper<TransportAuthVehicle>() @@ -1358,23 +1445,145 @@ .eq(WycTotalMonthly::getReportPeriod, period)); dataRows += wycOrderMapper.delete(new LambdaQueryWrapper<WycOrderMonthly>() .eq(WycOrderMonthly::getReportPeriod, period)); int auditRows = auditResultMapper.delete(new LambdaQueryWrapper<AuditResult>() auditRows = auditResultMapper.delete(new LambdaQueryWrapper<AuditResult>() .eq(AuditResult::getReportPeriod, period)); int auditRunRows = auditRunMapper.delete(new LambdaQueryWrapper<AuditRun>() auditRunRows = auditRunMapper.delete(new LambdaQueryWrapper<AuditRun>() .eq(AuditRun::getReportPeriod, period)); int batchRows = importBatchMapper.delete(new LambdaQueryWrapper<ImportBatch>() batchRows = importBatchMapper.delete(new LambdaQueryWrapper<ImportBatch>() .eq(ImportBatch::getReportPeriod, period)); } else { Set<String> ops = new LinkedHashSet<>(); Set<String> auditTypes = new LinkedHashSet<>(); Set<String> batchTypes = new LinkedHashSet<>(); for (String t : selected) { String op = CLEAR_TYPE_TO_OP.get(t); if (op == null) { log.warn("æ¸ ç©ºæ°æ®ï¼æªç¥æ°æ®ç±»å {}ï¼å·²å¿½ç¥", t); continue; } ops.add(op); String[] at = CLEAR_TYPE_TO_AUDIT.get(t); if (at != null) java.util.Collections.addAll(auditTypes, at); String[] bt = CLEAR_TYPE_TO_BATCH.get(t); if (bt != null) java.util.Collections.addAll(batchTypes, bt); } if (ops.isEmpty()) { throw new IllegalArgumentException("æªæå®ææçæ°æ®ç±»å"); } for (String op : ops) { dataRows += clearTypeData(op, period); } if (!auditTypes.isEmpty()) { List<Long> ruleIds = new ArrayList<>(); for (com.trafficaudit.rulemanage.entity.AuditRule rule : ruleMapper.selectList(null)) { if (rule.getReportType() != null && auditTypes.contains(rule.getReportType())) { ruleIds.add(rule.getId()); } } if (!ruleIds.isEmpty()) { auditRows = auditResultMapper.delete(new LambdaQueryWrapper<AuditResult>() .eq(AuditResult::getReportPeriod, period) .in(AuditResult::getRuleId, ruleIds)); } for (String rt : auditTypes) { auditRunRows += auditRunMapper.delete(new LambdaQueryWrapper<AuditRun>() .eq(AuditRun::getReportPeriod, period) .eq(AuditRun::getReportType, rt)); } } if (!batchTypes.isEmpty()) { batchRows = importBatchMapper.delete(new LambdaQueryWrapper<ImportBatch>() .eq(ImportBatch::getReportPeriod, period) .in(ImportBatch::getImportType, batchTypes)); } } Map<String, Object> stats = new LinkedHashMap<>(); stats.put("period", period); stats.put("scope", clearAll ? "all" : "types"); if (!clearAll) stats.put("types", new ArrayList<>(selected)); stats.put("dataRows", dataRows); stats.put("auditRows", auditRows); stats.put("auditRunRows", auditRunRows); stats.put("batchRows", batchRows); log.info("æ¸ ç©ºæ¥è¡¨æ {} 宿ï¼ä¸å¡æ°æ® {} è¡ãå®¡æ ¸ç»æ {} è¡ãå®¡æ ¸æ è®° {} è¡ãå¯¼å ¥æ¹æ¬¡ {} è¡", period, dataRows, auditRows, auditRunRows, batchRows); log.info("æ¸ ç©ºæ¥è¡¨æ {}ï¼{}ï¼å®æï¼ä¸å¡æ°æ® {} è¡ãå®¡æ ¸ç»æ {} è¡ãå®¡æ ¸æ è®° {} è¡ãå¯¼å ¥æ¹æ¬¡ {} è¡", period, clearAll ? "å ¨é¨ç±»å" : String.join(",", selected), dataRows, auditRows, auditRunRows, batchRows); return stats; } /** æâæ°æ®è¡¨æä½é®âæ¸ ç©ºå¯¹åºä¸å¡è¡¨ï¼æèµæåº¦æé¡¹ç®ç±»å«è¿æ»¤ï¼ï¼è¿åå é¤è¡æ° */ private int clearTypeData(String op, String period) { switch (op) { case "H2032": return h2032Mapper.delete(new LambdaQueryWrapper<H2032EnterpriseMonthly>() .eq(H2032EnterpriseMonthly::getReportPeriod, period)); case "TRANSPORT_AUTH": return transportAuthMapper.delete(new LambdaQueryWrapper<TransportAuthVehicle>() .eq(TransportAuthVehicle::getReportPeriod, period)); case "TRACK_MILEAGE": return trackMileageMapper.delete(new LambdaQueryWrapper<VehicleTrackMileage>() .eq(VehicleTrackMileage::getReportPeriod, period)); case "SCALE_SPLIT": return scaleSplitMapper.delete(new LambdaQueryWrapper<ScaleSplitTransport>() .eq(ScaleSplitTransport::getReportPeriod, period)); case "FREIGHT_TURNOVER": return freightTurnoverMapper.delete(new LambdaQueryWrapper<FreightTurnoverImport>() .eq(FreightTurnoverImport::getReportPeriod, period)); case "H2031": return passengerMapper.delete(new LambdaQueryWrapper<PassengerEnterpriseMonthly>() .eq(PassengerEnterpriseMonthly::getReportPeriod, period)); case "PASSENGER_AUTH": return passengerAuthMapper.delete(new LambdaQueryWrapper<PassengerAuthVehicle>() .eq(PassengerAuthVehicle::getReportPeriod, period)); case "PASSENGER_INDIVIDUAL": return passengerIndividualMapper.delete(new LambdaQueryWrapper<PassengerIndividualMonthly>() .eq(PassengerIndividualMonthly::getReportPeriod, period)); case "H204": return energyMapper.delete(new LambdaQueryWrapper<EnergyVehicleQuarterly>() .eq(EnergyVehicleQuarterly::getReportPeriod, period)); case "ENERGY_AUTH": return energyAuthMapper.delete(new LambdaQueryWrapper<EnergyAuthVehicle>() .eq(EnergyAuthVehicle::getReportPeriod, period)); case "INVEST_MONTHLY_PASSENGER": return deleteInvestmentMonthly(period, "客è¿ç«åº"); case "INVEST_MONTHLY_LOGISTICS": return deleteInvestmentMonthly(period, "ç©æµååº"); case "INVEST_SYSTEM": return investSystemMapper.delete(new LambdaQueryWrapper<InvestmentSystem>() .eq(InvestmentSystem::getReportPeriod, period)); case "CITY_BUS": return cityBusMapper.delete(new LambdaQueryWrapper<CityBusMonthly>() .eq(CityBusMonthly::getReportPeriod, period)); case "CITY_TAXI": return cityTaxiMapper.delete(new LambdaQueryWrapper<CityTaxiMonthly>() .eq(CityTaxiMonthly::getReportPeriod, period)); case "CITY_TAXI_AUTH": return cityTaxiAuthMapper.delete(new LambdaQueryWrapper<CityTaxiAuth>() .eq(CityTaxiAuth::getReportPeriod, period)); case "WYC_TOTAL": return wycTotalMapper.delete(new LambdaQueryWrapper<WycTotalMonthly>() .eq(WycTotalMonthly::getReportPeriod, period)); case "WYC_ORDER": return wycOrderMapper.delete(new LambdaQueryWrapper<WycOrderMonthly>() .eq(WycOrderMonthly::getReportPeriod, period)); default: log.warn("æ¸ ç©ºæ°æ®ï¼æªç¥æ°æ®è¡¨æä½ {}", op); return 0; } } /** æèµæåº¦æé¡¹ç®ç±»å«æ¸ é¤ï¼æèµé¡¹ç®ä¸»æ¡£ä¿çï¼ */ private int deleteInvestmentMonthly(String period, String category) { List<Long> projectIds = new ArrayList<>(); for (InvestmentProject p : investProjectMapper.selectList(new LambdaQueryWrapper<InvestmentProject>() .eq(InvestmentProject::getCategory, category))) { projectIds.add(p.getId()); } if (projectIds.isEmpty()) return 0; return investMonthlyMapper.delete(new LambdaQueryWrapper<InvestmentMonthly>() .eq(InvestmentMonthly::getReportPeriod, period) .in(InvestmentMonthly::getProjectId, projectIds)); } /** æ°æ®åååå 餿宿¥è¡¨ç±»åæå®æ¥è¡¨æçå®¡æ ¸ç»æï¼ééæ°æ§è¡å®¡æ ¸ï¼ */ private void deleteRuleResults(String reportType, String period) { List<Long> ruleIds = new ArrayList<>(); traffic-audit-web/src/views/DataImport.vue
@@ -103,11 +103,12 @@ <div v-show="sideOpen" class="side-content"> <div class="side-head"> <span>æ¬æå¯¼å ¥è¿åº¦ï¼{{ period || 'æªéæ©æ¥è¡¨æ' }}ï¼</span> <span class="side-head-btns"> <el-button type="text" icon="el-icon-refresh" @click="loadData">å·æ°</el-button> <el-button type="text" icon="el-icon-delete" style="color:#F56C6C" :loading="clearing" :disabled="!period || clearing || importing" @click="clearPeriodData">æ¸ ç©º</el-button> </span> </div> <div v-if="period" class="side-danger"> <el-button size="mini" type="danger" plain icon="el-icon-delete" :disabled="clearing || importing" @click="openClearDialog">æ¸ ç©ºæ°æ®â¦</el-button> <span class="side-danger-tip">ææ¥è¡¨ææ¸ åºï¼ç¨äºæ´æé导</span> </div> <div v-if="!period" class="tip">请å å¨ä¸æ¹éæ©æ¥è¡¨æ</div> <div v-else class="overview-grid"> @@ -123,6 +124,32 @@ </div> </div> </div> <el-dialog title="æ¸ ç©ºæ°æ®" :visible.sync="clearDialog" width="560px" append-to-body :close-on-click-modal="false"> <div class="clear-dlg"> <div class="clear-period">æ¥è¡¨æï¼<b>{{ period }}</b></div> <el-radio-group v-model="clearScope"> <el-radio label="all">æ¸ ç©ºè¯¥æ¥è¡¨æå ¨é¨å·²å¯¼å ¥æ°æ®</el-radio> <el-radio label="types">åªæ¸ 空æå®ç±»å</el-radio> </el-radio-group> <div v-if="clearScope === 'types'" class="clear-types"> <el-select v-model="clearTypes" multiple filterable collapse-tags placeholder="éæ©è¦æ¸ ç©ºçæ°æ®ç±»å" style="width:100%"> <el-option-group v-for="g in clearableGroups()" :key="g.key" :label="g.name"> <el-option v-for="t in g.types" :key="t.value" :value="t.value" :label="t.label + 'ï¼' + overviewState(t.value).text + 'ï¼'"></el-option> </el-option-group> </el-select> <div class="tip" style="margin-top:6px">å¯å¤éï¼æªå¯¼å ¥çç±»åæ²¡ææ°æ®å¯å ã</div> </div> <div class="clear-warn"> å°å 餿éèå´å 该æ¥è¡¨æçæ°æ®åºæ°æ®ï¼å¹¶åæ¥å é¤å¯¹åºå®¡æ ¸ç»æãå·²å®¡æ ¸æ è®°ä¸å¯¼å ¥æ¹æ¬¡è®°å½ï¼æèµé¡¹ç®ä¸»æ¡£ä¿çï¼ãæ¤æä½ä¸å¯æ¤éï¼è¯·ç¡®è®¤å·²æå¤ä»½æåå¤éæ°å¯¼å ¥ã </div> </div> <span slot="footer"> <el-button @click="clearDialog = false">åæ¶</el-button> <el-button type="danger" :loading="clearing" :disabled="clearScope === 'types' && !clearTypes.length" @click="confirmClear">ç¡®è®¤æ¸ ç©º</el-button> </span> </el-dialog> </el-main> </el-container> </el-container> @@ -163,6 +190,9 @@ cityDirLoading: false, importing: false, clearing: false, clearDialog: false, clearScope: 'all', clearTypes: [], sideOpen: false, result: '', error: '', @@ -525,19 +555,35 @@ .catch(e => { if (!e || !e._toast) this.$message.error('å¯¼å ¥è®°å½å 载失败ï¼è¯·å·æ°éè¯') }) .finally(() => { this.batchLoading = false }) }, clearPeriodData() { openClearDialog() { if (!this.period) { this.$message.warning('请å éæ©æ¥è¡¨æ'); return } if (this.importing) { this.$message.warning('æ£å¨å¯¼å ¥æ°æ®ï¼è¯·çå¾ å¯¼å ¥å®æå忏 空'); return } this.clearScope = 'all' this.clearTypes = [] this.clearDialog = true }, clearableGroups() { return this.groups.filter(g => !g.hidden) }, confirmClear() { if (!this.period) { this.$message.warning('请å éæ©æ¥è¡¨æ'); return } if (this.clearing) return this.$confirm( 'å°æ¸ 空 ' + this.period + ' æ¥è¡¨æå¨æ°æ®åºä¸çå ¨é¨å·²å¯¼å ¥æ°æ®ï¼åæ¶å é¤è¯¥æ¥è¡¨æçå®¡æ ¸ç»æä¸å¯¼å ¥æ¹æ¬¡è®°å½ï¼ä¾¿äºæ´æéæ°å¯¼å ¥ï¼ã\næ¤æä½ä¸å¯æ¤éï¼æ¯å¦ç»§ç»ï¼', 'æ¸ ç©º ' + this.period + ' æ°æ®', { type: 'warning', confirmButtonText: 'ç¡®è®¤æ¸ ç©º', cancelButtonText: 'åæ¶' } ).then(() => { this.clearing = true api.post('/import/clear', null, { params: { period: this.period }, timeout: 600000 }) if (this.clearScope === 'types' && !this.clearTypes.length) { this.$message.warning('è¯·éæ©è¦æ¸ ç©ºçæ°æ®ç±»å'); return } const scopeText = this.clearScope === 'all' ? '该æ¥è¡¨æå ¨é¨å·²å¯¼å ¥æ°æ®' : 'ä»¥ä¸ ' + this.clearTypes.length + ' 个类åï¼' + this.clearTypes.map(t => this.typeLabel(t)).join('ã') this.$confirm('å°æ¸ 空 ' + this.period + ' ç' + scopeText + 'ï¼å¹¶åæ¥å é¤å¯¹åºå®¡æ ¸ç»æãå·²å®¡æ ¸æ è®°ä¸å¯¼å ¥æ¹æ¬¡è®°å½ãæ¤æä½ä¸å¯æ¤éï¼æ¯å¦ç»§ç»ï¼', 'æ¸ ç©ºç¡®è®¤', { type: 'warning', confirmButtonText: 'ç¡®è®¤æ¸ ç©º', cancelButtonText: 'åæ¶' }) .then(() => { this.$message.success('å·²æ¸ ç©º ' + this.period + ' æ¥è¡¨æçæ°æ®ï¼å¯ä»¥éæ°å¯¼å ¥') this.clearing = true const params = { period: this.period } if (this.clearScope === 'types') params.types = this.clearTypes.join(',') return api.post('/import/clear', null, { params, timeout: 600000 }) .then(res => { const d = (res && res.data) || {} this.$message.success('å·²æ¸ ç©º ' + this.period + ' æ°æ®ï¼ä¸å¡æ°æ® ' + (d.dataRows || 0) + ' è¡ãå®¡æ ¸ç»æ ' + (d.auditRows || 0) + ' è¡ãå¯¼å ¥æ¹æ¬¡ ' + (d.batchRows || 0) + ' æ¡ï¼å¯ä»¥éæ°å¯¼å ¥') this.clearDialog = false this.loadData() }) .catch(e => { @@ -618,8 +664,12 @@ .import-side.side-open .side-toggle-text { writing-mode: horizontal-tb; letter-spacing: normal; margin-top: 0; } .side-content { padding: 8px 12px 12px; max-height: calc(100vh - 220px); overflow-y: auto; overscroll-behavior: contain; } .side-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-weight: 600; margin-bottom: 6px; } .side-head-btns { display: flex; align-items: center; gap: 2px; flex-shrink: 0; } .side-head-btns .el-button + .el-button { margin-left: 0; } .side-danger { display: flex; align-items: center; gap: 8px; margin: 4px 0 10px; padding: 6px 8px; background: #FEF0F0; border: 1px solid #FDE2E2; border-radius: 4px; } .side-danger-tip { font-size: 12px; color: #F56C6C; line-height: 1.3; } .clear-dlg { line-height: 1.7; } .clear-period { margin-bottom: 6px; } .clear-types { margin-top: 10px; } .clear-warn { margin-top: 12px; padding: 8px 10px; background: #FEF0F0; border: 1px solid #FDE2E2; border-radius: 4px; color: #F56C6C; font-size: 12px; line-height: 1.6; } .import-side .overview-grid { display: block; } .import-side .ov-row { display: block; margin-bottom: 6px; } .import-side .ov-group { width: auto; }