From 4e8766d35771bc71c858583b768600a2169a46c0 Mon Sep 17 00:00:00 2001
From: zhizhijie <zhizhijie@users.noreply.gitee.com>
Date: 星期二, 22 九月 2026 10:49:11 +0800
Subject: [PATCH] feat(数据查看): 隐藏报表期/所属地区+冻结收窄为市州与企业名称、网约车按市州竖排、市州月报显示项目名称、列名补单位、数值千分位与同比按百分比显示

---
 traffic-audit-web/src/views/DataView.vue                                                          |   74 +++++++++-----
 traffic-audit-server/src/main/java/com/trafficaudit/dataimport/controller/DataViewController.java |  211 +++++++++++++++++++++++++++++++-----------
 2 files changed, 205 insertions(+), 80 deletions(-)

diff --git a/traffic-audit-server/src/main/java/com/trafficaudit/dataimport/controller/DataViewController.java b/traffic-audit-server/src/main/java/com/trafficaudit/dataimport/controller/DataViewController.java
index 79aba3a..72961b3 100644
--- a/traffic-audit-server/src/main/java/com/trafficaudit/dataimport/controller/DataViewController.java
+++ b/traffic-audit-server/src/main/java/com/trafficaudit/dataimport/controller/DataViewController.java
@@ -23,6 +23,7 @@
 import com.trafficaudit.dataimport.entity.WycOrderMonthly;
 import com.trafficaudit.dataimport.entity.WycTotalMonthly;
 import com.trafficaudit.common.util.RegionUtil;
+import com.trafficaudit.reportexport.calc.WycSplitCalc;
 import com.trafficaudit.dataimport.mapper.FreightTurnoverImportMapper;
 import com.trafficaudit.dataimport.mapper.H2032EnterpriseMonthlyMapper;
 import com.trafficaudit.dataimport.mapper.PassengerAuthVehicleMapper;
@@ -97,6 +98,8 @@
     private WycOrderMonthlyMapper wycOrderMapper;
     @Resource
     private WycTotalMonthlyMapper wycTotalMapper;
+    @Resource
+    private WycSplitCalc wycSplitCalc;
 
     @GetMapping("/list")
     public Result<Map<String, Object>> list(@RequestParam("type") String type,
@@ -120,7 +123,9 @@
                         .orderByDesc(H2032EnterpriseMonthly::getId);
                 Page<H2032EnterpriseMonthly> p = new Page<>(safePage, safeSize);
                 Page<H2032EnterpriseMonthly> r = h2032Mapper.selectPage(p, w);
-                result.put("records", toMaps(r.getRecords(), propsOf(H2032_COLUMNS)));
+                List<Map<String, Object>> rows = toMaps(r.getRecords(), propsOf(H2032_COLUMNS));
+                fillCity(rows);
+                result.put("records", rows);
                 fillPage(result, r);
                 break;
             }
@@ -173,7 +178,9 @@
                         .orderByDesc(PassengerEnterpriseMonthly::getId);
                 Page<PassengerEnterpriseMonthly> p = new Page<>(safePage, safeSize);
                 Page<PassengerEnterpriseMonthly> r = passengerMapper.selectPage(p, w);
-                result.put("records", toMaps(r.getRecords(), propsOf(H2031_COLUMNS)));
+                List<Map<String, Object>> rows = toMaps(r.getRecords(), propsOf(H2031_COLUMNS));
+                fillCity(rows);
+                result.put("records", rows);
                 fillPage(result, r);
                 break;
             }
@@ -254,7 +261,9 @@
                         .orderByAsc(InvestmentMonthly::getId);
                 Page<InvestmentMonthly> p = new Page<>(safePage, safeSize);
                 Page<InvestmentMonthly> r = investmentMonthlyMapper.selectPage(p, w);
-                result.put("records", toMaps(r.getRecords(), propsOf(INVEST_MONTHLY_COLUMNS)));
+                List<Map<String, Object>> rows = toMaps(r.getRecords(), propsOf(INVEST_MONTHLY_COLUMNS));
+                fillProjectInfo(rows);
+                result.put("records", rows);
                 fillPage(result, r);
                 break;
             }
@@ -287,7 +296,9 @@
                         .orderByDesc(EnergyVehicleQuarterly::getId);
                 Page<EnergyVehicleQuarterly> p = new Page<>(safePage, safeSize);
                 Page<EnergyVehicleQuarterly> r = energyVehicleMapper.selectPage(p, w);
-                result.put("records", toMaps(r.getRecords(), propsOf(ENERGY_VEHICLE_COLUMNS)));
+                List<Map<String, Object>> rows = toMaps(r.getRecords(), propsOf(ENERGY_VEHICLE_COLUMNS));
+                fillCity(rows);
+                result.put("records", rows);
                 fillPage(result, r);
                 break;
             }
@@ -310,11 +321,7 @@
                 Page<PassengerIndividualMonthly> p = new Page<>(safePage, safeSize);
                 Page<PassengerIndividualMonthly> r = passengerIndividualMapper.selectPage(p, w);
                 List<Map<String, Object>> rows = toMaps(r.getRecords(), propsOf(PAX_INDIVIDUAL_COLUMNS));
-                for (Map<String, Object> row : rows) {
-                    Object rc = row.get("regionCode");
-                    String cityName = rc == null ? null : RegionUtil.cityByCode(String.valueOf(rc));
-                    row.put("city", cityName == null ? "" : cityName);
-                }
+                fillCity(rows);
                 result.put("records", rows);
                 fillPage(result, r);
                 break;
@@ -332,11 +339,16 @@
             case "wycOrder": {
                 LambdaQueryWrapper<WycOrderMonthly> w = new LambdaQueryWrapper<WycOrderMonthly>()
                         .eq(notEmpty(period), WycOrderMonthly::getReportPeriod, period)
-                        .orderByDesc(WycOrderMonthly::getId);
-                Page<WycOrderMonthly> p = new Page<>(safePage, safeSize);
-                Page<WycOrderMonthly> r = wycOrderMapper.selectPage(p, w);
-                result.put("records", toMaps(r.getRecords(), propsOf(WYC_ORDER_COLUMNS)));
-                fillPage(result, r);
+                        .orderByDesc(WycOrderMonthly::getReportPeriod);
+                List<WycOrderMonthly> list = wycOrderMapper.selectList(w);
+                List<Map<String, Object>> rows = new ArrayList<>();
+                for (WycOrderMonthly o : list) {
+                    rows.addAll(wycOrderCityRows(o));
+                }
+                result.put("records", rows);
+                result.put("total", (long) rows.size());
+                result.put("current", 1L);
+                result.put("size", (long) rows.size());
                 break;
             }
             default:
@@ -346,6 +358,95 @@
                 result.put("size", safeSize);
         }
         return Result.ok(result);
+    }
+
+    /** 鍖哄垝浠g爜 -> 甯傚窞鍚嶏紙鏃犳硶璇嗗埆杩斿洖绌轰覆锛� */
+    private String cityOf(String regionCode) {
+        if (regionCode == null || regionCode.trim().isEmpty()) return "";
+        String city = RegionUtil.cityByCode(regionCode.trim());
+        return city == null ? "" : city;
+    }
+
+    /** 鎸� regionCode 娲剧敓"甯傚窞"鍒楋紙浼佷笟绫昏〃閫氱敤锛� */
+    private void fillCity(List<Map<String, Object>> rows) {
+        for (Map<String, Object> row : rows) {
+            Object rc = row.get("regionCode");
+            row.put("city", cityOf(rc == null ? null : String.valueOf(rc)));
+        }
+    }
+
+    /** 鎶曡祫鏈堟姤锛氳ˉ椤圭洰鍚嶇О涓庡競宸烇紙鍘熻〃鍙湁 projectId锛岄〉闈㈡棤娉曡鲸璇嗛」鐩級 */
+    private void fillProjectInfo(List<Map<String, Object>> rows) {
+        java.util.Set<Long> ids = new java.util.LinkedHashSet<>();
+        for (Map<String, Object> row : rows) {
+            Object pid = row.get("projectId");
+            if (pid instanceof Number) ids.add(((Number) pid).longValue());
+        }
+        if (ids.isEmpty()) return;
+        Map<Long, InvestmentProject> byId = new LinkedHashMap<>();
+        for (InvestmentProject ip : investmentProjectMapper.selectBatchIds(ids)) {
+            byId.put(ip.getId(), ip);
+        }
+        for (Map<String, Object> row : rows) {
+            Object pid = row.get("projectId");
+            InvestmentProject ip = pid instanceof Number ? byId.get(((Number) pid).longValue()) : null;
+            row.put("projectName", ip == null ? null : ip.getProjectName());
+            row.put("city", ip == null ? null : ip.getCity());
+        }
+    }
+
+    private static double nz(Double v) {
+        return v == null ? 0.0 : v;
+    }
+
+    /** 缃戠害杞﹁鍗曞彴璐� -> 鎸夊競宸炵珫鎺掞細鍏ㄧ渷 + 17 甯傚窞 脳 鎸囨爣锛堝杩愰噺/鍛ㄨ浆閲忕敱 WycSplitCalc 鎷嗗垎鍙e緞璁$畻锛� */
+    private List<Map<String, Object>> wycOrderCityRows(WycOrderMonthly o) {
+        List<Map<String, Object>> rows = new ArrayList<>();
+        List<String> cities = RegionUtil.cityList();
+        double orderSum = nz(o.getOrderSum());
+        double[] orders = { nz(o.getOrderWuhan()), nz(o.getOrderHuangshi()), nz(o.getOrderShiyan()),
+                nz(o.getOrderYichang()), nz(o.getOrderXiangyang()), nz(o.getOrderEzhou()), nz(o.getOrderJingmen()),
+                nz(o.getOrderXiaogan()), nz(o.getOrderJingzhou()), nz(o.getOrderHuanggang()), nz(o.getOrderXianning()),
+                nz(o.getOrderSuizhou()), nz(o.getOrderEnshi()), nz(o.getOrderXiantao()), nz(o.getOrderQianjiang()),
+                nz(o.getOrderTianmen()), nz(o.getOrderShennong()) };
+
+        Map<String, Object> province = new LinkedHashMap<>();
+        province.put("reportPeriod", o.getReportPeriod());
+        province.put("period", o.getReportPeriod());
+        province.put("region", "鍏ㄧ渷");
+        province.put("orderCount", orderSum);
+        province.put("orderShare", orderSum > 0 ? 1.0 : null);
+        province.put("pax", o.getPinK());
+        province.put("turnover", o.getPinZ());
+        province.put("cityPax", o.getPinCK());
+        province.put("cityTurnover", o.getPinCZ());
+        province.put("note", "鍏ㄧ渷鍙e緞鐩存帴鍙栧彴璐� pin 鍊�");
+        rows.add(province);
+
+        Map<String, WycSplitCalc.WycMetrics> byCity = null;
+        String calcError = null;
+        try {
+            byCity = wycSplitCalc.calc(o.getReportPeriod()).getByCity();
+        } catch (Exception e) {
+            calcError = e.getMessage() == null ? "鎷嗗垎璁$畻澶辫触" : e.getMessage();
+        }
+        for (int i = 0; i < cities.size() && i < orders.length; i++) {
+            String city = cities.get(i);
+            Map<String, Object> row = new LinkedHashMap<>();
+            row.put("reportPeriod", o.getReportPeriod());
+            row.put("period", o.getReportPeriod());
+            row.put("region", city);
+            row.put("orderCount", orders[i]);
+            row.put("orderShare", orderSum > 0 ? orders[i] / orderSum : null);
+            WycSplitCalc.WycMetrics m = byCity == null ? null : byCity.get(city);
+            row.put("pax", m == null ? null : m.getTotalPax());
+            row.put("turnover", m == null ? null : m.getTotalTurnover());
+            row.put("cityPax", m == null ? null : m.getCityPax());
+            row.put("cityTurnover", m == null ? null : m.getCityTurnover());
+            row.put("note", m == null ? (calcError == null ? "鎷嗗垎鏈绠�" : calcError) : "");
+            rows.add(row);
+        }
+        return rows;
     }
 
     private boolean notEmpty(String s) {
@@ -434,12 +535,13 @@
     static {
         H2032_COLUMNS.add(col("reportPeriod", "鎶ヨ〃鏈�", 100));
         H2032_COLUMNS.add(col("regionCode", "鎵�灞炲湴鍖�", 100));
+        H2032_COLUMNS.add(col("city", "甯傚窞", 110));
         H2032_COLUMNS.add(col("enterpriseCode", "浼佷笟浠g爜", 130));
         H2032_COLUMNS.add(col("enterpriseName", "浼佷笟鍚嶇О", 220));
         H2032_COLUMNS.add(col("unifiedCreditCode", "缁熶竴绀句細淇$敤浠g爜", 180));
         H2032_COLUMNS.add(col("reportUnit", "濉姤鍗曚綅", 160));
         H2032_COLUMNS.add(col("vehicleTotal", "杞﹁締鏁板悎璁�", 110));
-        H2032_COLUMNS.add(col("tonsTotal", "鏍囪鍚ㄤ綅鏁板悎璁�", 130));
+        H2032_COLUMNS.add(col("tonsTotal", "鏍囪鍚ㄤ綅鏁板悎璁�(鍚�)", 150));
         H2032_COLUMNS.add(col("vehicleTractor", "鐗靛紩杞�", 90));
         H2032_COLUMNS.add(col("vehicleTrailer", "鎸傝溅", 90));
         H2032_COLUMNS.add(col("tonsTrailer", "鍚ㄤ綅-鎸傝溅", 110));
@@ -447,8 +549,8 @@
         H2032_COLUMNS.add(col("tonsContainer", "鍚ㄤ綅-闆嗚绠�", 120));
         H2032_COLUMNS.add(col("vehicleWhole", "鏁磋溅", 90));
         H2032_COLUMNS.add(col("tonsWhole", "鍚ㄤ綅-鏁磋溅", 110));
-        H2032_COLUMNS.add(col("freightTotal", "璐ц繍閲忓悎璁�", 110));
-        H2032_COLUMNS.add(col("turnoverTotal", "鍛ㄨ浆閲忓悎璁�", 110));
+        H2032_COLUMNS.add(col("freightTotal", "璐ц繍閲忓悎璁�(鍚�)", 130));
+        H2032_COLUMNS.add(col("turnoverTotal", "鍛ㄨ浆閲忓悎璁�(鍚ㄥ叕閲�)", 150));
         H2032_COLUMNS.add(col("freightContainer", "璐ц繍閲�-闆嗚绠�", 130));
         H2032_COLUMNS.add(col("freightCoal", "璐ц繍閲�-鐓ょ偔", 120));
         H2032_COLUMNS.add(col("freightOilGas", "璐ц繍閲�-娌规皵", 120));
@@ -458,7 +560,7 @@
         H2032_COLUMNS.add(col("freightBuilding", "璐ц繍閲�-寤烘潗", 120));
         H2032_COLUMNS.add(col("freightGrain", "璐ц繍閲�-绮", 120));
         H2032_COLUMNS.add(col("avgTonnage", "骞冲潎鍚ㄤ綅", 100));
-        H2032_COLUMNS.add(col("avgDistance", "骞冲潎杩愯窛", 100));
+        H2032_COLUMNS.add(col("avgDistance", "骞冲潎杩愯窛(鍏噷)", 120));
         H2032_COLUMNS.add(col("unitLeader", "鍗曚綅璐熻矗浜�", 110));
         H2032_COLUMNS.add(col("statsLeader", "缁熻璐熻矗浜�", 110));
         H2032_COLUMNS.add(col("contactPerson", "濉〃浜�", 100));
@@ -483,16 +585,16 @@
         SPLIT_COLUMNS.add(col("reportPeriod", "鎶ヨ〃鏈�", 100));
         SPLIT_COLUMNS.add(col("periodType", "鍙e緞", 90));
         SPLIT_COLUMNS.add(col("regionName", "甯傚窞", 130));
-        SPLIT_COLUMNS.add(col("aboveScaleFreight", "瑙勪笂璐ц繍閲�", 120));
-        SPLIT_COLUMNS.add(col("aboveScaleTurnover", "瑙勪笂鍛ㄨ浆閲�", 120));
+        SPLIT_COLUMNS.add(col("aboveScaleFreight", "瑙勪笂璐ц繍閲�(鏉ユ簮鏂囦欢鏈彁渚涜鍒�)", 220));
+        SPLIT_COLUMNS.add(col("aboveScaleTurnover", "瑙勪笂鍛ㄨ浆閲�(涓囧惃鍏噷)", 170));
         SPLIT_COLUMNS.add(col("aboveScaleRank", "瑙勪笂鎺掑悕", 100));
         SPLIT_COLUMNS.add(col("aboveScaleYoy", "瑙勪笂鍚屾瘮", 100));
-        SPLIT_COLUMNS.add(col("belowScaleFreight", "瑙勪笅璐ц繍閲�", 120));
-        SPLIT_COLUMNS.add(col("belowScaleTurnover", "瑙勪笅鍛ㄨ浆閲�", 120));
+        SPLIT_COLUMNS.add(col("belowScaleFreight", "瑙勪笅璐ц繍閲�(鏉ユ簮鏂囦欢鏈彁渚涜鍒�)", 220));
+        SPLIT_COLUMNS.add(col("belowScaleTurnover", "瑙勪笅鍛ㄨ浆閲�(涓囧惃鍏噷)", 170));
         SPLIT_COLUMNS.add(col("belowScaleRank", "瑙勪笅鎺掑悕", 100));
         SPLIT_COLUMNS.add(col("belowScaleYoy", "瑙勪笅鍚屾瘮", 100));
-        SPLIT_COLUMNS.add(col("totalFreight", "鍚堣璐ц繍閲�", 120));
-        SPLIT_COLUMNS.add(col("totalTurnover", "鍚堣鍛ㄨ浆閲�", 120));
+        SPLIT_COLUMNS.add(col("totalFreight", "鍚堣璐ц繍閲�(鏉ユ簮鏂囦欢鏈彁渚涜鍒�)", 220));
+        SPLIT_COLUMNS.add(col("totalTurnover", "鍚堣鍛ㄨ浆閲�(涓囧惃鍏噷)", 170));
         SPLIT_COLUMNS.add(col("totalRank", "鍚堣鎺掑悕", 100));
         SPLIT_COLUMNS.add(col("totalYoy", "鍚堣鍚屾瘮", 100));
 
@@ -513,6 +615,7 @@
 
         H2031_COLUMNS.add(col("reportPeriod", "鎶ヨ〃鏈�", 100));
         H2031_COLUMNS.add(col("regionCode", "鎵�灞炲湴鍖�", 100));
+        H2031_COLUMNS.add(col("city", "甯傚窞", 110));
         H2031_COLUMNS.add(col("enterpriseCode", "浼佷笟浠g爜", 130));
         H2031_COLUMNS.add(col("enterpriseName", "浼佷笟鍚嶇О", 220));
         H2031_COLUMNS.add(col("unifiedCreditCode", "缁熶竴绀句細淇$敤浠g爜", 180));
@@ -523,7 +626,7 @@
         H2031_COLUMNS.add(col("seatSchedule", "鐝嚎杞藉浣�", 110));
         H2031_COLUMNS.add(col("vehicleCharter", "鍖呰溅杞﹁締鏁�", 110));
         H2031_COLUMNS.add(col("seatCharter", "鍖呰溅杞藉浣�", 110));
-        H2031_COLUMNS.add(col("passengerTotal", "瀹㈣繍閲忓悎璁�", 110));
+        H2031_COLUMNS.add(col("passengerTotal", "瀹㈣繍閲忓悎璁�(浜�)", 130));
         H2031_COLUMNS.add(col("turnoverTotal", "鍛ㄨ浆閲忓悎璁�", 110));
         H2031_COLUMNS.add(col("passengerClass1", "瀹㈣繍閲忎竴绫�", 110));
         H2031_COLUMNS.add(col("passengerClass2", "瀹㈣繍閲忎簩绫�", 110));
@@ -548,15 +651,15 @@
         BUS_COLUMNS.add(col("opVehicles", "杩愯惀杞︽暟", 100));
         BUS_COLUMNS.add(col("stopTotal", "绔欑偣鎬讳釜鏁�", 110));
         BUS_COLUMNS.add(col("stopCity", "鍩庡競鍐呯珯鐐�", 110));
-        BUS_COLUMNS.add(col("passengerVolume", "瀹㈣繍閲�", 100));
-        BUS_COLUMNS.add(col("passengerCity", "鍩庡競鍐呭杩愰噺", 120));
-        BUS_COLUMNS.add(col("turnover", "鏃呭鍛ㄨ浆閲�", 110));
-        BUS_COLUMNS.add(col("turnoverCity", "鍩庡競鍐呭懆杞噺", 120));
-        BUS_COLUMNS.add(col("avgDistance", "骞冲潎杩愯窛", 100));
-        BUS_COLUMNS.add(col("avgDistanceCity", "鍩庡競鍐呭钩鍧囪繍璺�", 130));
-        BUS_COLUMNS.add(col("passengerChengxiang", "鍩庨檯鍩庝埂瀹㈣繍閲�", 130));
-        BUS_COLUMNS.add(col("turnoverChengxiang", "鍩庨檯鍩庝埂鍛ㄨ浆閲�", 130));
-        BUS_COLUMNS.add(col("avgDistanceChengxiang", "鍩庨檯鍩庝埂骞冲潎杩愯窛", 140));
+        BUS_COLUMNS.add(col("passengerVolume", "瀹㈣繍閲�(涓囦汉娆�)", 120));
+        BUS_COLUMNS.add(col("passengerCity", "鍩庡競鍐呭杩愰噺(涓囦汉娆�)", 150));
+        BUS_COLUMNS.add(col("turnover", "鏃呭鍛ㄨ浆閲�(涓囦汉鍏噷)", 170));
+        BUS_COLUMNS.add(col("turnoverCity", "鍩庡競鍐呭懆杞噺(涓囦汉鍏噷)", 180));
+        BUS_COLUMNS.add(col("avgDistance", "骞冲潎杩愯窛(鍏噷)", 120));
+        BUS_COLUMNS.add(col("avgDistanceCity", "鍩庡競鍐呭钩鍧囪繍璺�(鍏噷)", 150));
+        BUS_COLUMNS.add(col("passengerChengxiang", "鍩庨檯鍩庝埂瀹㈣繍閲�(涓囦汉娆�)", 160));
+        BUS_COLUMNS.add(col("turnoverChengxiang", "鍩庨檯鍩庝埂鍛ㄨ浆閲�(涓囦汉鍏噷)", 190));
+        BUS_COLUMNS.add(col("avgDistanceChengxiang", "鍩庨檯鍩庝埂骞冲潎杩愯窛(鍏噷)", 160));
         BUS_COLUMNS.add(col("ratePassengerMom", "瀹㈣繍閲忕幆姣�", 100));
         BUS_COLUMNS.add(col("ratePassengerCityMom", "鍩庡競鍐呯幆姣�", 100));
         BUS_COLUMNS.add(col("rateChengxiangMom", "鍩庨檯鍩庝埂鐜瘮", 110));
@@ -571,20 +674,20 @@
         TAXI_COLUMNS.add(col("city", "甯傚窞", 110));
         TAXI_COLUMNS.add(col("tripTotal", "杞藉杞︽鎬绘暟", 120));
         TAXI_COLUMNS.add(col("tripCity", "杞藉杞︽_鍩庡競鍐�", 130));
-        TAXI_COLUMNS.add(col("passengerVolume", "瀹㈣繍閲�", 100));
-        TAXI_COLUMNS.add(col("passengerCity", "鍩庡競鍐呭杩愰噺", 120));
-        TAXI_COLUMNS.add(col("turnover", "鏃呭鍛ㄨ浆閲�", 110));
-        TAXI_COLUMNS.add(col("turnoverCity", "鍩庡競鍐呭懆杞噺", 120));
+        TAXI_COLUMNS.add(col("passengerVolume", "瀹㈣繍閲�(涓囦汉娆�)", 120));
+        TAXI_COLUMNS.add(col("passengerCity", "鍩庡競鍐呭杩愰噺(涓囦汉娆�)", 150));
+        TAXI_COLUMNS.add(col("turnover", "鏃呭鍛ㄨ浆閲�(涓囦汉鍏噷)", 170));
+        TAXI_COLUMNS.add(col("turnoverCity", "鍩庡競鍐呭懆杞噺(涓囦汉鍏噷)", 180));
         TAXI_COLUMNS.add(col("opVehicles", "杩愯惀杞﹁締鏁�", 110));
-        TAXI_COLUMNS.add(col("avgDistance", "骞冲潎杩愯窛", 100));
-        TAXI_COLUMNS.add(col("avgDistanceCity", "鍩庡競鍐呭钩鍧囪繍璺�", 130));
+        TAXI_COLUMNS.add(col("avgDistance", "骞冲潎杩愯窛(鍏噷)", 120));
+        TAXI_COLUMNS.add(col("avgDistanceCity", "鍩庡競鍐呭钩鍧囪繍璺�(鍏噷)", 150));
         TAXI_COLUMNS.add(col("passengersPerTrip", "鍗曡溅娆¤浇瀹汉鏁�", 130));
         TAXI_COLUMNS.add(col("rateTripMom", "杞藉杞︽鐜瘮", 110));
         TAXI_COLUMNS.add(col("rateTripYoy", "杞藉杞︽鍚屾瘮", 110));
         TAXI_COLUMNS.add(col("ratePassengerMom", "瀹㈣繍閲忕幆姣�", 100));
         TAXI_COLUMNS.add(col("ratePassengerYoy", "瀹㈣繍閲忓悓姣�", 100));
         TAXI_COLUMNS.add(col("passengerCityRatio", "鍩庡競鍐呭杩愰噺鍗犳瘮", 140));
-        TAXI_COLUMNS.add(col("avgDistanceChengxiang", "鍩庨檯鍩庝埂骞冲潎杩愯窛", 140));
+        TAXI_COLUMNS.add(col("avgDistanceChengxiang", "鍩庨檯鍩庝埂骞冲潎杩愯窛(鍏噷)", 160));
         TAXI_COLUMNS.add(col("verifyExplanation", "鏍稿疄瑙i噴", 220));
         TAXI_AUTH_COLUMNS.add(col("reportPeriod", "鎶ヨ〃鏈�", 100));
         TAXI_AUTH_COLUMNS.add(col("city", "甯傚窞", 110));
@@ -605,6 +708,8 @@
         PAUTH_COLUMNS.add(col("seatCount", "杞藉浣嶆暟", 100));
         INVEST_MONTHLY_COLUMNS.add(col("reportPeriod", "鎶ヨ〃鏈�", 100));
         INVEST_MONTHLY_COLUMNS.add(col("projectId", "椤圭洰ID", 80));
+        INVEST_MONTHLY_COLUMNS.add(col("projectName", "椤圭洰鍚嶇О", 280));
+        INVEST_MONTHLY_COLUMNS.add(col("city", "甯傚窞", 90));
         INVEST_MONTHLY_COLUMNS.add(col("yearPlan", "鏈勾璁″垝鎶曡祫(涓囧厓)", 140));
         INVEST_MONTHLY_COLUMNS.add(col("yearCum", "鑷勾鍒濈疮璁″畬鎴�(涓囧厓)", 160));
         INVEST_MONTHLY_COLUMNS.add(col("monthDone", "鏈湀瀹屾垚鎶曡祫(涓囧厓)", 150));
@@ -634,6 +739,7 @@
         INVEST_SYSTEM_COLUMNS.add(col("monthDone", "鏈湀瀹屾垚鎶曡祫(涓囧厓)", 150));
         ENERGY_VEHICLE_COLUMNS.add(col("reportPeriod", "鎶ヨ〃鏈�", 100));
         ENERGY_VEHICLE_COLUMNS.add(col("regionCode", "鎵�灞炲湴鍖�", 100));
+        ENERGY_VEHICLE_COLUMNS.add(col("city", "甯傚窞", 110));
         ENERGY_VEHICLE_COLUMNS.add(col("enterpriseName", "浼佷笟鍚嶇О", 220));
         ENERGY_VEHICLE_COLUMNS.add(col("plateNo", "杞︾墝鍙�", 110));
         ENERGY_VEHICLE_COLUMNS.add(col("vehicleType", "杞﹁締绫诲瀷", 130));
@@ -674,20 +780,15 @@
         WYC_TOTAL_COLUMNS.add(col("pinZ", "鍏ㄧ渷缃戠害杞﹀懆杞噺(涓囦汉鍏噷)", 220));
         WYC_TOTAL_COLUMNS.add(col("pinCZ", "鍏朵腑鍩庡競鍐呭懆杞噺(涓囦汉鍏噷)", 220));
 
-        WYC_ORDER_COLUMNS.add(col("reportPeriod", "鎶ヨ〃鏈�", 100));
-        WYC_ORDER_COLUMNS.add(col("pinK", "鍏ㄧ渷瀹㈣繍閲�(涓囦汉娆�)", 170));
-        WYC_ORDER_COLUMNS.add(col("pinCK", "鍏朵腑鍩庡競鍐呭杩愰噺", 170));
-        WYC_ORDER_COLUMNS.add(col("pinZ", "鍏ㄧ渷鍛ㄨ浆閲�(涓囦汉鍏噷)", 180));
-        WYC_ORDER_COLUMNS.add(col("pinCZ", "鍏朵腑鍩庡競鍐呭懆杞噺", 170));
-        WYC_ORDER_COLUMNS.add(col("orderSum", "璁㈠崟鍚堣(鍗�)", 130));
-        String[] wycOrderCityProps = { "orderWuhan", "orderHuangshi", "orderShiyan", "orderYichang", "orderXiangyang",
-                "orderEzhou", "orderJingmen", "orderXiaogan", "orderJingzhou", "orderHuanggang", "orderXianning",
-                "orderSuizhou", "orderEnshi", "orderXiantao", "orderQianjiang", "orderTianmen", "orderShennong" };
-        String[] wycOrderCityNames = { "姝︽眽", "榛勭煶", "鍗佸牥", "瀹滄槍", "瑗勯槼", "閯傚窞", "鑽嗛棬", "瀛濇劅", "鑽嗗窞", "榛勫唸",
-                "鍜稿畞", "闅忓窞", "鎭╂柦", "浠欐", "娼滄睙", "澶╅棬", "绁炲啘鏋�" };
-        for (int i = 0; i < wycOrderCityProps.length; i++) {
-            WYC_ORDER_COLUMNS.add(col(wycOrderCityProps[i], wycOrderCityNames[i] + "璁㈠崟(鍗�)", 120));
-        }
+        WYC_ORDER_COLUMNS.add(col("region", "鍦板尯", 110));
+        WYC_ORDER_COLUMNS.add(col("period", "鏈熼棿", 100));
+        WYC_ORDER_COLUMNS.add(col("orderCount", "璁㈠崟鏁�(鍗�)", 130));
+        WYC_ORDER_COLUMNS.add(col("orderShare", "璁㈠崟鍗犳瘮", 100));
+        WYC_ORDER_COLUMNS.add(col("pax", "瀹㈣繍閲�(涓囦汉娆�)", 140));
+        WYC_ORDER_COLUMNS.add(col("turnover", "鏃呭鍛ㄨ浆閲�(涓囦汉鍏噷)", 180));
+        WYC_ORDER_COLUMNS.add(col("cityPax", "鍏朵腑鍩庡競鍐呭杩愰噺(涓囦汉娆�)", 190));
+        WYC_ORDER_COLUMNS.add(col("cityTurnover", "鍏朵腑鍩庡競鍐呮梾瀹㈠懆杞噺(涓囦汉鍏噷)", 230));
+        WYC_ORDER_COLUMNS.add(col("note", "璇存槑", 200));
 
     }
 }
\ No newline at end of file
diff --git a/traffic-audit-web/src/views/DataView.vue b/traffic-audit-web/src/views/DataView.vue
index 91ac846..33df725 100644
--- a/traffic-audit-web/src/views/DataView.vue
+++ b/traffic-audit-web/src/views/DataView.vue
@@ -22,7 +22,7 @@
           <span class="toolbar-sep"></span>
           <span class="toolbar-label">鏁版嵁绫诲瀷</span>
           <el-select v-model="type" size="small" style="width:300px" placeholder="閫夋嫨鏁版嵁绫诲瀷" filterable
-                     :title="currentTypeLabel" @change="onTypeSelect">
+                     popper-class="data-type-select" :title="currentTypeLabel" @change="onTypeSelect">
             <el-option-group v-for="g in modules" :key="g.key" :label="g.name">
               <el-option v-for="t in g.types" :key="t.value" :label="t.label" :value="t.value"></el-option>
             </el-option-group>
@@ -37,7 +37,7 @@
             <el-table :data="records" border v-loading="loading" size="small" style="width:100%" height="100%">
               <el-table-column v-for="c in renderColumns" :key="c.prop" :prop="c.prop" :label="c.label" :min-width="c.width" :fixed="c.fixed ? 'left' : false" show-overflow-tooltip>
                 <template slot-scope="scope">
-                  <span>{{ formatCell(scope.row[c.prop]) }}</span>
+                  <span>{{ formatCell(scope.row[c.prop], c.prop) }}</span>
                 </template>
               </el-table-column>
             </el-table>
@@ -122,33 +122,29 @@
       return g
     },
     visibleColumns() {
-      const hiddenProps = ['enterpriseCode', 'unifiedCreditCode', 'reportUnit']
-      const hiddenLabels = ['浼佷笟浠g爜', '缁熶竴绀句細淇$敤浠g爜', '濉姤鍗曚綅']
-      return (this.columns || []).filter(c =>
-        hiddenProps.indexOf(c.prop) < 0 && hiddenLabels.indexOf(c.label) < 0)
+      return (this.columns || []).filter(c => this.keepColumn(c))
     },
-    // 宸︿晶鍐荤粨"杩欐槸璋佺殑鏁版嵁"鎵�闇�鍒楋細妯悜婊氬姩鏃朵紒涓氬悕绉�/甯傚窞涓嶄細璺戝嚭瑙嗛噹銆�
-    // 鍙喕缁撲粠绗� 1 鍒楀紑濮嬬殑涓�娈佃繛缁垪锛岄伩鍏嶅喕缁撳垪涔嬮棿琚櫘閫氬垪鎵撴柇銆�
+    // 宸︿晶鍐荤粨"杩欐槸璋佺殑鏁版嵁"鐨勫垪锛氬競宸�/鍦板尯 + 浼佷笟(椤圭洰)鍚嶇О/杞︾墝鍙凤紝鏈�澶� 3 鍒椼��
+    // 鎶ヨ〃鏈熶笌鎵�灞炲湴鍖轰笉鍙備笌鍐荤粨锛堟姤琛ㄦ湡鏄瓫閫夋潯浠讹紝鎵�灞炲湴鍖烘槸鍖哄垝浠g爜锛屽凡鐢卞競宸炲垪鏇夸唬锛夈��
     renderColumns() {
-      const stickyProps = ['reportPeriod', 'regionCode', 'city', 'regionName', 'periodType',
-        'enterpriseName', 'projectName', 'plateNo']
-      const nameProps = ['enterpriseName', 'projectName', 'plateNo']
+      const stickyProps = ['city', 'regionName', 'region', 'periodType', 'enterpriseName', 'projectName', 'plateNo']
       const cols = this.visibleColumns
-      let limit = -1
-      for (let i = 0; i < cols.length && i < 6; i++) {
-        if (nameProps.indexOf(cols[i].prop) >= 0) { limit = Math.min(i, 3); break }
+      let count = 0
+      while (count < cols.length && count < 3 && stickyProps.indexOf(cols[count].prop) >= 0) {
+        count++
       }
-      if (limit < 0) {
-        // 琛ㄩ噷娌℃湁鍚嶇О鍒楋紙濡傝揣杩愰噺鍛ㄨ浆閲忥級鏃讹紝鍐荤粨寮�澶寸殑杩炵画鏍囪瘑鍒�
-        limit = 0
-        while (limit + 1 < cols.length && limit < 2 && stickyProps.indexOf(cols[limit + 1].prop) >= 0) {
-          limit++
-        }
-      }
-      return cols.map((c, i) => Object.assign({}, c, { fixed: i <= limit && stickyProps.indexOf(c.prop) >= 0 }))
+      return cols.map((c, i) => Object.assign({}, c, { fixed: i < count }))
     }
   },
   methods: {
+    // 鏁版嵁鏌ョ湅缁熶竴鍒楄繃婊わ細鍐呴儴鏍囪瘑鍒椾笉灞曠ず锛涙姤琛ㄦ湡锛堢敱绛涢�夋潯浠朵綋鐜帮級涓庢墍灞炲湴鍖猴紙鍖哄垝浠g爜锛屽凡琚競宸炲垪鏇夸唬锛変笉灞曠ず
+    keepColumn(c) {
+      if (!c) return false
+      const hiddenProps = ['enterpriseCode', 'unifiedCreditCode', 'reportUnit', 'projectId', 'regionCode', 'reportPeriod']
+      const hiddenLabels = ['浼佷笟浠g爜', '缁熶竴绀句細淇$敤浠g爜', '濉姤鍗曚綅', '椤圭洰ID', '鎵�灞炲湴鍖�', '鎶ヨ〃鏈�']
+      if (hiddenProps.indexOf(c.prop) >= 0 || hiddenLabels.indexOf(c.label) >= 0) return false
+      return true
+    },
     onModuleChange(key) {
       const g = this.modules.find(x => x.key === key)
       if (!g || !g.types.length) return
@@ -267,9 +263,21 @@
         document.exitFullscreen()
       }
     },
-    formatCell(v) {
+    // 鏄剧ず鏍煎紡鍖栵紙涓嶆敼鍔ㄥ簳灞傛暟鎹紝瀵煎嚭浠嶄负鍏ㄧ簿搴︼級锛�
+    //  - 姣旂巼绫诲垪锛堢幆姣�/鍚屾瘮/澧為��/鍗犳瘮锛夊簱鍐呮槸灏忔暟锛�0.045 = 4.5%锛夛紝鏄剧ず涓虹櫨鍒嗘瘮锛�
+    //  - 鎺掑悕绫诲垪鏄剧ず鏁存暟锛�
+    //  - 鍏朵綑鏁板�煎崈鍒嗕綅銆佷繚鐣欎袱浣嶅皬鏁帮紱鏁存暟鍘熸牱銆�
+    formatCell(v, prop) {
       if (v === null || v === undefined || v === '') return '-'
-      return v
+      const s = typeof v === 'string' ? v.trim() : v
+      if (typeof v !== 'number' && !/^-?\d+(\.\d+)?$/.test(String(s))) return v
+      const n = Number(s)
+      if (!isFinite(n)) return v
+      const key = String(prop || '').toLowerCase()
+      if (/rank/.test(key)) return Math.round(n).toLocaleString('zh-CN')
+      if (/(rate|yoy|mom|growth|ratio|percent|share)/.test(key)) return (n * 100).toFixed(2) + '%'
+      if (Number.isInteger(n)) return n.toLocaleString('zh-CN')
+      return n.toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 })
     }
   },
   mounted() {
@@ -310,4 +318,20 @@
 #app .table-area:fullscreen { padding:20px; background:#fff; overflow:auto; }
 #app .table-wrap:fullscreen { padding:20px; background:#fff; overflow:auto; display:flex; flex-direction:column; height:100vh; }
 #app .table-wrap:fullscreen .table-area { flex:1 1 auto; min-height:0; }
-</style>
\ No newline at end of file
+</style>
+<style>
+/* 鏁版嵁绫诲瀷涓嬫媺锛欵lement UI 榛樿鎶婂垎缁勬爣棰樺仛鎴� 12px 鐏拌壊灏忓瓧锛岀湅璧锋潵"姣旈�夐」鏇村皬鏇存贰"銆�
+   杩欓噷鎶婂畠鏀规垚鏄庣‘鐨勭粍鏍囬鏍峰紡锛堝姞娣便�佸姞绮椼�佺暐澶с�佸甫搴曡壊锛夛紝涓庨�夐」褰㈡垚鏈夋剰鐨勫眰绾с�� */
+.data-type-select .el-select-group__title {
+  font-size: 13px;
+  font-weight: 700;
+  color: #303133;
+  line-height: 28px;
+  background: #F5F7FA;
+  padding-left: 12px;
+  letter-spacing: .5px;
+}
+.data-type-select .el-select-group__title::after { display: none; }
+.data-type-select .el-select-group { padding-bottom: 6px; }
+.data-type-select .el-select-group .el-select-dropdown__item { padding-left: 20px; }
+</style>

--
Gitblit v1.9.1