3个文件已删除
12个文件已修改
18个文件已添加
| | |
| | | ('è½¦è¾æ°è¿æ¿å¯¹æ¯', 'RULE_001', 'ä¼ä¸ä¸æ¥è½¦è¾æ°ä¸è¿æ¿æ°æ®å¯¹æ¯ï¼å·®è·>5å°éæ ¸å®', 'vehicleTotal', 'DIFF', '5', 'RED', 'H2032', 1, 1), |
| | | ('å¨ä½è¿æ¿å¯¹æ¯', 'RULE_002', 'ä¼ä¸ä¸æ¥å¨ä½ä¸è¿æ¿æ°æ®å¯¹æ¯ï¼å·®è·>50éæ ¸å®', 'tonsTotal', 'DIFF', '50', 'RED', 'H2032', 1, 2), |
| | | ('å¨è½¬é轨迹对æ¯', 'RULE_003', '䏿¥å¨è½¬éä¸è½¨è¿¹æµç®å¨è½¬é对æ¯ï¼é«åº30%éæ ¸å®', 'turnoverTotal,trackMileage', 'RATIO', '1.3', 'RED', 'H2032', 1, 3), |
| | | ('è´§è¿ç±»åç¯æ¯', 'RULE_004', 'æ¬ææ°å¢è´§è¿ç±»åéæ ¸å®ï¼ä¸æä¸º0ãæ¬ææéï¼', 'freightContainer,freightCoal,freightOilGas,freightCrudeOil,freightMetalOre,freightIronOre,freightBuilding,freightGrain', 'MOM', '0', 'YELLOW', 'H2032', 1, 4), |
| | | ('è´§è¿ç±»åç¯æ¯', 'RULE_004', '䏿æ ï¼æ¬ææ°å¢ï¼æéï¼ä¸ææï¼æ¬ææ ï¼æéï¼è´§è¿ç±»åç¯æ¯ï¼', 'freightContainer,freightCoal,freightOilGas,freightCrudeOil,freightMetalOre,freightIronOre,freightBuilding,freightGrain', 'MOM', '0', 'YELLOW', 'H2032', 1, 4), |
| | | ('éè£
ç®±å¼å¸¸', 'RULE_005', 'æ éè£
ç®±è½¦ä½æéè£
箱货è¿ééæ ¸å®', 'freightContainer,vehicleContainer', 'NULL_CHECK', '0', 'RED', 'H2032', 1, 5), |
| | | ('æ´è½¦å¨ä½èå´', 'RULE_006', 'æ´è½¦å¨ä½ä¸å¨4-40å¨ä¹é´', 'tonsWhole', 'OUT_RANGE', '4,40', 'YELLOW', 'H2032', 1, 6); |
| | | |
| | |
| | | ('è½½å®¢ä½æ°è¿æ¿å¯¹æ¯(æ
客)', 'RULE_P002', 'æ ¸å®è½½å®¢ä½æ°ä¸è¿æ¿è½½å®¢ä½æ°å¯¹æ¯ï¼å·®è·>50éæ ¸å®', 'seatTotal', 'DIFF', '50', 'RED', 'H2031', 1, 22), |
| | | ('客è¿éç¯æ¯=0æ ¸å®', 'RULE_P003', 'ä¸ç±»/äºç±»/ä¸ç±»/åç±»/å
车客è¿éç¯æ¯ä¸ä¸ªæçäº0éæ ¸å®', 'passengerClass1,passengerClass2,passengerClass3,passengerClass4,passengerCharter', 'MOM_EQ_ZERO', '0', 'YELLOW', 'H2031', 1, 23), |
| | | ('æ
客å¨è½¬éç¯æ¯=0æ ¸å®', 'RULE_P004', 'ä¸ç±»/äºç±»/ä¸ç±»/åç±»/å
车æ
客å¨è½¬éç¯æ¯ä¸ä¸ªæçäº0éæ ¸å®', 'turnoverClass1,turnoverClass2,turnoverClass3,turnoverClass4,turnoverCharter', 'MOM_EQ_ZERO', '0', 'YELLOW', 'H2031', 1, 24), |
| | | ('å¹³åè¿è·ç¯æ¯è¶
±10%æ ¸å®', 'RULE_P005', 'ä¸ç±»/äºç±»/ä¸ç±»/å类平åè¿è·ç¯æ¯ä¸ä¸ªæè¶
è¿Â±10%éæ ¸å®', 'avgDistanceClass1,avgDistanceClass2,avgDistanceClass3,avgDistanceClass4', 'MOM_PCT', '10', 'YELLOW', 'H2031', 1, 25), |
| | | ('å¹³åè¿è·ç¯æ¯è¶
±20%æ ¸å®', 'RULE_P005', 'ä¸ç±»/äºç±»/ä¸ç±»/å类平åè¿è·ç¯æ¯ä¸ä¸ªæè¶
è¿Â±20%éæ ¸å®', 'avgDistanceClass1,avgDistanceClass2,avgDistanceClass3,avgDistanceClass4', 'MOM_PCT', '20', 'YELLOW', 'H2031', 1, 25), |
| | | ('å
车平åè¿è·çäºä¸ææ ¸å®', 'RULE_P006', 'æ
游å
车平åè¿è·çäºä¸ä¸ªæéæ ¸å®', 'avgDistanceCharter', 'MOM_EQ', '0', 'YELLOW', 'H2031', 1, 26), |
| | | ('æ ç线æç线客è¿éæ ¸å®', 'RULE_P007', 'æ 客è¿ç车ï¼ççº¿è½¦è¾æ°ä¸º0ï¼ä½æç线客è¿ééæ ¸å®', 'vehicleSchedule,passengerClass1,passengerClass2,passengerClass3,passengerClass4', 'EXISTENCE', '0', 'RED', 'H2031', 1, 27), |
| | | ('æ å
车æå
车客è¿éæ ¸å®', 'RULE_P008', 'æ 客è¿å
车ï¼å
è½¦è½¦è¾æ°ä¸º0ï¼ä½æå
车客è¿ééæ ¸å®', 'vehicleCharter,passengerCharter', 'EXISTENCE', '0', 'RED', 'H2031', 1, 28); |
| New file |
| | |
| | | # åè½æµè¯æ¥åï¼M1-åå¸å®¢è¿ å
¬äº¤/åºç§/轨é轮渡 åæ°æ ¸å¯¹ä¸ 7 æåå½ï¼2026-09-08ï¼ |
| | | |
| | | ## ä¸ãåè½è¯´æ |
| | | M1 第äºåï¼æ°å¢åå¸å®¢è¿è®¡ç®æå¡ `PaxCalc`ï¼`traffic-audit-server/.../reportexport/calc/PaxCalc.java`ï¼ï¼å¯¹ å
¬äº¤/巡游åºç§/轨é/轮渡 æä¾âæ â å¸å· â [客è¿é,å¨è½¬é,åå¸å
客è¿é,åå¸å
å¨è½¬é]ï¼è½¨é轮渡=轨é客è¿é,轨éå¨è½¬é,轮渡客è¿é,轮渡å¨è½¬éï¼âç©éµï¼ä¸æ¢æ exportCityBusDetail / exportCityTaxiDetail / exportCityRailFerryDetail çåæ°é»è¾åæï¼ä¾æ±æ»å¤§è¡¨ä¸å°è¡¨å
±ç¨ã |
| | | |
| | | ## äºãæµè¯ç¯å¢ |
| | | - åºï¼`traffic_audit`ï¼127.0.0.1:3308ï¼ï¼æ°æ® = 2026-07 ç°ç¶ï¼ |
| | | - 对账æ¯çï¼`docs/çææ±æ»å¤§è¡¨/_å¤ä»½_2026å¹´7æéè·¯è¿è¾éæ±æ»è¡¨_æ¸
çå_20260904.xlsx`ï¼å« 5-7 ææ°æ®çå·²ä¿®æ£æ¯çï¼`2026å¹´7æéè·¯è¿è¾éæ±æ»è¡¨.xlsx` 为 1-4 æç©ºéª¨æ¶ï¼ä¸å« 7 æå°è´¦åï¼ï¼ |
| | | - å·¥å
·ï¼mysql CLI + Python éç® vs æ¯ç O åï¼2026-07ï¼ï¼å端 `mvn -q -DskipTests compile` éè¿ã |
| | | |
| | | ## ä¸ãåæ°å£å¾ï¼ä¸æ¢æå¯¼åºä¸è´ï¼ |
| | | | å°è´¦é¡µ | æ¥æº | è¡ç»æï¼O å 2026-07ï¼ | |
| | | |---|---|---| |
| | | | å
¬äº¤ | `city_bus_monthly` æ city æ±æ» [passenger_volume,turnover,passenger_city,turnover_city] | å
¨ç r5-8ï¼å¸å· r(9+4i)..r(12+4i)ï¼å®¢è¿é/å¨è½¬é/åå¸å
客è¿é/åå¸å
å¨è½¬éï¼ | |
| | | | åºç§ | `city_taxi_monthly` ååæ®µ | å å
¬äº¤ | |
| | | | 轨éã轮渡 | `city_bus_monthly` ç rail_*/ferry_*ï¼è½¨é=æ¦æ±/é»ç³ï¼è½®æ¸¡=æ¦æ±ï¼ | 轨é r6/7=æ¦æ±ãr8/9=é»ç³ï¼è½®æ¸¡ r15/16=æ¦æ±ï¼å
¨ç=å计å
¬å¼ | |
| | | | å
¨ç | 17 å¸å·ä¹åï¼å«è·¨åºå¿å¤è¡ç´¯å ï¼ | æ¯çå
¨çè¡å
¬å¼ | |
| | | |
| | | ## åãç¨ä¾è¡¨ |
| | | | # | ç¨ä¾ | è¾å
¥ | 颿 | å®é
| ç»è®º | |
| | | |---|---|---|---|---|---| |
| | | | 1 | å
¬äº¤å°è´¦é¡µ 2026-07 | DB 2026-07 æ city æ±æ» | 䏿¯ç O å 18 è¡åï¼å
¨ç+17 å¸å·Ã4 ææ ï¼ä¸è´ | diff=0 | éè¿ | |
| | | | 2 | åºç§å°è´¦é¡µ 2026-07 | DB 2026-07 æ city æ±æ» | åä¸ | diff=0 | éè¿ | |
| | | | 3 | 轨éå°è´¦é¡µ 2026-07 | city_bus rail åæ®µï¼æ¦æ±/é»ç³ï¼ | æ¦æ± 11701.74/96240.86ãé»ç³ 30.09/404.37ãå
¨ç 11731.83 | ä¸è´ï¼0 diffï¼ | éè¿ | |
| | | | 4 | 轮渡å°è´¦é¡µ 2026-07 | city_bus ferry åæ®µï¼æ¦æ±ï¼ | å
¨ç=æ¦æ±=46.05ï¼å®¢è¿éï¼ | ä¸è´ï¼0 diffï¼ | éè¿ | |
| | | | 5 | Java ç¼è¯ | `mvn -q -DskipTests compile` | æ é误 | exit=0 | éè¿ | |
| | | |
| | | ## äºãåç°çé®é¢ä¸å¤ç½® |
| | | 1. 注éå
åºç° `rail_*/ferry_*`ï¼å
¶ä¸ `*/` æåç»æ¢ Javadoc åæ³¨é导è´ç¼è¯å¤±è´¥ â æ¹ä¸ºârail ä¸ ferry åæ®µâï¼ç¼è¯éè¿ï¼æ¬é®é¢ä»
影忳¨éåæ³ï¼ä¸å£å¾æ å
³ï¼ã |
| | | 2. 对账æ¯çéæ©ï¼`2026å¹´7æâ¦æ±æ»è¡¨.xlsx` æ¯ 1-4 æç©ºéª¨æ¶ï¼å°è´¦é¡µæ 5-7 æåï¼ï¼7 æå°è´¦æ°å¼é¡»ä»¥ `_å¤ä»½_â¦_æ¸
çå_20260904.xlsx` 为åºçº¿ââ已卿µè¯ç¯å¢æ³¨æï¼M2 å彿¶ç»ä¸ç¨è¯¥å¤ä»½æä»¶ã |
| | | 3. æ°æ®ä¾§å£å¾å¤æ ¸ï¼æ éæ¹å¨ï¼ï¼å¸å·åå¨å¤ä¸ªåºå¿ä»£ç è¡ï¼é¡»æ city æ±æ»ç´¯å ï¼ä¸ Java æ¢æå®ç°ä¸è´ï¼ã |
| | | |
| | | ## å
ãç»è®ºä¸ä¸ä¸æ¥ |
| | | - ç»è®ºï¼å
¬äº¤/åºç§/轨é/轮渡 7 æå°è´¦å¯ä»åºå®æ´å¤ç®ï¼0 å·®å¼ï¼ï¼`PaxCalc` å·²å
¥åºå¹¶éè¿ç¼è¯ã |
| | | - ä¸ä¸æ¥ï¼M1-ç½çº¦è½¦ï¼WyCSplitCalcï¼è®¢åÃå
¨ç pinÃ巡游åºç§æåï¼â åå¸å®¢è¿å°è´¦/å叿±æ»/åå¸åå¸å· 7 æåå½ â M1-MidCalc â M2 SummaryFiller ååä¸éæ ¼ diffã |
| New file |
| | |
| | | # åè½æµè¯æ¥åï¼M1-åå¸å®¢è¿ å叿±æ»æ´é¾åå½ï¼C7ï¼2026-09-08ï¼ |
| | | |
| | | ## ä¸ãåè½è¯´æ |
| | | éªè¯âå
¬äº¤/巡游åºç§/ç½çº¦è½¦/轨é/轮渡 â å叿±æ»âçæ´é¾å¯å¤ç®æ§ï¼å£å¾ C7ï¼ï¼æ»å®¢è¿éï¼å¨è½¬éï¼=å
¬äº¤åå¸å
+åºç§è½¦(巡游åå¸å
+ç½çº¦åå¸å
)+轨éå轮渡ï¼å
¨é¨ç®åå¸å
ï¼ãå
¬äº¤/åºç§å city_bus/city_taxi ç passenger_city/turnover_cityï¼ç½çº¦å WycSplitCalc pinï¼pinCK/pinCZï¼ï¼è½¨é轮渡å city_bus rail/ferry åæ®µââåä¸ºå½æå¼ä¸ 1-7 æç´¯è®¡å¼ä¸¤ç»ã |
| | | |
| | | ## äºãæµè¯ç¯å¢ |
| | | - åºï¼`traffic_audit`ï¼2026-01~07ï¼ï¼ç½çº¦ pinï¼`docs/åå¸å®¢è¿/模æ¿_ç½çº¦è½¦è®¢ååå
¨çæ»é.xlsx`ï¼1-7 æè¡é½å
¨ï¼ï¼ |
| | | - 对账æ¯çï¼`docs/çææ±æ»å¤§è¡¨/_å¤ä»½_2026å¹´7æéè·¯è¿è¾éæ±æ»è¡¨_æ¸
çå_20260904.xlsx` å叿±æ»é¡µï¼ |
| | | - å·¥å
·ï¼mysql CLI + openpyxl + Python éè¡æ¯å¯¹ï¼å®¹å·® 0.011ã |
| | | |
| | | ## ä¸ãç¨ä¾ä¸ç»æ |
| | | | å | æ¯å¯¹èå´ | ç»æ | |
| | | |---|---|---| |
| | | | 彿åï¼2026-07ï¼r14-20ï¼ | æ»/å
¬äº¤/åºç§è½¦/巡游/ç½çº¦/轨é/轮渡 à 客è¿é(B)+å¨è½¬é(D) | 0 å·®å¼ | |
| | | | 累计åï¼2026-1-7ï¼r3-9ï¼ | åä¸ | 0 å·®å¼ | |
| | | |
| | | å
³é®æ°å¼å½ä¸ï¼å½ææ» 33068.03 / 206194.82ï¼å
¬äº¤ 11508.07 / 59265.28ï¼å·¡æ¸¸ 5351.24 / 27422.13ï¼ç½çº¦ 4430.84 / 22705.61ï¼=pinCK/pinCZï¼ï¼è½¨é 11731.83 / 96645.23ï¼è½®æ¸¡ 46.05 / 156.57ï¼ç´¯è®¡æ» 237412.33 / 1479655.10ã |
| | | |
| | | ## åãç»è®ºä¸è¯´æ |
| | | - C7 ç»åå£å¾å¯ç±åºæ´é¾å¤ç®å½æä¸ç´¯è®¡ä¸¤ç»ï¼0 å·®å¼ï¼ï¼ç½çº¦ pin 1-7 æè¾å
¥å®æ´ã |
| | | - åå¸å®¢è¿å°è´¦é¡µ/åå¸åå¸å·é¡µä¸ºè·¨å°è´¦é¡µå
¬å¼é¡µï¼å·²å¨å模å¼åå½ä¸é页éªè¯ 0 å·®å¼ï¼ï¼M2 æåæå
¬å¼/å¼ååå³å¯ï¼ä¸éåç¬å对ã |
| | | - M1-åå¸å®¢è¿æ´ä½éè¿ï¼å
¬äº¤/åºç§/轨é轮渡/ç½çº¦/å叿±æ» 5 项åå½ 0 å·®å¼ã |
| | | - ä¸ä¸æ¥ï¼M1-MidCalcï¼ç线å
车/ä¸å£å¾æç»/客è¿é/æå/åæ/éè·¯è¿è¾å¨è½¬éï¼ã |
| New file |
| | |
| | | # åè½æµè¯æ¥åï¼M1-ç线å
车ï¼MidCalc ä¼ä¸+个ä½åæ°ï¼ä¸ 7 æåå½ï¼2026-09-08ï¼ |
| | | |
| | | ## ä¸ãåè½è¯´æ |
| | | æ±æ»å¤§è¡¨æ°æ®é©±å¨æ¹é M1 第äºåï¼æâç线å
车页âçæ°æ®åºåæ°åºå为å¯å¤ç¨ Java è®¡ç®æå¡ |
| | | `MidCalc`ï¼`traffic-audit-server/.../reportexport/calc/MidCalc.java`ï¼ï¼è¾åº |
| | | âæ â å¸å·/å
¨ç â [客è¿é(å«ä¸ªä½), å¨è½¬é(å«ä¸ªä½), 个ä½å®¢è¿é, 个ä½å¨è½¬é]ï¼ä¸äºº/ä¸äººå
¬éï¼âã |
| | | 宿¯ä¸å£å¾æç»/æå/åæ/éè·¯è¿è¾å¨è½¬éçæ´¾ç页卿°æ®åºä¸å¯ä¸çå
¬è·¯ççº¿æ°æ®æºã |
| | | |
| | | ## äºãæµè¯ç¯å¢ |
| | | - åºï¼`traffic_audit`ï¼127.0.0.1:3308ï¼ï¼æ°æ® = 2026-01~07 已导å
¥ç°ç¶ï¼ |
| | | - æ¯çåºçº¿ï¼`docs/çææ±æ»å¤§è¡¨/_å¤ä»½_2026å¹´7æéè·¯è¿è¾éæ±æ»è¡¨_æ¸
çå_20260904.xlsx`ï¼ç线å
车页ï¼2026 æåº¦æ°å¼å C/E/G/I/K/M/O åå·²ç¼åï¼ï¼ |
| | | - å·¥å
·ï¼mysql CLI åæ° + Python éæ ¼æ¯å¯¹ï¼`_m1_mid_regress.py`ï¼ç»æ `_m1_mid_regress.txt`ï¼ï¼å端 `mvn -q -DskipTests compile` éè¿ï¼exit=0ï¼ã |
| | | |
| | | ## ä¸ãåæ°å£å¾ï¼ç»æ¯çéæ ¼åæ¨ç¡®è®¤ï¼2026-07 ä¸ 1-7 æå
¨é¨å½ä¸ï¼ |
| | | | æ¯çè¡ | å£å¾ | æ¥æº | |
| | | |---|---|---| |
| | | | 客è¿é / æ
客å¨è½¬éï¼ä¸äºº / ä¸äººå
¬éï¼ | **ä¼ä¸æ»è®¡ + 个ä½å¹¶å
¥** | `h2031_enterprise_monthly.passenger_total / turnover_total`ï¼äºº/人å
¬éï¼Ã·10000ï¼å å `passenger_individual_monthly.passenger_count / turnover` ÷10000 | |
| | | | å
¶ä¸ï¼ä¸ªä½å®¢è¿é / ä¸ªä½æ
客å¨è½¬é | ä¸ªä½æ° ÷10000 | ä»
é»ç³/è¥é³/èé¨/åæ/é»å/éå· 6 å¸ææ° | |
| | | | æ¹åçï¼å
¨çï¼è¡ | 17 å¸å·ä¹å | 䏿¯çâå
¨çè¡=Σåå¸è¡âå
¬å¼ä¸è´ | |
| | | | 忝 | ä¸è®¡ç® | Q1ï¼ä»¥æ¯çç¼å 2025 åç
§ç»ä¸ºåºåï¼ç±ååå±å¡«è¡¨æ¶è®¡ç® | |
| | | |
| | | ## åãç¨ä¾è¡¨ |
| | | | # | ç¨ä¾ | è¾å
¥ | 颿 | å®é
| ç»è®º | |
| | | |---|---|---|---|---|---| |
| | | | 1 | ä¼ä¸å®¢è¿é/å¨è½¬éï¼å«ä¸ªä½å¹¶å
¥ï¼ | åº 2026-01~07 | 䏿¯çç线å
车åå¸è¡â客è¿é/å¨è½¬éâåéæ ¼ä¸è´ | 350 æ ¼ diff=0 | éè¿ | |
| | | | 2 | å
¶ä¸ä¸ªä½å®¢è¿é/å¨è½¬é | åº 2026-01~07 | 䏿¯çâå
¶ä¸ä¸ªä½âè¡éæ ¼ä¸è´ï¼6 å¸ï¼ | å«äºä¸è¿° 350 æ ¼ï¼diff=0 | éè¿ | |
| | | | 3 | æ¹åçè¡ = Σ 17 å¸å· | åºæ±æ» | 䏿¯çå
¬å¼å£å¾ä¸è´ | ä¸è´ | éè¿ | |
| | | | 4 | ä¸å£å¾åæâå
¬è·¯ç线âéç¹ | åº 2026-07 / 1-7 累计 | 彿 1631.2013ã累计 11204.5406ï¼æ¯çç¼åå¼ï¼ | 1612.2015+18.9998=1631.2013ï¼11062.7993+141.7413=11204.5406 | éè¿ | |
| | | | 5 | ä¸å£å¾åæé¡µéç¹ï¼å½æ/ç´¯è®¡ï¼ | åº 2026-01~07 éç® | 彿 4028.3213ã累计 27524.4906 ååç±»ç»å | 彿 1631.2013/1466.66/509/421.46ã累计 11204.5406/10194.09/3640.95/2484.91ï¼å
¨é¨ä¸è´ | éè¿ | |
| | | | 6 | Java ç¼è¯ | `mvn -q -DskipTests compile` | æ é误 | exit=0 | éè¿ | |
| | | |
| | | ## äºãåç°çé®é¢ä¸å¤ç½® |
| | | 1. åçåå½è¯¯æâ客è¿éâè¡å½ä½çº¯ä¼ä¸æ°ï¼æ¯å¯¹åç°é»ç³ç 6 叿¯çå¼ = ä¼ä¸+个ä½ï¼å·®éæ°ä¸ºè¯¥å¸ä¸ªä½å¼ï¼ï¼ |
| | | ç»éæ ¼åæ¨ç¡®è®¤**ç线å
车â客è¿é/å¨è½¬éâå£å¾å«ä¸ªä½**ï¼âå
¶ä¸ä¸ªä½âè¡ä¸ºå
¶åé â å·²æå«ä¸ªä½å£å¾å®ç°å¹¶å¤è· 0 å·®å¼ã |
| | | 2. æ¯å¯¹èæ¬åæææ¯ç**ææ¬æ°å**å½ä½ç©ºå¼è·³è¿ï¼å
¬äº¤å°è´¦é¡µ 2026-06 M åä»¥ææ¬åå¨ï¼å¦ `'4970.63'`ï¼ï¼ |
| | | 导è´â累计åé
å乡å
¬äº¤âä¸åº¦è¯¯ç®ä¸º 8676.57ãä¸ä¸å£å¾åæé¡µ 10194.09 ä¸ç¬¦ï¼å·®éæ°ä¸º 6 æ 1517.52ï¼ã |
| | | å·²æ¹ä¸ºâææ¬âæ°å¼âå½ä¸åå¤ç®ï¼**ä¸å£å¾åæé¡µå½æ/累计ä¸åºéç®é项 0 å·®å¼ï¼å¹¶éæ§æ®å¼**ã |
| | | å®ç°æ³¨æï¼è¯»æ¯çç¼åä¸å¾å
¼å®¹ææ¬æ°åã |
| | | 3. ä¸å£å¾æå页**å·¦å**ï¼A..Hï¼æ ææ¬¡æ é¢ï¼æ°å¼ç»æ¯å¯¹ä¸ºéæ§éä½ï¼A å客è¿é=2026-01 彿å¼ã |
| | | E åå¨è½¬é=2026-02 彿å¼ï¼17 å¸å·éæ ¼å»åï¼ï¼**å³åï¼J..Rï¼1-7 æç´¯è®¡ï¼ä¸åºéç® 0 å·®å¼**ã |
| | | å¤ç½®ï¼M2 çææ¶å·¦ååºæ¹ä¸ºâ彿 2026-07âéç®ä¿®æ£ï¼å³å沿ç¨ç°æå£å¾å³å¯ã |
| | | |
| | | ## å
ãç»è®ºä¸ä¸ä¸æ¥ |
| | | - ç»è®ºï¼ç线å
车页å¯ä»åºå®æ´å¤ç®ï¼350 æ ¼ 0 å·®å¼ï¼ï¼å£å¾éå®ï¼`MidCalc` å·²å
¥åºå¹¶éè¿ç¼è¯ã |
| | | - ä¸ä¸æ¥ï¼â M1 å©ä½æ´¾ç页å£å¾æ ¸å¯¹ï¼æå/åæ/éè·¯è¿è¾å¨è½¬éï¼å»ºè®®é M2 éç®å®ç°ï¼ï¼â¡ M2 SummaryFiller |
| | | ååå°è´¦+æåé¡µå¹¶éæ ¼ diffï¼å«æå页左åâ彿 2026-07âéä½ä¿®æ£çéªè¯ï¼ï¼â¢ 8 æå®å¼¹ã |
| New file |
| | |
| | | # åè½æµè¯æ¥åï¼M1-ç½çº¦è½¦ WycSplitCalc åæ°/æåæ ¸å¯¹ä¸ 7 æåå½ï¼2026-09-08ï¼ |
| | | |
| | | ## ä¸ãåè½è¯´æ |
| | | M1 第ä¸åï¼æ°å¢ç½çº¦è½¦æåè®¡ç®æå¡ `WycSplitCalc`ï¼`traffic-audit-server/.../reportexport/calc/WycSplitCalc.java`ï¼ï¼æ exportWycSplit çæåç®æ³æ½æå¯å¤ç¨ç©éµï¼è¾å
¥=ãç½çº¦è½¦è®¢ååå
¨çæ»é.xlsxãï¼pin B-E + 17 å¸å·è®¢å G-Wï¼+ 巡游åºç§ææ¥ï¼DBï¼ï¼è¾åº 17 å¸å·+å
¨çç 客è¿é/åå¸å
客è¿é/å¨è½¬é/åå¸å
å¨è½¬éã便±æ»å¤§è¡¨ç½çº¦è½¦å°è´¦é¡µä¸åå¸å®¢è¿å页å
±ç¨ï¼å£å¾ B5ï¼ã |
| | | |
| | | ## äºãæµè¯ç¯å¢ |
| | | - åºï¼`traffic_audit`ï¼2026-07 ç°ç¶ï¼ï¼ |
| | | - è¾å
¥æä»¶ï¼`docs/åå¸å®¢è¿/模æ¿_ç½çº¦è½¦è®¢ååå
¨çæ»é.xlsx`ï¼æåº¦è¾å
¥ sheetï¼2026-07 è¡å¨ openpyxl 第 8 è¡ï¼ï¼ |
| | | - 对账æ¯çï¼`docs/çææ±æ»å¤§è¡¨/_å¤ä»½_2026å¹´7æéè·¯è¿è¾éæ±æ»è¡¨_æ¸
çå_20260904.xlsx` ç½çº¦è½¦å°è´¦é¡µï¼ |
| | | - å·¥å
·ï¼openpyxl + mysql CLI + Python å¤å»ç®æ³æ¯å¯¹ï¼å端 `mvn -q -DskipTests compile` éè¿ã |
| | | |
| | | ## ä¸ãç®æ³ï¼ä¸ exportWycSplit ä¸è´ï¼ |
| | | - C[i]=订åå æ¯Ãå
¨çç½çº¦è½¦å®¢è¿é pinKï¼F[i]=巡游åºç§åå¸å
客è¿é/客è¿éï¼åå¸å
å æ¯ä»£çï¼ï¼ |
| | | - åå¸å
Hï¼æ¦æ±=C0ÃF0ï¼ä¿æèªèº«ï¼ï¼å
¶ä½ = (CiÃFi)/(ΣGâC0F0) à (pinCKâC0F0)ï¼ |
| | | - å¨è½¬é Gl[i]=CiÃå¹³åè¿è· / Σ(CiÃå¹³åè¿è·) à pinZï¼åå¸å
å¨è½¬é Hl åæ³ï¼ç¨åå¸å
å¹³åè¿è·ãpinCZï¼ï¼ |
| | | - 巡游åºç§å¹³åè¿è·ç¼ºçæ¶æ å¨è½¬é/客è¿é å 2 ä½å°æ°å
åºã |
| | | |
| | | ## åãç¨ä¾è¡¨ |
| | | | # | ç¨ä¾ | è¾å
¥ | 颿 | å®é
| ç»è®º | |
| | | |---|---|---|---|---|---| |
| | | | 1 | 2026-07 æåï¼17 å¸å·Ã4 ææ ï¼ | 订å+pin+åºç§ DB | 䏿¯çç½çº¦è½¦å°è´¦ O åä¸è´ | diff=0 | éè¿ | |
| | | | 2 | å
¨çè¡ | pin è¾å
¥ | 客è¿é 4852.30 / å¨è½¬é 28348.02 / åå¸å
4430.84 / åå¸å
å¨è½¬ 22705.61 | 䏿¯çä¸è´ | éè¿ | |
| | | | 3 | å æ»èªæ´½ | è®¡ç®æ°ç» | ΣC=pinKãΣH=pinCKãΣGl=pinZãΣHl=pinCZ | å
¨ç | éè¿ | |
| | | | 4 | æ¦æ±å£å¾ | è®¡ç® | åå¸å
=æ»éï¼æ åé
å乡ï¼ï¼H=1825.1975ãHl=13036.3929 | ä¸è´ | éè¿ | |
| | | | 5 | Java ç¼è¯ | `mvn -q -DskipTests compile` | æ é误 | exit=0 | éè¿ | |
| | | |
| | | ## äºãåç°çé®é¢ä¸å¤ç½® |
| | | 1. è¾å
¥æä»¶ç°ç¶å称为 `模æ¿_ç½çº¦è½¦è®¢ååå
¨çæ»é.xlsx`ï¼è ReportExportService.exportWycSplit ä»æç²¾ç¡®å `ç½çº¦è½¦è®¢ååå
¨çæ»é.xlsx` å®ä½ï¼resolveAnyTemplate ä¸ååç¼å¹é
ï¼â 该å°è¡¨çæè·¯å¾å½åå¯è½æ¥âæªæ¾å°æ¨¡æ¿âãWycSplitCalc.findInput å·²æ¯æä¸¤ç§å½åï¼å
ä¿è¯å¤§è¡¨åæ°å¯ç¨ï¼å°è¡¨å
¥å£ç模æ¿å®ä½å¾
M4 ç»ä¸æ¥çº¿æ¶ä¿®æ£ã |
| | | 2. ç±»å䏿件åä¸ä¸è´æ¾å¯¼è´ javac 失败并çµè¿æ å
³æä»¶æ¥éï¼javac é误æ¢å¤çº§èï¼â å·²ç»ä¸ä¸º WycSplitCalc.javaï¼ç¼è¯éè¿ã |
| | | |
| | | ## å
ãç»è®ºä¸ä¸ä¸æ¥ |
| | | - ç»è®ºï¼ç½çº¦è½¦æåå¯å®æ´å¤ç® 7 ææ¯çï¼0 å·®å¼ï¼ï¼`WycSplitCalc` å·²å
¥åºå¹¶éè¿ç¼è¯ã |
| | | - ä¸ä¸æ¥ï¼åå¸å®¢è¿å°è´¦/å叿±æ»/åå¸åå¸å· 7 ææ´é¾åå½ï¼å
¬äº¤+åºç§+ç½çº¦+轨é轮渡ç»åå£å¾ C7ï¼â M1-MidCalc â M2 SummaryFillerã |
| New file |
| | |
| | | # åè½æµè¯æ¥åï¼M1-è´§è¿ åæ°é¾è·¯æ ¸å¯¹ä¸ 7 æåå½ï¼2026-09-08ï¼ |
| | | |
| | | ## ä¸ãåè½è¯´æ |
| | | æ±æ»å¤§è¡¨æ°æ®é©±å¨æ¹é M1 第ä¸åï¼æâè´§è¿å£å¾âï¼è§ä¸/è§ä¸/å计 à 货è¿é/å¨è½¬é Ã å½æ/累计ï¼åºå为å¯å¤ç¨ç Java è®¡ç®æå¡ `FreightCalc`ï¼`traffic-audit-server/.../reportexport/calc/FreightCalc.java`ï¼ï¼å¹¶éªè¯ï¼**ä»
åæ°æ®åºå³å¯éç®åº 7 æå·²ä¿®æ£æ¯çä¸è´§è¿éæåãè´§è¿å¨è½¬éæåä¸¤å¼ æå页çå
¨é¨è§ä¸/è§ä¸æ°å¼ï¼éæ ¼ diff=0ï¼**ï¼ä¸ºåç» SummaryFiller å忝çæä¾åæºç©éµã |
| | | |
| | | ## äºãæµè¯ç¯å¢ |
| | | - åºï¼`traffic_audit`ï¼127.0.0.1:3308ï¼ï¼æ°æ® = 2026-07 已导å
¥ç°ç¶ï¼ |
| | | - æ¯çåºçº¿ï¼`docs/çææ±æ»å¤§è¡¨/2026å¹´7æéè·¯è¿è¾éæ±æ»è¡¨.xlsx`ï¼2026-07 已修æ£çï¼ï¼ |
| | | - å·¥å
·ï¼mysql CLI åæ° + Python éç®æ¯å¯¹ï¼å端 `mvn -q compile` éè¿ï¼exit=0ï¼ã |
| | | |
| | | ## ä¸ãåæ°å£å¾ï¼ä¸æ¢æ exportFreightRank/exportTurnoverRank åç¡®è®¤åæ§ B1 ä¸è´ï¼ |
| | | | ææ | æ¥æº | |
| | | |---|---| |
| | | | è§ä¸è´§è¿éï¼å½æ/累计ï¼ä¸å¨ï¼ | `h2032_enterprise_monthly.freight_total`ï¼å¨ï¼æå¸å·æ±æ» ÷10000 | |
| | | | å计货è¿éï¼ä¸å¨ï¼ | `freight_turnover_import.freight_mMM`ï¼å½æï¼/ `freight_m01..mMM`ï¼ç´¯è®¡ï¼ | |
| | | | è§ä¸è´§è¿é | å计 â è§ä¸ï¼æå表ä¸åè´§è¿éåï¼ä¸å¯ç´æ¥åï¼ | |
| | | | è§ä¸/å计å¨è½¬é | `scale_split_transport` MONTH / CUMULATIVE ç `above_scale_turnover` / `total_turnover` | |
| | | | è§ä¸å¨è½¬é | å计 â è§ä¸ï¼ä¸æå表 below åæ ¸å¯¹ä¸è´ï¼ | |
| | | | æ¹åçè¡ | 17 å¸å·ä¹åï¼ä¸æ¯çâå
¨çè¡=Σåå¸è¡âå
¬å¼ä¸è´ï¼ | |
| | | |
| | | ## åãç¨ä¾è¡¨ |
| | | | # | ç¨ä¾ | è¾å
¥ | 颿 | å®é
| ç»è®º | |
| | | |---|---|---|---|---|---| |
| | | | 1 | è´§è¿éæå·累计ï¼1-7æï¼ | åº 2026-01~07 | 䏿¯ç B4:B21ï¼è§ä¸ï¼ãG4:G21ï¼è§ä¸ï¼éæ ¼ä¸è´ | diff=0 | éè¿ | |
| | | | 2 | è´§è¿éæåÂ·å½æï¼7æï¼ | åº 2026-07 | 䏿¯ç B25:B42ãG25:G42 éæ ¼ä¸è´ | diff=0 | éè¿ | |
| | | | 3 | è´§è¿å¨è½¬éæå·累计 | scale_split CUMULATIVE | 䏿¯ç B5:B22ãG5:G22 ä¸è´ | diff=0 | éè¿ | |
| | | | 4 | è´§è¿å¨è½¬éæåÂ·å½æ | scale_split MONTH | 䏿¯ç B27:B44ãG27:G44 ä¸è´ | diff=0 | éè¿ | |
| | | | 5 | å
¨çè¡ä¸ Σ åå¸ä¸è´æ§ | 17 å¸å·æ±å | å
¨çè§ä¸å½æ=3754.7823ï¼æ¯çï¼ | 计=3754.7823 | éè¿ | |
| | | | 6 | Java ç¼è¯ | `mvn -q -DskipTests compile` | æ é误 | exit=0 | éè¿ | |
| | | |
| | | ## äºãåç°çé®é¢ä¸å¤ç½® |
| | | 1. H2032 æ `region_code` æ±æ»æ¶åå¨âä¸å¸å¤åºå¿ä»£ç âï¼åçèæ¬è¯¯ç¨è¦çèéç´¯å â å·²æ¹ç´¯å ï¼0 å·®å¼ã |
| | | 2. 累计å计é¦çåªå å° 6 æï¼æ¼ m07ï¼â å·²æ¹ 1..7 å
¨å ï¼0 å·®å¼ã |
| | | 3. `freight_turnover_import.region_name` åå¨âæåº/ç¥åæ¶æåº/天é¨/天é¨å¸âçå«å â ç»ä¸ç» RegionUtil å«åå½ä¸åæ¯å¯¹ï¼0 å·®å¼ã |
| | | 4. å¨è½¬é两页å¨ä»»ä½çæ¬æ¯å¯¹ä¸å 0 å·®å¼ï¼æå表å£å¾ç¨³å®ï¼ã |
| | | ï¼ä¸è¿°å为åå½èæ¬é®é¢ï¼éä¸å¡å£å¾é®é¢ï¼å·²å¨ Python åå½ä¸ Java å®ç°ä¸åæ¥ä¿®æ£ãï¼ |
| | | |
| | | ## å
ãç»è®ºä¸ä¸ä¸æ¥ |
| | | - ç»è®ºï¼è´§è¿å£å¾é¾è·¯å¯ä»åºå®æ´å¤ç® 7 ææ¯çï¼å£å¾éå®ï¼`FreightCalc` å·²å
¥åºå¹¶éè¿ç¼è¯ã |
| | | - 说æï¼åæ¯æªå¨æ¬æå¡è®¡ç®ââæ Q1 ç±ååå±ä»¥æ¯çç¼å 2025 åç
§ç»ä¸ºåºåï¼å»å¹´åæ DB å为空ï¼å·²æ ¸å¯¹ï¼ã |
| | | - ä¸ä¸æ¥ï¼â M1-PaxCalcï¼å
¬äº¤/åºç§/轨é轮渡/ç½çº¦/ç线å
车/åå¸å®¢è¿å£å¾ï¼ç¨åå¸å®¢è¿ä¸è¡¨ 7 æåå½ï¼ï¼â¡ M1-MidCalcï¼â¢ M2 SummaryFiller ååå°è´¦+æåé¡µå¹¶éæ ¼ diffï¼â£ 8 æå®å¼¹ã |
| New file |
| | |
| | | # åè½æµè¯æ¥å_ä¸å£å¾æåå·¦åå é¤ä¸7æå彿¶å£å8ææ©å_2026-09-08 |
| | | |
| | | ## ä¸ãåè½è¯´æ |
| | | 1. æ 2026-09-08 ä¸å¡ææ¿ï¼ãç¡®è®¤åæ§æ±æ»â¦ã第å
è第 6 æ¡ï¼ï¼å 餿±æ»å¤§è¡¨ `ä¸å£å¾æå` 页 r1-20 **å·¦å**ï¼A..Hï¼éæ§å½ææ°æ®ï¼A=2026-01 客è¿éãE=2026-02 å¨è½¬éï¼æ ææ¬¡æ é¢ï¼ï¼é¡µå
ä»
ä¿çä¸¤å¼ å¯è§è¡¨ï¼r1-20ã1-7 æç´¯è®¡ãä¸ r22-41ã7 æå½æãï¼åå¨ J..Rï¼ã |
| | | 2. ç¨åºä¾§åæ¥ï¼`ReportExportService.restoreSummaryMonthlyBlocks` 对 `ä¸å£å¾æå` 页 A..Hï¼0-based 0-7 åï¼**æ°¸ä¸ä»å¤ä»½æ¯çåå¡«**ï¼æç»âæ¯çå äºãä¸çæå夿´»âã |
| | | 3. 7 æå彿¶å£ï¼å«æå页左åå é¤ä¸èµ·éªï¼ï¼éè¿ååæ© 8 ææ¯çï¼M0 çå¼éå»ºå¨ v4ï¼ã |
| | | |
| | | ## äºãæµè¯ç¯å¢ |
| | | - æ¯çï¼`docs/çææ±æ»å¤§è¡¨/2026å¹´7æéè·¯è¿è¾éæ±æ»è¡¨.xlsx`ï¼æ¸
çå骨æ¶ï¼ä¸ `_å¤ä»½_2026å¹´7æéè·¯è¿è¾éæ±æ»è¡¨_æ¸
çå_20260904.xlsx`ï¼å®æ´ 7 æï¼è¿åæºï¼ã |
| | | - çæé¾è·¯ï¼å端 `mvn spring-boot:run`ï¼8090ï¼ï¼æ¥å£ `GET /api/report/export/summaryWorkbook?period=2026-07|2026-08&mode=month`ã |
| | | - æ ¡éªå·¥å
·ï¼openpyxl å
容级 diffï¼data_only=False å读ï¼ã`mvn -DskipTests compile`ã |
| | | |
| | | ## ä¸ãç¨ä¾è¡¨ |
| | | | # | ç¨ä¾ | è¾å
¥/æä½ | 颿 | å®é
| ç»è®º | |
| | | |---|---|---|---|---|---| |
| | | | 1 | æ¯çå é¤å·¦å | 7 ææ¯ç `ä¸å£å¾æå` A1:H20 æ¸
空 + ç§»é¤ A1:H1/A22:H22 åå¹¶ | ä»
J1:R1ãJ22:R22 ä¿çåå¹¶ï¼A..H r1-20 æ å
容 | æ¸
148 æ ¼ï¼åå¹¶ä»
å© J1:R1/J22:R22ï¼æ´ç°¿ diff ä»
æ¤åº | éè¿ | |
| | | | 2 | ç¨åºä¸åå¡«å·¦å | åç«¯çæ 2026-07 æ±æ»è¡¨ï¼èµ°è¿åé»è¾ï¼ | çæç©æå页æ A..H éæ§å | çæç© vs å¤ä»½æ¯ç diff=179ï¼å
¶ä¸ 148=å·¦åå é¤ï¼é¢æï¼ã31=æ¥æå int/float åæ³ï¼æ¾ç¤ºç¸åï¼ | éè¿ | |
| | | | 3 | 7 æ M1 æ°å¼åå½ | è´§è¿/å
¬äº¤åºç§è½¨é/ç½çº¦/å叿±æ»/ç线å
è½¦èæ¬å¤è·ï¼åº 2026-01~07ï¼ | å页䏿¯çç¼å 0 å·®å¼ | freight/pax/wyc/urban/mid å
¨ diffs=0 | éè¿ | |
| | | | 4 | Java ç¼è¯ | `mvn -q -DskipTests compile` | æ é误 | exit=0 | éè¿ | |
| | | | 5 | 8 ææ©åï¼v4ï¼ | ä¿®æ£å 7 ææ´æ¬ â 8 ææ¯ç `2026å¹´8æéè·¯è¿è¾éæ±æ»è¡¨.xlsx` | 8 个å°è´¦/åæé¡µ +2 åï¼2026å¹´8æ/8æåæ¯ï¼ï¼ç´¯è®¡æ»å¨ï¼2025 åç
§å³ç§» | 8 页 maxCol +2ï¼ç´¯è®¡ +Qã忝忝 +AJï¼7â8 ææ°å¼æ ¼ 2387 个 0 å·®å¼ | éè¿ | |
| | | | 6 | æ©åçå¼ç»è | æ° 8 æä¸¤å表头ãéèåãæå页 | 两è¡çºµåå并表头ï¼éèå平移ä¿çï¼æå页æ å·¦å | Q/R è¡¨å¤´ä¸ 15/16 å忬¾åå¹¶ï¼å页è¡ä½æ£ç¡®ï¼ï¼éèåæ >=17 +2 ä¿çï¼æå页ä»
J ç³»åå¹¶ | éè¿ | |
| | | | 7 | ç¨åºè¯»æ° 8 ææ¯ç | åç«¯çæ 2026-08ï¼POI 读æ¯çï¼ | 䏿¥ Zip-bombãè¾åº=æ¯ç | styles.xml æ¯å¼ 0.0099 触å POI 误æ¥â`ZipSecureFile.setMinInflateRatio(0.0001)` åä¿®å¤ï¼çæç©ä¸ 8 ææ¯çå
容 diff=0 | éè¿ | |
| | | |
| | | ## åãåç°çé®é¢ä¸å¤ç½® |
| | | 1. POI Zip-bomb 误æ¥ï¼openpyxl éåå styles.xml åç¼©æ¯ 0.009988 < 0.01ï¼POI æè¯»æ°ç 8 ææ¯çãå¤ç½®ï¼`exportSummaryWorkbook` 读æ¯çå临æ¶è°ä½éå¼ï¼0.0001ï¼å¹¶å¨ finally è¿åï¼ä»
å½±åæ¬æ¹æ³è¯»åå
鍿¨¡æ¿ã |
| | | 2. åå²éçï¼8 æçå¼ååï¼v3 产åºï¼çæ° 8 æåæ 两è¡åå¹¶ãéèåæ è®°ä¸¢å¤±ãä»¥âæ¸
çåå¤ä»½â为æºä¼å¸¦åæåå·¦åï¼v4 ä¿®æ£æºä¸ºâå·²å å·¦åç 7 æçæç©â并补两è¡åå¹¶ä¸éèå平移ã |
| | | 3. æ¬ç 8 ææ¯ç 2026 ç»ç´¯è®¡å
¬å¼å·²æ»å¨è³ 1-8 æï¼+Q/+AJï¼ï¼ä½ 8 æå½æå¼ä»ä¸ºç©ºï¼å¾
8 ææ°æ®å¯¼å
¥åç± M2/M3 å¡«å¼ã |
| | | |
| | | ## äºãç»è®º |
| | | - ä¸å£å¾æåå·¦åå é¤å¨æ¯çä¸ç¨åºçæé¾è·¯åçæï¼7 æå彿¶å£éè¿ï¼æå页éåéªè¯æ å·¦åãå
¶ä½é¡µä¸åº 0 å·®å¼ï¼ã |
| | | - 8 ææ©åæ¯çå·²çæå¹¶éè¿ç¨åºç«¯å°ç«¯è¯»åéªè¯ï¼å¯ä½ä¸ºåç» 8 ææ°æ®å¡«å
çæ¯çã |
| | | - éçï¼M2 SummaryFiller / M3 8 æå®å¼¹ï¼å¯¼æ°åå¡« 2026-08 彿å¼ï¼ãæ¯çç¼åæ ¡éªèµ° Q1 å£å¾ã |
| New file |
| | |
| | | # åè½æµè¯æ¥å_æ´æ¹8项åå½éªè¯_2026-09-08 |
| | | |
| | | ## åè½è¯´æ |
| | | éå¯¹ç¨æ· 2026-09-08 æåºç 8 æ¡çé¢ä¸åè½æ´æ¹ï¼â䏿¬¡è¯´æ¹ç没æ¹âï¼éæ¡è½å°å¹¶åå½ï¼ |
| | | 1. æ°æ®æ¥ç页æ»å¨å°åºèªå¨å è½½æ´å¤æ°æ®è¡ï¼ä¸ååªæ¾ç¤ºä¸é¡µï¼ï¼ |
| | | 2. å®¡æ ¸è§åé弿¹å¨åï¼è§ååç§°/è§å说æä¸çç¾åæ¯ééå¼èå¨ï¼å¦ ±10%â±20%â±30%âåéï¼ï¼å¹¶å¯¹å
¨é¨è§åçæãæä¹
åï¼ |
| | | 3. å
¬è·¯æ
客âè¿æ¿è½¦è¾æ°â导å
¥å
¼å®¹æ°çè¿æ¿åºå¯¼åºæä»¶ï¼.xlsï¼è¡¨å¤´ OWNERNAME/æ»è½¦è¾æ°/客使°ï¼æ ä¼ä¸ä»£ç åï¼ï¼åæ¶å
¼å®¹æ§ä¸æååè¡¨å¤´ï¼ |
| | | 4. å®¡æ ¸ç»æï¼å é¤âä¼ä¸è§£éâååè§£éè¾å
¥æ¡ï¼ç¹å»âæ°æ®âå¼¹åºè¯¥ä¼ä¸è¯¥æ¥è¡¨æçææ¥æ ·å¼æ¥çï¼ |
| | | 5. çææ±æ»å¤§è¡¨ï¼æ´æ¬ï¼ï¼å¯¼åºæ¶åæ¶å
¨é¨é¡µçéï¼ç线å
车ç页ä¸ååç¼ºæ°æ®ï¼ãè¿åéèè¡ãææ°æ®èªå¨å 宽åå®½ãæ°å¼ä¿ç两ä½å°æ°æ¾ç¤ºï¼ä¸ä¸¢å¤±å
¨ç²¾åº¦ï¼ãå
¬å¼ä¿ç䏿å¼èªå¨éç®ï¼ |
| | | 6. æ¥è¡¨çæé¡µï¼åå¸å®¢è¿æ¥è¡¨æ ç¾ä¸ç tag å é¤ãåç§°ä¸å
¶å®ä¸è´ï¼âéè·¯è¿è¾éæ±æ»è¡¨ï¼æ´æ¬ï¼âç§»å
¥é¦ä¸ªç¬ç« Tabâæ±æ»å¤§è¡¨âï¼ |
| | | 7. å®¡æ ¸ç»æé¡µçéæ é¡ºåºï¼æ¥è¡¨æå¨æ¥è¡¨ç±»åå·¦è¾¹ï¼ |
| | | 8. æ¥è¡¨çææä»½ä¸æï¼é»è®¤æå
å±ç¤ºå½å年份ï¼2026 å¹´ 1â12 æï¼ï¼åå±ç¤º 2025 å¹´ä¸ 2027 å¹´ã |
| | | |
| | | ## æµè¯ç¯å¢ |
| | | - æ¬æºï¼Windowsï¼å端 Spring Boot :8090ï¼å端 Vue2 :8080ï¼é¡µé¢ç»éæ°ç¼è¯å è½½ææ°ä»£ç ï¼å端已éå¯ï¼ã |
| | | - ç»å½ï¼adminï¼app.captcha.required=false æµè¯æ¨¡å¼ï¼ã |
| | | - æ°æ®åºï¼æ¬æº traffic-audit å¼ååºï¼å« 2026-08 è´§è¿ææ¥ 13056 æ¡çæ¢ææ°æ®ï¼ã |
| | | - æ¥æï¼2026-09-08ã |
| | | |
| | | ## ç¨ä¾è¡¨ï¼è¾å
¥ / 颿 / å®é
/ ç»è®ºï¼ |
| | | |
| | | | # | è¾å
¥ | 颿 | å®é
| ç»è®º | |
| | | |---|------|------|------|------| |
| | | | 1 | æ°æ®æ¥ç页ï¼H203-2ï¼å
± 13056 æ¡ï¼ï¼å°è¡¨æ ¼ç«åæ»å¨å°åº | èªå¨è¿½å ä¸ä¸é¡µï¼è¡æ° 20â40ï¼é¡µç¾ä»â第 1 页âåâ第 2 页â | åå§ 20 è¡ï¼å®¹å¨é« 299ãå
å®¹é« 796ï¼ï¼æ»å¨å 40 è¡ï¼å
å®¹é« 1592ï¼scrollTop 496.8ï¼ï¼âå
± 13056 æ¡è®°å½ï¼å½å第 2 页â | éè¿ | |
| | | | 2 | è§å管çï¼å° P005 éå¼ 20â30â20 åå¤ä¿å | åç§°/说æä¸ç ±N% éå¨ï¼Â±20%â±30%ï¼ï¼å
¶å®æ å
³æ°åä¸å¨ï¼éå¼é¡µé¢ä»ä¸è´ | P005 以å B001ï¼å¢éï¼ãE005ï¼Â±%ï¼ãRULE_003ï¼é«åº%ï¼ãT001ï¼å·®è·%ï¼å宿µéè¿ï¼æ¾å¼ï¼0.2â0.1ï¼ä¸æ¯å¼ï¼1.3â1.5ï¼å£å¾åæ£ç¡®å¹¶æä¹
å | éè¿ | |
| | | | 3 | 导å
¥ 2026-08 å
¬è·¯æ
å®¢è¿æ¿è½¦è¾æ°ï¼æ° .xlsï¼OWNERNAME/æ»è½¦è¾æ°/客使°ï¼ | 750 å®¶ä¼ä¸å
¨é¨å
¥åºãæ½æ ·æ°å¼ä¸æºæä»¶ä¸è´ï¼æ§ä¸æè¡¨å¤´æä»¶ä»å¯å¯¼å
¥ | æ°æ¨¡æ¿æ¾å
¥ docs/å
¬è·¯æ
客/模æ¿_å
¬è·¯æ
å®¢è¿æ¿è½¦è¾æ°.xls 导å
¥æåï¼æ½æ¥ç§å½å¿å¿å° 5/35ãå®é叿¶¢å® 26/668 䏿ºæä»¶ä¸è´ï¼ä¼ä¸ä»£ç åä¸ºç©ºå±æ£å¸¸ï¼æ°æ¨¡æ¿æ æ¤åï¼ | éè¿ | |
| | | | 4 | å®¡æ ¸ç»æé¡µï¼â æ£æ¥è¡å
æä½åï¼â¡ç¹å»âæ°æ®â | â æ âä¼ä¸è§£éâå/è¾å
¥æ¡ï¼åªæ æ°æ®/确认/忽ç¥ï¼â¡ å¼¹åºè¯¥ä¼ä¸è¯¥æ¥è¡¨æçææ¥æ ·å¼ï¼æ é¢=ä¼ä¸å+æ¥è¡¨æ ææ¥æ°æ®ï¼ååº=è¿åæ
åµâè¿è¾ç产æ
åµâ平忿 âå¡«æ¥äººä¿¡æ¯ï¼åºé¨å
³éå¯ç¨ï¼ | 宿µæ 4 åâä¼ä¸è§£éâæ®çï¼âæ°æ®âå¼¹çªå
容ä¸ååºé¡ºåºç¬¦å颿ï¼å
³éæ£å¸¸ | éè¿ | |
| | | | 5 | 导åºâéè·¯è¿è¾éæ±æ»è¡¨ï¼æ´æ¬ï¼â2026-08 å¹¶èæ¬æ ¡éª 19 个 sheet | å
¨é¨é¡µæ autoFilterãæ éèè¡ï¼æ°å¼åå
æ ¼ä¿ç两ä½å°æ°æ¾ç¤ºä¸å
¨ç²¾åº¦ï¼ç³»ç»æ±å/忝å
¬å¼ä¿çï¼æå¼å³éç® | æ ¡éªæä»¶ï¼docs/çææ±æ»å¤§è¡¨/è¾åº/çæ_éè·¯è¿è¾éæ±æ»è¡¨_2026-08_æ¸
çéªè¯.xlsxï¼19 页 filter=Noneãhidden=[]ï¼C4/D4 çé¿æ±åä¸åæ¯å
¬å¼ä¿ç | éè¿ | |
| | | | 6 | æ¥è¡¨çæé¡µæ£æ¥ Tab 䏿 ç¾ | 顺åºï¼æ±æ»å¤§è¡¨âè´§è¿æ¥è¡¨âæ
客æ¥è¡¨âåå¸å®¢è¿æ¥è¡¨âæèµæ¥è¡¨âè½èæ¥è¡¨ï¼åå¸å®¢è¿æ tagï¼æ´æ¬ä»åå¸å®¢è¿ç§»åº | æ±æ»å¤§è¡¨ç¬ç«ä¸ºé¦ç»ï¼åå¸å®¢è¿æ ç¾æ âå
¬äº¤/åºç§/轨é轮渡/æ±æ»âtag | éè¿ | |
| | | | 7 | å®¡æ ¸ç»æé¡µçéæ | æ¥è¡¨æå¨æ¥è¡¨ç±»å左边 | çéæ é¡ºåºä¸ºâæ¥è¡¨æ â æ¥è¡¨ç±»å â æ§è¡å®¡æ ¸æé®â | éè¿ | |
| | | | 8 | æ¥è¡¨çæé¡µç¹å¼æä»½ä¸æ | é»è®¤å±å¼å½å年份 2026 å¹´ 1â12 æï¼å
¶æ¬¡ 2025 å¹´ï¼å次 2027 å¹´ | 宿µä¸æé¡ºåºï¼2026å¹´1æâ¦2026å¹´12æã2025å¹´1æâ¦2025å¹´12æã2027å¹´1æâ¦2027å¹´12æ | éè¿ | |
| | | |
| | | ## åç°çé®é¢ä¸å¤ç½® |
| | | - åå²é®é¢ï¼è§ååç§°/说æéé¤éå¼å¤è¿æ··æä¸é弿 å
³çæ°åï¼å¦è¿è·åºé´ [10,3000]ï¼ï¼æ§å®ç°ä¼è¯¯æ¹ãæ¬è½®æ¹ä¸ºâææ§éå¼å¹é
对å¾ä¸çç¾åæ¯çæ®µææ¿æ¢âï¼å¹¶å¯¹è¯»å表åå¹çèªæï¼å®æµæªå误伤æ å
³æ°åã |
| | | - åå²é®é¢ï¼æ±æ»å¤§è¡¨æ¯çæ¬èº«å¸¦çéä¸éèè¡ï¼æ§å¯¼åºä¼åæ ·å¸¦åºï¼çèµ·æ¥åç¼ºæ°æ®ãæ¬è½®å¯¼åºåç»ä¸æ¸
çå¹¶éªè¯ 19 页å
¨å¹²åã |
| | | - åå²é®é¢ï¼å
¬è·¯æ
å®¢è¿æ¿å¯¼å
¥æ¤ååªè®¤âä¼ä¸ä»£ç /ä¼ä¸åç§°/è½¦è¾æ°/è½½å®¢ä½æ°â䏿ååï¼åäºä¸è½½çæ°æ¨¡æ¿å°ä¸¤å导è´å¯¼ä¸è¿å»ãæ¬è½®æå«å+表头大åå
¼å®¹æ°æ§ä¸¤ç§ç»æã |
| | | - 夿³¨ï¼docs/å®¡æ ¸çé¢ææ¥æ¨¡æ¿/HTML_å®¡æ ¸ç»æ_Aug_2026.html ä¸ºæ¬æ¬¡å®¡æ ¸ç»æé¡µä¸å¼¹çªéªè¯çæ¡£ã |
| | | |
| | | ## ç»è®º |
| | | 8 æ¡æ´æ¹å
¨é¨å®æå¹¶éè¿åå½éªè¯ï¼ç¸å
³æ¹å¨è§ä»£ç æäº¤ï¼DataImportService/ReportExportService/RuleManageController/AuditResult.vue/DataView.vue/ReportExport.vue/DataImport.vueï¼ã |
| New file |
| | |
| | | # åè½æµè¯æ¥å_æ±æ»å¤§è¡¨æ¥ææ ¼å¼ä¸è§åèå¨åæ°æ®æ¥çæ»å¨å è½½_2026-09-08 |
| | | |
| | | - åè½èå´ï¼æ¬æ¹ 7 é¡¹è¦æ±ï¼æ¥æç»ä¸æ¾ç¤ºãVBA å宽å®ãæ°æ®æ¥çæ»å¨å è½½ãå°æ°ä½/æå夿 ¸ãè¦æ±åºçº¿æ¸
åãRULE_004 ååæéãRULE_P005 éå¼ä¸åç§°/说æèå¨ï¼ |
| | | - æµè¯ç¯å¢ï¼æ¬æº traffic-auditï¼å端 8090ãå端 8080 çç¼è¯è¿è¡ä¸ï¼ï¼MySQL 5.7 @ localhost:3308 traffic_auditï¼Chrome å
嵿µè§å¨çæºï¼Playwright/CUAï¼å®æµ UI |
| | | - éªè¯åºçº¿ï¼`docs/è¦æ±ä¸éªæ¶åºçº¿æ¸
å.md`ï¼å³çåºçº¿ãç¡®è®¤åæ§æ±æ»â¦_2026-09-07ã |
| | | |
| | | ## ç¨ä¾ä¸ç»è®º |
| | | |
| | | | # | ç¨ä¾ï¼è¾å
¥ï¼ | 颿 | å®é
| ç»è®º | |
| | | |---|---|---|---|---| |
| | | | 1 | çææ±æ»å¤§è¡¨ 2026-07/08ï¼æ£æ¥è´§è¿é¡µ CQ åçæ¥æéç¹æ¾ç¤º | ææ¬¡æ¾ç¤º `yyyy"å¹´"m"æ"`ï¼ä¸å¾æ¾ç¤ºææ°å | 两æä»¶å
¨ç°¿æ«æï¼æ¥æååå
æ ¼åæ ¼å¼=0ï¼`è´§è¿`页 CQ3 ç = datetime(2023-10-01) 䏿 ¼å¼ `yyyy"å¹´"m"æ"`ï¼æ General æ°åæ®ç | â
éè¿ | |
| | | | 2 | å
¨ç°¿æ ¼å¼ä½æ£ï¼å¯¼åºç 7/8 æå¤§è¡¨ï¼ | æ°å¼ 0.00 / ç¾åæ¯ 0.00% / æå 0ï¼æ 3/4 ä½å°æ°ãæ åºè² | bad3=0ãGeneral æ°å¼=0ãfills=0ï¼ä¸¤ä»½æä»¶ï¼ | â
éè¿ | |
| | | | 3 | æå䏿°å¼å°¾æ°æ½æ¥ï¼è´§è¿éæå/è´§è¿å¨è½¬éæå/ä¸å£å¾æå/éè·¯è¿è¾å¨è½¬é | æåæ´åæ´æ°ï¼æ°å¼åæ¾ç¤ºä¸¤ä½å°æ°ä¸ä¿çå
¨ç²¾åº¦ | è´§è¿éæå C/F/H/K/M/P åæ ¼å¼ `0`ï¼34 è¡ï¼ï¼è´§è¿å¨è½¬éæå/éè·¯è¿è¾å¨è½¬éæå为 `=RANK()(0)` å
¬å¼åï¼æ°å¼/忝å 0.00/0.00%ï¼å¨è½¬éæ 3/4 ä½å°æ° | â
éè¿ | |
| | | | 4 | VBA å®äº¤ä»ç© | æä¾å¯å¯¼å
¥æ¨¡åï¼å«å
¨è¡¨/å½å表两个å®ä¸ç¨æ³ | `docs/å·¥å
·/VBA_çæç©å
¨è¡¨èªå¨å宽_2026-09-08.txt`ï¼AutoFitAllSheets + AutoFitActiveSheet + 说æï¼ | â
éè¿ | |
| | | | 5 | æ°æ®æ¥ç页æ»å¨å°åºèªå¨å è½½ | æ®é/å
¨å±æ»å¨è³åºé¨è¿½å ä¸ä¸é¡µï¼è¡æ°éå¢ãæ»æ°ä¸åãæ JS æ¥é | Chrome çæºï¼è¡æ° 20â40â60â80â100â120â140ï¼å
± 13056 æ¡ä¸åï¼æ§å¶å° error/warning=0 | â
éè¿ | |
| | | | 6 | RULE_004 ååï¼è´§è¿ç±»åç¯æ¯ï¼å®¡æ ¸ 2026-07 | 䏿æ âæ¬ææã䏿æâæ¬ææ åæé | å½ä¸ 7 å®¶ï¼æ°å¢ 6ãæ¶å¤± 3ï¼1 å®¶ååï¼ï¼æ ·ä¾ `91420700090568838U æ¬ææ¶å¤±: éè£
ç®±ï¼ä¸æ=32210ï¼æ¬ææ ï¼` ä¸åºä¸ 6/7 ææ°æ®éåå»åï¼`91429006793269842X` æ°å¢ç
¤ç+æ¶å¤±æ²¹æ°ååå½ä¸ä¸å»å | â
éè¿ | |
| | | | 7 | RULE_P005 éå¼èå¨ï¼20 â 30 â 20 | åç§°/说æéç ±N% ééå¼èªå¨æ¹åå¹¶æä¹
å | å表 20 æ¶åç§°=å¹³åè¿è·ç¯æ¯è¶
±20%æ ¸å®ï¼æ¹ 30 ååè¡¨ä¸ DB å为 ±30%ï¼æ¹å 20 æ¢å¤ ±20%ï¼DB id=11 threshold=20 æä¹
å确认 | â
éè¿ | |
| | | |
| | | ## å
³é®æ°æ®ä¸æ½æ¥è¯æ® |
| | | - æ ¼å¼ä½æ£ï¼ä¸¤ä»½å¯¼åºï¼æ±æ»è¡ï¼`SUM: bad3=0 genNum=0 dtBadFmt=0`ï¼åæåé¡µæ ¼å¼ TOP è§ä¸è¡¨ï¼ |
| | | - è´§è¿éæåï¼`0`Ã204 / `0.00`Ã108 / `0.00%`Ã210 |
| | | - è´§è¿å¨è½¬éæåï¼`0.00`Ã85 / `0.00%`Ã108ï¼æåå为 RANK å
¬å¼ï¼æ ¼å¼ 0ï¼ |
| | | - éè·¯è¿è¾å¨è½¬éï¼`0.00`Ã216 / `0.00%`Ã107ï¼æ 3/4 ä½å°æ° |
| | | - RULE_004 åºæ ¸å¯¹ SQLï¼6/7 æå 636 å®¶ï¼å®¡æ ¸ç»æï¼`audit_result` join `audit_rule` id=4ï¼2026-07 å
± 7 æ¡ï¼ |
| | | - `æ¬ææ°å¢: éè£
ç®±=9716`ã`æ¬ææ°å¢: éç¿ç³=2114`ã`æ¬ææ¶å¤±: éè£
ç®±ï¼ä¸æ=32210ï¼æ¬ææ ï¼`ã |
| | | - `æ¬ææ°å¢: éå±ç¿ç³=223041`ã`æ¬ææ°å¢: ç³æ²¹å¤©ç¶æ°åå¶å=10757ï¼æ¬ææ¶å¤±: ç
¤çåå¶åï¼ä¸æ=10137ï¼æ¬ææ ï¼`ã |
| | | - `æ¬ææ°å¢: ç
¤çåå¶å=20231ï¼æ¬ææ¶å¤±: ç³æ²¹å¤©ç¶æ°åå¶åï¼ä¸æ=22310ï¼æ¬ææ ï¼` ç |
| | | - RULE_P005 API åºåï¼`GET /api/rules/list?reportType=H2031`ï¼id=11ï¼threshold=20 å称±20% â `POST /api/rules/update {id:11,threshold:"30"}` ååç§°/æè¿°Â±30% â æ¹å 20 åæ¢å¤ Â±20%ï¼`audit_rule` è¡¨æ ¸å¯¹ä¸è´ã |
| | | - æ°æ®æ¥çï¼`GET /api/data/list?type=h2032&page=1&size=20` total=13056ãé¡µé´ 0 éå¤ï¼UI æ»å¨å®æµè§ #5ã |
| | | |
| | | ## æ¶åæ¹å¨ |
| | | - `docs/çææ±æ»å¤§è¡¨/2026å¹´7æéè·¯è¿è¾éæ±æ»è¡¨.xlsx`ã`2026å¹´8æéè·¯è¿è¾éæ±æ»è¡¨.xlsx`ï¼çå¼å½ä¸ï¼æ¥æéç¹/0.00/æå 0/å»åºè²ï¼æ¬æ¬¡å¤éªå¯¼åºææ¤æ¯çï¼ |
| | | - `traffic-audit-server/.../auditengine/service/AuditEngineService.java`ï¼RULE_004 æ°å¢/æ¶å¤±ååï¼ |
| | | - `traffic-audit-server/.../rulemanage/controller/RuleManageController.java`ï¼éå¼ Â±N% â åç§°/说æèå¨ï¼ |
| | | - `traffic-audit-web/src/views/DataView.vue`ï¼æ»å¨æè·çå¬ä¿®å¤ + å è½½æ´å¤ï¼è§ä¸ï¼ |
| | | - `docs/init.sql`ï¼RULE_004 说æãRULE_P005 åç§°/说æç§ååæ¥ï¼ |
| | | - `docs/å·¥å
·/VBA_çæç©å
¨è¡¨èªå¨å宽_2026-09-08.txt`ï¼æ°å¢ï¼ |
| | | - `docs/è¦æ±ä¸éªæ¶åºçº¿æ¸
å.md`ï¼æ°å¢ï¼å«æ¬æ¹ç»è®°ï¼ |
| | | |
| | | ## ä¿®å¤è¿ç¨è®°å½ï¼DataViewï¼ |
| | | - åçä»
çå¬ window ä¸ `.table-wrap`ï¼å®æµåç°æ®é/å
¨å±ä¸çæ£æ»å¨å®¹å¨æ¯ el-table å
é¨ `.el-table__body-wrapper`ï¼overflow-y:autoï¼ï¼åç卿®é模å¼ä¸ä¼è§¦åã |
| | | - ä¿®å¤ï¼`onScroll` æ¹ä¸ºåäºä»¶ target çå®é
æ»å¨å®¹å¨åº¦éï¼scrollTop/clientHeight/scrollHeightï¼ï¼scroll çå¬å `capture:true`ï¼scroll ä¸å泡ä½å¯æè·ï¼ï¼mounted/beforeDestroy æå¯¹æ³¨å/ç§»é¤ã |
| | | - ä¿®å¤å Chrome çæºå¤æµï¼è§ #5ï¼éè¿ï¼æ§å¶å°æ å¼å¸¸ã |
| | | |
| | | ## åç°çé®é¢ä¸å¤ç½® |
| | | - æ é»å¡é®é¢ãå¾
åæ²¿ç¨åºçº¿ï¼8 ææ°æ®å¯¼å
¥å M2/M3 å¡«å¼å¤éªï¼æ¥æéç¹å¨ 8 ææ¯ç䏿¾ç¤ºä¸ºåºåå·æçæ¾ç¤ºå£å¾å·²å¨åºçº¿ F3 å
³éã |
| | | |
| | | ## ç»è®º |
| | | æ¬æ¹ 7 é¡¹è¦æ±å
¨é¨å®ç°å¹¶éè¿å®æµï¼å¯äº¤ä»ãç¸å
³äº§ç©ï¼å¯¼åºéªè¯æä»¶å¨ `docs/çææ±æ»å¤§è¡¨/è¾åº/çæ_éè·¯è¿è¾éæ±æ»è¡¨_2026-07_æ ¼å¼éªè¯.xlsx` ä¸ `_2026-08_æ ¼å¼éªè¯.xlsx`ã |
| New file |
| | |
| | | # åè½æµè¯æ¥å_æ±æ»å¤§è¡¨çå¼ç»ä¸_2026-09-08 |
| | | |
| | | ## ä¸ãåè½è¯´æ |
| | | ç¨æ·ææ¿ï¼2026-09-08ï¼ï¼æ±æ»å¤§è¡¨çå¼ç»ä¸ï¼å项è§åââ |
| | | 1) æ°å¼ä¿ç两ä½å°æ°ï¼æ°å¼/å
¬å¼æ ¼æ¾ç¤º 0.00ï¼åæ¯ç¾åæ¯ 0.00% ä¿çï¼ï¼ |
| | | 2) æååæ´æ°ï¼æ ¼å¼ 0ï¼ï¼ |
| | | 3) è¡¨æ ¼å宽æå
容èªéåºï¼é¿å
¬å¼ææ¬ä¸åæåæçï¼ï¼ |
| | | 4) èæ¯è²å
¨é¨ç»ä¸å»é¤ï¼æ å¡«å
ï¼ã |
| | | |
| | | æ¶åæä»¶ï¼ |
| | | - æ¯çï¼`docs/çææ±æ»å¤§è¡¨/2026å¹´7æéè·¯è¿è¾éæ±æ»è¡¨.xlsx`ã`2026å¹´8æéè·¯è¿è¾éæ±æ»è¡¨.xlsx` |
| | | - è¿åæºï¼ååå½ä¸ï¼é²çææ¶æ§åºè²/æ§æ ¼å¼â夿´»âï¼ï¼`_å¤ä»½_2026å¹´7æéè·¯è¿è¾éæ±æ»è¡¨_æ¸
çå_20260904.xlsx` |
| | | - ç¨åºï¼`ReportExportService`ï¼æ°å¢ `applyDonorNumberFormat`ï¼è¿ååå¡«æ¶åæ¥ donor æ°åæ ¼å¼ï¼ |
| | | |
| | | ## äºãæµè¯ç¯å¢ |
| | | - å端 8090ï¼`start-dev.ps1` å¯å¨ï¼ï¼`mvn -q -DskipTests compile` exit=0 |
| | | - æ¥å£ï¼`GET /api/report/export/summaryWorkbook?period=2026-07|2026-08&mode=month` |
| | | - æ ¡éªï¼python3 + openpyxlï¼å¼çº§/æ ·å¼çº§å读ï¼data_only=Falseï¼diff |
| | | |
| | | ## ä¸ãç¨ä¾è¡¨ |
| | | | # | ç¨ä¾ | æä½ | 颿 | å®é
| ç»è®º | |
| | | |---|---|---|---|---|---| |
| | | | 1 | æ¯çå»åºè² | 7/8 ææ¯çä¸å¤ä»½ç»ä¸èæ¬å¤ç | å
¨ç°¿æ solid å¡«å
| 7 ææ¯ç fills=0ï¼8 ææ¯çæ¸
é¤ 57908 æ ¼åºè²å=0ï¼å¤ä»½æ¸
é¤ 57886 æ ¼å=0 | éè¿ | |
| | | | 2 | æ°å¼ä¸¤ä½å°æ° | æ°å¼+å
¬å¼æ ¼æåè¯ä¹å½ä¸ | æ°æ®æ ¼æ¾ç¤º 0.00ï¼åæ¯/ç¾åæ¯ä¿ç | 7 ææ¯ç 38778 æ ¼å½ä¸ï¼å¯¼åº 7/8 ææ°æ®æ ¼å 0.00 / 0.00% | éè¿ | |
| | | | 3 | æåæ´æ° | æååè¡¨å¤´åæ°æ®æ ¼è®¾ä¸º 0 | æåæ¾ç¤ºæ´æ° | æ¯çä¸å¯¼åºæååå为 0ï¼æ½æ¥`è´§è¿éæå`/`ä¸å£å¾æå`æ£ç¡® | éè¿ | |
| | | | 4 | å宽èªéåº | å
¬å¼ä¸è®¡å®½ãæ°å¼åä¿åº 12 | é¿å
¬å¼åæ¶ç¼©å°æ°å¼å®½ | `è´§è¿` I/V/Xâ¦ç± 42 â 12ï¼é¿ææ¬åï¼å¦ Qï¼ä¿ç | éè¿ | |
| | | | 5 | å
容ä¸å | å¤çååå
¨ç°¿å¼çº§ diff | diff=0 | 7 æ v1âv2 diff=0ï¼8 ææå vs 忝çä»
6 å¤ç©ºä¸²`''âNone` | éè¿ | |
| | | | 6 | 7 æå¯¼åºç«¯å°ç«¯ | æ°ç弿¯ç+å¤ä»½çæ 2026-07 | æ åºè²ãæ ¼å¼ç»ä¸ãæ ¡éªè¡åºè²ä¸å¤æ´» | fills=0ï¼åºç§/å
¬äº¤æå¼ 0.00ã忝 0.00%ã`è´§è¿`r117/118 æ ¡éªè¡ 0.00 䏿 åºè²ï¼æ®ä½ä»
å表éçæ¥æéç¹å | éè¿ | |
| | | | 7 | 8 æå¯¼åºç«¯å°ç«¯ | çæ 2026-08 | ä¸ 8 ææ¯ç 0 å·®å¼ãæ åºè² | å¼ diff=0ï¼fills=0ï¼æ½æ¥æ ¼å¼æ£ç¡® | éè¿ | |
| | | | 8 | Java ç¼è¯ | `mvn -q -DskipTests compile` | exit=0 | exit=0 | éè¿ | |
| | | |
| | | ## åãåç°çé®é¢ä¸å¤ç½® |
| | | 1. **骨æ¶ç©ºåè¿åæ¶æ ¼å¼ä¸¢å¤±/åºè²å¤æ´»**ï¼æ¯ç 5-7 æåå·²æ¸
空ï¼å«åæ¯å
¬å¼ï¼ï¼å¯¼åºè¿ååªåå¼ä¸åæ ·å¼ï¼å¯¼è´æ´æ°å¼æ¾ç¤º `1234`ï¼ç¼º .00ï¼ã忝å
¬å¼ä»¥ General æ¾ç¤ºå°æ°æ¯ä¾ã`è´§è¿`r117/118 æ ¡éªè¡æå¤ä»½æ§åºè²å¸¦åï¼30 æ ¼ï¼ã |
| | | å¤ç½®ï¼(a) å¤ä»½æºæä»¶ååçå¼ç»ä¸ï¼å»åºè²ã0.00ãæå 0ï¼ï¼(b) Java æ°å¢ `applyDonorNumberFormat`ï¼è¿ååå¡«æ¶åæ¥ donor æ°åæ ¼å¼ï¼åæ¯/æ´æ°å¼/æ ¡éªè¡æ¾ç¤ºç»ä¸ã |
| | | 2. **å宽被é¿å
¬å¼æç**ï¼é¦çèªéåºæå
¬å¼ææ¬è®¡å
¥å®½åº¦ï¼I/V/Xâ¦å被æå° 42ãå¤ç½®ï¼å®½åº¦ä»
æéæå
容计ç®ãé¿å
¬å¼ä¸è®¡å®½ãæ°å¼/å
¬å¼åä¿åº 12ã |
| | | 3. **åè¯ä¹è¯¯å¤**ï¼è¡ 3 ææ¬¡æ¥æåºåï¼46082â¦ï¼æ¾ä½¿æ´å被å¤âæ¥æåâæ¼å½ä¸ãå¤ç½®ï¼æ¥ææ ¼æ° ⤠æ°å¼æ ¼æ°æ¶ææ°å¼åå½ä¸ï¼æ¥æåºåæå¨åå
æ ¼æ ¼å¼ä¸å¨ï¼ã |
| | | 4. **Excel å ç¨ 8 ææ¯ç**ï¼openpyxl æ æ³è½çï¼çå¾
ç¨æ·å
³éçªå£åè¦çï¼é¢è§å¯æ¬å
è¡æä¾æ¡é¢ã |
| | | 5. **æ¥æéç¹åï¼å表éçï¼**ï¼2019-2026 åºåå· General ææ¬¡è¡ï¼å¦`å
¬è·¯æ»å®¢è¿`r2 60 æ ¼ã`ä¸å£å¾è®¡ç®è¿ç¨`A å 192 æ ¼ï¼éæ°æ®ï¼æªæ¹å¨ï¼å¦éç»ä¸ä¸ºæ¥ææ¾ç¤ºå¯å¦è¡ææ¿ã |
| | | |
| | | ## äºãç»è®º |
| | | - çå¼ç»ä¸å项è§åå¨ 7/8 ææ¯çä¸å¯¼åºäº§ç©ç«¯å°ç«¯çæï¼å
¨ç°¿å
容鶿¹å¨ã |
| | | - åç»ï¼8 æå½ææ°æ®å¯¼å
¥åæ M2/M3 å¡«å¼å¹¶å¤éªï¼æ¥æéç¹åæ¾ç¤ºæ¹å¼å¾
ä¸å¡ç¡®è®¤ã |
| New file |
| | |
| | | # 工使¥ç»_2026-09-08 |
| | | |
| | | ## 仿¥å·¥ä½ |
| | | 1. æ±æ»å¤§è¡¨æ°æ®é©±å¨æ¹é ââç¨æ·è¯å®¡æ¹æ¡ v1 åé¦å¹¶å½æ¡£ï¼`docs/ç¡®è®¤åæ§æ±æ»â¦`第å
/ä¸èãæ¹æ¡ v1.1 修订ï¼ï¼ |
| | | - æ©åæ¹å¼æéï¼æ¯æå¢æä»½æ¶æ©åï¼ï¼ä¸ä½ 12 ææ»¡çï¼ |
| | | - æ§è¡é¡ºåºæ E1ï¼å
åå½ 7 æãåå¡« 8 æï¼ |
| | | - è´§è¿/å
¬è·¯æ
客/åå¸å®¢è¿ä¸ç±»ç¬ç«å°è¡¨å端å
¨é¨éèï¼å
é¨ä¸é´è¡¨ä¿çï¼ |
| | | - ç¡®ç«çºªå¾ï¼ä»¥åæ§ææ¡£ä¸ºå¯ä¸å³çåºçº¿ï¼å·²ç¡®è®¤é¡¹ä¸åé夿é®ã |
| | | 2. M0 å½±åé¢å®æµä¸å®ç°çç¥ï¼æéæ©åï¼10 é¿è¡¨é¡µéææ©åãæå页䏿©ï¼ââè§ `docs/æ±æ»å¤§è¡¨æ°æ®é©±å¨æ¹é æ¹æ¡â¦` éå½ã |
| | | 3. M1 è®¡ç®æå¡æ½åä¸ 7 æåå½ï¼éåæµè¯æ¥åè§ `docs/åè½æµè¯æ¥å/`ï¼å 0 å·®å¼ï¼ï¼ |
| | | - M1-è´§è¿ï¼æ°å¢ `FreightCalc`ï¼è§ä¸/è§ä¸/å计 à 货è¿é/å¨è½¬é Ã å½æ/累计ï¼ï¼ |
| | | - M1-åå¸å®¢è¿ï¼æ°å¢ `PaxCalc`ï¼å
¬äº¤/åºç§/轨é轮渡å°è´¦é¡µï¼ï¼ |
| | | - M1-ç½çº¦è½¦ï¼æ°å¢ `WycSplitCalc`ï¼17 å¸å·æå + å
¨ç pinï¼ï¼ |
| | | - M1-åå¸å®¢è¿æ´é¾åå½ï¼å叿±æ»é¡µå½æ r14-20ã累计 r3-9 0 å·®å¼ï¼ï¼ |
| | | - M1-ç线å
è½¦ï¼æ°å¢ `MidCalc`ï¼h2031 ä¼ä¸æ»è®¡ + 个ä½å¹¶å
¥å£å¾ï¼350 æ ¼ 0 å·®å¼ï¼ã |
| | | |
| | | ## æµè¯ç»ææè¦ |
| | | - äºä¸ª M1 ååèª 7 æåå½ 0 å·®å¼å¹¶éè¿ `mvn -q -DskipTests compile`ï¼exit=0ï¼ã |
| | | - éæ ¼å¤æ ¸ä¿®æ£ï¼9/8 æï¼ç¨æ·è´¨è¯¢â8676.57 ä»ä½èæ¥âåå®ä½ï¼ï¼è¯¥æ°æ¯æåçæ¯å¯¹èæ¬ææ¯ç**ææ¬æ°å** |
| | | ï¼å
¬äº¤å°è´¦é¡µ 2026-06 M åçï¼å¦ `'4970.63'`ï¼å½ç©ºå¼è·³è¿æè´ï¼è¡¥ç® 6 æï¼1517.52ï¼åï¼ |
| | | **ä¸å£å¾åæé¡µå½æ/累计ä¸åºéç®é项 0 å·®å¼ï¼å«ç´¯è®¡å
¬äº¤ 10194.09ï¼ï¼å¹¶éæ§æ®å¼**ã |
| | | - 夿 ¸ç»è®ºï¼ä¸å£å¾æå页**å³åï¼1-7 æç´¯è®¡ï¼ä¸åº 0 å·®å¼**ï¼**å·¦åï¼A..Hï¼ä¸ºéæ§éä½** |
| | | ï¼å®¢è¿é=2026-01 彿ãå¨è½¬é=2026-02 彿ï¼17 å¸å·éæ ¼å»åï¼ââè®°å
¥ M2 ä¿®æ£ã |
| | | - ç¨æ·è¡¥å
确认ï¼å·²å
¥ãç¡®è®¤åæ§â¦ã第å
èï¼ï¼8 ææ©åçâ彿å¼/åæ¯âæ é¢ä¸ºä¸¤è¡åå¹¶åå
æ ¼ï¼æ©åé¡»ä¿çã |
| | | |
| | | ## éçé®é¢ä¸å¾
å |
| | | - M0ï¼æåº¦çå¼é建å¨ï¼æéæ©åï¼å«ä¸¤è¡åå¹¶æ é¢ä¿çãææ¬æ°å读åå½ä¸ï¼å®ç°ï¼ |
| | | - M1ï¼æ´¾ç页å£å¾æ ¸å¯¹åºæ¬å®æï¼åæé¡µ 0 å·®å¼ãæå累计å 0 å·®å¼ï¼ï¼å©ä½æåå·¦åéä½ä¿®æ£å¹¶å
¥ M2ï¼ |
| | | - M2ï¼SummaryFiller ååå°è´¦é¡µ+æå页ï¼éæ ¼ diffï¼å«æå页左忹â彿 2026-07âçä¿®æ£éªè¯ï¼ï¼ |
| | | - M3ï¼8 æå®å¼¹ï¼å
æ©å 2026-08ï¼å导å
¥ 8 ææ°æ®çæï¼ï¼ |
| | | - M4ï¼å°è¡¨å端éè + å¤ä»½è¿å/æ¸
çã |
| | | |
| | | |
| | | --- |
| | | |
| | | ## è¡¥å
ï¼2026-09-08 ä¸åï¼åä¸ä¼è¯ç»ï¼ï¼ä¸å£å¾æåå·¦åå é¤ â 7 æå彿¶å£ â 8 ææ©å |
| | | ### 仿¥æ°å¢ |
| | | 1. **ææ¿ç»è®°**ï¼ãç¡®è®¤åæ§æ±æ»â¦ã第å
è第 6 æ¡ââä¸å£å¾æå页 r1-20 A..H 鿧左忴åå é¤ï¼ç¨åºæ°¸ä¸åå¡«ï¼é 7 ææ¶å£éªè¯åæ© 8 æã |
| | | 2. **æ¯çå é¤**ï¼`docs/çææ±æ»å¤§è¡¨/2026å¹´7æéè·¯è¿è¾éæ±æ»è¡¨.xlsx` ç `ä¸å£å¾æå` A1:H20 æ¸
空 148 æ ¼ï¼ç§»é¤ A1:H1/A22:H22 空åå¹¶åºï¼æ´ç°¿ diff ä»
æ¤åºï¼æ¹å¨å坿¬ `_test_tmp/rankleft_before_202607_mother.xlsx`ï¼ã |
| | | 3. **ç¨åºé²å¤æ´»**ï¼`ReportExportService.restoreSummaryMonthlyBlocks` 对 `ä¸å£å¾æå` 页 A..Hï¼å 0-7ï¼æ°¸ä¸ä»å¤ä»½æ¯çåå¡«ï¼å¦ä¿®å¤ POI Zip-bomb 误读ï¼è¯»æ¯çåä¸´æ¶æ¾ä½å缩æ¯éå¼å¹¶ finally è¿åï¼ã |
| | | 4. **7 æå彿¶å£**ï¼M1 äºåèæ¬å¤è· diffs=0ï¼ç¨åºçæ 2026-07 ä¸å®æ´ 7 æåºå diff ä»
å©å·¦åå é¤ 148 æ ¼ + 31 夿¥æ int/float åæ³ï¼æ¾ç¤ºç¸åï¼ã |
| | | 5. **8 ææ©åï¼M0 v4ï¼**ï¼äº§åºæ°æ¯ç `docs/çææ±æ»å¤§è¡¨/2026å¹´8æéè·¯è¿è¾éæ±æ»è¡¨.xlsx`ï¼8 个å°è´¦/åæé¡µ +2 åã累计æ»å¨ +Qã忝忝 +AJã2025 åç
§å³ç§»ã两è¡å并表头ãéèå平移ä¿çãæå页æ å·¦åï¼ï¼ç¨åºçæ 2026-08 = æ°æ¯ç 0 å·®å¼ã |
| | | ### æµè¯ç»ææè¦ |
| | | - å
¨é¨ç¨ä¾è§ãåè½æµè¯æ¥å_ä¸å£å¾æåå·¦åå é¤ä¸7æå彿¶å£å8ææ©å_2026-09-08.mdãã |
| | | - 7â8 ææ°å¼æ ¼ 2387 个 0 å·®å¼ï¼ç¼è¯ exit=0ã |
| | | ### éçä¸ä¸ä¸æ¥ |
| | | - M2 SummaryFillerãM3 8 æå®å¼¹ï¼8 ææ°æ®å¯¼å
¥å填彿å¼ä¸æåï¼ãå°è¡¨å端éèï¼M4ï¼ã |
| | | - 8 ææ°æ¯çç 8 æå½æå¼åä»ä¸ºç©ºï¼çå¾
æ°æ®å¯¼å
¥ä¸å¡«å¼éªè¯ã |
| | | --- |
| | | |
| | | ## è¡¥å
ï¼2026-09-08 ä¸åï¼åä¸ä¼è¯ç»ï¼ï¼æ±æ»å¤§è¡¨çå¼ç»ä¸ï¼æ°å¼0.00/æåæ´æ°/å宽èªéåº/å»åºè²ï¼ |
| | | ### 仿¥æ°å¢ |
| | | 1. **æ¯ççå¼ç»ä¸**ï¼7 æã8 ææ¯çå 7 ææ¸
çåå¤ä»½ï¼è¿åæºï¼ç»ä¸å¤çââå»é¤å
¨é¨ solid åºè²ï¼8 æ 57908 æ ¼ãå¤ä»½ 57886 æ ¼ï¼ãæ°å¼ä¸å
¬å¼æ ¼æåå½ä¸ 0.00ãæåå 0ãå宽æéæå
容èªéåºï¼é¿å
¬å¼ä¸è®¡å®½ãæ°å¼åä¿åº 12ï¼`è´§è¿`I/V/X ç± 42 æ¶ç¼©å° 12ï¼ã |
| | | 2. **ç¨åºåæ¥**ï¼`ReportExportService.applyDonorNumberFormat`ââè¿ååå¡« 5-7 æåæ¶åæ¥ donor æ°åæ ¼å¼ï¼ä¿®å¤æ´æ°å¼ç¼º .00ã忝å
¬å¼ General æ¾ç¤ºå°æ°æ¯ä¾ãæ ¡éªè¡æ§åºè²å¤æ´»ä¸ç±»é®é¢ã |
| | | 3. **éªè¯äº§ç©**ï¼å¯¼åº 2026-07/2026-08 端å°ç«¯å¤éªï¼fills=0ãæ½æ¥æ ¼å¼æ£ç¡®ã8 æä¸æ¯çå¼ diff=0ï¼ï¼è¯¦è§ãåè½æµè¯æ¥å_æ±æ»å¤§è¡¨çå¼ç»ä¸_2026-09-08.mdãã |
| | | ### æµè¯ç»ææè¦ |
| | | - 7/8 ææ¯çä¸å¯¼åºå
¨ç°¿æ åºè²ï¼æ°å¼æ ¼ 0.00/0.00%ï¼æåå 0ï¼å
容鶿¹å¨ã |
| | | - `mvn -q -DskipTests compile` exit=0ã |
| | | ### éçä¸ä¸ä¸æ¥ |
| | | - 8 æå½ææ°æ®å¯¼å
¥åæ M2/M3 å¡«å¼å¤éªï¼æ¥æéç¹åï¼å表 General åºåå·ææ¬¡è¡ï¼æ¾ç¤ºæ¹å¼å¾
ä¸å¡ç¡®è®¤ã |
| | | - 临æ¶èæ¬ `_unify_all.py` å `_test_tmp/` 坿¬ä¸å ä¸å
¥åºã |
| | | --- |
| | | |
| | | ## è¡¥å
ï¼2026-09-08 æé´ï¼åä¸ä¼è¯ç»ï¼ï¼æ¥ææ ¼å¼/å°æ°å¤æ ¸/VBA/æ»å¨å è½½/è§åååä¸éå¼èå¨ |
| | | ### 仿¥æ°å¢ |
| | | 1. **æ¥æéç¹ç»ä¸**ï¼7/8 ææ¯çä¸å¯¼åºå
¨ç°¿æ¥æååå
æ ¼ç»ä¸ `yyyy"å¹´"m"æ"`ï¼ä¿®å¤è´§è¿é¡µ CQ åçææ¬¡æ¾ç¤ºææ°åçé®é¢ï¼å
¨ç°¿æ«ææ¥æåæ ¼å¼=0ï¼ã |
| | | 2. **å°æ°ä½/æå夿 ¸ï¼çº¦å®ï¼æ°å¼ä¿çå
¨ç²¾åº¦æ¾ç¤º 0.00ï¼æåæ´æ° 0ï¼**ï¼å¯¼åº 2026-07/08 å¤éªââæ 3/4 ä½å°æ°ãæ General æ°å¼ãæ åºè²ï¼è´§è¿éæåå `0`ï¼å¨è½¬é/éè·¯è¿è¾å¨è½¬éæå为 RANK å
¬å¼åæ ¼å¼ `0`ã |
| | | 3. **VBA å宽å®äº¤ä»**ï¼`docs/å·¥å
·/VBA_çæç©å
¨è¡¨èªå¨å宽_2026-09-08.txt`ï¼AutoFitAllSheets/AutoFitActiveSheetï¼ã |
| | | 4. **æ°æ®æ¥çæ»å¨å 载修å¤+çæºéªè¯**ï¼å®ä½çæ£æ»å¨å®¹å¨ä¸º el-table å
é¨ body-wrapperï¼onScroll åäºä»¶ target 度é + capture çå¬ï¼Chrome çæºæ»å¨ 20â40ââ¦â140 è¡éå¢ãæ»æ° 13056 ä¸åãæ§å¶å° 0 æ¥éã |
| | | 5. **RULE_004 åå**ï¼ä¸ææ âæ¬ææ°å¢ã䏿æâæ¬ææ åæéï¼2026-07 宿µå½ä¸ 7 å®¶ï¼æ°å¢ 6ãæ¶å¤± 3ã1 å®¶ååï¼ï¼æ¶å¤±æ ·ä¾ä¸åºæ°æ®éåå»åã |
| | | 6. **RULE_P005 éå¼èå¨**ï¼åç§°/说æ ±N% ééå¼åæ®µåæ¥å¹¶æä¹
åï¼å®æµ 20â30â20ï¼DB 夿 ¸ä¸è´ï¼ï¼å
¶å®å« ±N% è§ååçã |
| | | ### æµè¯ç»ææè¦ |
| | | - 详è§ãåè½æµè¯æ¥å_æ±æ»å¤§è¡¨æ¥ææ ¼å¼ä¸è§åèå¨åæ°æ®æ¥çæ»å¨å è½½_2026-09-08.mdãã |
| | | - `mvn` ç¼è¯éè¿ï¼åä¸äº¤æ¥å·²å®æï¼ï¼å端çç¼è¯ 3 次æåï¼15:19/15:24ï¼ã |
| | | ### éçä¸ä¸ä¸æ¥ |
| | | - 8 æå½ææ°æ®å¯¼å
¥å M2/M3 å¡«å¼å¤éªï¼ä¸´æ¶èæ¬ `_verify_*.py/.sql`ã`_do_patch1.py` ä¸å ä¸å
¥åºã |
| | | --- |
| | | |
| | | ## è¡¥å
ï¼2026-09-08 åæï¼åä¸ä¼è¯ç»ï¼ï¼ç¨æ· 8 æ¡æ´æ¹å
¨é¨è½å°å¹¶åå½ |
| | | ### 仿¥æ°å¢ |
| | | 1. **æ°æ®æ¥çæ»å¨å è½½ï¼çæºå¤æµï¼**ï¼è¡¨æ ¼åºå®é«åº¦ãæ»å¨å®¹å¨ç»å®å° el-table å
é¨ body-wrapperï¼å®æµ 20â40 è¡è¿½å ã页ç¾ç¬¬1页â第2页ï¼13056 æ¡æ»æ°ä¸åï¼ã |
| | | 2. **è§åéå¼è卿®åå°å
¨é¨è§å**ï¼`RuleManageController.syncThresholdText` æ¹ä¸ºæâæ§éå¼å¯¹åºçæ®µâæ¿æ¢ï¼æ¯æ ±N%ã>N%ã0.5â50%ã1.3âé«åº30% çå£å¾ï¼ï¼è¯»å表å¹çèªæï¼å®æµ P005/B001/E005/RULE_003/T001 æ¾å¼ä¸æ¯å¼å£å¾åæ£ç¡®å¹¶æä¹
åï¼è¯´æä¸ä¸é弿 å
³çæ°åä¸å被误æ¹ã |
| | | 3. **å
¬è·¯æ
å®¢è¿æ¿è½¦è¾æ°å¯¼å
¥å
¼å®¹æ°æ¨¡æ¿**ï¼åäºä¸è½½çè¿æ¿åºå¯¼åº .xlsï¼è¡¨å¤´ OWNERNAME/æ»è½¦è¾æ°/客使°ãæ ä¼ä¸ä»£ç åï¼ä¸æ§ä¸æåååå¯å¯¼å
¥ï¼`docs/å
¬è·¯æ
客/模æ¿_å
¬è·¯æ
å®¢è¿æ¿è½¦è¾æ°.xlsx` æ¢ä¸º `.xls`ï¼2026-08 å
± 750 å®¶å
¥åºãæ½æ ·ä¸æºæä»¶ä¸è´ã |
| | | 4. **å®¡æ ¸ç»æâæ°æ®âæ¹ææ¥æ ·å¼å¼¹çª + å é¤ä¼ä¸è§£éå**ï¼è¡å
ä»
å© æ°æ®/确认/忽ç¥ï¼å¼¹çªæ è¿åæ
åµâè¿è¾ç产æ
åµâ平忿 âå¡«æ¥äººä¿¡æ¯ ååºï¼æ é¢=ä¼ä¸å+æ¥è¡¨æã |
| | | 5. **æ±æ»å¤§è¡¨å¯¼åºæ¸
ç**ï¼`cleanSummarySheetPresentation` åæ¶å页çéå¹¶è¿åéèè¡ï¼ç线å
车ç页ä¸ååç¼ºæ°æ®ï¼ï¼ä¿ç两ä½å°æ°æ¾ç¤º/å
¨ç²¾åº¦ãå
¬å¼ä¸æå¼èªå¨éç®ï¼æå
容èªå¨å 宽å宽ï¼åªå 宽ä¸ç¼©çªãè·³è¿åå¹¶æ é¢ï¼ï¼19 页导åºèæ¬æ ¡éªéè¿ã |
| | | 6. **æ¥è¡¨çæ Tab éç»**ï¼âæ±æ»å¤§è¡¨ï¼æ´æ¬ï¼âç¬ç«ä¸ºé¦ä¸ª Tabï¼åå¸å®¢è¿æ¥è¡¨å»æ tagãå½åä¸å
¶å®ä¸è´ã |
| | | 7. **å®¡æ ¸é¡µçéæ é¡ºåº**ï¼æ¥è¡¨æç§»å°æ¥è¡¨ç±»å左边ã |
| | | 8. **æä»½ä¸æå¹´ä»½é¡ºåº**ï¼é»è®¤å½åå¹´ 2026 卿åï¼å
¶å 2025ã2027ã |
| | | ### æµè¯ç»ææè¦ |
| | | - 详è§ãåè½æµè¯æ¥å_æ´æ¹8项åå½éªè¯_2026-09-08.mdãï¼8/8 éè¿ï¼åç«¯å·²éæ°ç¼è¯ãå端已éå¯å è½½æ°ä»£ç ã |
| | | ### éçä¸ä¸ä¸æ¥ |
| | | - 8 æå½ææ°æ® M2/M3 å¡«å¼å¤éªï¼9 æèµ·çéæå¯¼å
¥âæ©åâå®¡æ ¸âçæå®æ´é¾å¾
ä¸å¡æ°æ®å°ä½åç»§ç»ã |
| | | - æ¬å°ä¸´æ¶æä»¶ï¼_*.ps1/_*.sql/*.bak/docs.zip/çæäº§ç©xlsx çï¼æªå
¥åºï¼å¾
æ´çæ¸
çã |
| | | |
| | | --- |
| | | |
| | | ## ä¸çåç¶æï¼2026-09-08 17:2xï¼ |
| | | - ç¨åºå·²æææ°ä»£ç éå¯å¹¶éªè¯å°±ç»ªï¼å端 8090 OKãå端 8080 OKï¼`start-dev.ps1`ï¼ï¼æµè§å¨è®¿é® http://localhost:8080 å³å¯ä½¿ç¨ï¼adminï¼ã |
| | | - 仿¥æ¹å¨å·²æäº¤å¹¶æ¨éå
¬å¸ gitea mainï¼`0548cc1`ï¼8 æ¡æ´æ¹ + æµè¯æ¥å + æ¬å·¥ä½æ¥ç»ï¼ã |
| | | - ææ¥å¾
åï¼8 æå½ææ°æ® M2/M3 å¡«å¼å¤éªï¼9 æèµ·éæâ导å
¥âæ©åâå®¡æ ¸âæ±æ»å¤§è¡¨âæ´é¾éªè¯ï¼ä¸´æ¶æä»¶ï¼_*.ps1/_*.sql/*.bak/docs.zip/çæäº§ç© xlsx çï¼æ´çæ¸
çã |
| New file |
| | |
| | | VBA å®ï¼çææ±æ»å¤§è¡¨ï¼æä»»æå·¥ä½ç°¿ï¼å
¨å·¥ä½è¡¨å宽èªéåº |
| | | æ¥æï¼2026-09-08 |
| | | 说æï¼æå¼è¦å¤çç xlsx â Alt+F11 â èåâæå
¥â模åâ â ç²è´´ä»¥ä¸ä»£ç â å
³éç¼è¾å¨ â Alt+F8 è¿è¡ AutoFitAllSheetsã |
| | | ä¹å¯å°æ¬æä»¶å¦å为 .basï¼å¨ VBA ç¼è¾å¨éâæä»¶â导å
¥æä»¶âã |
| | | |
| | | -------------------------------------------------------------------------------- |
| | | Option Explicit |
| | | |
| | | ' 主å®ï¼å¯¹å
¨é¨å·¥ä½è¡¨åæ´åå宽èªéåºï¼å
¬å¼å
æ´ä½éç®ï¼ä»¥æ¾ç¤ºå¼å®½åº¦ä¸ºåï¼ |
| | | Public Sub AutoFitAllSheets() |
| | | Application.ScreenUpdating = False |
| | | Application.Calculation = xlCalculationAutomatic |
| | | Application.CalculateFullRebuild |
| | | Dim ws As Worksheet |
| | | For Each ws In ThisWorkbook.Worksheets |
| | | ws.Activate |
| | | On Error Resume Next |
| | | ' èªå¨éåºæ´å宽度ï¼éèè¡/åä¸å½±åï¼åå¹¶åå
æ ¼å
çæåä¸ä¼è¢« Excel èªå¨è®¡å
¥ï¼ |
| | | ws.Cells.EntireColumn.AutoFit |
| | | On Error GoTo 0 |
| | | Next ws |
| | | Application.ScreenUpdating = True |
| | | MsgBox "å
¨é¨å·¥ä½è¡¨å宽èªéåºå®æã", vbInformation, "宿" |
| | | End Sub |
| | | |
| | | ' å¤ç¨å®ï¼åªå¯¹âå½åéä¸çå·¥ä½è¡¨âæ§è¡èªéåº |
| | | Public Sub AutoFitActiveSheet() |
| | | Application.ScreenUpdating = False |
| | | Application.CalculateFullRebuild |
| | | ActiveSheet.Cells.EntireColumn.AutoFit |
| | | Application.ScreenUpdating = True |
| | | MsgBox "å½å表å宽èªéåºå®æã", vbInformation, "宿" |
| | | End Sub |
| | | -------------------------------------------------------------------------------- |
| | | |
| | | 注æï¼ |
| | | 1) è¿è¡åå
å
¨éçä¸éæ¯å¦æâ###âæº¢åºåï¼è¥ä¸ªå«åå åå¹¶æ é¢ä»åçªï¼å¯æå¨æä¸ä¸è¯¥åã |
| | | 2) æ¬å®åªæ¹å宽ï¼ä¸æ¹ä»»ä½æ°æ®ãå
¬å¼ãåºè²ä¸è¾¹æ¡ã |
| | | 3) 建议çæåç«å»è¿è¡ä¸æ¬¡ï¼åå¦å为æ£å¼äº¤ä»æä»¶ã |
| | |
| | | # æ±æ»å¤§è¡¨âæ°æ®é©±å¨èªå¨å¡«è¡¨âæ¹é æ¹æ¡ v1ï¼2026-09-07ï¼ |
| | | |
| | | > **v1.1 修订ï¼2026-09-08ï¼ç¨æ·ææ¿ï¼**ï¼æ¬æä»¶æ£æä¸â12 ææ»¡çåçå¼â建议**ä½åº**ï¼æ©åæâæ¯æé墿份æ¶åæ©åâæ§è¡ï¼=D1 åå£å¾ï¼å½æå¼å+忝åæå
¥ç´¯è®¡ä¹åã累计æ»å¨ã2025+ åç
§ç»å³ç§»ï¼ãæ§è¡é¡ºåºæ E1ï¼å
åå½ 7 æãåå¡« 8 æãD5 è½å°ï¼è´§è¿/å
¬è·¯æ
客/åå¸å®¢è¿ä¸ç±»ç¬ç«å°è¡¨å端å
¨é¨éèï¼å
é¨ä¸é´è¡¨ä¿çä¸å±ç¤ºã已确认å£å¾ä»¥ãç¡®è®¤åæ§æ±æ»â¦2026-09-07ãææ¡£ï¼å«å
/ä¸èè¡¥å
ï¼ä¸ºå¯ä¸å³çåºçº¿ã |
| | | |
| | | |
| | | åç½®ææ¿ï¼è§ `docs/ç¡®è®¤åæ§æ±æ»ä¸å©ä½çé®_æ±æ»å¤§è¡¨æ°æ®é©±å¨æ¹é _2026-09-07.md`ï¼A1âE3ãQ1âQ3 å·²å
¨é¨ç¡®è®¤ï¼ãæ¬æ¹æ¡æ®æ¤ç¼åã |
| | | |
| | | ## ä¸ãç®æ |
| | |
| | | 2. U203 çåé
å乡(chengxiang)åæ®µä¸ä¸å£å¾æç»ç»ä»¶å
¬å¼ç对åºééæ ¼å¯¹è´¦ï¼7 æåç®ï¼ï¼å¯è½æå£å¾å·®ã |
| | | 3. ç½çº¦æååå²å£å¾ï¼B5ï¼é以 7 æå·²æåç»æéå®è¾å
¥è¾åºï¼é¿å
åçº§åæ°å¼æ¼ç§»ã |
| | | 4. åå¸å®¢è¿é¡µåç
§ç»ä¸ºåç¼©ç»æï¼ä¸å
¶å®å°è´¦é¡µä¸åï¼åç¬å®ç°ï¼7 æå¯¹è´¦è¦çã |
| | | |
| | | ## éå½ï¼M0 å½±åé¢å®æµï¼2026-09-08ï¼æ¯ç 2026-07 â 08ï¼ |
| | | - éè¦âéææ©åï¼å¨ç´¯è®¡ååæå
¥å½æå¼+忝 2 åï¼ç´¯è®¡æ»å¨ï¼2025+ åç
§ç»å³ç§» 2 åï¼âç页 = **10 个é¿è¡¨é¡µ**ï¼` è´§è¿`(maxCol145/åå¹¶140)ãå
¬è·¯æ»å®¢è¿(274/194)ãç线å
车(285/204)ãåå¸å®¢è¿(72/55)ãå
¬äº¤(86/76)ãåºç§(86/76)ãç½çº¦è½¦(86/70)ã轨é轮渡(72/110)ãä¸å£å¾æç»(87/157)ãä¸å£å¾å®¢è¿é(68/111)ï¼å¹³ç§»åºå
¬å¼æ°ä»¥åè®¡ï¼æ¶å¹³ç§»åå¼ç¨ï¼å
¬äº¤ 2004 / åºç§ 1872 / ç½çº¦ 1664 / ä¸å£å¾æç» 6654 / è´§è¿ 6638 / ç线 5688ï¼ã |
| | | - **ä¸éè¦éææ©å**ï¼6 个æå页ï¼è´§è¿éæå/è´§è¿å¨è½¬éæå/ä¸å£å¾æå/å叿±æ»/åå¸åå¸å·/éè·¯è¿è¾å¨è½¬éï¼å½æåä¸ç´¯è®¡å为è¡ç»æï¼åºå®åä½ï¼ç±æ°æ®é©±å¨å¡«å
å¼/å
¬å¼ï¼ï¼ä¸å£å¾åæã2025å¹´åå¸å®¢è¿éãä¸å£å¾è®¡ç®è¿ç¨åæ°ä¸è¶³ 17 æä¸ºè®¡ç®é¡µï¼ä¸å¨ã |
| | | - **M0 å®ç°çç¥ï¼ææ¯èªå®ï¼**ï¼éç¨â**æåº¦çå¼é建å¨**âèé POI å°±å°å平移ââæ 10 个é¿è¡¨é¡µçåå¸å±åæ°å为âæä»½ç»(m æå¼å=2m+1/忝=2m+2/累计=2m+3/ç´¯è®¡åæ¯=2m+4ï¼2025+ åç
§ç»èµ·ç¹éä¹å³ç§»ï¼âï¼çæç®æ ææ¶æ m é建åå¸å±ä¸æä»½è¡¨å¤´/累计/忝å
¬å¼ï¼æºå
容(7æçæ¯ç)ä½ä¸ºçå¼èæ¬å 2025 åç
§æ°æ®åºåã䏿¬¡å»ºæå 8..12 æä¸è·¨å¹´æ°æ¬å¤ç¨ãæå页ä¸èµ°æ©åï¼ç´æ¥ææ å°å¡«å½æ/累计/æåã |
| | | |
| | |
| | | - **Q3**ï¼ç线å
车æ å°ä»¥ `docs/å
¬è·¯æ
客/` 模æ¿ä¸ç®åè¯´æææ¡£ä¸ºåï¼å®ç°éæ§ä¹ååç¬æ ¸å¯¹ã |
| | | |
| | | â å¾
确认项已æ¸
é¶ãå¼å·¥é¡ºåºï¼â åºãæ¹é æ¹æ¡ï¼æ å°æ¸
å/åæ°é¾è·¯/忥éªè¯ï¼ãâ â¡ æ¹æ¡ç¡®è®¤ â ⢠å¨ä»£ç ã |
| | | |
| | | ## å
ã2026-09-08 ç¨æ·è¡¥å
确认ï¼v1 æ¹æ¡è¯å®¡åé¦ï¼ |
| | | 1. **æ©åæ¹å¼**ï¼æ¹ä¸ºâæ¯æé墿份æ¶åæ©åâï¼=D1 åå£å¾ï¼å½æå¼å+忝åæå
¥ç´¯è®¡ä¹åã累计æ»å¨ã2025+ åç
§ç»å³ç§»ï¼ï¼**ä¸ä½åº**ä¸ºä¸æ¬¡æ§ 12 ææ»¡çãæ¹æ¡ v1 ä¸â12 ææ»¡çåçå¼â建议ä½åºã |
| | | 2. **æ§è¡é¡ºåº**ï¼æ E1 å·²ææ¿ââ**å
åå½ 7 æãåå¡« 8 æ**ï¼ä¸åéå¤è¯¢é®ï¼ã |
| | | 3. **D5 è½å°**ï¼è´§è¿ãå
¬è·¯æ
客ãåå¸å®¢è¿ä¸ç±»**ç¬ç«å°è¡¨å端å
¨é¨éè**ï¼å
é¨ä¸é´åæè¡¨ä¿çï¼ä»
å
é¨è®¡ç®ï¼ä¸å±ç¤ºï¼ã |
| | | |
| | | 4. **8 ææ©åæ é¢æ ¼å¼**ï¼æ°å¢â彿å¼ââ忝âä¸¤ç»æ 颿¯**两è¡çºµååå¹¶çåå
æ ¼**ï¼å¦â2026å¹´8æâä¸â8æä¸å»å¹´åæ¯âï¼ï¼æåº¦çå¼é建å¨/æ©åå®ç°é¡»ä¿ç该两è¡åå¹¶æ 颿 ·å¼ï¼ä»
æå
¥æ°æ®åä¸åæ¯åãæ é¢éå平移ã |
| | | 5. **å®ç°æ³¨æäºé¡¹ï¼9/8 宿µï¼**ï¼æ¯çå°è´¦é¡µé¨åæä»½åå
æ ¼ä»¥**ææ¬æ°å**åå¨ï¼å¦å
¬äº¤é¡µ 2026-06 M å '4970.63'ï¼ï¼ç¨åºè¯»æ¯çç¼åæ¶é¡»ç»ä¸åâææ¬âæ°å¼âå½ä¸ï¼å¦å伿¼ç®/æ¼æ¯å¯¹ã |
| | | |
| | | 6. **ä¸å£å¾æå页âå·¦åâå é¤ï¼9/9 ææ¿ï¼**ï¼`ä¸å£å¾æå` 页 r1-20 ç A..H 鿧彿åï¼A=2026-01 客è¿éãE=2026-02 å¨è½¬éï¼æ ææ¬¡æ é¢ï¼**æ´åå é¤**ï¼ä¸åæ M2âæ¹å½æ 2026-07 éç®ä¿®æ£âå¤çï¼é¡µå
ä»
ä¿çä¸¤å¼ å¯è§è¡¨ï¼r1-20ã1-7 æç´¯è®¡ãä¸ r22-41ã7 æå½æãï¼åå¨ J..Rï¼å«å¸å·åï¼ãåæ¶ç§»é¤ A1:H1ãA22:H22 两个空æ 颿®çåå¹¶åºï¼A..I ä»ä¸ºéè空åãç¨åºä¾§ï¼`restoreSummaryMonthlyBlocks` 对 `ä¸å£å¾æå` 页 **A..Hï¼0-based 0-7 åï¼æ°¸ä¸ä»å¤ä»½æ¯çåå¡«**ï¼é¿å
âæ¯çå äºãä¸çæå夿´»âã该å é¤é **7 æå彿¶å£ä¸å¹¶éªè¯**ï¼å«æå页/åæé¡µ/å°è´¦é¡µä¸åº 0 å·®å¼ï¼ï¼éè¿ååæ© 8 æã |
| | | ï¼2026-09-08 å·²æ§è¡å¹¶éªè¯ï¼æ¯çå é¤+ç¨åºæé¤+7 ææ¶å£+8 ææ©åæ¯çï¼è¯¦è§ãåè½æµè¯æ¥å_ä¸å£å¾æåå·¦åå é¤ä¸7æå彿¶å£å8ææ©å_2026-09-08.mdãï¼ |
| | | |
| | | ## ä¸ãå·¥ä½çºªå¾ï¼èª 2026-09-08 èµ·ï¼ |
| | | - 以æ¬ãç¡®è®¤åæ§æ±æ»â¦ãææ¡£ä¸ºå¯ä¸å³çåºçº¿ï¼å¡å·²å¨ A1-E3 / Q1-Q3 / æ¬è¡¨ç¡®è®¤è¿çå£å¾ï¼ç´æ¥æ§è¡ï¼ä¸åé夿é®ã |
| | | - åªå°±ææ¡£æªè¦ççæ°å³çåç¨æ·æé®ã |
| | | |
| New file |
| | |
| | | # è¦æ±ä¸éªæ¶åºçº¿æ¸
åï¼å¹²æ´»åå¿
è¯»ï¼ |
| | | |
| | | > ç¨éï¼æ±æ»ç¨æ·ï¼ä¸å¡ï¼éç»æåºç**æç¡®è¦æ±/å£å¾**ï¼æ¯æ¬¡æ¹ä»£ç /æ¯ç/è§ååå
对ç
§æ¬è¡¨ï¼é¿å
âåä¸åãæ¼å£å¾ãéå¤é®âã |
| | | > åºçº¿ææ¡£ï¼ãç¡®è®¤åæ§æ±æ»ä¸å©ä½çé®_æ±æ»å¤§è¡¨æ°æ®é©±å¨æ¹é _2026-09-07.mdãï¼å¯ä¸å³çåºçº¿ï¼ç¬¬å
è为 09-08 ææ¿ï¼ã |
| | | > ç»´æ¤ï¼ä¼è¯æ¨è¿æ¶åæ¥å¢è¡¥ï¼ç¶æï¼â
å·²å®ç° / ð§è¿è¡ä¸ / â¬å¾
åã |
| | | |
| | | ## ä¸ãæ±æ»å¤§è¡¨çå¼ä¸çæå£å¾ |
| | | | ç¼å· | è¦æ±/å£å¾ | ç¶æ | 夿³¨ | |
| | | |---|---|---|---| |
| | | | F1 | æ°å¼ï¼å«å
¬å¼ç»æï¼ä¸å¾**æ¾ç¤ºä¸¤ä½å°æ°**ï¼0.00ï¼ï¼ä½**ä¿çå
¨ç²¾åº¦å°æ°**ï¼ä¸å¾åèäºå
¥æ¹å¼ | â
2026-09-08 | 7/8ææ¯ç+导åºå·²éªï¼æ 3/4 ä½å°æ°æ®ç | |
| | | | F2 | **æåä¸å¾æ¾ç¤ºæ´æ°**ï¼0 æ ¼å¼ï¼å«å¢éæåï¼ | â
2026-09-08 | 表头âæå/å¢éæåâï¼å
è®¸å¸¦ç©ºæ ¼ï¼æ´åçæ | |
| | | | F3 | æ¥æ/ææ¬¡ç±»åå
æ ¼ç»ä¸æ¾ç¤º **yyyy"å¹´"m"æ"**ï¼å¦è´§è¿é¡µ CQ åçæ¥æéç¹ä¸å¾æ¾ç¤ºææ°åï¼ | â
2026-09-08 | æ¯ç+导åºåéª | |
| | | | F4 | èæ¯è²å
¨é¨ç»ä¸ï¼**æ å¡«å
/å»åºè²**ï¼ï¼çæäº§ç©ä¸å¾ä»è¿åæºå¸¦æ§åºè²å¤æ´» | â
2026-09-08 | è¿åæºå¤ä»½ååå½ä¸ | |
| | | | F5 | åå®½ææ¾ç¤ºå
容**èªéåº**ï¼é¿å
¬å¼ææ¬ä¸å¾æçå宽ï¼çæçæç»è¡¨å¯å¨ Excel éè· VBA å
¨è¡¨èªéåº | â
2026-09-08 | VBA è§ `docs/å·¥å
·/VBA_çæç©å
¨è¡¨èªå¨å宽_2026-09-08.txt` | |
| | | | F6 | çæé¾è·¯ = å¤å¶æ¯çâå¡«å¼/è¿åï¼**æ¯çæä»¶æ¬èº«ä¸å¸¦ä¸å¡æ°æ®ä½ä¼ªè£
**ï¼æ°æ®ä¸å¾ç±å¯¼å
¥+计ç®åå
¥ | ð§ æ¨è¿ä¸ | ä¾ãç¡®è®¤åæ§ãE1 å
åå½7æåå¡«8æ | |
| | | | F7 | æ±æ»å¤§è¡¨å«å½æ + 1-Xæç´¯è®¡ + åæ¯ï¼æå/åæè¡¨é彿ä¸ç´¯è®¡ä¸¤å¥ | â
ï¼å½æ+ç´¯è®¡ç»æï¼ | 彿æåä¿®æ£å·²å
¥ M2 éªè¯ | |
| | | | F8 | 2025 å¹´åæ°æ®ä»¥æ¯çç¼å为åï¼**æ¯çç¼åä¼å
ä½åæ¯åºå**ï¼åºåªåæ ¡éªï¼äººå·¥æ ¸å¯¹é导ä¸è´åæååºå¼ï¼Q1ï¼ | â
å£å¾ç¡®è®¤ | | |
| | | | F9 | å
é¨è®¡ç®é¡µä¸å¯¹å¤ï¼è´§è¿/å
¬è·¯æ
客/åå¸å®¢è¿å°è¡¨å端å
¨é¨éèï¼å
é¨ä¸é´è¡¨ä¿çï¼ | â
ææ¿ | | |
| | | | F10 | æ©åæææéï¼å æä»½ææ©åï¼ä¸é¢å 12 ææ»¡çï¼ï¼æ°å¢åâ彿/åæ¯âæ é¢ä¸ºä¸¤è¡åå¹¶åå
æ ¼ï¼æ©åé¡»ä¿ç | â
M0 v4 | | |
| | | | F11 | åæ¯æ æ°æ®çâå¢é为 0 éæ ¸å®âç±»è§åå·²å
¥å
¬äº¤/åºç§/è´§è¿/æ
å®¢å®¡æ ¸è§åï¼è¡¥å
è§åç±»å
ç¼ï¼ | ð§ | å®¡æ ¸è§åç±»è¿æä»¥å¯¼å
¥ä¸æ¥è¡¨ä¸ºå
| |
| | | |
| | | ## äºãæ°æ®å¯¼å
¥ |
| | | | ç¼å· | è¦æ± | ç¶æ | 夿³¨ | |
| | | |---|---|---|---| |
| | | | I1 | 导å
¥è¿ç¨æ¾ç¤º**è¿åº¦**ï¼å¯¼å
¥å¤±è´¥æç¤ºå°**è¡å·** | â
| | |
| | | | I2 | å
许éå¤å¯¼å
¥ï¼éæ°å¯¼å
¥è¦çï¼ | â
ææ¿ | | |
| | | | I3 | åå¸å®¢è¿å¯¼å
¥ç±»å䏿éå«ï¼**å
¬äº¤/åºç§ææ¥ãç½çº¦è½¦æåãç½çº¦è½¦è®¢åãå
¨çæ»éç**æ¨¡æ¿ | â
å·²å | æ¯çå¨ `docs/åå¸å®¢è¿` | |
| | | | I4 | 导å
¥æ¨¡æ¿å·®å¼ï¼ä¼ä¸ä»£ç /åä½è¯¦ç»åç§°åææ ï¼è¦ä¸ä¸ç§æ¨¡æ¿çå·®å¼å
¼å®¹ | â
å·²å
¼å®¹ | è§ 09-04 æµè¯æ¥å | |
| | | | I5 | æ°æ®æ¥çï¼**æ»å¨å°åºé¨èªå¨å 载并æ¾ç¤ºæ´å¤è¡**ï¼å
¨å±/æ®é模å¼åå¯ç¿»é¡µï¼ | â
2026-09-08 | DataView.vue ä¿®å¤æ»å¨å®¹å¨+capture çå¬ï¼Chrome çæº 20â140 è¡éå¢éªè¯ | |
| | | |
| | | ## ä¸ãæ¥è¡¨çæ |
| | | | ç¼å· | è¦æ± | ç¶æ | 夿³¨ | |
| | | |---|---|---|---| |
| | | | R1 | éææ©å±çæï¼ä¿çæ¯çç¼å䏿¯çç¨åºå¤å¶ï¼ç´¯è®¡å
¬å¼å»ææªå°æä»½ã忝忝èå¨ | â
M0/M1 | | |
| | | | R2 | çæâéè·¯è¿è¾éæ±æ»è¡¨ï¼æ´æ¬ï¼â= å½æè¡¨ + 累计ï¼1-Xæï¼| â
| | |
| | | | R3 | çæç©ä¸æ¯ç/åº 0 å·®å¼ä¸ºéªæ¶æ åï¼å«ä¸å£å¾åæé¡µãæå页累计åï¼ | â
7æåå½ | | |
| | | | R4 | ç¬ç«å°è¡¨ä¿çä½å端éèï¼ç大表è·éåå¯åæ¶ | â
ææ¿ | | |
| | | | R5 | æå/åæ/æ±æ»ç**å½ææ°æ®**è¦ä¸ç´¯è®¡æ°æ®åå«è®¡ç®ï¼ç¦æ¢æç´¯è®¡å¼å½å½æå¼ | ð§ M2/M3 å®å¼¹ | | |
| | | |
| | | ## åãå®¡æ ¸è§å |
| | | | ç¼å· | è¦æ± | ç¶æ | 夿³¨ | |
| | | |---|---|---|---| |
| | | | A1 | RULE_004ï¼è´§è¿ç±»åç¯æ¯ï¼ï¼**䏿æ âæ¬ææ°å¢ï¼æéï¼ä¸ææâæ¬ææ ï¼æé**ï¼ååï¼ | â
2026-09-08 | 弿+DB+init.sql å·²æ¹ï¼2026-07 宿µï¼æ°å¢6/æ¶å¤±3/åå1 å®¶ï¼ä¸æºæ°æ®å»å | |
| | | | A2 | è§ååç§°/说æéçéå¼ï¼Â±N%ï¼**ééå¼å段æ¹å¨èªå¨åæ¥**ï¼å¦ ±10%â±20%ï¼ï¼å
¶å®å«éå¼è§ååç | â
2026-09-08 | 宿µ 20â30â20ï¼åç§°/说æéå¨å¹¶æä¹
åï¼DB id=11 夿 ¸ä¸è´ | |
| | | | A3 | æ´è½¦å¨ä½å¤å®ç¨**å¹³åå¨ä½=æ´è½¦å¨ä½/æ´è½¦æ°**ï¼åºé´ 4-40 | â
| 09-04 ä¿®å¤ | |
| | | | A4 | å®¡æ ¸ç»æéçå¼å¸¸æ°å¼è¦å¯è§£éï¼å¦â轨迹æµç®=1.04E7âéç»åºç®æ³è¯´æ/å£å¾æ æ³¨ï¼ | ⬠| å£å¾è§£é页æ¨è¿ä¸ | |
| | | |
| | | ## äºãå·¥ä½çºªå¾ä¸äº¤ä» |
| | | | ç¼å· | è¦æ± | ç¶æ | |
| | | |---|---|---| |
| | | | W1 | æ¯å®æä¸ä¸ªåè½ï¼ç«å³æµè¯å¹¶åãåè½æµè¯æ¥å_<åè½>_<æ¥æ>.mdãå° `docs/åè½æµè¯æ¥å/` | â
å¸¸ææ§è¡ | |
| | | | W2 | æ¯å¤©ä¸çåã工使¥ç»_<æ¥æ>.mdãå° `docs/工使¥ç»/` | â
å¸¸ææ§è¡ | |
| | | | W3 | 干活åè¯»æ¬æ¸
åä¸ãç¡®è®¤åæ§æ±æ»â¦ãï¼å·²ç¡®è®¤é¡¹ä¸åéå¤åç¨æ·æé® | â
æ§è¡ | |
| | | | W4 | 个人 gitee(origin) ææ¹å¨å
fetch/åå¹¶ï¼å
¬å¸ gitea(main) å
æµè¯+æ¥åâåå¹¶âcommitâpushï¼ç¦å¼ºæ¨ | â
æ§è¡ | |
| | | |
| | | ## å
ãæ¬ä¼è¯ï¼2026-09-08 ä¸å/æé´ï¼å¤çç»è®° |
| | | 1. æ¥æéç¹ç»ä¸ yyyyå¹´mæï¼F3ï¼+ ä¿®å¤è´§è¿é¡µ CQ åæ¥ææ¾ç¤ºææ°åçé®é¢ï¼ |
| | | 2. æä¾å
¨è¡¨å宽èªéåº VBAï¼F5ï¼ï¼ |
| | | 3. DataView æ»å¨å°åºå è½½æ´å¤ï¼I5ï¼ï¼ |
| | | 4. æå/å°æ°ä½æ ¼å¼å¤æ ¸ï¼F1/F2ï¼è´§è¿éæåæå=æ´æ°ãå¨è½¬éæåæ°æ®=0.00ãéè·¯è¿è¾å¨è½¬éæ 3/4 ä½å°æ°ï¼ï¼ |
| | | 5. æ¬æ¸
å建ç«ï¼W3ï¼ï¼ |
| | | 6. RULE_004 ååæéï¼A1ï¼ï¼RULE_P005 éå¼ 20% ä¸åç§°/说æèå¨ï¼A2ï¼ã |
| | | 7. æ¬æ¹å®æµæ¶å£ï¼å
¨ç°¿æ ¼å¼ä½æ£ï¼bad3/General/åºè²=0ï¼ãRULE_004 åå 2026-07 å½ä¸æ ¸å¯¹ãP005 èå¨ 20â30â20ãDataView Chrome çæºæ»å¨å è½½ 20â140 è¡ââ详è§ãåè½æµè¯æ¥å_æ±æ»å¤§è¡¨æ¥ææ ¼å¼ä¸è§åèå¨åæ°æ®æ¥çæ»å¨å è½½_2026-09-08.mdãã |
| | |
| | | return null; |
| | | } |
| | | |
| | | /** è´§è¿ç±»åç¯æ¯ï¼æ¬ææ°å¢ï¼ä¸æä¸º0ãæ¬æ>0ï¼éæ ¸å®ï¼å°çä¸ç®¡ */ |
| | | /** è´§è¿ç±»åç¯æ¯ï¼RULE_004ï¼ï¼ä¸ææ âæ¬ææ°å¢ æ 䏿æâæ¬ææ ï¼åæéæ ¸å® */ |
| | | private AuditResult checkMom(AuditRule rule, H2032EnterpriseMonthly report, |
| | | Map<String, H2032EnterpriseMonthly> lastMonthMap) { |
| | | H2032EnterpriseMonthly lastMonth = lastMonthMap.get(key(report.getEnterpriseCode())); |
| | | if (lastMonth == null) return null; |
| | | List<String> hits = new ArrayList<>(); |
| | | List<String> addHits = new ArrayList<>(); |
| | | List<String> delHits = new ArrayList<>(); |
| | | for (String field : rule.getCheckField().split(",")) { |
| | | double current = getH2032FieldValue(report, field); |
| | | double last = getH2032FieldValue(lastMonth, field); |
| | | if (current > 0 && last == 0) { |
| | | hits.add(h2032FieldLabel(field) + "=" + fmt(current)); |
| | | addHits.add(h2032FieldLabel(field) + "=" + fmt(current)); |
| | | } else if (last > 0 && current == 0) { |
| | | delHits.add(h2032FieldLabel(field) + "ï¼ä¸æ=" + fmt(last) + "ï¼æ¬ææ ï¼"); |
| | | } |
| | | } |
| | | if (!hits.isEmpty()) { |
| | | return buildResult(rule, report, "æ¬ææ°å¢: " + String.join("ã", hits), |
| | | "ä¸æè¯¥ç±»å为0", "æ¬ææ°å¢è´§è¿ç±»åï¼ä¸ææ ï¼"); |
| | | if (!addHits.isEmpty() || !delHits.isEmpty()) { |
| | | StringBuilder msg = new StringBuilder(); |
| | | if (!addHits.isEmpty()) msg.append("æ¬ææ°å¢: ").append(String.join("ã", addHits)); |
| | | if (!delHits.isEmpty()) { |
| | | if (msg.length() > 0) msg.append("ï¼"); |
| | | msg.append("æ¬ææ¶å¤±: ").append(String.join("ã", delHits)); |
| | | } |
| | | return buildResult(rule, report, msg.toString(), |
| | | "䏿æ âæ¬ææ°å¢ æ 䏿æâæ¬ææ ", "è´§è¿ç±»åç¯æ¯æ°å¢/æ¶å¤±éæ ¸å®"); |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | /** æè´§è¿éä½å¯¹åºè½¦è¾ä¸º0 éæ ¸å®ï¼å¦ æéè£
箱货è¿éæ éè£
箱车è¾ï¼ */ |
| | | private AuditResult checkNull(AuditRule rule, H2032EnterpriseMonthly report) { |
| | | String[] fields = rule.getCheckField().split(","); |
| | |
| | | } |
| | | } |
| | | |
| | | /** å
¬è·¯æ
å®¢è¿æ¿è½¦è¾æ°ï¼ç¬ç«æ¨¡æ¿ï¼ä¼ä¸ä»£ç /ä¼ä¸åç§°/è½¦è¾æ°/è½½å®¢ä½æ°ï¼ */ |
| | | /** å
¬è·¯æ
å®¢è¿æ¿è½¦è¾æ°ï¼å
¼å®¹ä¸¤ç§è¡¨å¤´ï¼â ä¼ä¸ä»£ç /ä¼ä¸åç§°/è½¦è¾æ°/è½½å®¢ä½æ°ï¼â¡ è¿æ¿åºå¯¼åº OWNERNAME/æ»è½¦è¾æ°/客使°ï¼æ ä¼ä¸ä»£ç åï¼ */ |
| | | public ImportResult importPassengerAuth(MultipartFile file, String period) throws Exception { |
| | | List<PassengerAuthVehicle> authList = new ArrayList<>(); |
| | | try (Workbook wb = WorkbookFactory.create(file.getInputStream())) { |
| | | Sheet sheet = wb.getSheetAt(0); |
| | | Map<String, Integer> colMap = buildHeaderMap(sheet.getRow(0)); |
| | | requireHeaderCols(sheet, "æ
å®¢è¿æ¿è½¦è¾æ°", "ä¼ä¸åç§°", "è½¦è¾æ°", "è½½å®¢ä½æ°"); |
| | | Map<String, Integer> colMap = buildHeaderMapCompat(sheet.getRow(0)); |
| | | Integer nameCol = firstColIdx(colMap, "ä¼ä¸åç§°", "OWNERNAME"); |
| | | Integer vehicleCol = firstColIdx(colMap, "è½¦è¾æ°", "æ»è½¦è¾æ°"); |
| | | Integer seatCol = firstColIdx(colMap, "è½½å®¢ä½æ°", "客使°"); |
| | | Integer codeCol = firstColIdx(colMap, "ä¼ä¸ä»£ç "); |
| | | if (nameCol == null || vehicleCol == null || seatCol == null) { |
| | | throw new RuntimeException("æéæ°æ®ç±»åãæ
å®¢è¿æ¿è½¦è¾æ°ã䏿件å
容ä¸ç¬¦ï¼è¡¨å¤´éå«ãä¼ä¸åç§°/è½¦è¾æ°/è½½å®¢ä½æ°ãæãOWNERNAME/æ»è½¦è¾æ°/客使°ãï¼è¯·ç¡®è®¤æ¯å¦ééäºæ°æ®ç±»åæä½¿ç¨äºæ§æ¨¡æ¿"); |
| | | } |
| | | for (int r = 1; r <= sheet.getLastRowNum(); r++) { |
| | | Row row = sheet.getRow(r); |
| | | if (row == null) continue; |
| | | String name = gs(row, colMap, "ä¼ä¸åç§°"); |
| | | String name = getString(row, nameCol); |
| | | if (name == null || name.trim().isEmpty()) continue; |
| | | PassengerAuthVehicle auth = new PassengerAuthVehicle(); |
| | | auth.setReportPeriod(period); |
| | | auth.setEnterpriseCode(gs(row, colMap, "ä¼ä¸ä»£ç ")); |
| | | auth.setEnterpriseCode(codeCol == null ? null : getString(row, codeCol)); |
| | | auth.setEnterpriseName(name.trim()); |
| | | auth.setVehicleCount(gi(row, colMap, "è½¦è¾æ°")); |
| | | auth.setSeatCount(gi(row, colMap, "è½½å®¢ä½æ°")); |
| | | auth.setVehicleCount(getInt(row, vehicleCol)); |
| | | auth.setSeatCount(getInt(row, seatCol)); |
| | | authList.add(auth); |
| | | } |
| | | } catch (Exception e) { |
| | |
| | | return colMap; |
| | | } |
| | | |
| | | /** å
¼å®¹è¡¨å¤´æ å°ï¼å»å¼å·/å»ç©ºç½ï¼çº¯è±æè¡¨å¤´ç»ä¸å¤§åï¼å¦ 'OWNERNAME' â OWNERNAMEï¼ï¼ä¾¿äºæ°æ§æ¨¡æ¿æ··ç¨ */ |
| | | private Map<String, Integer> buildHeaderMapCompat(Row header) { |
| | | Map<String, Integer> colMap = new HashMap<>(); |
| | | if (header == null) return colMap; |
| | | for (Cell cell : header) { |
| | | if (cell == null) continue; |
| | | String h = FORMATTER.formatCellValue(cell).replace("'", "").replace("\"", "").trim(); |
| | | if (h.isEmpty()) continue; |
| | | boolean ascii = true; |
| | | for (int i = 0; i < h.length(); i++) { |
| | | if (h.charAt(i) > 127) { ascii = false; break; } |
| | | } |
| | | if (ascii) h = h.toUpperCase(); |
| | | if (!colMap.containsKey(h)) colMap.put(h, cell.getColumnIndex()); |
| | | } |
| | | return colMap; |
| | | } |
| | | |
| | | /** æå«å顺åºå第ä¸ä¸ªåå¨çåå·ï¼å
¨é¨ç¼ºå¤±è¿å null */ |
| | | private Integer firstColIdx(Map<String, Integer> colMap, String... aliases) { |
| | | for (String a : aliases) { |
| | | Integer idx = colMap.get(a); |
| | | if (idx != null) return idx; |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | private int colIdx(Map<String, Integer> colMap, String header) { |
| | | Integer idx = colMap.get(header); |
| | | return idx == null ? -1 : idx; |
| New file |
| | |
| | | package com.trafficaudit.reportexport.calc; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.trafficaudit.common.util.RegionUtil; |
| | | import com.trafficaudit.dataimport.entity.FreightTurnoverImport; |
| | | import com.trafficaudit.dataimport.entity.H2032EnterpriseMonthly; |
| | | import com.trafficaudit.dataimport.entity.ScaleSplitTransport; |
| | | import com.trafficaudit.dataimport.mapper.FreightTurnoverImportMapper; |
| | | import com.trafficaudit.dataimport.mapper.H2032EnterpriseMonthlyMapper; |
| | | import com.trafficaudit.dataimport.mapper.ScaleSplitTransportMapper; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import javax.annotation.Resource; |
| | | import java.util.HashMap; |
| | | import java.util.LinkedHashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * è´§è¿å£å¾è®¡ç®æå¡ï¼æ±æ»å¤§è¡¨æ°æ®é©±å¨æ¹é M1-è´§è¿ï¼2026-09-08ï¼ã |
| | | * |
| | | * å£å¾ï¼å³çåºçº¿ docs/ç¡®è®¤åæ§æ±æ»â¦_2026-09-07.md B1ï¼2026-07 ä¸å·²ä¿®æ£æ¯çä¸¤å¼ æå页 |
| | | * è§ä¸/è§ä¸ 彿+累计 éæ ¼åå½ 0 å·®å¼ï¼ï¼ |
| | | * 1. è§ä¸è´§è¿é = h2032_enterprise_monthly.freight_totalï¼å¨ï¼æ 17 å¸å·æ±æ» ÷10000ï¼ä¸å¨ï¼ã |
| | | * 2. å计货è¿é = freight_turnover_import.freight_mMMï¼å½æï¼/ freight_m01..mMMï¼ç´¯è®¡ï¼ã |
| | | * 3. è§ä¸è´§è¿é = å计 â è§ä¸ï¼æå表ä¸åè´§è¿éåï¼ä¸è½ç´æ¥åè§ä¸ï¼ã |
| | | * 4. è§ä¸/å计å¨è½¬é = scale_split_transport MONTH|CUMULATIVE ç above_scale_turnover / total_turnover |
| | | * ï¼åè®¡ä¸ freight_turnover_import.turnover_mMM åæºï¼å·²æ ¸å¯¹ä¸è´ï¼ï¼è§ä¸å¨è½¬ = å计 â è§ä¸ã |
| | | * 5. 忝ï¼å»å¹´åå£å¾ï¼ä¸å¨æ¬æå¡è®¡ç®ï¼æ Q1 以æ¯çç¼å 2025 åç
§ç»ä¸ºåºåï¼ç±ååå±å¡«è¡¨æ¶è®¡ç®ã |
| | | * |
| | | * è¾åº key = RegionUtil è§èå¸å·åï¼æ¦æ±å¸â¦ç¥åæ¶æåºï¼+ PROVINCEï¼æ¹åçï¼å
¨çè¡ = 17 å¸å·ä¹åï¼ |
| | | * 䏿¯çâå
¨çè¡=Σåå¸è¡âå
¬å¼ä¸è´ï¼ã |
| | | */ |
| | | @Service |
| | | public class FreightCalc { |
| | | |
| | | public static final String PROVINCE = "æ¹åç"; |
| | | |
| | | /** å个æé´ï¼å½ææç´¯è®¡ï¼çè´§è¿é/å¨è½¬éä¸å£å¾ææ ï¼æ æ°æ®ä¸º null */ |
| | | public static class FreightMetrics { |
| | | private final Double aboveFreight; // è§ä¸è´§è¿éï¼ä¸å¨ï¼ |
| | | private final Double belowFreight; // è§ä¸è´§è¿éï¼ä¸å¨ï¼ |
| | | private final Double totalFreight; // è§ä¸+è§ä¸è´§è¿éï¼ä¸å¨ï¼ |
| | | private final Double aboveTurnover; // è§ä¸è´§ç©å¨è½¬éï¼ä¸å¨å
¬éï¼ |
| | | private final Double belowTurnover; // è§ä¸è´§ç©å¨è½¬éï¼ä¸å¨å
¬éï¼ |
| | | private final Double totalTurnover; // è§ä¸+è§ä¸è´§ç©å¨è½¬éï¼ä¸å¨å
¬éï¼ |
| | | |
| | | public FreightMetrics(Double aboveFreight, Double belowFreight, Double totalFreight, |
| | | Double aboveTurnover, Double belowTurnover, Double totalTurnover) { |
| | | this.aboveFreight = aboveFreight; |
| | | this.belowFreight = belowFreight; |
| | | this.totalFreight = totalFreight; |
| | | this.aboveTurnover = aboveTurnover; |
| | | this.belowTurnover = belowTurnover; |
| | | this.totalTurnover = totalTurnover; |
| | | } |
| | | |
| | | public Double getAboveFreight() { return aboveFreight; } |
| | | public Double getBelowFreight() { return belowFreight; } |
| | | public Double getTotalFreight() { return totalFreight; } |
| | | public Double getAboveTurnover() { return aboveTurnover; } |
| | | public Double getBelowTurnover() { return belowTurnover; } |
| | | public Double getTotalTurnover() { return totalTurnover; } |
| | | } |
| | | |
| | | /** å
¨éè´§è¿ç©éµï¼month=彿ï¼cumulative=æªè³ period æç´¯è®¡ */ |
| | | public static class FreightMatrix { |
| | | private final String period; |
| | | private final Map<String, FreightMetrics> month; |
| | | private final Map<String, FreightMetrics> cumulative; |
| | | |
| | | public FreightMatrix(String period, Map<String, FreightMetrics> month, Map<String, FreightMetrics> cumulative) { |
| | | this.period = period; |
| | | this.month = month; |
| | | this.cumulative = cumulative; |
| | | } |
| | | |
| | | public String getPeriod() { return period; } |
| | | public Map<String, FreightMetrics> getMonth() { return month; } |
| | | public Map<String, FreightMetrics> getCumulative() { return cumulative; } |
| | | } |
| | | |
| | | @Resource |
| | | private H2032EnterpriseMonthlyMapper h2032Mapper; |
| | | @Resource |
| | | private FreightTurnoverImportMapper freightTurnoverMapper; |
| | | @Resource |
| | | private ScaleSplitTransportMapper scaleSplitMapper; |
| | | |
| | | /** è®¡ç® periodï¼å¦ 2026-07ï¼ç彿ä¸ç´¯è®¡è´§è¿ç©éµ */ |
| | | public FreightMatrix calc(String period) { |
| | | int year = Integer.parseInt(period.substring(0, 4)); |
| | | int month = Integer.parseInt(period.substring(5, 7)); |
| | | |
| | | // H2032 è§ä¸è´§è¿éï¼å¨ï¼ï¼å¸å· -> ææ¡¶ |
| | | Map<String, Map<Integer, Double>> h2032TonByCityMonth = new HashMap<>(); |
| | | List<H2032EnterpriseMonthly> h2032List = h2032Mapper.selectList( |
| | | new LambdaQueryWrapper<H2032EnterpriseMonthly>().likeRight(H2032EnterpriseMonthly::getReportPeriod, year)); |
| | | for (H2032EnterpriseMonthly rec : h2032List) { |
| | | String rp = rec.getReportPeriod(); |
| | | if (rp == null || rp.compareTo(period) > 0) continue; |
| | | String city = RegionUtil.cityByCode(rec.getRegionCode()); |
| | | if (city == null) continue; |
| | | double freight = rec.getFreightTotal() == null ? 0.0 : rec.getFreightTotal(); |
| | | h2032TonByCityMonth.computeIfAbsent(city, k -> new HashMap<>()) |
| | | .merge(Integer.parseInt(rp.substring(5, 7)), freight, Double::sum); |
| | | } |
| | | |
| | | // freight_turnover_importï¼å计货è¿é/å¨è½¬éï¼ä»
ååå¸è¡ï¼æ¹åçè¡ç±æ±åå¾åºï¼ |
| | | Map<String, FreightTurnoverImport> ftMap = new HashMap<>(); |
| | | for (FreightTurnoverImport e : freightTurnoverMapper.selectList( |
| | | new LambdaQueryWrapper<FreightTurnoverImport>() |
| | | .eq(FreightTurnoverImport::getReportPeriod, period))) { |
| | | String city = RegionUtil.normalizeCityName(e.getRegionName()); |
| | | if (city != null && !PROVINCE.equals(city)) ftMap.put(city, e); |
| | | } |
| | | |
| | | // scale_split_transportï¼è§ä¸/å计å¨è½¬é |
| | | Map<String, ScaleSplitTransport> splitMonth = new HashMap<>(); |
| | | Map<String, ScaleSplitTransport> splitCumulative = new HashMap<>(); |
| | | for (ScaleSplitTransport rec : scaleSplitMapper.selectList( |
| | | new LambdaQueryWrapper<ScaleSplitTransport>() |
| | | .eq(ScaleSplitTransport::getReportPeriod, period))) { |
| | | String city = RegionUtil.normalizeCityName(rec.getRegionName()); |
| | | if (city == null || PROVINCE.equals(city)) continue; |
| | | if ("MONTH".equals(rec.getPeriodType())) splitMonth.put(city, rec); |
| | | else if ("CUMULATIVE".equals(rec.getPeriodType())) splitCumulative.put(city, rec); |
| | | } |
| | | |
| | | Map<String, FreightMetrics> monthMap = new LinkedHashMap<>(); |
| | | Map<String, FreightMetrics> cumulativeMap = new LinkedHashMap<>(); |
| | | for (String city : RegionUtil.cityList()) { |
| | | monthMap.put(city, buildMetrics(city, month, h2032TonByCityMonth, ftMap, splitMonth, false)); |
| | | cumulativeMap.put(city, buildMetrics(city, month, h2032TonByCityMonth, ftMap, splitCumulative, true)); |
| | | } |
| | | monthMap.put(PROVINCE, sumOf(monthMap)); |
| | | cumulativeMap.put(PROVINCE, sumOf(cumulativeMap)); |
| | | return new FreightMatrix(period, monthMap, cumulativeMap); |
| | | } |
| | | |
| | | /** åå叿æ ãcumulative=true æ¶ H2032 å 1..month å
¨æ¡¶ãå计å m01..mMM ä¹åï¼false æ¶åªå彿ã */ |
| | | private FreightMetrics buildMetrics(String city, int month, |
| | | Map<String, Map<Integer, Double>> h2032TonByCityMonth, |
| | | Map<String, FreightTurnoverImport> ftMap, |
| | | Map<String, ScaleSplitTransport> splitMap, |
| | | boolean cumulative) { |
| | | Double aboveFreight = null; |
| | | Map<Integer, Double> h2032Buckets = h2032TonByCityMonth.get(city); |
| | | if (h2032Buckets != null) { |
| | | double ton; |
| | | if (cumulative) { |
| | | ton = 0.0; |
| | | for (int m = 1; m <= month; m++) ton += h2032Buckets.getOrDefault(m, 0.0); |
| | | } else { |
| | | ton = h2032Buckets.getOrDefault(month, 0.0); |
| | | } |
| | | aboveFreight = ton / 10000.0; |
| | | } |
| | | |
| | | FreightTurnoverImport ft = ftMap.get(city); |
| | | Double totalFreight = null; |
| | | Double totalTurnoverFromFt = null; |
| | | if (ft != null) { |
| | | if (cumulative) { |
| | | double f = 0.0, t = 0.0; |
| | | for (int m = 1; m <= month; m++) { |
| | | f += monthField(ft, m, true); |
| | | t += monthField(ft, m, false); |
| | | } |
| | | totalFreight = f; |
| | | totalTurnoverFromFt = t; |
| | | } else { |
| | | totalFreight = monthField(ft, month, true); |
| | | totalTurnoverFromFt = monthField(ft, month, false); |
| | | } |
| | | } |
| | | |
| | | ScaleSplitTransport split = splitMap.get(city); |
| | | Double aboveTurnover = split == null ? null : split.getAboveScaleTurnover(); |
| | | Double totalTurnover = split != null && split.getTotalTurnover() != null |
| | | ? split.getTotalTurnover() : totalTurnoverFromFt; |
| | | |
| | | Double belowFreight = totalFreight == null || aboveFreight == null ? null : totalFreight - aboveFreight; |
| | | Double belowTurnover = totalTurnover == null ? null |
| | | : totalTurnover - (aboveTurnover == null ? 0.0 : aboveTurnover); |
| | | return new FreightMetrics(aboveFreight, belowFreight, totalFreight, |
| | | aboveTurnover, belowTurnover, totalTurnover); |
| | | } |
| | | |
| | | /** æ¹åçè¡ = 17 å¸å·ä¹åï¼ä¸æ¯çå
¨çè¡ Î£ å
¬å¼ä¸è´ï¼å
¨å¸å·æ æ°æ®æ¶è¾åº 0ï¼ */ |
| | | private FreightMetrics sumOf(Map<String, FreightMetrics> byCity) { |
| | | double af = 0.0, bf = 0.0, tf = 0.0, at = 0.0, bt = 0.0, tt = 0.0; |
| | | for (String city : RegionUtil.cityList()) { |
| | | FreightMetrics m = byCity.get(city); |
| | | if (m == null) continue; |
| | | af += nz(m.getAboveFreight()); |
| | | bf += nz(m.getBelowFreight()); |
| | | tf += nz(m.getTotalFreight()); |
| | | at += nz(m.getAboveTurnover()); |
| | | bt += nz(m.getBelowTurnover()); |
| | | tt += nz(m.getTotalTurnover()); |
| | | } |
| | | return new FreightMetrics(af, bf, tf, at, bt, tt); |
| | | } |
| | | |
| | | private double monthField(FreightTurnoverImport e, int m, boolean freight) { |
| | | switch (m) { |
| | | case 1: return freight ? nz(e.getFreightM01()) : nz(e.getTurnoverM01()); |
| | | case 2: return freight ? nz(e.getFreightM02()) : nz(e.getTurnoverM02()); |
| | | case 3: return freight ? nz(e.getFreightM03()) : nz(e.getTurnoverM03()); |
| | | case 4: return freight ? nz(e.getFreightM04()) : nz(e.getTurnoverM04()); |
| | | case 5: return freight ? nz(e.getFreightM05()) : nz(e.getTurnoverM05()); |
| | | case 6: return freight ? nz(e.getFreightM06()) : nz(e.getTurnoverM06()); |
| | | case 7: return freight ? nz(e.getFreightM07()) : nz(e.getTurnoverM07()); |
| | | case 8: return freight ? nz(e.getFreightM08()) : nz(e.getTurnoverM08()); |
| | | case 9: return freight ? nz(e.getFreightM09()) : nz(e.getTurnoverM09()); |
| | | case 10: return freight ? nz(e.getFreightM10()) : nz(e.getTurnoverM10()); |
| | | case 11: return freight ? nz(e.getFreightM11()) : nz(e.getTurnoverM11()); |
| | | case 12: return freight ? nz(e.getFreightM12()) : nz(e.getTurnoverM12()); |
| | | default: return 0.0; |
| | | } |
| | | } |
| | | |
| | | private double nz(Double v) { return v == null ? 0.0 : v; } |
| | | } |
| New file |
| | |
| | | package com.trafficaudit.reportexport.calc; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.trafficaudit.common.util.RegionUtil; |
| | | import com.trafficaudit.dataimport.entity.PassengerEnterpriseMonthly; |
| | | import com.trafficaudit.dataimport.entity.PassengerIndividualMonthly; |
| | | import com.trafficaudit.dataimport.mapper.PassengerEnterpriseMonthlyMapper; |
| | | import com.trafficaudit.dataimport.mapper.PassengerIndividualMonthlyMapper; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import javax.annotation.Resource; |
| | | import java.util.HashMap; |
| | | import java.util.LinkedHashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * å
¬è·¯ç线ï¼å«ä¸ªä½ï¼å£å¾è®¡ç®æå¡ï¼æ±æ»å¤§è¡¨æ°æ®é©±å¨æ¹é M1-ç线å
车ï¼2026-09-08ï¼ã |
| | | * |
| | | * å£å¾ï¼2026-07 ä¸ _å¤ä»½_2026å¹´7æéè·¯è¿è¾éæ±æ»è¡¨_æ¸
çå_20260904.xlsx ç线å
车页 |
| | | * ä¼ä¸/个ä½è¡ 1-7 æéæ ¼åå½ 0 å·®å¼ï¼350 æ ¼å
¨ä¸ï¼ï¼ |
| | | * 1. ç线å
车页â客è¿é/æ
客å¨è½¬éâè¡ = h2031_enterprise_monthly æ 17 å¸å·æ±æ» |
| | | * ï¼passenger_total / turnover_totalï¼äºº / 人å
¬éï¼é¤ä»¥ 10000ï¼åå¹¶å
¥ä¸ªä½å®¢è¿ |
| | | * ï¼passenger_individual_monthly åå£å¾ï¼ï¼âå
¶ä¸ä¸ªä½å®¢è¿é/å¨è½¬éâè¡ = ä¸ªä½æ°é¤ä»¥ 10000 |
| | | * ï¼å½åä»
é»ç³/è¥é³/èé¨/åæ/é»å/éå·ææ°ï¼ã |
| | | * 2. å
¨çè¡ = 17 å¸å·ä¹åï¼ä¸æ¯çâå
¨çè¡=åå¸è¡æ±åâå
¬å¼ä¸è´ï¼ä¸å£å¾åæé¡µâå
¬è·¯ç线â |
| | | * = æ¬å£å¾å
¨çå计ï¼å½æ 1631.2013ã累计 11204.5406 䏿¯ç 0 å·®å¼ï¼ã |
| | | * 3. 忝以æ¯çç¼å 2025 åç
§ç»ä¸ºåºåï¼Q1ï¼ï¼ä¸å¨æ¬æå¡è®¡ç®ã |
| | | * |
| | | * è¾åºï¼æ â å¸å·ï¼å« PROVINCE=æ¹åçï¼ â double[4] = |
| | | * [客è¿é(å«ä¸ªä½), å¨è½¬é(å«ä¸ªä½), 个ä½å®¢è¿é, 个ä½å¨è½¬é]ï¼ |
| | | * åä½å为æ¯çå±ç¤ºå£å¾ï¼ä¸äºº / ä¸äººå
¬éï¼ï¼ä¼ä¸åç¬é = arr[0]-arr[2] ä¸ arr[1]-arr[3]ã |
| | | */ |
| | | @Service |
| | | public class MidCalc { |
| | | |
| | | public static final String PROVINCE = "æ¹åç"; |
| | | |
| | | @Resource |
| | | private PassengerEnterpriseMonthlyMapper passengerMapper; |
| | | @Resource |
| | | private PassengerIndividualMonthlyMapper individualMapper; |
| | | |
| | | /** ç线å
车页æ°å¼ç©éµï¼æ â å¸å·/å
¨ç â [客è¿é,å¨è½¬é,个ä½å®¢è¿é,个ä½å¨è½¬é] */ |
| | | public Map<Integer, Map<String, double[]>> banxianMonthly(String yearPrefix, int limit) { |
| | | Map<Integer, Map<String, double[]>> result = new LinkedHashMap<>(); |
| | | List<PassengerEnterpriseMonthly> entRows = passengerMapper.selectList( |
| | | new LambdaQueryWrapper<PassengerEnterpriseMonthly>().likeRight( |
| | | PassengerEnterpriseMonthly::getReportPeriod, yearPrefix)); |
| | | for (PassengerEnterpriseMonthly r : entRows) { |
| | | int m = monthOf(r.getReportPeriod()); |
| | | if (m < 1 || m > limit) continue; |
| | | String city = RegionUtil.cityByCode(r.getRegionCode()); |
| | | if (city == null) continue; |
| | | double pax = nz(r.getPassengerTotal()); |
| | | double turn = nz(r.getTurnoverTotal()); |
| | | if (pax == 0.0 && turn == 0.0) { |
| | | pax = nz(r.getPassengerClass1()) + nz(r.getPassengerClass2()) |
| | | + nz(r.getPassengerClass3()) + nz(r.getPassengerClass4()) |
| | | + nz(r.getPassengerCharter()); |
| | | turn = nz(r.getTurnoverClass1()) + nz(r.getTurnoverClass2()) |
| | | + nz(r.getTurnoverClass3()) + nz(r.getTurnoverClass4()) |
| | | + nz(r.getTurnoverCharter()); |
| | | } |
| | | accumulate(result, m, city, pax / 10000.0, turn / 10000.0, 0.0, 0.0); |
| | | } |
| | | List<PassengerIndividualMonthly> indRows = individualMapper.selectList( |
| | | new LambdaQueryWrapper<PassengerIndividualMonthly>().likeRight( |
| | | PassengerIndividualMonthly::getReportPeriod, yearPrefix)); |
| | | for (PassengerIndividualMonthly r : indRows) { |
| | | int m = monthOf(r.getReportPeriod()); |
| | | if (m < 1 || m > limit) continue; |
| | | String city = RegionUtil.cityByCode(r.getRegionCode()); |
| | | if (city == null) continue; |
| | | double pax = nz(r.getPassengerCount()) / 10000.0; |
| | | double turn = nz(r.getTurnover()) / 10000.0; |
| | | accumulate(result, m, city, pax, turn, pax, turn); |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | private void accumulate(Map<Integer, Map<String, double[]>> result, int m, String city, |
| | | double paxAll, double turnAll, double paxIndi, double turnIndi) { |
| | | Map<String, double[]> monthMap = result.computeIfAbsent(m, k -> new HashMap<>()); |
| | | add(monthMap.computeIfAbsent(city, k -> new double[4]), paxAll, turnAll, paxIndi, turnIndi); |
| | | add(monthMap.computeIfAbsent(PROVINCE, k -> new double[4]), paxAll, turnAll, paxIndi, turnIndi); |
| | | } |
| | | |
| | | private void add(double[] arr, double paxAll, double turnAll, double paxIndi, double turnIndi) { |
| | | arr[0] += paxAll; |
| | | arr[1] += turnAll; |
| | | arr[2] += paxIndi; |
| | | arr[3] += turnIndi; |
| | | } |
| | | |
| | | private int monthOf(String reportPeriod) { |
| | | if (reportPeriod == null) return 0; |
| | | String[] parts = reportPeriod.split("-"); |
| | | if (parts.length < 2) return 0; |
| | | try { |
| | | return Integer.parseInt(parts[1]); |
| | | } catch (NumberFormatException e) { |
| | | return 0; |
| | | } |
| | | } |
| | | |
| | | private double nz(Double v) { |
| | | return v == null ? 0.0 : v; |
| | | } |
| | | } |
| New file |
| | |
| | | package com.trafficaudit.reportexport.calc; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.trafficaudit.dataimport.entity.CityBusMonthly; |
| | | import com.trafficaudit.dataimport.entity.CityTaxiMonthly; |
| | | import com.trafficaudit.dataimport.mapper.CityBusMonthlyMapper; |
| | | import com.trafficaudit.dataimport.mapper.CityTaxiMonthlyMapper; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import javax.annotation.Resource; |
| | | import java.util.HashMap; |
| | | import java.util.LinkedHashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * åå¸å®¢è¿å£å¾è®¡ç®æå¡ï¼æ±æ»å¤§è¡¨æ°æ®é©±å¨æ¹é M1-åå¸å®¢è¿-å
¬äº¤/åºç§/轨é轮渡ï¼2026-09-08ï¼ã |
| | | * |
| | | * å£å¾ä¸æ¢æå¤è¡¨å¯¼åº loadCityBusByMonth / loadCityTaxiByMonth / loadCityRailFerryByMonth å®å
¨ä¸è´ |
| | | * ï¼å³çåºçº¿ A2/B4/B5/C7ï¼2026-07 ä¸ _å¤ä»½â¦_æ¸
çå_20260904.xlsx å
¬äº¤/åºç§/轨é轮渡å°è´¦é¡µ O ååå½ 0 å·®å¼ï¼ï¼ |
| | | * - å
¬äº¤/åºç§ï¼ææ â å¸å· â [客è¿é, æ
客å¨è½¬é, åå¸å
客è¿é, åå¸å
æ
客å¨è½¬é]ï¼æ DB city åæ®µåç»ï¼"å
¨ç"=å
¨é¨å¸å·åè®¡ï¼ |
| | | * - 轨é/轮渡ï¼åä¸ city_bus_monthly 表ç rail / ferry åæ®µï¼è½¨é=æ¦æ±/é»ç³ï¼è½®æ¸¡=æ¦æ±ï¼å
¨ç=å计ï¼ã |
| | | * |
| | | * è¾åºä¸ºâæ â å¸å· â double[4]âï¼ç´¯è®¡ç±ååå±å¯¹ 1..m ææ±åã忝æ Q1 以æ¯çç¼å 2025 åç
§ç»ä¸ºåºåï¼ä¸å¨æ¬æå¡è®¡ç®ã |
| | | */ |
| | | @Service |
| | | public class PaxCalc { |
| | | |
| | | public static final String PROVINCE = "å
¨ç"; |
| | | |
| | | @Resource |
| | | private CityBusMonthlyMapper cityBusMapper; |
| | | @Resource |
| | | private CityTaxiMonthlyMapper cityTaxiMapper; |
| | | |
| | | /** å
¬äº¤ï¼æ â å¸å· â [客è¿é,å¨è½¬é,åå¸å
客è¿é,åå¸å
å¨è½¬é] */ |
| | | public Map<Integer, Map<String, double[]>> busMonthly(String yearPrefix, int limit) { |
| | | Map<Integer, Map<String, double[]>> result = new LinkedHashMap<>(); |
| | | List<CityBusMonthly> rows = cityBusMapper.selectList( |
| | | new LambdaQueryWrapper<CityBusMonthly>().likeRight(CityBusMonthly::getReportPeriod, yearPrefix)); |
| | | for (CityBusMonthly r : rows) { |
| | | int m = monthOf(r.getReportPeriod()); |
| | | if (m < 1 || m > limit) continue; |
| | | String city = r.getCity() == null ? "æªç¥" : r.getCity(); |
| | | accumulate(result, city, m, |
| | | nz(r.getPassengerVolume()), nz(r.getTurnover()), |
| | | nz(r.getPassengerCity()), nz(r.getTurnoverCity())); |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | /** 巡游åºç§ï¼æ â å¸å· â [客è¿é,å¨è½¬é,åå¸å
客è¿é,åå¸å
å¨è½¬é] */ |
| | | public Map<Integer, Map<String, double[]>> taxiMonthly(String yearPrefix, int limit) { |
| | | Map<Integer, Map<String, double[]>> result = new LinkedHashMap<>(); |
| | | List<CityTaxiMonthly> rows = cityTaxiMapper.selectList( |
| | | new LambdaQueryWrapper<CityTaxiMonthly>().likeRight(CityTaxiMonthly::getReportPeriod, yearPrefix)); |
| | | for (CityTaxiMonthly r : rows) { |
| | | int m = monthOf(r.getReportPeriod()); |
| | | if (m < 1 || m > limit) continue; |
| | | String city = r.getCity() == null ? "æªç¥" : r.getCity(); |
| | | accumulate(result, city, m, |
| | | nz(r.getPassengerVolume()), nz(r.getTurnover()), |
| | | nz(r.getPassengerCity()), nz(r.getTurnoverCity())); |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | /** 轨é/è½®æ¸¡ï¼æ â å¸å· â [轨é客è¿é,轨éå¨è½¬é,轮渡客è¿é,轮渡å¨è½¬é] */ |
| | | public Map<Integer, Map<String, double[]>> railFerryMonthly(String yearPrefix, int limit) { |
| | | Map<Integer, Map<String, double[]>> result = new LinkedHashMap<>(); |
| | | List<CityBusMonthly> rows = cityBusMapper.selectList( |
| | | new LambdaQueryWrapper<CityBusMonthly>().likeRight(CityBusMonthly::getReportPeriod, yearPrefix)); |
| | | for (CityBusMonthly r : rows) { |
| | | int m = monthOf(r.getReportPeriod()); |
| | | if (m < 1 || m > limit) continue; |
| | | String city = r.getCity() == null ? "æªç¥" : r.getCity(); |
| | | accumulate(result, city, m, |
| | | nz(r.getRailPassengerVolume()), nz(r.getRailTurnover()), |
| | | nz(r.getFerryPassengerVolume()), nz(r.getFerryTurnover())); |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | private void accumulate(Map<Integer, Map<String, double[]>> result, String city, int m, |
| | | double v0, double v1, double v2, double v3) { |
| | | Map<String, double[]> cityMap = result.computeIfAbsent(m, k -> new HashMap<>()); |
| | | double[] arr = cityMap.computeIfAbsent(city, k -> new double[4]); |
| | | arr[0] += v0; |
| | | arr[1] += v1; |
| | | arr[2] += v2; |
| | | arr[3] += v3; |
| | | double[] prov = cityMap.computeIfAbsent(PROVINCE, k -> new double[4]); |
| | | prov[0] += v0; |
| | | prov[1] += v1; |
| | | prov[2] += v2; |
| | | prov[3] += v3; |
| | | } |
| | | |
| | | private int monthOf(String reportPeriod) { |
| | | if (reportPeriod == null) return 0; |
| | | String[] parts = reportPeriod.split("-"); |
| | | if (parts.length < 2) return 0; |
| | | try { |
| | | return Integer.parseInt(parts[1]); |
| | | } catch (NumberFormatException e) { |
| | | return 0; |
| | | } |
| | | } |
| | | |
| | | private double nz(Double v) { return v == null ? 0.0 : v; } |
| | | } |
| | | |
| New file |
| | |
| | | package com.trafficaudit.reportexport.calc; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.trafficaudit.common.util.RegionUtil; |
| | | import com.trafficaudit.dataimport.entity.CityTaxiMonthly; |
| | | import com.trafficaudit.dataimport.mapper.CityTaxiMonthlyMapper; |
| | | import org.apache.poi.ss.usermodel.Cell; |
| | | import org.apache.poi.ss.usermodel.CellType; |
| | | import org.apache.poi.ss.usermodel.DataFormatter; |
| | | import org.apache.poi.ss.usermodel.Row; |
| | | import org.apache.poi.ss.usermodel.Workbook; |
| | | import org.apache.poi.ss.usermodel.WorkbookFactory; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import javax.annotation.Resource; |
| | | import java.io.File; |
| | | import java.io.FileInputStream; |
| | | import java.io.InputStream; |
| | | import java.util.ArrayList; |
| | | import java.util.LinkedHashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * ç½çº¦è½¦æåå£å¾è®¡ç®æå¡ï¼æ±æ»å¤§è¡¨æ°æ®é©±å¨æ¹é M1-ç½çº¦è½¦ï¼2026-09-08ï¼ã |
| | | * ç®æ³ä¸ exportWycSplit / ãç½çº¦è½¦æå.xlsxãæé¡µä¸è´ï¼B5ï¼è®¢å+å
¨ç pin+巡游åºç§æåï¼ï¼ |
| | | * 客è¿é=订åå æ¯Ãå
¨çæ»éï¼åå¸å
=巡游åºç§åå¸å
å æ¯ä»£çï¼æ¦æ±ä¿æèªèº«ãå
¶ä½æå©ä½å æ¯åæå°å
¨çåå¸å
pinï¼ï¼ |
| | | * å¨è½¬é=客è¿éÃ巡游åºç§å¹³åè¿è·å æ¯åæå
¨çå¨è½¬é pinï¼åå¸å
å¨è½¬éåæ³ï¼ç¨åå¸å
å¹³åè¿è·ï¼ã |
| | | * 2026-07 ä¸ _å¤ä»½â¦_æ¸
çå_20260904.xlsx ç½çº¦è½¦å°è´¦é¡µ O ååå½ 0 å·®å¼ï¼17 å¸å·Ã客è¿é/å¨è½¬é/åå¸å
客è¿é/åå¸å
å¨è½¬éï¼ã |
| | | */ |
| | | @Service |
| | | public class WycSplitCalc { |
| | | |
| | | /** åå¸å·æåç»æï¼å«åé
å乡å£å¾ï¼ä¾ä¸åå°è´¦è¡ä½¿ç¨ï¼ */ |
| | | public static class WycMetrics { |
| | | private final double totalPax; // 客è¿éæ»éï¼ä¸äººï¼ |
| | | private final double cityPax; // åå¸å
客è¿éï¼ä¸äººï¼ |
| | | private final double suburbanPax; // åé
å乡客è¿é = totalPax - cityPax |
| | | private final double totalTurnover; // æ
客å¨è½¬éæ»éï¼ä¸äººå
¬éï¼ |
| | | private final double cityTurnover; // åå¸å
æ
客å¨è½¬éï¼ä¸äººå
¬éï¼ |
| | | private final double suburbanTurnover; |
| | | |
| | | public WycMetrics(double totalPax, double cityPax, double totalTurnover, double cityTurnover) { |
| | | this.totalPax = totalPax; |
| | | this.cityPax = cityPax; |
| | | this.suburbanPax = totalPax - cityPax; |
| | | this.totalTurnover = totalTurnover; |
| | | this.cityTurnover = cityTurnover; |
| | | this.suburbanTurnover = totalTurnover - cityTurnover; |
| | | } |
| | | |
| | | public double getTotalPax() { return totalPax; } |
| | | public double getCityPax() { return cityPax; } |
| | | public double getSuburbanPax() { return suburbanPax; } |
| | | public double getTotalTurnover() { return totalTurnover; } |
| | | public double getCityTurnover() { return cityTurnover; } |
| | | public double getSuburbanTurnover() { return suburbanTurnover; } |
| | | } |
| | | |
| | | public static class WycResult { |
| | | private final String period; |
| | | private final Map<String, WycMetrics> byCity; // key=RegionUtil è§èå¸å·å |
| | | private final WycMetrics province; // å
¨ç = pin è¾å
¥ |
| | | |
| | | public WycResult(String period, Map<String, WycMetrics> byCity, WycMetrics province) { |
| | | this.period = period; |
| | | this.byCity = byCity; |
| | | this.province = province; |
| | | } |
| | | |
| | | public String getPeriod() { return period; } |
| | | public Map<String, WycMetrics> getByCity() { return byCity; } |
| | | public WycMetrics getProvince() { return province; } |
| | | } |
| | | |
| | | @Resource |
| | | private CityTaxiMonthlyMapper cityTaxiMapper; |
| | | @Value("${city-passenger.template-dir:docs/åå¸å®¢è¿}") |
| | | private String templateDir; |
| | | |
| | | private static final String[] INPUT_CANDIDATES = {"ç½çº¦è½¦è®¢ååå
¨çæ»é.xlsx", "模æ¿_ç½çº¦è½¦è®¢ååå
¨çæ»é.xlsx"}; |
| | | |
| | | /** è®¡ç® periodï¼å¦ 2026-07ï¼ç½çº¦è½¦æåç»æ */ |
| | | public WycResult calc(String period) throws Exception { |
| | | Map<String, Object> input = loadMonthlyInput(period); |
| | | if (input == null) { |
| | | throw new RuntimeException("ãç½çº¦è½¦è®¢ååå
¨çæ»é.xlsxãç¼ºå°æ¥è¡¨æ " + period + " çæ°æ®è¡ï¼è¯·å
ç»´æ¤å½æè®¢åä¸å
¨ç pin"); |
| | | } |
| | | double pinK = (Double) input.get("pinK"); |
| | | double pinCK = (Double) input.get("pinCK"); |
| | | double pinZ = (Double) input.get("pinZ"); |
| | | double pinCZ = (Double) input.get("pinCZ"); |
| | | double orderSum = (Double) input.get("orderSum"); |
| | | double[] orderArr = (double[]) input.get("orders"); |
| | | if (pinK <= 0 || pinCK <= 0 || pinZ <= 0 || pinCZ <= 0 || orderSum <= 0) { |
| | | throw new RuntimeException("ç½çº¦è½¦è¾å
¥ " + period + " è¡ä¸å®æ´ï¼å
¨ç pin / 订å缺失ï¼è¯·æ ¸å¯¹ãç½çº¦è½¦è®¢ååå
¨çæ»é.xlsxã"); |
| | | } |
| | | List<String> cities = RegionUtil.cityList(); |
| | | int n = cities.size(); |
| | | if (orderArr == null || orderArr.length < n) { |
| | | throw new RuntimeException("ç½çº¦è½¦è®¢ååæ°ä¸è¶³ï¼åºä¸º 17 å¸å·è®¢ååï¼"); |
| | | } |
| | | Map<String, double[]> taxi = taxiMonthlyOf(period); |
| | | List<String> missingTaxi = new ArrayList<>(); |
| | | double[] Dtax = new double[n]; |
| | | double[] Etax = new double[n]; |
| | | double[] avgD = new double[n]; |
| | | double[] avgDc = new double[n]; |
| | | for (int i = 0; i < n; i++) { |
| | | double[] a = taxi.get(cities.get(i)); |
| | | if (a == null || a[0] <= 0) { |
| | | missingTaxi.add(cities.get(i)); |
| | | continue; |
| | | } |
| | | Dtax[i] = a[0]; |
| | | Etax[i] = a[2]; |
| | | avgD[i] = a[4]; |
| | | avgDc[i] = a[5]; |
| | | } |
| | | if (!missingTaxi.isEmpty()) { |
| | | throw new RuntimeException("巡游åºç§ææ¥ç¼ºå°ä»¥ä¸å¸å·æ°æ®ï¼" + String.join("ã", missingTaxi)); |
| | | } |
| | | double[] C = new double[n]; |
| | | double[] H = new double[n]; |
| | | double[] Gl = new double[n]; |
| | | double[] Hl = new double[n]; |
| | | double sumG = 0.0; |
| | | double sumDl = 0.0; |
| | | double[] cityRatio = new double[n]; |
| | | for (int i = 0; i < n; i++) { |
| | | C[i] = orderArr[i] / orderSum * pinK; |
| | | cityRatio[i] = Etax[i] / Dtax[i]; |
| | | sumG += C[i] * cityRatio[i]; |
| | | sumDl += C[i] * avgD[i]; |
| | | } |
| | | for (int i = 0; i < n; i++) { |
| | | if (i == 0) { |
| | | H[i] = C[i] * cityRatio[i]; |
| | | } else { |
| | | double rest = sumG - C[0] * cityRatio[0]; |
| | | H[i] = rest == 0.0 ? 0.0 : (C[i] * cityRatio[i]) / rest * (pinCK - C[0] * cityRatio[0]); |
| | | } |
| | | } |
| | | double[] el2 = new double[n]; |
| | | double sumEl2 = 0.0; |
| | | for (int i = 0; i < n; i++) { |
| | | el2[i] = H[i] * avgDc[i]; |
| | | sumEl2 += el2[i]; |
| | | Gl[i] = sumDl == 0.0 ? 0.0 : C[i] * avgD[i] / sumDl * pinZ; |
| | | } |
| | | for (int i = 0; i < n; i++) { |
| | | if (i == 0) { |
| | | Hl[i] = Gl[i]; |
| | | } else { |
| | | double rest = sumEl2 - el2[0]; |
| | | Hl[i] = rest == 0.0 ? 0.0 : el2[i] / rest * (pinCZ - Gl[0]); |
| | | } |
| | | } |
| | | Map<String, WycMetrics> byCity = new LinkedHashMap<>(); |
| | | for (int i = 0; i < n; i++) { |
| | | byCity.put(cities.get(i), new WycMetrics(C[i], H[i], Gl[i], Hl[i])); |
| | | } |
| | | WycMetrics province = new WycMetrics(pinK, pinCK, pinZ, pinCZ); |
| | | return new WycResult(period, byCity, province); |
| | | } |
| | | |
| | | /** 巡游åºç§ææ¥ï¼DBï¼ææå è½½ï¼å¸å· -> [客è¿é,å¨è½¬é,åå¸å
客è¿é,åå¸å
å¨è½¬é,å¹³åè¿è·,åå¸å
å¹³åè¿è·] */ |
| | | private Map<String, double[]> taxiMonthlyOf(String period) { |
| | | Map<String, double[]> map = new LinkedHashMap<>(); |
| | | List<CityTaxiMonthly> rows = cityTaxiMapper.selectList( |
| | | new LambdaQueryWrapper<CityTaxiMonthly>().eq(CityTaxiMonthly::getReportPeriod, period)); |
| | | for (CityTaxiMonthly r : rows) { |
| | | String city = RegionUtil.normalizeCityName(r.getCity()); |
| | | if (city == null || city.isEmpty()) city = "æªç¥"; |
| | | double[] a = map.computeIfAbsent(city, k -> new double[6]); |
| | | a[0] += nz(r.getPassengerVolume()); |
| | | a[1] += nz(r.getTurnover()); |
| | | a[2] += nz(r.getPassengerCity()); |
| | | a[3] += nz(r.getTurnoverCity()); |
| | | if (r.getAvgDistance() != null && r.getAvgDistance() > 0) a[4] = r.getAvgDistance(); |
| | | if (r.getAvgDistanceCity() != null && r.getAvgDistanceCity() > 0) a[5] = r.getAvgDistanceCity(); |
| | | } |
| | | for (double[] a : map.values()) { |
| | | if (a[4] <= 0 && a[0] > 0) a[4] = round(a[1] / a[0], 2); |
| | | if (a[5] <= 0 && a[2] > 0) a[5] = round(a[3] / a[2], 2); |
| | | } |
| | | return map; |
| | | } |
| | | |
| | | /** 读å docs/åå¸å®¢è¿/ãç½çº¦è½¦è®¢ååå
¨çæ»é.xlsxãï¼æ period(yyyy-MM) è¡å pin(B-E) ä¸ 17 å¸å·è®¢å(G-W) */ |
| | | private Map<String, Object> loadMonthlyInput(String period) throws Exception { |
| | | File f = findInput(); |
| | | try (InputStream in = new FileInputStream(f); |
| | | Workbook wb = WorkbookFactory.create(in)) { |
| | | org.apache.poi.ss.usermodel.Sheet sh = wb.getSheetAt(0); |
| | | DataFormatter df = new DataFormatter(); |
| | | List<String> cities = RegionUtil.cityList(); |
| | | int n = cities.size(); |
| | | for (int i = 1; i <= sh.getLastRowNum(); i++) { |
| | | Row row = sh.getRow(i); |
| | | if (row == null) continue; |
| | | Cell c0 = row.getCell(0); |
| | | if (c0 == null) continue; |
| | | String m = df.formatCellValue(c0).trim(); |
| | | if (m.isEmpty()) continue; |
| | | if (m.length() > 7) m = m.substring(0, 7); |
| | | if (!period.equals(m)) continue; |
| | | Map<String, Object> map = new LinkedHashMap<>(); |
| | | map.put("pinK", cellNum(row, 1, df, 0.0)); |
| | | map.put("pinCK", cellNum(row, 2, df, 0.0)); |
| | | map.put("pinZ", cellNum(row, 3, df, 0.0)); |
| | | map.put("pinCZ", cellNum(row, 4, df, 0.0)); |
| | | double[] orders = new double[n]; |
| | | double orderSum = 0.0; |
| | | for (int k = 0; k < n; k++) { |
| | | orders[k] = cellNum(row, 6 + k, df, 0.0); |
| | | orderSum += orders[k]; |
| | | } |
| | | if (orderSum <= 0) orderSum = cellNum(row, 5, df, 0.0); |
| | | map.put("orders", orders); |
| | | map.put("orderSum", orderSum); |
| | | return map; |
| | | } |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | private File findInput() throws Exception { |
| | | String rel = templateDir; |
| | | while (rel.startsWith("./")) rel = rel.substring(2); |
| | | String[] roots = { |
| | | templateDir, |
| | | System.getProperty("user.dir") + "/" + rel, |
| | | System.getProperty("user.dir") + "/../" + rel |
| | | }; |
| | | for (String root : roots) { |
| | | if (root == null || root.trim().isEmpty()) continue; |
| | | for (String name : INPUT_CANDIDATES) { |
| | | File f = new File(root, name); |
| | | if (f.exists() && f.isFile()) return f; |
| | | } |
| | | } |
| | | throw new RuntimeException("æªæ¾å°ãç½çº¦è½¦è®¢ååå
¨çæ»é.xlsxãï¼å« 模æ¿_ åç¼å½åï¼ï¼è¯·æ¾å° docs/åå¸å®¢è¿ ç®å½"); |
| | | } |
| | | |
| | | private double cellNum(Row row, int idx, DataFormatter df, double def) { |
| | | Cell c = row.getCell(idx); |
| | | if (c == null) return def; |
| | | if (c.getCellType() == CellType.NUMERIC) return c.getNumericCellValue(); |
| | | String s = df.formatCellValue(c).replace(",", "").trim(); |
| | | if (s.isEmpty()) return def; |
| | | try { |
| | | return Double.parseDouble(s); |
| | | } catch (NumberFormatException e) { |
| | | return def; |
| | | } |
| | | } |
| | | |
| | | private double nz(Double v) { return v == null ? 0.0 : v; } |
| | | |
| | | private double round(double v, int scale) { |
| | | double factor = Math.pow(10, scale); |
| | | return Math.round(v * factor) / factor; |
| | | } |
| | | } |
| | |
| | | import org.apache.poi.hssf.usermodel.HSSFSheet; |
| | | import org.apache.poi.hssf.usermodel.HSSFWorkbook; |
| | | import org.apache.poi.ss.util.CellRangeAddress; |
| | | import org.apache.poi.openxml4j.util.ZipSecureFile; |
| | | import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCellType; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import org.springframework.stereotype.Service; |
| | |
| | | if (template == null) { |
| | | throw new RuntimeException("æªæ¾å°æ±æ»è¡¨æ¯çã" + year + "å¹´" + month + "æéè·¯è¿è¾éæ±æ»è¡¨.xlsxãï¼docs/çææ±æ»å¤§è¡¨ï¼"); |
| | | } |
| | | double savedZipRatio = ZipSecureFile.getMinInflateRatio(); |
| | | ZipSecureFile.setMinInflateRatio(0.0001); // æ°çæ¯ç styles.xml ç± openpyxl é«å缩ï¼0.0099<0.01ï¼è§¦å POI Zip-bomb 误æ¥ï¼è¯»ååè¿å |
| | | try (InputStream in = new FileInputStream(template); |
| | | XSSFWorkbook wb = new XSSFWorkbook(in)) { |
| | | File donor = resolveSummaryDonor(year, month); |
| | |
| | | log.info("æ±æ»å·¥ä½ç°¿è£åªè³ {} æå®æï¼æ¸
空/æ¹ååå
æ ¼æ°={}", toMonth, trimmed); |
| | | } |
| | | dynamicSummaryYear(wb, year); |
| | | applyTwoDecimalFormat(wb); // æ±æ»å¤§è¡¨ä¿ç人工æ¯çå宽/çå¼ï¼ä¸å autoFitï¼é¿å
¬å¼ä¼æå宽顶çï¼ |
| | | cleanSummarySheetPresentation(wb); // åæ¶å页çéãè¿åéèè¡ï¼å¦åâç线å
车âç页çèµ·æ¥åç¼ºæ°æ®ï¼ |
| | | applyTwoDecimalFormat(wb); // æ°å¼æ¾ç¤ºä¸¤ä½å°æ°ï¼ä¿çå
¨ç²¾åº¦ï¼ï¼% / æ¥æçæ¢ææ ·å¼ä¸æ¹å |
| | | autoFitContentColumns(wb); // ææ°æ®èªå¨å 宽å宽ï¼åªå 宽ä¸ç¼©çªï¼è·³è¿åå¹¶æ 颿 ¼ï¼é²é¿ææ¬æååæçï¼ |
| | | if (!wb.getCTWorkbook().isSetCalcPr()) wb.getCTWorkbook().addNewCalcPr(); |
| | | wb.getCTWorkbook().getCalcPr().setFullCalcOnLoad(true); // è¿å/æ¹åå
¬å¼åæå¼å³éç® |
| | | return toBytes(wb); |
| | | } finally { |
| | | ZipSecureFile.setMinInflateRatio(savedZipRatio); |
| | | } |
| | | } |
| | | |
| | |
| | | if (ds == null) continue; |
| | | Sheet bs = wb.getSheet(ds.getSheetName()); |
| | | if (bs == null) continue; |
| | | // ä¸å£å¾æå页 A..H éæ§å·¦åå·²äº 2026-09-09 ææ¿æ´åå é¤ï¼è¯¥åºåæ°¸ä¸ä»å¤ä»½æ¯çåå¡«ï¼é¿å
âçæå夿´»â |
| | | boolean skipMidRankLeftBlock = "ä¸å£å¾æå".equals(ds.getSheetName()); |
| | | for (int r = ds.getFirstRowNum(); r <= ds.getLastRowNum(); r++) { |
| | | Row dr = ds.getRow(r); |
| | | if (dr == null) continue; |
| | | Row br = bs.getRow(r); |
| | | for (Cell dc : dr) { |
| | | if (dc == null) continue; |
| | | if (skipMidRankLeftBlock && dc.getColumnIndex() < 8) continue; |
| | | CellType t = dc.getCellType(); |
| | | if (t == CellType.BLANK) continue; |
| | | String dtx = summaryCellText(dc); |
| | |
| | | Cell tc = (bc != null) ? bc : tr.getCell(dc.getColumnIndex()); |
| | | if (tc == null) tc = tr.createCell(dc.getColumnIndex()); |
| | | tc.setBlank(); |
| | | applyDonorNumberFormat(wb, tc, dc); |
| | | if (t == CellType.FORMULA) { |
| | | String f = dc.getCellFormula(); |
| | | if (f != null) tc.setCellFormula(f); |
| | |
| | | return restored; |
| | | } |
| | | |
| | | /** è¿ååå¡«æ¶åæ¥ donorï¼å·²åçå¼ç»ä¸ï¼çæ°åæ ¼å¼ï¼ä¿è¯åæ¯/æ°å¼/æåæ ¼æ¾ç¤ºæ ¼å¼ä¸æ¯çä¸è´ */ |
| | | private void applyDonorNumberFormat(XSSFWorkbook wb, Cell dst, Cell src) { |
| | | if (wb == null || dst == null || src == null) return; |
| | | try { |
| | | String fmt = src.getCellStyle().getDataFormatString(); |
| | | if (fmt == null || fmt.isEmpty() || "General".equalsIgnoreCase(fmt)) return; |
| | | org.apache.poi.ss.usermodel.DataFormat df = wb.createDataFormat(); |
| | | short idx = df.getFormat(fmt); |
| | | CellStyle cur = dst.getCellStyle(); |
| | | if (cur != null && idx == cur.getDataFormat()) return; |
| | | CellStyle ns = wb.createCellStyle(); |
| | | if (cur != null) ns.cloneStyleFrom(cur); |
| | | ns.setDataFormat(idx); |
| | | dst.setCellStyle(ns); |
| | | } catch (Exception ignore) { |
| | | // ä¸ªå«æ ¼å¼å¼å¸¸ä¸é»å¡è¿å |
| | | } |
| | | } |
| | | /** åå
æ ¼å
å®¹ææ¬åï¼å
¬å¼å¸¦ = åç¼ï¼ï¼ç¨äºè·¨ç°¿æ¯å¯¹ */ |
| | | private String summaryCellText(Cell c) { |
| | | if (c == null) return null; |
| | |
| | | } |
| | | |
| | | /** æ±æ»è¡¨å¯¼åºåæå
容èªå¨å 宽å宽ï¼åªå 宽ä¸ç¼©çªï¼è·³è¿åå¹¶åå
æ ¼æ é¢ï¼é²é¿æ 颿ååæçï¼ */ |
| | | /** æ±æ»å¤§è¡¨è¾åºåæ¸
çæ¯çæ®ç䏿¥ççéä¸è¡éèï¼çéç®å¤´/éèè¡ä¼è®©æ´é¡µçèµ·æ¥âç¼ºæ°æ®â */ |
| | | private void cleanSummarySheetPresentation(org.apache.poi.ss.usermodel.Workbook wb) { |
| | | if (wb == null) return; |
| | | for (int s = 0; s < wb.getNumberOfSheets(); s++) { |
| | | org.apache.poi.ss.usermodel.Sheet sh = wb.getSheetAt(s); |
| | | if (sh == null) continue; |
| | | if (sh instanceof org.apache.poi.xssf.usermodel.XSSFSheet) { |
| | | org.apache.poi.xssf.usermodel.XSSFSheet xs = (org.apache.poi.xssf.usermodel.XSSFSheet) sh; |
| | | if (xs.getCTWorksheet().isSetAutoFilter()) xs.getCTWorksheet().unsetAutoFilter(); |
| | | for (org.apache.poi.ss.usermodel.Row row : xs) { |
| | | if (row == null) continue; |
| | | org.apache.poi.xssf.usermodel.XSSFRow xr = (org.apache.poi.xssf.usermodel.XSSFRow) row; |
| | | if (xr.getCTRow().isSetHidden()) xr.getCTRow().unsetHidden(); |
| | | } |
| | | } else { |
| | | sh.setAutoFilter(null); |
| | | } |
| | | } |
| | | } |
| | | |
| | | private void autoFitContentColumns(org.apache.poi.ss.usermodel.Workbook wb) { |
| | | if (wb == null) return; |
| | | org.apache.poi.ss.usermodel.DataFormatter dfmt = new org.apache.poi.ss.usermodel.DataFormatter(); |
| | |
| | | |
| | | import javax.annotation.Resource; |
| | | import java.time.LocalDateTime; |
| | | import java.util.regex.Pattern; |
| | | import java.util.regex.Matcher; |
| | | import java.util.List; |
| | | |
| | | /** è§å管çï¼ææ¥è¡¨ç±»åæ¥ç/å¯å/è°æ´éå¼ */ |
| | |
| | | qw.eq(AuditRule::getReportType, reportType.trim()); |
| | | } |
| | | qw.orderByAsc(AuditRule::getSortOrder); |
| | | return Result.ok(ruleMapper.selectList(qw)); |
| | | List<AuditRule> list = ruleMapper.selectList(qw); |
| | | for (AuditRule r : list) syncThresholdText(r); // åç§°/说æééå¼å¨æå±ç¤ºï¼å¦ ±10% â ±20%ï¼ |
| | | return Result.ok(list); |
| | | } |
| | | |
| | | /** å¯åè§å */ |
| | |
| | | if (body.getId() == null) return Result.error("缺å°è§åID"); |
| | | AuditRule rule = ruleMapper.selectById(body.getId()); |
| | | if (rule == null) return Result.error("è§åä¸åå¨"); |
| | | String oldThreshold = rule.getThreshold(); |
| | | if (body.getThreshold() != null) rule.setThreshold(body.getThreshold()); |
| | | if (body.getAlertLevel() != null) rule.setAlertLevel(body.getAlertLevel()); |
| | | if (body.getDescription() != null) rule.setDescription(body.getDescription()); |
| | | // éå¼å忶忥è§ååç§°ä¸è¯´æï¼åç§°/说æé䏿§éå¼å¯¹åºç N% çæ®µææ°é弿¹åï¼ï¼å¹¶éä¿åæä¹
å |
| | | if (body.getThreshold() != null && !body.getThreshold().equals(oldThreshold)) { |
| | | syncThresholdText(rule, oldThreshold); |
| | | } |
| | | rule.setUpdatedAt(LocalDateTime.now()); |
| | | ruleMapper.updateById(rule); |
| | | return Result.ok("å·²ä¿å"); |
| | | } |
| | | } |
| | | |
| | | /** % åçæ°å¼ï¼åç§°/说æä¸ééå¼å¨æååççæ®µï¼% åå¯è½æ¯ ±ã>ãè¶
è¿ãé«åº çæè¿°è¯ï¼ä»
æ¿æ¢æ°åæ¬èº«ï¼ */ |
| | | private static final Pattern PCT_NUM = Pattern.compile("\\d+(?:\\.\\d+)?(?=%)"); |
| | | |
| | | /** è§£æéå¼å符串ä¸ç¬¬ä¸ä¸ªæ°å¼ï¼æ æ³è§£æè¿å null */ |
| | | private Double parseThresholdNum(String threshold) { |
| | | if (threshold == null || threshold.trim().isEmpty()) return null; |
| | | java.util.regex.Matcher m = Pattern.compile("\\d+(?:\\.\\d+)?").matcher(threshold.trim()); |
| | | if (!m.find()) return null; |
| | | try { |
| | | return Double.parseDouble(m.group()); |
| | | } catch (Exception e) { |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | /** æ°å¼å±ç¤ºï¼æ´æ°å»æå°æ°ä½ï¼å
¶ä½ä¿çå精度 */ |
| | | private String fmtNum(double v) { |
| | | long l = Math.round(v); |
| | | if (Math.abs(v - l) < 1e-9) return Long.toString(l); |
| | | return new java.math.BigDecimal(String.valueOf(v)).stripTrailingZeros().toPlainString(); |
| | | } |
| | | |
| | | /** ç±é弿°å¼æ¨å¯¼â说ææåéåçæ¯ç¾åä¹å âçåéå£å¾ï¼ |
| | | * â é弿¬èº«å°±æ¯ç¾åæ°ï¼å¦ 20 â ±20%ï¼ï¼ |
| | | * â¡ é弿¯å°æ°æ¯ä¾ï¼å¦ 0.02 â 2%ã0.5 â 50%ï¼ï¼æ¤æ¶ <1 æå¯ç¨ï¼ |
| | | * ⢠é弿¯æ¯å¼ï¼å¦ 1.3 â é«åº30%ï¼ï¼æ¤æ¶ >1 æå¯ç¨ã */ |
| | | private double[] thresholdPercentCandidates(double v) { |
| | | double[] cands; |
| | | if (v > 0 && v < 1) { |
| | | cands = new double[]{v, v * 100}; |
| | | } else if (v > 1) { |
| | | cands = new double[]{v, (v - 1) * 100}; |
| | | } else { |
| | | cands = new double[]{v}; |
| | | } |
| | | return cands; |
| | | } |
| | | |
| | | /** ææ§éå¼å¹é
ææ¬ä¸å·²æçç¾åæ¯ç段ï¼ä»
æ¿æ¢â䏿§éå¼å¯¹å¾ä¸âçæ°å为æ°éå¼å¯¹åºæ°åï¼å¯¹ä¸ä¸çæ°åï¼å¦è¯´æéä¸é弿 å
³çæ°å¼ï¼ä¿æä¸å¨ */ |
| | | private String decorateThresholdText(String text, String oldThreshold, String newThreshold) { |
| | | if (text == null || text.trim().isEmpty()) return text; |
| | | Double oldNum = parseThresholdNum(oldThreshold); |
| | | Double newNum = parseThresholdNum(newThreshold); |
| | | if (oldNum == null || newNum == null) return text; |
| | | double[] oldCands = thresholdPercentCandidates(oldNum); |
| | | double[] newCands = thresholdPercentCandidates(newNum); |
| | | if (oldCands.length != newCands.length) return text; |
| | | java.util.regex.Matcher m = PCT_NUM.matcher(text); |
| | | StringBuffer sb = new StringBuffer(); |
| | | while (m.find()) { |
| | | double token; |
| | | try { |
| | | token = Double.parseDouble(m.group()); |
| | | } catch (Exception e) { |
| | | continue; |
| | | } |
| | | String repl = null; |
| | | for (int i = 0; i < oldCands.length; i++) { |
| | | if (Math.abs(oldCands[i] - token) < 1e-9) { |
| | | repl = fmtNum(newCands[i]); |
| | | break; |
| | | } |
| | | } |
| | | if (repl == null) continue; |
| | | m.appendReplacement(sb, Matcher.quoteReplacement(repl)); |
| | | } |
| | | m.appendTail(sb); |
| | | return sb.toString(); |
| | | } |
| | | |
| | | /** åç§°/说æééå¼åæ¥ï¼update æ¶æ æ§âæ° æ¹åå¹¶æä¹
åï¼ */ |
| | | private void syncThresholdText(AuditRule rule, String oldThreshold) { |
| | | if (rule == null || rule.getThreshold() == null) return; |
| | | rule.setRuleName(decorateThresholdText(rule.getRuleName(), oldThreshold, rule.getThreshold())); |
| | | rule.setDescription(decorateThresholdText(rule.getDescription(), oldThreshold, rule.getThreshold())); |
| | | } |
| | | |
| | | /** 读å表æ¶èªæï¼ä»
彿æ¬ç段ä¸å½åéå¼å¯¹åºæ¶ææ¹åï¼å¹çï¼ä¸è¯¯ä¼¤ä¸é弿 å
³çæ°åï¼ */ |
| | | private void syncThresholdText(AuditRule rule) { |
| | | syncThresholdText(rule, rule == null ? null : rule.getThreshold()); |
| | | } |
| | | } |
| | |
| | | <el-main :class="{ 'main-focus': focusMode }" style="display:flex;flex-direction:column;min-height:0"> |
| | | <h3 v-show="!focusMode" style="flex:none;margin:0 0 10px">å®¡æ ¸ç»æ</h3> |
| | | <el-form :inline="true" style="flex:none"> |
| | | <el-form-item label="æ¥è¡¨æ"> |
| | | <el-date-picker v-model="period" type="month" placeholder="éæ©æä»½" value-format="yyyy-MM" @change="onPeriodChange"></el-date-picker> |
| | | </el-form-item> |
| | | <el-form-item label="æ¥è¡¨ç±»å"> |
| | | <el-radio-group v-model="reportType" @change="onTypeChange"> |
| | | <el-radio label="H2032">è´§è¿ææ¥</el-radio> |
| | |
| | | |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | <el-form-item label="æ¥è¡¨æ"> |
| | | <el-date-picker v-model="period" type="month" placeholder="éæ©æä»½" value-format="yyyy-MM" @change="onPeriodChange"></el-date-picker> |
| | | </el-form-item> |
| | | |
| | | <el-form-item> |
| | | <el-button type="primary" @click="executeAudit" :loading="loading">æ§è¡å®¡æ ¸</el-button> |
| | | <el-button type="success" plain @click="markAudited" :loading="marking">æ è®°å·²å®¡æ ¸</el-button> |
| | |
| | | <i :class="statusIcon(row.status)"></i> {{ statusText(row.status) }} |
| | | </el-tag> |
| | | <span class="spacer"></span> |
| | | <el-link v-if="dataType(reportType)" type="primary" :underline="false" size="mini" @click="goData(row)">æ°æ®</el-link> |
| | | <el-tag v-if="explainType(reportType)" size="mini" :type="row.verifyExplanation ? 'success' : 'warning'" |
| | | style="cursor:pointer" :title="expandedExplain === row.reportId ? 'æ¶èµ·è§£é' : 'å±å¼å¡«å/æ¥çè§£é'" |
| | | @click="toggleExplain(row.reportId)"> |
| | | {{ row.verifyExplanation ? 'è§£éï¼å·²å¡«å' : 'è§£éï¼æªå¡«å' }} |
| | | </el-tag> |
| | | <el-link v-if="dataType(reportType)" type="primary" :underline="false" size="mini" @click="openMonthReport(row)">æ°æ®</el-link> |
| | | <el-button v-if="row.status === 'PENDING'" size="mini" type="success" icon="el-icon-check" round @click="review(row, 'CONFIRMED')">确认</el-button> |
| | | <el-button v-if="row.status === 'PENDING'" size="mini" type="info" icon="el-icon-close" round plain @click="review(row, 'IGNORED')">忽ç¥</el-button> |
| | | <span v-else class="done-text">å·²å¤ç</span> |
| | |
| | | <div class="detail-line"><span class="dt-label">å®é
</span><span class="dt-val">{{ row.actualValue }}</span></div> |
| | | <div class="detail-line"><span class="dt-label">åºå</span><span class="dt-val">{{ row.thresholdValue }}</span></div> |
| | | <div class="detail-line"><span class="dt-label">å·®å¼</span><span class="dt-val dt-warn">{{ row.deviation }}</span></div> |
| | | </div> |
| | | </div> |
| | | <div v-if="explainType(reportType) && expandedExplain === row.reportId" class="explain-side" style="margin:0 12px 10px"> |
| | | <div class="explain-head"> |
| | | <span class="explain-title">ä¼ä¸è§£é</span> |
| | | <el-tag size="mini" :type="row.verifyExplanation ? 'success' : 'warning'">{{ row.verifyExplanation ? '已填å' : 'æªå¡«å' }}</el-tag> |
| | | <span style="flex:1"></span> |
| | | <el-button size="mini" text @click="expandedExplain = null">æ¶èµ·</el-button> |
| | | </div> |
| | | <span v-if="row.verifyExplanation" class="explain-cur">{{ row.verifyExplanation }}</span> |
| | | <el-input v-model="explainDrafts[row.reportId]" type="textarea" :rows="2" resize="none" |
| | | placeholder="å¡«å/ä¿®æ¹è¯¥ä¼ä¸çè§£é说æâ¦"></el-input> |
| | | <div class="explain-actions"> |
| | | <el-button size="mini" type="primary" plain :loading="savingExplainId === row.reportId" @click="saveExplain(row)">ä¿åè§£é</el-button> |
| | | <el-button v-if="(explainDrafts[row.reportId] || '') !== (row.verifyExplanation || '')" size="mini" text @click="resetDraft(row.reportId)">éç½®</el-button> |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | <b>{{ item.ruleName }}</b> |
| | | <el-tag :type="item.alertLevel === 'RED' ? 'danger' : 'warning'" size="mini">{{ item.alertLevel }}</el-tag> |
| | | <el-tag :type="statusType(item.status)" size="mini">{{ statusText(item.status) }}</el-tag> |
| | | <el-link v-if="dataType(reportType)" type="primary" :underline="false" size="mini" @click="goData(item)">æ°æ®</el-link> |
| | | <el-link v-if="dataType(reportType)" type="primary" :underline="false" size="mini" @click="openMonthReport(item)">æ°æ®</el-link> |
| | | <span style="flex:1"></span> |
| | | <el-button v-if="item.status === 'PENDING'" size="mini" type="success" @click="review(item, 'CONFIRMED')">确认</el-button> |
| | | <el-button v-if="item.status === 'PENDING'" size="mini" type="info" @click="review(item, 'IGNORED')">忽ç¥</el-button> |
| | |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="ä¼ä¸è§£é" width="340"> |
| | | <template slot-scope="scope"> |
| | | <div v-if="explainType(reportType) && scope.row.items[0]" class="explain-cell"> |
| | | <div v-if="expandedExplain !== scope.row.items[0].reportId" class="explain-compact"> |
| | | <el-tag size="mini" :type="scope.row.items[0].verifyExplanation ? 'success' : 'warning'">{{ scope.row.items[0].verifyExplanation ? '已填å' : 'æªå¡«å' }}</el-tag> |
| | | <div v-if="scope.row.items[0].verifyExplanation" class="explain-preview">{{ scope.row.items[0].verifyExplanation }}</div> |
| | | <el-button size="mini" text type="primary" @click="expandedExplain = scope.row.items[0].reportId">å¡«å/ä¿®æ¹</el-button> |
| | | </div> |
| | | <div v-else class="explain-side"> |
| | | <div class="explain-head"> |
| | | <span class="explain-title">ä¼ä¸è§£é</span> |
| | | <span style="flex:1"></span> |
| | | <el-button size="mini" text @click="expandedExplain = null">æ¶èµ·</el-button> |
| | | </div> |
| | | <span v-if="scope.row.items[0].verifyExplanation" class="explain-cur">{{ scope.row.items[0].verifyExplanation }}</span> |
| | | <el-input v-model="explainDrafts[scope.row.items[0].reportId]" type="textarea" :rows="2" resize="none" |
| | | placeholder="å¡«å/ä¿®æ¹è¯¥ä¼ä¸çè§£é说æâ¦"></el-input> |
| | | <div class="explain-actions"> |
| | | <el-button size="mini" type="primary" plain :loading="savingExplainId === scope.row.items[0].reportId" @click="saveExplain(scope.row.items[0])">ä¿åè§£é</el-button> |
| | | <el-button v-if="(explainDrafts[scope.row.items[0].reportId] || '') !== (scope.row.items[0].verifyExplanation || '')" size="mini" text @click="resetDraft(scope.row.items[0].reportId)">éç½®</el-button> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <span v-else style="color:#C0C4CC;font-size:12px">â</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="æä½" width="130"> |
| | | <template slot-scope="scope"> |
| | | <el-button v-if="hasPending(scope.row)" size="mini" type="success" plain @click="reviewAll(scope.row, 'CONFIRMED')">å
¨é¨ç¡®è®¤</el-button> |
| | |
| | | </div> |
| | | </el-main> |
| | | </el-container> |
| | | |
| | | <el-dialog title="æ°æ®æ¥çï¼ææ¥æ ·å¼ï¼" :visible.sync="monthVisible" width="880px" top="4vh" custom-class="mr-dialog"> |
| | | <div v-if="monthLoading" style="padding:40px 0;text-align:center;color:#909399">å è½½ä¸â¦</div> |
| | | <div v-else-if="!monthRecords.length" style="padding:30px 0;text-align:center;color:#909399"> |
| | | æªæ¥è¯¢å°è¯¥ä¼ä¸ã该æ¥è¡¨æçå¡«æ¥æ°æ®ï¼å¯è½è¿æªå¯¼å
¥ï¼ |
| | | </div> |
| | | <div v-else class="mr-body"> |
| | | <div v-for="(rec, ri) in monthRecords" :key="ri" class="mr-card"> |
| | | <div class="mr-title">{{ monthTitle(rec) }}</div> |
| | | <table class="mr-meta"> |
| | | <tbody> |
| | | <tr v-for="(m, mi) in monthMeta(rec)" :key="mi"> |
| | | <td class="mr-meta-k">{{ m.label }}</td> |
| | | <td class="mr-meta-v">{{ fmtVal(m.value) }}</td> |
| | | </tr> |
| | | </tbody> |
| | | </table> |
| | | <div v-for="sec in monthSections(rec)" :key="sec.title" class="mr-sec"> |
| | | <div class="mr-sec-title">{{ sec.title }}</div> |
| | | <table class="mr-sec-tab" border="1"> |
| | | <thead> |
| | | <tr> |
| | | <th style="width:34%">ææ åç§°</th> |
| | | <th v-for="(h, hi) in sec.head" :key="hi" style="width:16.5%">{{ h }}</th> |
| | | </tr> |
| | | </thead> |
| | | <tbody> |
| | | <tr v-for="(rw, rwi) in sec.rows" :key="rwi"> |
| | | <td>{{ rw.label }}</td> |
| | | <td v-for="(c, ci) in rw.cells" :key="ci">{{ fmtVal(c.v) }}</td> |
| | | </tr> |
| | | </tbody> |
| | | </table> |
| | | </div> |
| | | <div v-if="rec.verifyExplanation || rec.reportNotes" class="mr-note"> |
| | | <div v-if="rec.verifyExplanation" class="mr-note-line"><b>æ ¸å®è§£éï¼</b>{{ rec.verifyExplanation }}</div> |
| | | <div v-if="rec.reportNotes" class="mr-note-line"><b>夿³¨ï¼</b>{{ rec.reportNotes }}</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <span slot="footer"> |
| | | <el-button size="small" @click="monthVisible = false">å
³é</el-button> |
| | | </span> |
| | | </el-dialog> |
| | | </el-container> |
| | | </template> |
| | | <script> |
| | |
| | | import api from '@/api' |
| | | const DATA_TYPE_MAP = { H2032: 'h2032', H2031: 'h2031', CITY_BUS: 'cityBus', CITY_TAXI: 'cityTaxi' } |
| | | const EXPLAIN_TYPES = ['H2032', 'H2031', 'CITY_BUS', 'CITY_TAXI'] |
| | | |
| | | const MONTH_CFG = { |
| | | h2032: { |
| | | meta: [['æ¥è¡¨æ', 'reportPeriod'], ['ä¼ä¸åç§°', 'enterpriseName'], ['ç»ä¸ç¤¾ä¼ä¿¡ç¨ä»£ç ', 'unifiedCreditCode'], ['å¡«æ¥åä½', 'reportUnit']], |
| | | sections: [ |
| | | { title: 'ä¸ãè¿åæ
åµ', head: ['è½¦è¾æ°ï¼è¾ï¼', 'æ è®°å¨ä½æ°ï¼å¨ï¼'], rows: [ |
| | | ['æ»è®¡', ['vehicleTotal', 'tonsTotal']], |
| | | ['å
¶ä¸ï¼çµå¼è½¦', ['vehicleTractor', null]], |
| | | ['æè½¦', ['vehicleTrailer', 'tonsTrailer']], |
| | | ['å
¶ä¸ï¼éè£
箱车', ['vehicleContainer', 'tonsContainer']], |
| | | ['æ´è½¦', ['vehicleWhole', 'tonsWhole']] |
| | | ]}, |
| | | { title: 'äºãè¿è¾ç产æ
åµ', head: ['è´§è¿éï¼å¨ï¼', 'è´§ç©å¨è½¬éï¼å¨å
¬éï¼'], rows: [ |
| | | ['è¿è¾é', ['freightTotal', 'turnoverTotal']], |
| | | ['å
¶ä¸ï¼éè£
ç®±', ['freightContainer', null]], |
| | | ['å
¶ä¸ï¼ç
¤çåå¶å', ['freightCoal', null]], |
| | | ['ç³æ²¹ãå¤©ç¶æ°åå¶å', ['freightOilGas', null]], |
| | | ['å
¶ä¸ï¼åæ²¹', ['freightCrudeOil', null]], |
| | | ['éå±ç¿ç³', ['freightMetalOre', null]], |
| | | ['å
¶ä¸ï¼éç¿ç³', ['freightIronOre', null]], |
| | | ['ç¿å»ºæ§å»ºçææ', ['freightBuilding', null]], |
| | | ['ç²®é£', ['freightGrain', null]] |
| | | ]}, |
| | | { title: '平忿 ', head: [], rows: [ |
| | | ['货车平åå¨ä½', ['avgTonnage', null]], |
| | | ['货车平åè¿è·', ['avgDistance', null]] |
| | | ]}, |
| | | { title: 'å¡«æ¥äººä¿¡æ¯', head: [], rows: [ |
| | | ['åä½è´è´£äºº', ['unitLeader', null]], ['ç»è®¡è´è´£äºº', ['statsLeader', null]], |
| | | ['填表人', ['contactPerson', null]], ['èç³»çµè¯', ['contactPhone', null]], ['æ¥åºæ¥æ', ['reportDate', null]] |
| | | ]} |
| | | ] |
| | | }, |
| | | h2031: { |
| | | meta: [['æ¥è¡¨æ', 'reportPeriod'], ['ä¼ä¸åç§°', 'enterpriseName']], |
| | | sections: [ |
| | | { title: 'ä¸ãè¿åæ
åµ', head: ['è½¦è¾æ°ï¼è¾ï¼', 'æ ¸å®è½½å®¢ä½ï¼å®¢ä½ï¼'], rows: [ |
| | | ['æ»è®¡', ['vehicleTotal', 'seatTotal']], |
| | | ['客è¿ç车ï¼å«å®çº¿æ
游客è¿å®¢è½¦ï¼', ['vehicleSchedule', 'seatSchedule']], |
| | | ['客è¿å
车ï¼å«éå®çº¿æ
游客è¿å®¢è½¦ï¼', ['vehicleCharter', 'seatCharter']] |
| | | ]}, |
| | | { title: 'äºãè¿è¾ç产æ
åµ', head: ['客è¿éï¼äººæ¬¡ï¼', 'æ
客å¨è½¬éï¼äººå
¬éï¼'], rows: [ |
| | | ['æ»è®¡', ['passengerTotal', 'turnoverTotal']], |
| | | ['ä¸ç±»å®¢è¿ç线ï¼å«å®çº¿æ
游ï¼', ['passengerClass1', 'turnoverClass1']], |
| | | ['äºç±»å®¢è¿ç线ï¼å«å®çº¿æ
游ï¼', ['passengerClass2', 'turnoverClass2']], |
| | | ['ä¸ç±»å®¢è¿ç线ï¼å«å®çº¿æ
游ï¼', ['passengerClass3', 'turnoverClass3']], |
| | | ['å类客è¿ç线ï¼å«å®çº¿æ
游ï¼', ['passengerClass4', 'turnoverClass4']], |
| | | ['客è¿å
车ï¼å«éå®çº¿æ
游ï¼', ['passengerCharter', 'turnoverCharter']] |
| | | ]}, |
| | | { title: '客è¿å¹³åè¿è·', head: [], rows: [ |
| | | ['客è¿å¹³åè¿è·', ['avgDistanceTotal', null]], |
| | | ['ä¸ç±»å®¢è¿ç线平åè¿è·', ['avgDistanceClass1', null]], |
| | | ['äºç±»å®¢è¿ç线平åè¿è·', ['avgDistanceClass2', null]], |
| | | ['ä¸ç±»å®¢è¿ç线平åè¿è·', ['avgDistanceClass3', null]], |
| | | ['å类客è¿ç线平åè¿è·', ['avgDistanceClass4', null]], |
| | | ['客è¿å
车平åè¿è·', ['avgDistanceCharter', null]] |
| | | ]} |
| | | ] |
| | | }, |
| | | cityBus: { |
| | | meta: [['æ¥è¡¨æ', 'reportPeriod'], ['å¸å·', 'city'], ['ä¼ä¸åç§°', 'enterpriseName']], |
| | | sections: [ |
| | | { title: 'ä¸ãå
Œ
±æ±½çµè½¦è¿è¥', head: [], rows: [ |
| | | ['è¿è¥è½¦æ°ï¼è¾ï¼', ['opVehicles', null]], ['è¿è¥ç«ç¹æ»ä¸ªæ°ï¼ä¸ªï¼', ['stopTotal', null]], |
| | | ['å
¶ä¸ï¼åå¸è¿è¥ç«ç¹', ['stopCity', null]], ['客è¿éï¼ä¸äººæ¬¡ï¼', ['passengerVolume', null]], |
| | | ['å
¶ä¸ï¼åå¸å®¢è¿é', ['passengerCity', null]], ['æ
客å¨è½¬éï¼ä¸äººå
¬éï¼', ['turnover', null]], |
| | | ['å
¶ä¸ï¼å叿
客å¨è½¬é', ['turnoverCity', null]] |
| | | ]}, |
| | | { title: 'äºãæ´¾çææ ä¸å¢é', head: [], rows: [ |
| | | ['å¹³åè¿è·ï¼å
¬éï¼', ['avgDistance', null]], ['åå¸å
å¹³åè¿è·', ['avgDistanceCity', null]], |
| | | ['åé
å乡客è¿é', ['passengerChengxiang', null]], ['åé
å乡å¨è½¬é', ['turnoverChengxiang', null]], |
| | | ['åé
å乡平åè¿è·', ['avgDistanceChengxiang', null]], ['客è¿éç¯æ¯', ['ratePassengerMom', null]], |
| | | ['åå¸å
客è¿éç¯æ¯', ['ratePassengerCityMom', null]], ['åé
å乡客è¿éç¯æ¯', ['rateChengxiangMom', null]], |
| | | ['客è¿é忝', ['ratePassengerYoy', null]], ['åå¸å
客è¿éå æ¯', ['passengerCityRatio', null]], |
| | | ['åé
å乡客è¿éå æ¯', ['chengxiangRatio', null]], ['填表人', ['contactPerson', null]], |
| | | ['æ¥åºæ¥æ', ['reportDate', null]] |
| | | ]} |
| | | ] |
| | | }, |
| | | cityTaxi: { |
| | | meta: [['æ¥è¡¨æ', 'reportPeriod'], ['å¸å·', 'city'], ['ä¼ä¸åç§°', 'enterpriseName']], |
| | | sections: [ |
| | | { title: 'ä¸ã巡游åºç§è¿è¥æå¡', head: [], rows: [ |
| | | ['è½½å®¢è½¦æ¬¡æ»æ°ï¼ä¸è½¦æ¬¡ï¼', ['tripTotal', null]], ['å
¶ä¸ï¼åå¸è½½å®¢è½¦æ¬¡', ['tripCity', null]], |
| | | ['客è¿éï¼ä¸äººæ¬¡ï¼', ['passengerVolume', null]], ['å
¶ä¸ï¼åå¸å®¢è¿é', ['passengerCity', null]], |
| | | ['æ
客å¨è½¬éï¼ä¸äººå
¬éï¼', ['turnover', null]], ['å
¶ä¸ï¼å叿
客å¨è½¬é', ['turnoverCity', null]], |
| | | ['è¿è¥è½¦è¾æ°ï¼è¾ï¼', ['opVehicles', null]] |
| | | ]}, |
| | | { title: 'äºãæ´¾çææ ä¸å¢é', head: [], rows: [ |
| | | ['å¹³åè¿è·ï¼å
¬éï¼', ['avgDistance', null]], ['åå¸å
å¹³åè¿è·', ['avgDistanceCity', null]], |
| | | ['å车次载客人æ°', ['passengersPerTrip', null]], ['è½½å®¢è½¦æ¬¡ç¯æ¯', ['rateTripMom', null]], |
| | | ['è½½å®¢è½¦æ¬¡åæ¯', ['rateTripYoy', null]], ['客è¿éç¯æ¯', ['ratePassengerMom', null]], |
| | | ['客è¿é忝', ['ratePassengerYoy', null]], ['åå¸å
客è¿éå æ¯', ['passengerCityRatio', null]], |
| | | ['åé
å乡平åè¿è·', ['avgDistanceChengxiang', null]] |
| | | ]} |
| | | ] |
| | | } |
| | | } |
| | | export default { |
| | | components: { AppHeader }, |
| | | name: 'AuditResult', |
| | |
| | | return { |
| | | period: '', reportType: 'H2032', loading: false, marking: false, results: [], ruleStats: [], statsCollapsed: false, |
| | | enterpriseFilter: '', ruleFilter: '', viewMode: 'merged', batchSelection: [], focusMode: false, |
| | | explainDrafts: {}, savingExplainId: null, expandedExplain: null |
| | | explainDrafts: {}, savingExplainId: null, expandedExplain: null, |
| | | monthVisible: false, monthLoading: false, monthType: '', monthPeriod: '', monthKeyword: '', monthRecords: [], monthColumns: [] |
| | | } |
| | | }, |
| | | computed: { |
| | |
| | | methods: { |
| | | dataType(t) { return DATA_TYPE_MAP[t] || '' }, |
| | | explainType(t) { return EXPLAIN_TYPES.indexOf(t) >= 0 }, |
| | | goData(row) { |
| | | openMonthReport(row) { |
| | | const type = DATA_TYPE_MAP[this.reportType] |
| | | if (!type) return |
| | | this.$router.push({ path: '/data', query: { type, period: row.reportPeriod, keyword: row.enterpriseName || row.city || '' } }) |
| | | this.monthType = type |
| | | this.monthPeriod = row.reportPeriod |
| | | this.monthKeyword = row.enterpriseName || row.city || '' |
| | | this.monthRecords = [] |
| | | this.monthColumns = [] |
| | | this.monthVisible = true |
| | | this.monthLoading = true |
| | | api.get('/data/list', { |
| | | params: { |
| | | type, period: row.reportPeriod, |
| | | keyword: row.enterpriseName || row.city || '', |
| | | page: 1, size: 50 |
| | | }, timeout: 60000 |
| | | }).then(res => { |
| | | const d = res.data || {} |
| | | this.monthRecords = d.records || [] |
| | | this.monthColumns = d.columns || [] |
| | | if (!this.monthRecords.length) this.$message.warning('æªæ¥è¯¢å°è¯¥ä¼ä¸è¯¥æ¥è¡¨æçå¡«æ¥æ°æ®ï¼å¯è½å°æªå¯¼å
¥ï¼') |
| | | }).catch(e => { |
| | | if (e && e._toast) return |
| | | this.$message.error('ææ¥æ°æ®æ¥è¯¢å¤±è´¥') |
| | | }).finally(() => { this.monthLoading = false }) |
| | | }, |
| | | monthTitle(rec) { |
| | | const cfg = MONTH_CFG[this.monthType] || null |
| | | if (!cfg) return (this.monthKeyword || '') + 'ï¼' + this.monthPeriod + 'ï¼' |
| | | const name = rec.enterpriseName || rec.city || this.monthKeyword || '' |
| | | return name + ' ' + (rec.reportPeriod || this.monthPeriod || '') + ' ææ¥æ°æ®' |
| | | }, |
| | | monthMeta(rec) { |
| | | const cfg = MONTH_CFG[this.monthType] || null |
| | | if (!cfg) return [] |
| | | return cfg.meta.map(m => ({ label: m[0], value: rec[m[1]] })).filter(m => m.value !== undefined) |
| | | }, |
| | | monthSections(rec) { |
| | | const cfg = MONTH_CFG[this.monthType] |
| | | if (!cfg) return [] |
| | | return cfg.sections.map(sec => ({ |
| | | title: sec.title, head: sec.head || [], |
| | | rows: sec.rows.map(r => ({ label: r[0], cells: (r[1] || []).map(prop => ({ prop, v: prop ? rec[prop] : null })) })) |
| | | .filter(rw => rw.cells.some(c => c.v !== null && c.v !== undefined && c.v !== '')) |
| | | })).filter(sec => sec.rows.length) |
| | | }, |
| | | fmtVal(v) { |
| | | if (v === null || v === undefined || v === '') return 'â' |
| | | if (typeof v === 'number') return String(v) |
| | | return String(v) |
| | | }, |
| | | goExplain(row) { |
| | | this.$router.push({ path: '/explain', query: { reportType: this.reportType, keyword: row.enterpriseName || row.city || '', period: row.reportPeriod } }) |
| | |
| | | .stat-num { color: #909399; } |
| | | .stat-num b { font-weight: 700; } |
| | | .hit-num { color: #E6A23C; } |
| | | |
| | | .mr-dialog .el-dialog__body { padding: 12px 18px; } |
| | | .mr-body { max-height: 66vh; overflow-y: auto; } |
| | | .mr-card { border: 1px solid #DCDFE6; border-radius: 6px; margin-bottom: 14px; overflow: hidden; } |
| | | .mr-title { background: #409EFF; color: #fff; font-weight: 600; padding: 8px 12px; font-size: 15px; } |
| | | .mr-meta { width: 100%; border-collapse: collapse; background: #F7F9FC; } |
| | | .mr-meta td { border: 1px solid #EBEEF5; padding: 6px 10px; font-size: 13px; } |
| | | .mr-meta-k { width: 120px; color: #909399; background: #F0F4FA; } |
| | | .mr-meta-v { color: #303133; font-weight: 600; } |
| | | .mr-sec { padding: 10px 12px 4px; } |
| | | .mr-sec-title { font-weight: 600; color: #303133; margin: 4px 0 8px; } |
| | | .mr-sec-tab { width: 100%; border-collapse: collapse; font-size: 13px; } |
| | | .mr-sec-tab th, .mr-sec-tab td { border: 1px solid #DCDFE6; padding: 5px 8px; text-align: left; color: #303133; } |
| | | .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; } |
| | | </style> |
| | |
| | | scaleSplit: '模æ¿_è§ä¸è§ä¸æåè¿è¾é.xlsx', |
| | | freightTurnover: '模æ¿_è´§è¿éå¨è½¬é.xlsx', |
| | | passengerMonthly: 'å
¬è·¯æ
客è¿è¾æåº¦ç产æ
åµ.xlsxï¼å«è¿æ¿è½¦è¾æ°sheetï¼', |
| | | passengerAuth: '模æ¿_å
¬è·¯æ
å®¢è¿æ¿è½¦è¾æ°.xlsxï¼åï¼ä¼ä¸ä»£ç /ä¼ä¸åç§°/è½¦è¾æ°/è½½å®¢ä½æ°ï¼', |
| | | passengerAuth: '模æ¿_å
¬è·¯æ
å®¢è¿æ¿è½¦è¾æ°.xlsï¼æ¯æ ä¼ä¸ä»£ç /ä¼ä¸åç§°/è½¦è¾æ°/è½½å®¢ä½æ° ä¸ è¿æ¿åºå¯¼åº OWNERNAME/æ»è½¦è¾æ°/客使°ï¼', |
| | | passengerIndividual: '个ä½å®¢è¿éæ±æ».xlsxï¼åï¼æå±å°åº/ä¼ä¸ä»£ç /ä¼ä¸åç§°/个ä½å®¢è¿é/ä¸ªä½æ
客å¨è½¬éï¼', |
| | | energyMonthly: 'é路货è¿è½¦è¾è½æºæ¶èæ
åµï¼2026å¹´ï¼.xlsxï¼è½èæç»+è¿æ¿è½¦è¾ä¿¡æ¯ä¸¤sheetï¼', |
| | | energyAuth: '模æ¿_è½è车è¾è¿æ¿ä¿¡æ¯.xlsxï¼åï¼è½¦çå·/车è¾ç±»å/çæç±»å/æ è®°å¨ä½/åçµå¼è´¨éï¼', |
| | |
| | | scaleSplit: 'è´§è¿/模æ¿_è§ä¸è§ä¸æåè¿è¾é.xlsx', |
| | | freightTurnover: 'è´§è¿/模æ¿_è´§è¿éå¨è½¬é.xlsx', |
| | | passengerMonthly: 'å
¬è·¯æ
客/模æ¿_交ä¼ç»H203-1表_å
¬è·¯æ
客è¿è¾æåº¦ç产æ
åµ.xlsx', |
| | | passengerAuth: 'å
¬è·¯æ
客/模æ¿_å
¬è·¯æ
å®¢è¿æ¿è½¦è¾æ°.xlsx', |
| | | passengerAuth: 'å
¬è·¯æ
客/模æ¿_å
¬è·¯æ
å®¢è¿æ¿è½¦è¾æ°.xls', |
| | | passengerIndividual: 'å
¬è·¯æ
客/个ä½å®¢è¿éæ±æ».xlsx', |
| | | energyMonthly: 'è½è/模æ¿_é路货è¿è½¦è¾è½æºæ¶èæ
åµï¼2026ï¼.xlsx', |
| | | energyAuth: 'è½è/模æ¿_è½è车è¾è¿æ¿ä¿¡æ¯.xlsx', |
| | |
| | | total: 0, |
| | | records: [], |
| | | columns: [], |
| | | loading: false |
| | | loading: false, |
| | | loadingMore: false |
| | | } |
| | | }, |
| | | methods: { |
| | | loadData() { |
| | | this.loading = true |
| | | this.loadingMore = false |
| | | api.get('/data/list', { |
| | | params: { |
| | | type: this.type, |
| | |
| | | this.$message.error('æ°æ®æ¥è¯¢å¤±è´¥') |
| | | }).finally(() => { |
| | | this.loading = false |
| | | this.$nextTick(() => this.attachBodyScroll()) |
| | | }) |
| | | }, |
| | | // el-table åºå®é«åº¦åï¼çæ£çç«åæ»å¨å®¹å¨æ¯å
é¨ç body-wrapperï¼é¡µé¢æ¬èº«ä¸æ»å¨ï¼ |
| | | attachBodyScroll() { |
| | | const wrap = this.$refs.tableWrap |
| | | if (!wrap) return |
| | | const bw = wrap.querySelector('.el-table__body-wrapper') |
| | | if (bw && bw._vwScrollHandler !== this.onScroll) { |
| | | if (bw._vwScrollHandler) bw.removeEventListener('scroll', bw._vwScrollHandler) |
| | | bw.addEventListener('scroll', this.onScroll, { passive: true }) |
| | | bw._vwScrollHandler = this.onScroll |
| | | } |
| | | }, |
| | | // æ»å¨å°åºé¨èªå¨è¿½å ä¸ä¸é¡µï¼ä¿çæå¨å页跳页è½åï¼ |
| | | loadMore() { |
| | | if (this.loading || this.loadingMore) return |
| | | if (this.records.length >= this.total || this.total <= 0) return |
| | | const nextPage = this.page + 1 |
| | | this.loadingMore = true |
| | | api.get('/data/list', { |
| | | params: { |
| | | type: this.type, |
| | | period: this.period || undefined, |
| | | keyword: this.keyword || undefined, |
| | | page: nextPage, |
| | | size: this.size |
| | | } |
| | | }).then(res => { |
| | | const d = res.data || {} |
| | | const addRows = d.records || [] |
| | | if (!addRows.length) { |
| | | this.page = nextPage - 1 |
| | | return |
| | | } |
| | | this.records = this.records.concat(addRows) |
| | | this.page = nextPage |
| | | if (d.total != null) this.total = d.total |
| | | if (d.columns && d.columns.length) this.columns = d.columns |
| | | }).catch(e => { |
| | | if (e && e._toast) return |
| | | this.$message.error('å è½½æ´å¤å¤±è´¥') |
| | | }).finally(() => { |
| | | this.loadingMore = false |
| | | this.$nextTick(() => this.attachBodyScroll()) |
| | | }) |
| | | }, |
| | | onScroll(e) { |
| | | // æ®é/å
¨å±ä¸çæ£çæ»å¨å®¹å¨é½æ¯ el-table å
é¨ body-wrapperï¼æè·é¶æ®µå¯æ¶å°ï¼ï¼ |
| | | // 页颿´ä½æ»å¨æ¶ä»¥ window/document 为åã |
| | | const t = e && e.target |
| | | let scrollTop, clientHeight, scrollHeight |
| | | if (t && t.nodeType === 1 && t !== document && typeof t.scrollTop === 'number' && t.scrollHeight > t.clientHeight) { |
| | | scrollTop = t.scrollTop |
| | | clientHeight = t.clientHeight |
| | | scrollHeight = t.scrollHeight |
| | | } else { |
| | | const se = document.scrollingElement || document.documentElement |
| | | scrollTop = se.scrollTop |
| | | clientHeight = window.innerHeight |
| | | scrollHeight = se.scrollHeight |
| | | } |
| | | if (scrollHeight > 0 && scrollTop + clientHeight >= scrollHeight - 80) { |
| | | this.loadMore() |
| | | } |
| | | }, |
| | | toggleFullscreen() { |
| | | const el = this.$refs.tableWrap |
| | |
| | | if (q.period) this.period = q.period |
| | | if (q.keyword) this.keyword = q.keyword |
| | | this.loadData() |
| | | window.addEventListener('scroll', this.onScroll, { passive: true }) |
| | | if (this.$refs.tableWrap) { |
| | | // capture=trueï¼el-table å
é¨ body-wrapper çæ»å¨å¨æè·é¶æ®µä¹è½æ¶å° |
| | | this.$refs.tableWrap.addEventListener('scroll', this.onScroll, { passive: true, capture: true }) |
| | | } |
| | | this.$nextTick(() => this.attachBodyScroll()) |
| | | }, |
| | | beforeDestroy() { |
| | | window.removeEventListener('scroll', this.onScroll) |
| | | if (this.$refs.tableWrap) { |
| | | this.$refs.tableWrap.removeEventListener('scroll', this.onScroll, { capture: true }) |
| | | const bw = this.$refs.tableWrap.querySelector('.el-table__body-wrapper') |
| | | if (bw && bw._vwScrollHandler) bw.removeEventListener('scroll', bw._vwScrollHandler) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | <style scoped> |
| | | .el-header { background: #409EFF; color: white; line-height: 60px; font-size: 18px; } |
| | | #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; |
| | | display: flex; |
| | | flex-direction: column; |
| | | height: 100vh; |
| | | } |
| | | #app .table-wrap:fullscreen .table-area { |
| | | flex: 1 1 auto; |
| | |
| | | noteDraft: '', |
| | | modules: [ |
| | | { |
| | | key: 'summary', title: 'æ±æ»å¤§è¡¨', items: [ |
| | | { key: 'summaryWorkbook', label: 'éè·¯è¿è¾éæ±æ»è¡¨ï¼æ´æ¬ï¼', fileName: 'çæ_éè·¯è¿è¾éæ±æ»è¡¨.xlsx', status: null, statusNote: '' } |
| | | ], checked: [] |
| | | }, |
| | | { |
| | | key: 'freight', title: 'è´§è¿æ¥è¡¨', items: [ |
| | | { key: 'cityDetail', label: 'è´§è¿éåå¸å·æç»', fileName: 'çæ_è´§è¿éåå¸å·æç».xlsx', status: null, statusNote: '' }, |
| | | { key: 'freightRank', label: 'è´§è¿éæå', fileName: 'çæ_è´§è¿éæå.xlsx', status: null, statusNote: '' }, |
| | |
| | | { key: 'passengerMidAnalysis', label: 'ä¸å£å¾åæ', fileName: 'çæ_å
¬è·¯æ
客ä¸å£å¾åæ.xlsx', status: null, statusNote: '' } |
| | | ], checked: [] |
| | | }, { |
| | | key: 'cityPassenger', title: 'åå¸å®¢è¿æ¥è¡¨', tag: 'å
¬äº¤/åºç§/轨é轮渡/æ±æ»', tagType: 'success', items: [ |
| | | key: 'cityPassenger', title: 'åå¸å®¢è¿æ¥è¡¨', items: [ |
| | | { key: 'cityBusDetail', label: 'åå¸å
¬äº¤å®¢è¿éåå¸å·æç»', fileName: 'çæ_åå¸å
¬äº¤å®¢è¿éåå¸å·æç».xlsx', status: null, statusNote: '' }, |
| | | { key: 'cityTaxiDetail', label: '巡游åºç§å®¢è¿éåå¸å·æç»', fileName: 'çæ_巡游åºç§å®¢è¿éåå¸å·æç».xlsx', status: null, statusNote: '' }, |
| | | { key: 'cityRailFerryDetail', label: '轨é轮渡客è¿éåå¸å·æç»', fileName: 'çæ_轨é轮渡客è¿éåå¸å·æç».xlsx', status: null, statusNote: '' }, |
| | | { key: 'cityPassengerCitySum', label: 'åå¸å®¢è¿å®¢è¿éåå¸å·ç´¯è®¡', fileName: 'çæ_åå¸å®¢è¿å®¢è¿éåå¸å·ç´¯è®¡.xlsx', status: null, statusNote: '' }, |
| | | { key: 'cityPassengerDetailSum', label: 'åå¸å®¢è¿åå¸å·æç»è¡¨', fileName: 'çæ_åå¸å®¢è¿åå¸å·æç»è¡¨.xlsx', status: null, statusNote: '' }, |
| | | { key: 'cityPassengerSummary', label: 'åå¸å®¢è¿æ±æ»', fileName: 'çæ_åå¸å®¢è¿æ±æ».xlsx', status: null, statusNote: '' }, |
| | | { key: 'wycSplit', label: 'ç½çº¦è½¦å®¢è¿éæå表', fileName: 'çæ_ç½çº¦è½¦å®¢è¿éæå表.xlsx', status: null, statusNote: '' }, |
| | | { key: 'summaryWorkbook', label: 'éè·¯è¿è¾éæ±æ»è¡¨ï¼æ´æ¬ï¼', fileName: 'çæ_éè·¯è¿è¾éæ±æ»è¡¨.xlsx', status: null, statusNote: '' } |
| | | { key: 'wycSplit', label: 'ç½çº¦è½¦å®¢è¿éæå表', fileName: 'çæ_ç½çº¦è½¦å®¢è¿éæå表.xlsx', status: null, statusNote: '' } |
| | | ], checked: [] |
| | | }, |
| | | { |
| | |
| | | // æ¥è¡¨æä¸æåç»ï¼å¹´æ¥æå¹´ä»½ï¼ææ¥/壿¥æå¹´åç»å 1-12 æï¼è½èåªåå£åº¦æ«æï¼ |
| | | periodGroups() { |
| | | const year = new Date().getFullYear() |
| | | const years = [year - 1, year, year + 1] |
| | | const years = [year, year - 1, year + 1] |
| | | if (this.cycle === 'year') { |
| | | return [{ label: '鿩年份', options: years.map(y => ({ label: y + '年', value: String(y) })) }] |
| | | } |