Ver Fonte

新增子表字典维护以及首页

hsh há 2 anos atrás
pai
commit
faaecc4d91

+ 38 - 0
src/api/target-management/target-dict.js

@@ -0,0 +1,38 @@
+// 指标字典
+import request from '../../utils/request'
+
+// 查询指标字典数据
+export function selectTargetDictTree(data) {
+    return request({
+        url: '/targetManagement/selectTargetDictTree',
+        method: 'post',
+        data,
+    })
+}
+
+// 查询指标字典数据
+export function selectTargetDict(data) {
+    return request({
+        url: '/targetManagement/selectTargetDict',
+        method: 'post',
+        data,
+    })
+}
+
+// 保存指标字典数据
+export function saveTargetDict(data) {
+    return request({
+        url: '/targetManagement/saveTargetDict',
+        method: 'post',
+        data,
+    })
+}
+
+// 修改指标字典数据
+export function updateTargetDict(data) {
+    return request({
+        url: '/targetManagement/updateTargetDict',
+        method: 'post',
+        data,
+    })
+}

+ 20 - 0
src/api/target-management/target-sql.js

@@ -0,0 +1,20 @@
+// 指标字典sql
+import request from '../../utils/request'
+
+// (预)执行指标分子/分母sql结果
+export function targetSqlExecute(data) {
+    return request({
+        url: '/targetManagement/targetSqlExecute',
+        method: 'post',
+        data,
+    })
+}
+
+// 保存指标分子/分母sql
+export function targetSqlSave(data) {
+    return request({
+        url: '/targetManagement/targetSqlSave',
+        method: 'post',
+        data,
+    })
+}

+ 17 - 0
src/router/modules/dashboard.js

@@ -923,6 +923,23 @@ const route = [
             },
         ],
     },
+    {
+        path: '/targetManagement',
+        component: Layout,
+        meta: { title: '指标管理' },
+        children: [
+            {
+                path: 'targetHome/targetHomePage',
+                component: createNameComponent(() => import('@/views/target-management/target-home/TargetHomePage.vue')),
+                meta: { title: '指标管理综合首页' },
+            },
+            {
+                path: 'targetDict/targetDictConfig',
+                component: createNameComponent(() => import('@/views/target-management/target-dict/TargetDictConfig.vue')),
+                meta: { title: '指标字典维护' },
+            }
+        ],
+    },
 ];
 
 export default route

+ 604 - 0
src/utils/high-charts.js

@@ -237,4 +237,608 @@ export function highPieUtils(id, name, data) {
         //自适应大小, 不用的话不会自适应大小。
         linearBarDom.resize()
     }
+}
+
+/**
+ * @param id 图渲染容器id
+ * @param name 图表标题
+ * @param Tnames 示例标题集合
+ * @param Xnames X轴标题集合
+ * @param seriesData series数据集合
+ * @param yAxisName y轴单位说明
+ * @param unit Y轴单位
+ * @param db x轴倍数,默认是1
+ * @param statusInfos 标签显示开关标志
+ */
+export function highBarsUtils(id, name, Tnames, Xnames, seriesData, yAxisName, unit, db, statusInfos) {
+    let myChart = echarts.getInstanceByDom(id)
+    if (myChart == null) {
+        myChart = echarts.init(id)
+    }
+    if (db == null) {
+        db = 1
+    }
+    if (statusInfos == null) {
+        // 默认配置
+        statusInfos = {
+            zflag: false, // 柱子是否显示数据
+            toolBoxFlag: false, // 是否显示下载,切换标签
+        }
+    }
+
+    let option;
+    const labelOption = {
+        show: statusInfos.zflag,
+        rotate: 90,
+        align: 'left',
+        verticalAlign: 'middle',
+        position: 'insideBottom',
+        distance: 15,
+        formatter: '{c}  {name|{a}}',
+        fontSize: 16,
+        rich: {
+            name: {}
+        }
+    };
+
+    let mainData = []
+    if (seriesData) {
+        seriesData.forEach((t, index) => {
+            if (index === 1) {
+                let d1 = {
+                    name: Tnames[index],
+                    type: 'bar',
+                    barGap: 0,
+                    label: labelOption,
+                    emphasis: {
+                        focus: 'series'
+                    },
+                    data: t.data
+                }
+                mainData.push(d1)
+            } else {
+                let d = {
+                    name: Tnames[index],
+                    type: 'bar',
+                    label: labelOption,
+                    emphasis: {
+                        focus: 'series'
+                    },
+                    data: t.data
+                }
+                mainData.push(d)
+            }
+        })
+
+    }
+
+    option = {
+        // tooltip: {
+        //     trigger: 'axis',
+        //     axisPointer: {
+        //         type: 'shadow'
+        //     }
+        // },
+        tooltip: {
+            trigger: 'axis',
+            confine: true,
+            axisPointer: {
+                type: 'shadow'
+            },
+            formatter: function (param) {
+                let relVal = param[0].name + '<br>'
+                param.forEach((item, index) => {
+                    if (item.value && 'bar' == param[index].seriesType) {
+                        relVal += item.marker + ' ' + item.seriesName + ' : ' + item.value + unit + '</br>'
+                    } else if (item.value && 'line' == param[index].seriesType) {
+
+                    } else {
+                        relVal += item.marker + ' ' + item.seriesName + ' : - </br>'
+                    }
+                })
+                return relVal
+            }
+        },
+        title: {
+            text: name,
+            x: 'center',
+            y: 'bottom',
+            textAlign: 'center',
+        },
+        legend: {
+            orient: 'horizontal',
+            type: 'scroll', 
+            data: Tnames,
+        },
+        toolbox: {
+            show: statusInfos.toolBoxFlag,
+            orient: 'vertical',
+            left: 'right',
+            top: 'center',
+            feature: {
+                mark: { show: false },
+                dataView: { show: false, readOnly: false },
+                magicType: { show: false, type: ['line', 'bar', 'stack'] },
+                restore: { show: false },
+                saveAsImage: { show: true }
+            }
+        },
+        xAxis: [
+            {
+                type: 'category',
+                axisTick: { show: false },
+                data: Xnames
+            }
+        ],
+        yAxis: [
+            {
+                type: 'value',
+                name: unit,
+                nameLocation: 'end',
+                axisLabel: {
+                    show: true,
+                    interval: 0,
+                    formatter: function (value, index) {
+                        return value / db
+                    }
+                }
+            }
+        ],
+        series: mainData
+    };
+
+    option && myChart.setOption(option);
+
+    window.onresize = function () {
+        //自适应大小, 不用的话不会自适应大小。
+        myChart.resize()
+    }
+
+}
+
+/**
+ * 
+ * @param {*} id 图渲染容器id
+ */
+export function highBarsNiceUtils(id) {
+    let myChart = echarts.getInstanceByDom(id)
+    if (myChart == null) {
+        myChart = echarts.init(id)
+    }
+    var option;
+    var dataMap = {};
+    function dataFormatter(obj) {
+        // prettier-ignore
+        var pList = ['北京', '天津', '河北', '山西', '内蒙古', '辽宁', '吉林', '黑龙江', '上海', '江苏', '浙江', '安徽', '福建', '江西', '山东', '河南', '湖北', '湖南', '广东', '广西', '海南', '重庆', '四川', '贵州', '云南', '西藏', '陕西', '甘肃', '青海', '宁夏', '新疆'];
+        var temp;
+        for (var year = 2002; year <= 2011; year++) {
+            var max = 0;
+            var sum = 0;
+            temp = obj[year];
+            for (var i = 0, l = temp.length; i < l; i++) {
+                max = Math.max(max, temp[i]);
+                sum += temp[i];
+                obj[year][i] = {
+                    name: pList[i],
+                    value: temp[i]
+                };
+            }
+            obj[year + 'max'] = Math.floor(max / 100) * 100;
+            obj[year + 'sum'] = sum;
+        }
+        return obj;
+    }
+    // prettier-ignore
+    dataMap.dataGDP = dataFormatter({
+        //max : 60000,
+        2011: [16251.93, 11307.28, 24515.76, 11237.55, 14359.88, 22226.7, 10568.83, 12582, 19195.69, 49110.27, 32318.85, 15300.65, 17560.18, 11702.82, 45361.85, 26931.03, 19632.26, 19669.56, 53210.28, 11720.87, 2522.66, 10011.37, 21026.68, 5701.84, 8893.12, 605.83, 12512.3, 5020.37, 1670.44, 2102.21, 6610.05],
+        2010: [14113.58, 9224.46, 20394.26, 9200.86, 11672, 18457.27, 8667.58, 10368.6, 17165.98, 41425.48, 27722.31, 12359.33, 14737.12, 9451.26, 39169.92, 23092.36, 15967.61, 16037.96, 46013.06, 9569.85, 2064.5, 7925.58, 17185.48, 4602.16, 7224.18, 507.46, 10123.48, 4120.75, 1350.43, 1689.65, 5437.47],
+        2009: [12153.03, 7521.85, 17235.48, 7358.31, 9740.25, 15212.49, 7278.75, 8587, 15046.45, 34457.3, 22990.35, 10062.82, 12236.53, 7655.18, 33896.65, 19480.46, 12961.1, 13059.69, 39482.56, 7759.16, 1654.21, 6530.01, 14151.28, 3912.68, 6169.75, 441.36, 8169.8, 3387.56, 1081.27, 1353.31, 4277.05],
+        2008: [11115, 6719.01, 16011.97, 7315.4, 8496.2, 13668.58, 6426.1, 8314.37, 14069.87, 30981.98, 21462.69, 8851.66, 10823.01, 6971.05, 30933.28, 18018.53, 11328.92, 11555, 36796.71, 7021, 1503.06, 5793.66, 12601.23, 3561.56, 5692.12, 394.85, 7314.58, 3166.82, 1018.62, 1203.92, 4183.21],
+        2007: [9846.81, 5252.76, 13607.32, 6024.45, 6423.18, 11164.3, 5284.69, 7104, 12494.01, 26018.48, 18753.73, 7360.92, 9248.53, 5800.25, 25776.91, 15012.46, 9333.4, 9439.6, 31777.01, 5823.41, 1254.17, 4676.13, 10562.39, 2884.11, 4772.52, 341.43, 5757.29, 2703.98, 797.35, 919.11, 3523.16],
+        2006: [8117.78, 4462.74, 11467.6, 4878.61, 4944.25, 9304.52, 4275.12, 6211.8, 10572.24, 21742.05, 15718.47, 6112.5, 7583.85, 4820.53, 21900.19, 12362.79, 7617.47, 7688.67, 26587.76, 4746.16, 1065.67, 3907.23, 8690.24, 2338.98, 3988.14, 290.76, 4743.61, 2277.35, 648.5, 725.9, 3045.26],
+        2005: [6969.52, 3905.64, 10012.11, 4230.53, 3905.03, 8047.26, 3620.27, 5513.7, 9247.66, 18598.69, 13417.68, 5350.17, 6554.69, 4056.76, 18366.87, 10587.42, 6590.19, 6596.1, 22557.37, 3984.1, 918.75, 3467.72, 7385.1, 2005.42, 3462.73, 248.8, 3933.72, 1933.98, 543.32, 612.61, 2604.19],
+        2004: [6033.21, 3110.97, 8477.63, 3571.37, 3041.07, 6672, 3122.01, 4750.6, 8072.83, 15003.6, 11648.7, 4759.3, 5763.35, 3456.7, 15021.84, 8553.79, 5633.24, 5641.94, 18864.62, 3433.5, 819.66, 3034.58, 6379.63, 1677.8, 3081.91, 220.34, 3175.58, 1688.49, 466.1, 537.11, 2209.09],
+        2003: [5007.21, 2578.03, 6921.29, 2855.23, 2388.38, 6002.54, 2662.08, 4057.4, 6694.23, 12442.87, 9705.02, 3923.11, 4983.67, 2807.41, 12078.15, 6867.7, 4757.45, 4659.99, 15844.64, 2821.11, 713.96, 2555.72, 5333.09, 1426.34, 2556.02, 185.09, 2587.72, 1399.83, 390.2, 445.36, 1886.35],
+        2002: [4315, 2150.76, 6018.28, 2324.8, 1940.94, 5458.22, 2348.54, 3637.2, 5741.03, 10606.85, 8003.67, 3519.72, 4467.55, 2450.48, 10275.5, 6035.48, 4212.82, 4151.54, 13502.42, 2523.73, 642.73, 2232.86, 4725.01, 1243.43, 2312.82, 162.04, 2253.39, 1232.03, 340.65, 377.16, 1612.6]
+    });
+    // prettier-ignore
+    dataMap.dataPI = dataFormatter({
+        //max : 4000,
+        2011: [136.27, 159.72, 2905.73, 641.42, 1306.3, 1915.57, 1277.44, 1701.5, 124.94, 3064.78, 1583.04, 2015.31, 1612.24, 1391.07, 3973.85, 3512.24, 2569.3, 2768.03, 2665.2, 2047.23, 659.23, 844.52, 2983.51, 726.22, 1411.01, 74.47, 1220.9, 678.75, 155.08, 184.14, 1139.03],
+        2010: [124.36, 145.58, 2562.81, 554.48, 1095.28, 1631.08, 1050.15, 1302.9, 114.15, 2540.1, 1360.56, 1729.02, 1363.67, 1206.98, 3588.28, 3258.09, 2147, 2325.5, 2286.98, 1675.06, 539.83, 685.38, 2482.89, 625.03, 1108.38, 68.72, 988.45, 599.28, 134.92, 159.29, 1078.63],
+        2009: [118.29, 128.85, 2207.34, 477.59, 929.6, 1414.9, 980.57, 1154.33, 113.82, 2261.86, 1163.08, 1495.45, 1182.74, 1098.66, 3226.64, 2769.05, 1795.9, 1969.69, 2010.27, 1458.49, 462.19, 606.8, 2240.61, 550.27, 1067.6, 63.88, 789.64, 497.05, 107.4, 127.25, 759.74],
+        2008: [112.83, 122.58, 2034.59, 313.58, 907.95, 1302.02, 916.72, 1088.94, 111.8, 2100.11, 1095.96, 1418.09, 1158.17, 1060.38, 3002.65, 2658.78, 1780, 1892.4, 1973.05, 1453.75, 436.04, 575.4, 2216.15, 539.19, 1020.56, 60.62, 753.72, 462.27, 105.57, 118.94, 691.07],
+        2007: [101.26, 110.19, 1804.72, 311.97, 762.1, 1133.42, 783.8, 915.38, 101.84, 1816.31, 986.02, 1200.18, 1002.11, 905.77, 2509.14, 2217.66, 1378, 1626.48, 1695.57, 1241.35, 361.07, 482.39, 2032, 446.38, 837.35, 54.89, 592.63, 387.55, 83.41, 97.89, 628.72],
+        2006: [88.8, 103.35, 1461.81, 276.77, 634.94, 939.43, 672.76, 750.14, 93.81, 1545.05, 925.1, 1011.03, 865.98, 786.14, 2138.9, 1916.74, 1140.41, 1272.2, 1532.17, 1032.47, 323.48, 386.38, 1595.48, 382.06, 724.4, 50.9, 484.81, 334, 67.55, 79.54, 527.8],
+        2005: [88.68, 112.38, 1400, 262.42, 589.56, 882.41, 625.61, 684.6, 90.26, 1461.51, 892.83, 966.5, 827.36, 727.37, 1963.51, 1892.01, 1082.13, 1100.65, 1428.27, 912.5, 300.75, 463.4, 1481.14, 368.94, 661.69, 48.04, 435.77, 308.06, 65.34, 72.07, 509.99],
+        2004: [87.36, 105.28, 1370.43, 276.3, 522.8, 798.43, 568.69, 605.79, 83.45, 1367.58, 814.1, 950.5, 786.84, 664.5, 1778.45, 1649.29, 1020.09, 1022.45, 1248.59, 817.88, 278.76, 428.05, 1379.93, 334.5, 607.75, 44.3, 387.88, 286.78, 60.7, 65.33, 461.26],
+        2003: [84.11, 89.91, 1064.05, 215.19, 420.1, 615.8, 488.23, 504.8, 81.02, 1162.45, 717.85, 749.4, 692.94, 560, 1480.67, 1198.7, 798.35, 886.47, 1072.91, 658.78, 244.29, 339.06, 1128.61, 298.69, 494.6, 40.7, 302.66, 237.91, 48.47, 55.63, 412.9],
+        2002: [82.44, 84.21, 956.84, 197.8, 374.69, 590.2, 446.17, 474.2, 79.68, 1110.44, 685.2, 783.66, 664.78, 535.98, 1390, 1288.36, 707, 847.25, 1015.08, 601.99, 222.89, 317.87, 1047.95, 281.1, 463.44, 39.75, 282.21, 215.51, 47.31, 52.95, 305]
+    });
+    // prettier-ignore
+    dataMap.dataSI = dataFormatter({
+        //max : 26600,
+        2011: [3752.48, 5928.32, 13126.86, 6635.26, 8037.69, 12152.15, 5611.48, 5962.41, 7927.89, 25203.28, 16555.58, 8309.38, 9069.2, 6390.55, 24017.11, 15427.08, 9815.94, 9361.99, 26447.38, 5675.32, 714.5, 5543.04, 11029.13, 2194.33, 3780.32, 208.79, 6935.59, 2377.83, 975.18, 1056.15, 3225.9],
+        2010: [3388.38, 4840.23, 10707.68, 5234, 6367.69, 9976.82, 4506.31, 5025.15, 7218.32, 21753.93, 14297.93, 6436.62, 7522.83, 5122.88, 21238.49, 13226.38, 7767.24, 7343.19, 23014.53, 4511.68, 571, 4359.12, 8672.18, 1800.06, 3223.49, 163.92, 5446.1, 1984.97, 744.63, 827.91, 2592.15],
+        2009: [2855.55, 3987.84, 8959.83, 3993.8, 5114, 7906.34, 3541.92, 4060.72, 6001.78, 18566.37, 11908.49, 4905.22, 6005.3, 3919.45, 18901.83, 11010.5, 6038.08, 5687.19, 19419.7, 3381.54, 443.43, 3448.77, 6711.87, 1476.62, 2582.53, 136.63, 4236.42, 1527.24, 575.33, 662.32, 1929.59],
+        2008: [2626.41, 3709.78, 8701.34, 4242.36, 4376.19, 7158.84, 3097.12, 4319.75, 6085.84, 16993.34, 11567.42, 4198.93, 5318.44, 3554.81, 17571.98, 10259.99, 5082.07, 5028.93, 18502.2, 3037.74, 423.55, 3057.78, 5823.39, 1370.03, 2452.75, 115.56, 3861.12, 1470.34, 557.12, 609.98, 2070.76],
+        2007: [2509.4, 2892.53, 7201.88, 3454.49, 3193.67, 5544.14, 2475.45, 3695.58, 5571.06, 14471.26, 10154.25, 3370.96, 4476.42, 2975.53, 14647.53, 8282.83, 4143.06, 3977.72, 16004.61, 2425.29, 364.26, 2368.53, 4648.79, 1124.79, 2038.39, 98.48, 2986.46, 1279.32, 419.03, 455.04, 1647.55],
+        2006: [2191.43, 2457.08, 6110.43, 2755.66, 2374.96, 4566.83, 1915.29, 3365.31, 4969.95, 12282.89, 8511.51, 2711.18, 3695.04, 2419.74, 12574.03, 6724.61, 3365.08, 3187.05, 13469.77, 1878.56, 308.62, 1871.65, 3775.14, 967.54, 1705.83, 80.1, 2452.44, 1043.19, 331.91, 351.58, 1459.3],
+        2005: [2026.51, 2135.07, 5271.57, 2357.04, 1773.21, 3869.4, 1580.83, 2971.68, 4381.2, 10524.96, 7164.75, 2245.9, 3175.92, 1917.47, 10478.62, 5514.14, 2852.12, 2612.57, 11356.6, 1510.68, 240.83, 1564, 3067.23, 821.16, 1426.42, 63.52, 1951.36, 838.56, 264.61, 281.05, 1164.79],
+        2004: [1853.58, 1685.93, 4301.73, 1919.4, 1248.27, 3061.62, 1329.68, 2487.04, 3892.12, 8437.99, 6250.38, 1844.9, 2770.49, 1566.4, 8478.69, 4182.1, 2320.6, 2190.54, 9280.73, 1253.7, 205.6, 1376.91, 2489.4, 681.5, 1281.63, 52.74, 1553.1, 713.3, 211.7, 244.05, 914.47],
+        2003: [1487.15, 1337.31, 3417.56, 1463.38, 967.49, 2898.89, 1098.37, 2084.7, 3209.02, 6787.11, 5096.38, 1535.29, 2340.82, 1204.33, 6485.05, 3310.14, 1956.02, 1777.74, 7592.78, 984.08, 175.82, 1135.31, 2014.8, 569.37, 1047.66, 47.64, 1221.17, 572.02, 171.92, 194.27, 719.54],
+        2002: [1249.99, 1069.08, 2911.69, 1134.31, 754.78, 2609.85, 943.49, 1843.6, 2622.45, 5604.49, 4090.48, 1337.04, 2036.97, 941.77, 5184.98, 2768.75, 1709.89, 1523.5, 6143.4, 846.89, 148.88, 958.87, 1733.38, 481.96, 934.88, 32.72, 1007.56, 501.69, 144.51, 153.06, 603.15]
+    });
+    // prettier-ignore
+    dataMap.dataTI = dataFormatter({
+        //max : 25000,
+        2011: [12363.18, 5219.24, 8483.17, 3960.87, 5015.89, 8158.98, 3679.91, 4918.09, 11142.86, 20842.21, 14180.23, 4975.96, 6878.74, 3921.2, 17370.89, 7991.72, 7247.02, 7539.54, 24097.7, 3998.33, 1148.93, 3623.81, 7014.04, 2781.29, 3701.79, 322.57, 4355.81, 1963.79, 540.18, 861.92, 2245.12],
+        2010: [10600.84, 4238.65, 7123.77, 3412.38, 4209.03, 6849.37, 3111.12, 4040.55, 9833.51, 17131.45, 12063.82, 4193.69, 5850.62, 3121.4, 14343.14, 6607.89, 6053.37, 6369.27, 20711.55, 3383.11, 953.67, 2881.08, 6030.41, 2177.07, 2892.31, 274.82, 3688.93, 1536.5, 470.88, 702.45, 1766.69],
+        2009: [9179.19, 3405.16, 6068.31, 2886.92, 3696.65, 5891.25, 2756.26, 3371.95, 8930.85, 13629.07, 9918.78, 3662.15, 5048.49, 2637.07, 11768.18, 5700.91, 5127.12, 5402.81, 18052.59, 2919.13, 748.59, 2474.44, 5198.8, 1885.79, 2519.62, 240.85, 3143.74, 1363.27, 398.54, 563.74, 1587.72],
+        2008: [8375.76, 2886.65, 5276.04, 2759.46, 3212.06, 5207.72, 2412.26, 2905.68, 7872.23, 11888.53, 8799.31, 3234.64, 4346.4, 2355.86, 10358.64, 5099.76, 4466.85, 4633.67, 16321.46, 2529.51, 643.47, 2160.48, 4561.69, 1652.34, 2218.81, 218.67, 2699.74, 1234.21, 355.93, 475, 1421.38],
+        2007: [7236.15, 2250.04, 4600.72, 2257.99, 2467.41, 4486.74, 2025.44, 2493.04, 6821.11, 9730.91, 7613.46, 2789.78, 3770, 1918.95, 8620.24, 4511.97, 3812.34, 3835.4, 14076.83, 2156.76, 528.84, 1825.21, 3881.6, 1312.94, 1896.78, 188.06, 2178.2, 1037.11, 294.91, 366.18, 1246.89],
+        2006: [5837.55, 1902.31, 3895.36, 1846.18, 1934.35, 3798.26, 1687.07, 2096.35, 5508.48, 7914.11, 6281.86, 2390.29, 3022.83, 1614.65, 7187.26, 3721.44, 3111.98, 3229.42, 11585.82, 1835.12, 433.57, 1649.2, 3319.62, 989.38, 1557.91, 159.76, 1806.36, 900.16, 249.04, 294.78, 1058.16],
+        2005: [4854.33, 1658.19, 3340.54, 1611.07, 1542.26, 3295.45, 1413.83, 1857.42, 4776.2, 6612.22, 5360.1, 2137.77, 2551.41, 1411.92, 5924.74, 3181.27, 2655.94, 2882.88, 9772.5, 1560.92, 377.17, 1440.32, 2836.73, 815.32, 1374.62, 137.24, 1546.59, 787.36, 213.37, 259.49, 929.41],
+        2004: [4092.27, 1319.76, 2805.47, 1375.67, 1270, 2811.95, 1223.64, 1657.77, 4097.26, 5198.03, 4584.22, 1963.9, 2206.02, 1225.8, 4764.7, 2722.4, 2292.55, 2428.95, 8335.3, 1361.92, 335.3, 1229.62, 2510.3, 661.8, 1192.53, 123.3, 1234.6, 688.41, 193.7, 227.73, 833.36],
+        2003: [3435.95, 1150.81, 2439.68, 1176.65, 1000.79, 2487.85, 1075.48, 1467.9, 3404.19, 4493.31, 3890.79, 1638.42, 1949.91, 1043.08, 4112.43, 2358.86, 2003.08, 1995.78, 7178.94, 1178.25, 293.85, 1081.35, 2189.68, 558.28, 1013.76, 96.76, 1063.89, 589.91, 169.81, 195.46, 753.91],
+        2002: [2982.57, 997.47, 2149.75, 992.69, 811.47, 2258.17, 958.88, 1319.4, 3038.9, 3891.92, 3227.99, 1399.02, 1765.8, 972.73, 3700.52, 1978.37, 1795.93, 1780.79, 6343.94, 1074.85, 270.96, 956.12, 1943.68, 480.37, 914.5, 89.56, 963.62, 514.83, 148.83, 171.14, 704.5]
+    });
+    // prettier-ignore
+    dataMap.dataEstate = dataFormatter({
+        //max : 3600,
+        2011: [1074.93, 411.46, 918.02, 224.91, 384.76, 876.12, 238.61, 492.1, 1019.68, 2747.89, 1677.13, 634.92, 911.16, 402.51, 1838.14, 987, 634.67, 518.04, 3321.31, 465.68, 208.71, 396.28, 620.62, 160.3, 222.31, 17.44, 398.03, 134.25, 29.05, 79.01, 176.22],
+        2010: [1006.52, 377.59, 697.79, 192, 309.25, 733.37, 212.32, 391.89, 1002.5, 2600.95, 1618.17, 532.17, 679.03, 340.56, 1622.15, 773.23, 564.41, 464.21, 2813.95, 405.79, 188.33, 266.38, 558.56, 139.64, 223.45, 14.54, 315.95, 110.02, 25.41, 60.53, 143.44],
+        2009: [1062.47, 308.73, 612.4, 173.31, 286.65, 605.27, 200.14, 301.18, 1237.56, 2025.39, 1316.84, 497.94, 656.61, 305.9, 1329.59, 622.98, 546.11, 400.11, 2470.63, 348.98, 121.76, 229.09, 548.14, 136.15, 205.14, 13.28, 239.92, 101.37, 23.05, 47.56, 115.23],
+        2008: [844.59, 227.88, 513.81, 166.04, 273.3, 500.81, 182.7, 244.47, 939.34, 1626.13, 1052.03, 431.27, 506.98, 281.96, 1104.95, 512.42, 526.88, 340.07, 2057.45, 282.96, 95.6, 191.21, 453.63, 104.81, 195.48, 15.08, 193.27, 93.8, 19.96, 38.85, 89.79],
+        2007: [821.5, 183.44, 467.97, 134.12, 191.01, 410.43, 153.03, 225.81, 958.06, 1365.71, 981.42, 366.57, 511.5, 225.96, 953.69, 447.44, 409.65, 301.8, 2029.77, 239.45, 67.19, 196.06, 376.84, 93.19, 193.59, 13.24, 153.98, 83.52, 16.98, 29.49, 91.28],
+        2006: [658.3, 156.64, 397.14, 117.01, 136.5, 318.54, 131.01, 194.7, 773.61, 1017.91, 794.41, 281.98, 435.22, 184.67, 786.51, 348.7, 294.73, 254.81, 1722.07, 192.2, 44.45, 158.2, 336.2, 80.24, 165.92, 11.92, 125.2, 73.21, 15.17, 25.53, 68.9],
+        2005: [493.73, 122.67, 330.87, 106, 98.75, 256.77, 112.29, 163.34, 715.97, 799.73, 688.86, 231.66, 331.8, 171.88, 664.9, 298.19, 217.17, 215.63, 1430.37, 165.05, 38.2, 143.88, 286.23, 76.38, 148.69, 10.02, 108.62, 63.78, 14.1, 22.97, 55.79],
+        2004: [436.11, 106.14, 231.08, 95.1, 73.81, 203.1, 97.93, 137.74, 666.3, 534.17, 587.83, 188.28, 248.44, 167.2, 473.27, 236.44, 204.8, 191.5, 1103.75, 122.52, 30.64, 129.12, 264.3, 68.3, 116.54, 5.8, 95.9, 56.84, 13, 20.78, 53.55],
+        2003: [341.88, 92.31, 185.19, 78.73, 61.05, 188.49, 91.99, 127.2, 487.82, 447.47, 473.16, 162.63, 215.84, 138.02, 418.21, 217.58, 176.8, 186.49, 955.66, 100.93, 25.14, 113.69, 231.72, 59.86, 103.79, 4.35, 83.9, 48.09, 11.41, 16.85, 47.84],
+        2002: [298.02, 73.04, 140.89, 65.83, 51.48, 130.94, 76.11, 118.7, 384.86, 371.09, 360.63, 139.18, 188.09, 125.27, 371.13, 199.31, 145.17, 165.29, 808.16, 82.83, 21.45, 90.48, 210.82, 53.49, 95.68, 3.42, 77.68, 41.52, 9.74, 13.46, 43.04]
+    });
+    // prettier-ignore
+    dataMap.dataFinancial = dataFormatter({
+        //max : 3200,
+        2011: [2215.41, 756.5, 746.01, 519.32, 447.46, 755.57, 207.65, 370.78, 2277.4, 2600.11, 2730.29, 503.85, 862.41, 357.44, 1640.41, 868.2, 674.57, 501.09, 2916.13, 445.37, 105.24, 704.66, 868.15, 297.27, 456.23, 31.7, 432.11, 145.05, 62.56, 134.18, 288.77],
+        2010: [1863.61, 572.99, 615.42, 448.3, 346.44, 639.27, 190.12, 304.59, 1950.96, 2105.92, 2326.58, 396.17, 767.58, 241.49, 1361.45, 697.68, 561.27, 463.16, 2658.76, 384.53, 78.12, 496.56, 654.7, 231.51, 375.08, 27.08, 384.75, 100.54, 54.53, 97.87, 225.2],
+        2009: [1603.63, 461.2, 525.67, 361.64, 291.1, 560.2, 180.83, 227.54, 1804.28, 1596.98, 1899.33, 359.6, 612.2, 165.1, 1044.9, 499.92, 479.11, 402.57, 2283.29, 336.82, 65.73, 389.97, 524.63, 194.44, 351.74, 23.17, 336.21, 88.27, 45.63, 75.54, 198.87],
+        2008: [1519.19, 368.1, 420.74, 290.91, 219.09, 455.07, 147.24, 177.43, 1414.21, 1298.48, 1653.45, 313.81, 497.65, 130.57, 880.28, 413.83, 393.05, 334.32, 1972.4, 249.01, 47.33, 303.01, 411.14, 151.55, 277.66, 22.42, 287.16, 72.49, 36.54, 64.8, 171.97],
+        2007: [1302.77, 288.17, 347.65, 218.73, 148.3, 386.34, 126.03, 155.48, 1209.08, 1054.25, 1251.43, 223.85, 385.84, 101.34, 734.9, 302.31, 337.27, 260.14, 1705.08, 190.73, 34.43, 247.46, 359.11, 122.25, 168.55, 11.51, 231.03, 61.6, 27.67, 51.05, 149.22],
+        2006: [982.37, 186.87, 284.04, 169.63, 108.21, 303.41, 100.75, 74.17, 825.2, 653.25, 906.37, 166.01, 243.9, 79.75, 524.94, 219.72, 174.99, 204.72, 899.91, 129.14, 16.37, 213.7, 299.5, 89.43, 143.62, 6.44, 152.25, 50.51, 23.69, 36.99, 99.25],
+        2005: [840.2, 147.4, 213.47, 135.07, 72.52, 232.85, 83.63, 35.03, 675.12, 492.4, 686.32, 127.05, 186.12, 69.55, 448.36, 181.74, 127.32, 162.37, 661.81, 91.93, 13.16, 185.18, 262.26, 73.67, 130.5, 7.57, 127.58, 44.73, 20.36, 32.25, 80.34],
+        2004: [713.79, 136.97, 209.1, 110.29, 55.89, 188.04, 77.17, 32.2, 612.45, 440.5, 523.49, 94.1, 171, 65.1, 343.37, 170.82, 118.85, 118.64, 602.68, 74, 11.56, 162.38, 236.5, 60.3, 118.4, 5.4, 90.1, 42.99, 19, 27.92, 70.3],
+        2003: [635.56, 112.79, 199.87, 118.48, 55.89, 145.38, 73.15, 32.2, 517.97, 392.11, 451.54, 87.45, 150.09, 64.31, 329.71, 165.11, 107.31, 99.35, 534.28, 61.59, 10.68, 147.04, 206.24, 48.01, 105.48, 4.74, 77.87, 42.31, 17.98, 24.8, 64.92],
+        2002: [561.91, 76.86, 179.6, 124.1, 48.39, 137.18, 75.45, 31.6, 485.25, 368.86, 347.53, 81.85, 138.28, 76.51, 310.07, 158.77, 96.95, 92.43, 454.65, 35.86, 10.08, 134.52, 183.13, 41.45, 102.39, 2.81, 67.3, 42.08, 16.75, 21.45, 52.18]
+    });
+    option = {
+        baseOption: {
+            timeline: {
+                axisType: 'category',
+                // realtime: false,
+                // loop: false,
+                autoPlay: true,
+                // currentIndex: 2,
+                playInterval: 1000,
+                // controlStyle: {
+                //     position: 'left'
+                // },
+                data: [
+                    '2002-01-01',
+                    '2003-01-01',
+                    '2004-01-01',
+                    {
+                        value: '2005-01-01',
+                        tooltip: {
+                            formatter: '{b} GDP达到一个高度'
+                        },
+                        symbol: 'diamond',
+                        symbolSize: 16
+                    },
+                    '2006-01-01',
+                    '2007-01-01',
+                    '2008-01-01',
+                    '2009-01-01',
+                    '2010-01-01',
+                    {
+                        value: '2011-01-01',
+                        tooltip: {
+                            formatter: function (params) {
+                                return params.name + 'GDP达到又一个高度';
+                            }
+                        },
+                        symbol: 'diamond',
+                        symbolSize: 18
+                    }
+                ],
+                label: {
+                    formatter: function (s) {
+                        return new Date(s).getFullYear();
+                    }
+                }
+            },
+            title: {
+                subtext: '数据来自国家统计局'
+            },
+            tooltip: {},
+            legend: {
+                left: 'right',
+                data: ['第一产业', '第二产业', '第三产业', 'GDP', '金融', '房地产'],
+                selected: {
+                    GDP: false,
+                    金融: false,
+                    房地产: false
+                }
+            },
+            calculable: true,
+            grid: {
+                top: 80,
+                bottom: 100,
+                tooltip: {
+                    trigger: 'axis',
+                    axisPointer: {
+                        type: 'shadow',
+                        label: {
+                            show: true,
+                            formatter: function (params) {
+                                return params.value.replace('\n', '');
+                            }
+                        }
+                    }
+                }
+            },
+            xAxis: [
+                {
+                    type: 'category',
+                    axisLabel: { interval: 0 },
+                    data: [
+                        '北京',
+                        '\n天津',
+                        '河北',
+                        '\n山西',
+                        '内蒙古',
+                        '\n辽宁',
+                        '吉林',
+                        '\n黑龙江',
+                        '上海',
+                        '\n江苏',
+                        '浙江',
+                        '\n安徽',
+                        '福建',
+                        '\n江西',
+                        '山东',
+                        '\n河南',
+                        '湖北',
+                        '\n湖南',
+                        '广东',
+                        '\n广西',
+                        '海南',
+                        '\n重庆',
+                        '四川',
+                        '\n贵州',
+                        '云南',
+                        '\n西藏',
+                        '陕西',
+                        '\n甘肃',
+                        '青海',
+                        '\n宁夏',
+                        '新疆'
+                    ],
+                    splitLine: { show: false }
+                }
+            ],
+            yAxis: [
+                {
+                    type: 'value',
+                    name: 'GDP(亿元)'
+                }
+            ],
+            series: [
+                { name: 'GDP', type: 'bar' },
+                { name: '金融', type: 'bar' },
+                { name: '房地产', type: 'bar' },
+                { name: '第一产业', type: 'bar' },
+                { name: '第二产业', type: 'bar' },
+                { name: '第三产业', type: 'bar' },
+                {
+                    name: 'GDP占比',
+                    type: 'pie',
+                    center: ['75%', '35%'],
+                    radius: '28%',
+                    z: 100
+                }
+            ]
+        },
+        options: [
+            {
+                title: { text: '2002全国宏观经济指标' },
+                series: [
+                    { data: dataMap.dataGDP['2002'] },
+                    { data: dataMap.dataFinancial['2002'] },
+                    { data: dataMap.dataEstate['2002'] },
+                    { data: dataMap.dataPI['2002'] },
+                    { data: dataMap.dataSI['2002'] },
+                    { data: dataMap.dataTI['2002'] },
+                    {
+                        data: [
+                            { name: '第一产业', value: dataMap.dataPI['2002sum'] },
+                            { name: '第二产业', value: dataMap.dataSI['2002sum'] },
+                            { name: '第三产业', value: dataMap.dataTI['2002sum'] }
+                        ]
+                    }
+                ]
+            },
+            {
+                title: { text: '2003全国宏观经济指标' },
+                series: [
+                    { data: dataMap.dataGDP['2003'] },
+                    { data: dataMap.dataFinancial['2003'] },
+                    { data: dataMap.dataEstate['2003'] },
+                    { data: dataMap.dataPI['2003'] },
+                    { data: dataMap.dataSI['2003'] },
+                    { data: dataMap.dataTI['2003'] },
+                    {
+                        data: [
+                            { name: '第一产业', value: dataMap.dataPI['2003sum'] },
+                            { name: '第二产业', value: dataMap.dataSI['2003sum'] },
+                            { name: '第三产业', value: dataMap.dataTI['2003sum'] }
+                        ]
+                    }
+                ]
+            },
+            {
+                title: { text: '2004全国宏观经济指标' },
+                series: [
+                    { data: dataMap.dataGDP['2004'] },
+                    { data: dataMap.dataFinancial['2004'] },
+                    { data: dataMap.dataEstate['2004'] },
+                    { data: dataMap.dataPI['2004'] },
+                    { data: dataMap.dataSI['2004'] },
+                    { data: dataMap.dataTI['2004'] },
+                    {
+                        data: [
+                            { name: '第一产业', value: dataMap.dataPI['2004sum'] },
+                            { name: '第二产业', value: dataMap.dataSI['2004sum'] },
+                            { name: '第三产业', value: dataMap.dataTI['2004sum'] }
+                        ]
+                    }
+                ]
+            },
+            {
+                title: { text: '2005全国宏观经济指标' },
+                series: [
+                    { data: dataMap.dataGDP['2005'] },
+                    { data: dataMap.dataFinancial['2005'] },
+                    { data: dataMap.dataEstate['2005'] },
+                    { data: dataMap.dataPI['2005'] },
+                    { data: dataMap.dataSI['2005'] },
+                    { data: dataMap.dataTI['2005'] },
+                    {
+                        data: [
+                            { name: '第一产业', value: dataMap.dataPI['2005sum'] },
+                            { name: '第二产业', value: dataMap.dataSI['2005sum'] },
+                            { name: '第三产业', value: dataMap.dataTI['2005sum'] }
+                        ]
+                    }
+                ]
+            },
+            {
+                title: { text: '2006全国宏观经济指标' },
+                series: [
+                    { data: dataMap.dataGDP['2006'] },
+                    { data: dataMap.dataFinancial['2006'] },
+                    { data: dataMap.dataEstate['2006'] },
+                    { data: dataMap.dataPI['2006'] },
+                    { data: dataMap.dataSI['2006'] },
+                    { data: dataMap.dataTI['2006'] },
+                    {
+                        data: [
+                            { name: '第一产业', value: dataMap.dataPI['2006sum'] },
+                            { name: '第二产业', value: dataMap.dataSI['2006sum'] },
+                            { name: '第三产业', value: dataMap.dataTI['2006sum'] }
+                        ]
+                    }
+                ]
+            },
+            {
+                title: { text: '2007全国宏观经济指标' },
+                series: [
+                    { data: dataMap.dataGDP['2007'] },
+                    { data: dataMap.dataFinancial['2007'] },
+                    { data: dataMap.dataEstate['2007'] },
+                    { data: dataMap.dataPI['2007'] },
+                    { data: dataMap.dataSI['2007'] },
+                    { data: dataMap.dataTI['2007'] },
+                    {
+                        data: [
+                            { name: '第一产业', value: dataMap.dataPI['2007sum'] },
+                            { name: '第二产业', value: dataMap.dataSI['2007sum'] },
+                            { name: '第三产业', value: dataMap.dataTI['2007sum'] }
+                        ]
+                    }
+                ]
+            },
+            {
+                title: { text: '2008全国宏观经济指标' },
+                series: [
+                    { data: dataMap.dataGDP['2008'] },
+                    { data: dataMap.dataFinancial['2008'] },
+                    { data: dataMap.dataEstate['2008'] },
+                    { data: dataMap.dataPI['2008'] },
+                    { data: dataMap.dataSI['2008'] },
+                    { data: dataMap.dataTI['2008'] },
+                    {
+                        data: [
+                            { name: '第一产业', value: dataMap.dataPI['2008sum'] },
+                            { name: '第二产业', value: dataMap.dataSI['2008sum'] },
+                            { name: '第三产业', value: dataMap.dataTI['2008sum'] }
+                        ]
+                    }
+                ]
+            },
+            {
+                title: { text: '2009全国宏观经济指标' },
+                series: [
+                    { data: dataMap.dataGDP['2009'] },
+                    { data: dataMap.dataFinancial['2009'] },
+                    { data: dataMap.dataEstate['2009'] },
+                    { data: dataMap.dataPI['2009'] },
+                    { data: dataMap.dataSI['2009'] },
+                    { data: dataMap.dataTI['2009'] },
+                    {
+                        data: [
+                            { name: '第一产业', value: dataMap.dataPI['2009sum'] },
+                            { name: '第二产业', value: dataMap.dataSI['2009sum'] },
+                            { name: '第三产业', value: dataMap.dataTI['2009sum'] }
+                        ]
+                    }
+                ]
+            },
+            {
+                title: { text: '2010全国宏观经济指标' },
+                series: [
+                    { data: dataMap.dataGDP['2010'] },
+                    { data: dataMap.dataFinancial['2010'] },
+                    { data: dataMap.dataEstate['2010'] },
+                    { data: dataMap.dataPI['2010'] },
+                    { data: dataMap.dataSI['2010'] },
+                    { data: dataMap.dataTI['2010'] },
+                    {
+                        data: [
+                            { name: '第一产业', value: dataMap.dataPI['2010sum'] },
+                            { name: '第二产业', value: dataMap.dataSI['2010sum'] },
+                            { name: '第三产业', value: dataMap.dataTI['2010sum'] }
+                        ]
+                    }
+                ]
+            },
+            {
+                title: { text: '2011全国宏观经济指标' },
+                series: [
+                    { data: dataMap.dataGDP['2011'] },
+                    { data: dataMap.dataFinancial['2011'] },
+                    { data: dataMap.dataEstate['2011'] },
+                    { data: dataMap.dataPI['2011'] },
+                    { data: dataMap.dataSI['2011'] },
+                    { data: dataMap.dataTI['2011'] },
+                    {
+                        data: [
+                            { name: '第一产业', value: dataMap.dataPI['2011sum'] },
+                            { name: '第二产业', value: dataMap.dataSI['2011sum'] },
+                            { name: '第三产业', value: dataMap.dataTI['2011sum'] }
+                        ]
+                    }
+                ]
+            }
+        ]
+    };
+
+    option && myChart.setOption(option);
+
+    window.onresize = function () {
+        //自适应大小, 不用的话不会自适应大小。
+        myChart.resize()
+    }
+
 }

+ 249 - 0
src/views/target-management/target-comm/SqlEditPage.vue

@@ -0,0 +1,249 @@
+<template>
+    <el-row :gutter="5">
+        <PageLayer>
+            <template #header class="hd-cl">
+                <el-button type="primary" icon="Check" @click="submitForm(sqlFormRef)"
+                    style="margin-left: 10px">保存</el-button>
+                <el-button type="primary" icon="Refresh" style="margin-left: 10px"
+                    @click="resetForm(sqlFormRef)">重置</el-button>
+            </template>
+            <template #main>
+                <el-form ref="sqlFormRef" :model="sqlForm" :rules="rules" label-width="120px" class="demo-ruleForm"
+                    :size="formSize" status-icon>
+                    <el-row>
+                        <el-col :span="12">
+                            <el-form-item label="指标名称" prop="name" :disabled="true">
+                                <el-input v-model="sqlForm.name" />
+                            </el-form-item>
+                        </el-col>
+                        <el-col :span="4">
+                            <el-form-item label="指标编码" prop="id" :disabled="true">
+                                <el-input v-model="sqlForm.id" />
+                            </el-form-item>
+                        </el-col>
+                        <el-col :span="4">
+                            <el-form-item label="父级编码" prop="pid" :disabled="true">
+                                <el-input v-model="sqlForm.pid" />
+                            </el-form-item>
+                        </el-col>
+                        <el-col :span="4">
+                            <el-form-item label="序号" prop="sort" :disabled="true">
+                                <el-input v-model="sqlForm.sort" />
+                            </el-form-item>
+                        </el-col>
+                    </el-row>
+                    <el-row>
+                        <el-col :span="12">
+                            <el-form-item label="开始时间">
+                                <el-form-item prop="startTime">
+                                    <el-date-picker v-model="sqlForm.startTime" type="date" label="选择时间" placeholder="选择时间"
+                                        format="YYYYMMDD" value-format="YYYYMMDD" />
+                                </el-form-item>
+                            </el-form-item>
+                        </el-col>
+                        <el-col :span="12">
+                            <el-form-item label="结束时间">
+                                <el-form-item prop="endTime">
+                                    <el-date-picker v-model="sqlForm.endTime" type="date" label="选择时间" placeholder="选择时间"
+                                        format="YYYYMMDD" value-format="YYYYMMDD" />
+                                </el-form-item>
+                            </el-form-item>
+                        </el-col>
+                    </el-row>
+                    <el-row>
+                        <el-col :span="12">
+                            <el-form-item label="公式-分子" prop="calcChild">
+                                <el-input v-model="sqlForm.calcChild" type="textarea" :rows="24" />
+                            </el-form-item>
+                        </el-col>
+                        <el-col :span="12">
+                            <el-form-item label="公式-分母" prop="calcMom">
+                                <el-input v-model="sqlForm.calcMom" type="textarea" :rows="24" />
+                            </el-form-item>
+                        </el-col>
+                    </el-row>
+                    <el-row>
+                        <el-col :span="12">
+                            <el-form-item>
+                                <el-button type="primary" @click="sqlExecute(sqlFormRef)"> sql运行 </el-button>
+                            </el-form-item>
+                        </el-col>
+                    </el-row>
+                    <el-row>
+                        <el-col :span="8">
+                            <el-form-item label="公式-分子结果" prop="childResult">
+                                <el-input v-model="sqlForm.childResult" type="textarea" />
+                            </el-form-item>
+                        </el-col>
+                        <el-col :span="8">
+                            <el-form-item label="公式-分母结果" prop="momResult">
+                                <el-input v-model="sqlForm.momResult" type="textarea" />
+                            </el-form-item>
+                        </el-col>
+                        <el-col :span="8">
+                            <el-form-item label="分子/分母-结果" prop="calcResult">
+                                <el-input v-model="sqlForm.calcResult" type="textarea" />
+                            </el-form-item>
+                        </el-col>
+                    </el-row>
+                </el-form>
+            </template>
+        </PageLayer>
+    </el-row>
+</template>
+<script setup name="SqlEditPage" lang="ts">
+import { ref, watch, onMounted, nextTick } from 'vue'
+import type { FormInstance, FormRules } from 'element-plus'
+import PageLayer from '../../../layout/PageLayer.vue'
+import { ElMessage } from 'element-plus'
+import { targetSqlExecute, targetSqlSave } from '../../../api/target-management/target-sql'
+
+const formSize = ref('default')
+const sqlFormRef = ref<FormInstance>()
+let sqlForm = $ref({
+    id: '', // 指标编码
+    name: '', // 指标名称
+    pid: '', // 父级编码
+    sort: '', // 指标序号
+    startTime: '', // 指标序号
+    endTime: '', // 总分
+    calcChild: '', // 计算分子sql
+    calcMom: '', // 计算分母sql
+    childResult: '', // 计算分子结果
+    momResult: '', // 计算分母结果
+    calcResult: '' // 计算结果
+})
+
+const props = defineProps({
+    sqlEditData: {
+        type: Object,
+        default: {}
+    }
+})
+
+onMounted(() => {
+    nextTick(() => {
+        sqlForm = props.sqlEditData
+    })
+})
+
+watch(
+    () => sqlForm,
+    () => {
+
+    })
+
+const resetForm = (formEl: FormInstance | undefined) => {
+    if (!formEl) return
+    sqlForm.startTime = ''
+    sqlForm.endTime = ''
+    sqlForm.childResult = ''
+    sqlForm.momResult = ''
+    sqlForm.calcResult = ''
+}
+
+const rules = ref<FormRules>({
+    startTime: [
+        { required: true, message: '请选择指标查询开始时间', trigger: 'blur' },
+    ],
+    endTime: [
+        { required: true, message: '请选择指标查询结束时间', trigger: 'blur' },
+    ],
+    calcChild: [
+        { required: true, message: '请填写sql语句', trigger: 'blur' },
+    ],
+})
+
+const submitForm = async (formEl: FormInstance | undefined) => {
+    if (!formEl) return
+
+    await formEl.validate((valid: boolean, field: any) => {
+        if (valid) {
+            targetSqlSave(sqlForm)
+                .then((res: any) => {
+                    let r = JSON.parse(JSON.stringify(res))
+                    if (r.cg) {
+                        console.log(r.cg)
+                    }
+
+                });
+
+        } else {
+            if (field.startTime) {
+                ElMessage({
+                    type: "info",
+                    message: field.startTime[0].message,
+                    duration: 2500,
+                    showClose: true,
+                });
+            } else if (field.endTime) {
+                ElMessage({
+                    type: "info",
+                    message: field.endTime[0].message,
+                    duration: 2500,
+                    showClose: true,
+                });
+            } else {
+                ElMessage({
+                    type: "info",
+                    message: field.calcChild[0].message,
+                    duration: 2500,
+                    showClose: true,
+                });
+            }
+            return
+        }
+    })
+}
+
+const sqlExecute = (formEl: FormInstance | undefined) => {
+    if (!formEl) return
+
+    // 验证是否填写完整
+    formEl.validate((valid: boolean, field: any) => {
+        if (valid) {
+            if (sqlForm.calcChild === '') {
+                ElMessage({
+                    type: "info",
+                    message: "未编写sql,请确认!",
+                    duration: 2500,
+                    showClose: true,
+                });
+                return
+            }
+
+            targetSqlExecute(sqlForm)
+                .then((res: any) => {
+                    let r = JSON.parse(JSON.stringify(res))
+                    sqlForm.childResult = r.r1
+                    sqlForm.momResult = r.r2
+                    sqlForm.calcResult = r.r3
+
+                });
+        } else {
+            if (field.startTime) {
+                ElMessage({
+                    type: "info",
+                    message: field.startTime[0].message,
+                    duration: 2500,
+                    showClose: true,
+                });
+            } else {
+                ElMessage({
+                    type: "info",
+                    message: field.endTime[0].message,
+                    duration: 2500,
+                    showClose: true,
+                });
+            }
+            return
+        }
+    })
+}
+
+</script>
+<style lang="scss" scoped deep>
+.hd-cl {
+    margin-bottom: 1px !important;
+}
+</style>

+ 85 - 0
src/views/target-management/target-comm/targetTree.vue

@@ -0,0 +1,85 @@
+<template>
+    <el-input class="qt-cl" v-model="filterText" placeholder="输入关键词搜索" />
+    <div style="position: relative; width: 100%; overflow: auto" class="th-dg">
+        <el-tree ref="treeRef" class="filter-tree" :data="treeData" :props="defaultProps" node-key="id" default-expand-all
+            :check-strictly="isCheck" highlight-current :filter-node-method="filterNode" :height="targetTreeData.height"
+            @node-click="handleNodeClick" :expand-on-click-node="isOkDoor">
+        </el-tree>
+    </div>
+</template>
+<script setup name="TargetTree" lang="ts">
+import { ref, onMounted, watch, nextTick, computed } from 'vue'
+import { ElTree } from 'element-plus'
+
+const { targetTreeData } = defineProps({
+    targetTreeData: {
+        type: Object,
+        default: {}
+    }
+})
+
+const treeData = computed(() => {
+    return targetTreeData.data
+})
+
+const isCheck = ref(false)
+const isOkDoor = ref(false)
+const filterText = ref('')
+const treeRef = ref<InstanceType<typeof ElTree>>()
+
+onMounted(() => {
+    nextTick(() => {
+        //给树节点赋值回显
+        isCheck.value = true
+        treeRef.value?.setCheckedKeys(targetTreeData.data)
+        isCheck.value = false
+    })
+
+})
+
+interface Tree {
+    [key: string]: any
+}
+
+const defaultProps = {
+    value: 'id',
+    label: 'label',
+    children: 'children',
+}
+watch(filterText, (val) => {
+    treeRef.value!.filter(val)
+})
+
+const filterNode = (value: string, data: Tree) => {
+    if (!value) return true
+    return data.label.includes(value)
+}
+
+// 传递被点击的指标字典信息给父页面
+const emit = defineEmits(['treeNodeClick'])
+const handleNodeClick = (data: any, node: any, obj: any) => {
+    if (node) {
+        emit('treeNodeClick', data, node, obj)
+    }
+
+}
+</script>
+<style lang="scss" scoped deep>
+.qt-cl {
+    height: 36px !important;
+}
+
+.th-dg {
+    height: 870px;
+}
+
+.custom_icon {
+    background-image: url("./wenjianjia@2x.png"); //注意:路径改为你自己的
+    background-size: cover;
+    background-position: center;
+    display: inline-block;
+    width: 32px;
+    height: 32px;
+    vertical-align: middle;
+}
+</style>

+ 534 - 0
src/views/target-management/target-dict/TargetDictConfig.vue

@@ -0,0 +1,534 @@
+<template>
+    <el-row :gutter="5">
+        <el-col :span="8">
+            <TargetTree v-if="isShowTree" :targetTreeData="targetTreeData" @treeNodeClick="treeNodeClick" />
+        </el-col>
+        <el-col :span="16">
+            <PageLayer>
+                <template #header class="hd-cl">
+                    <el-button type="primary" icon="Plus" @click="resetForm(ruleFormRef)"
+                        style="margin-left: 10px">新增</el-button>
+                    <el-button type="primary" icon="Edit" @click="editForm(ruleFormRef)"
+                        style="margin-left: 10px">编辑</el-button>
+                    <el-button type="primary" icon="Check" @click="submitForm(ruleFormRef)"
+                        style="margin-left: 10px">保存</el-button>
+                    <el-button type="primary" icon="Refresh" style="margin-left: 10px"
+                        @click="resetForm(ruleFormRef)">重置</el-button>
+                </template>
+                <template #main>
+                    <el-form ref="ruleFormRef" :model="ruleForm" :rules="rules" label-width="120px" class="demo-ruleForm"
+                        :size="formSize" status-icon :disabled="isShowForm">
+                        <el-row>
+                            <el-col :span="12">
+                                <el-form-item label="指标名称" prop="name">
+                                    <el-input v-model="ruleForm.name" />
+                                </el-form-item>
+                            </el-col>
+                            <el-col :span="6">
+                                <el-form-item label="指标编码" prop="id">
+                                    <el-input v-model="ruleForm.id" />
+                                </el-form-item>
+                            </el-col>
+                            <el-col :span="6">
+                                <el-form-item label="父级编码" prop="pid">
+                                    <el-input v-model="ruleForm.pid" />
+                                </el-form-item>
+                            </el-col>
+                        </el-row>
+                        <el-row>
+                            <el-col :span="6">
+                                <el-form-item label="指标序号" prop="sort">
+                                    <el-input v-model="ruleForm.sort" />
+                                </el-form-item>
+                            </el-col>
+                            <el-col :span="6">
+                                <el-form-item label="总分" prop="score">
+                                    <el-input v-model="ruleForm.score" />
+                                </el-form-item>
+                            </el-col>
+                            <el-col :span="6">
+                                <el-form-item label="所占比率" prop="ratio" :disabled="true">
+                                    <el-input v-model="ruleForm.ratio" />
+                                </el-form-item>
+                            </el-col>
+                            <el-col :span="6">
+                                <el-form-item label="对接类型">
+                                    <el-select v-model="ruleForm.type" placeholder="请选择类型">
+                                        <el-option label="V1" value="0" />
+                                        <el-option label="V2" value="1" />
+                                    </el-select>
+                                </el-form-item>
+                            </el-col>
+                        </el-row>
+                        <el-row>
+                            <el-col :span="6">
+                                <el-form-item label="状态" prop="state">
+                                    <el-select v-model="ruleForm.state" placeholder="请选择状态">
+                                        <el-option label="开启" value="Y" />
+                                        <el-option label="关闭" value="N" />
+                                    </el-select>
+                                </el-form-item>
+                            </el-col>
+                            <el-col :span="6">
+                                <el-form-item label="启用时间">
+                                    <el-form-item prop="openTime">
+                                        <el-date-picker v-model="ruleForm.openTime" type="date" label="选择时间"
+                                            placeholder="选择时间" style="width: 100%" />
+                                    </el-form-item>
+                                </el-form-item>
+                            </el-col>
+                            <el-col :span="6">
+                                <el-form-item label="责任科室" prop="deptCode">
+                                    <el-select-v2 ref="deptInfoRef" v-model="ruleForm.deptCode" clearable remote filterable
+                                        :remote-method="deptMethod" :options="deptWardList" />
+                                </el-form-item>
+                            </el-col>
+                            <el-col :span="6">
+                                <el-form-item label="责任人" prop="opId">
+                                    <el-select-v2 ref="opInfoRef" v-model="ruleForm.opId" clearable remote filterable
+                                        :remote-method="empMethod" :options="empList" />
+                                </el-form-item>
+                            </el-col>
+                        </el-row>
+                        <el-form-item label="是否叶子节点" prop="isLeaf">
+                            <el-switch v-model="ruleForm.isLeaf" active-value="1" inactive-value="0" active-color="#13ce66"
+                                inactive-color="#ff4949" @change='changeNode(ruleFormRef)' />
+                        </el-form-item>
+                        <el-form-item label="指标定义" prop="definition">
+                            <el-input v-model="ruleForm.definition" type="textarea" />
+                        </el-form-item>
+                        <el-form-item label="评审方法" prop="method">
+                            <el-input v-model="ruleForm.method" type="textarea" />
+                        </el-form-item>
+                        <el-form-item label="计分细则" prop="scoreRule">
+                            <el-input v-model="ruleForm.scoreRule" type="textarea" />
+                        </el-form-item>
+                        <el-form-item label="数据来源" prop="source">
+                            <el-input v-model="ruleForm.source" type="textarea" />
+                        </el-form-item>
+                        <el-divider />
+                        <el-form ref="ruleFormRef" label-width="120px" :model="sqlForm" class="demo-ruleForm"
+                            :size="formSize">
+                            <el-row>
+                                <el-col :span="12">
+                                    <el-form-item label="开始时间">
+                                        <el-form-item prop="startTime">
+                                            <el-date-picker v-model="sqlForm.startTime" type="date" label="选择时间"
+                                                placeholder="选择时间" format="YYYYMMDD" value-format="YYYYMMDD" />
+                                        </el-form-item>
+                                    </el-form-item>
+                                </el-col>
+                                <el-col :span="12">
+                                    <el-form-item label="结束时间">
+                                        <el-form-item prop="endTime">
+                                            <el-date-picker v-model="sqlForm.endTime" type="date" label="选择时间"
+                                                placeholder="选择时间" format="YYYYMMDD" value-format="YYYYMMDD" />
+                                        </el-form-item>
+                                    </el-form-item>
+                                </el-col>
+                            </el-row>
+                            <el-row>
+                                <el-col :span="8">
+                                    <el-form-item label="公式-分子结果" prop="childResult">
+                                        <el-input v-model="sqlForm.childResult" type="textarea" />
+                                    </el-form-item>
+                                </el-col>
+                                <el-col :span="8">
+                                    <el-form-item label="公式-分母结果" prop="momResult">
+                                        <el-input v-model="sqlForm.momResult" type="textarea" />
+                                    </el-form-item>
+                                </el-col>
+                                <el-col :span="8">
+                                    <el-form-item label="分子/分母-结果" prop="calcResult">
+                                        <el-input v-model="sqlForm.calcResult" type="textarea" />
+                                    </el-form-item>
+                                </el-col>
+                            </el-row>
+                            <el-row>
+                                <el-col :span="12">
+                                    <el-form-item>
+                                        <el-button type="primary" @click="sqlEdit(ruleFormRef)"> 指标sql编辑 </el-button>
+                                    </el-form-item>
+                                </el-col>
+                                <el-col :span="12">
+                                    <el-form-item>
+                                        <el-button type="primary" @click="sqlExecute(ruleFormRef)"> 指标运行结果 </el-button>
+                                    </el-form-item>
+                                </el-col>
+                            </el-row>
+                        </el-form>
+                    </el-form>
+                </template>
+            </PageLayer>
+        </el-col>
+    </el-row>
+
+    <el-drawer :title="'Sql编辑'" v-model="isSqlEdit" size="80%" destroy-on-close>
+        <SqlEditPage :sqlEditData="sqlEditData" />
+    </el-drawer>
+</template>
+<script setup name="TargetDictConfig" lang="ts">
+import { ref, reactive, onMounted, nextTick } from 'vue'
+import TargetTree from '../target-comm/targetTree.vue'
+import SqlEditPage from '../target-comm/SqlEditPage.vue'
+import { ElMessage } from 'element-plus'
+import type { FormInstance, FormRules } from 'element-plus'
+import { formatDate } from '../../../utils/date'
+import { clone } from '../../../utils/clone'
+import PageLayer from '../../../layout/PageLayer.vue'
+import { queryDept } from '../../../api/public-api'
+import { selectTargetDict, selectTargetDictTree, saveTargetDict } from '../../../api/target-management/target-dict'
+import { employeeList } from "../../../api/zhu-yuan-yi-sheng/pat-info-query"
+import { targetSqlExecute } from '../../../api/target-management/target-sql'
+
+const targetTreeData = ref({
+    data: [{}],
+    height: 900,
+})
+
+const isShowTree = ref(false)
+const isShowForm = ref(false)
+const nowDay = new Date()
+const ds = formatDate(nowDay)
+const deptWardList = ref([])
+const empList = ref([])
+const deptInfoRef = ref()
+const opInfoRef = ref()
+
+const isSqlEdit = ref(false)
+let sqlEditData = ref({
+    id: '', // 指标编码
+    name: '', // 指标名称
+    pid: '', // 父级编码
+    sort: '', // 指标序号
+    calcChild: '', // 计算分子sql
+    calcMom: '', // 计算分母sql
+})
+
+const queryParam = reactive({
+    id: '', // 指标编码
+    name: '', // 指标名称
+    pid: '', // 父级编码
+    sort: '', // 指标序号
+    type: '', // 对接类型
+    state: '', // 状态
+    openTime: '', // 启用时间
+    deptId: '', // 责任科室id
+    source: '', // 数据来源
+    calcChild: '', // 计算分子sql
+    calcMom: '', // 计算分母sql
+    isLeaf: '', //是否叶子节点(0:否, 1:是)
+})
+
+onMounted(() => {
+    nextTick(() => {
+        qeryTargetDictTree()
+        deptMethod('')
+        empMethod('')
+    })
+})
+
+const deptMethod = (val: string) => {
+    queryDept(val).then((res: any) => {
+        deptWardList.value = res
+    })
+}
+
+const empMethod = (val: string) => {
+    employeeList(val).then((res: any) => {
+        empList.value = res
+    })
+}
+
+// 查询指标字典树
+const qeryTargetDictTree = () => {
+    isShowTree.value == true ? false : true
+    queryParam.id = '';
+    queryParam.pid = '';
+    selectTargetDictTree(queryParam)
+        .then((res: any) => {
+            targetTreeData.value.data = res
+            isShowTree.value = true
+        });
+}
+
+// ------  指标字典新增,修改保存表单开始  ------
+// ruleForm.value.name = '123'
+// ruleForm.name = '21312'
+let ruleForm = $ref({
+    id: '', // 指标编码
+    name: '', // 指标名称
+    pid: '', // 父级编码
+    sort: '', // 指标序号
+    score: '', // 总分
+    ratio: '', // 所占比率
+    type: '0', // 对接类型
+    state: 'Y', // 状态
+    openTime: ds, // 启用时间
+    dept: '', // 责任科室
+    deptCode: '', // 责任科室id
+    op: '', // 责任人
+    opId: '', // 责任人id
+    definition: '', // 指标定义
+    method: '', // 评审方法
+    scoreRule: '', // 计分细则
+    source: '', // 数据来源
+    isLeaf: '0', // 是否叶子节点(0:否, 1:是)
+    calcChild: '', // 计算-分子
+    calcMom: '', // 计算-分母
+})
+
+let sqlForm = $ref({
+    id: '', // 指标编码
+    pid: '', // 父级编码
+    calcChild: '', // 计算分子sql
+    calcMom: '', // 计算分母sql
+    startTime: '', // 计算开始时间
+    endTime: '', // 计算结束时间
+    childResult: '', // 计算分子结果
+    momResult: '', // 计算分母结果
+    calcResult: '' // 计算结果
+})
+
+const formSize = ref('default')
+const ruleFormRef = ref<FormInstance>()
+
+const rules = $ref<FormRules>({
+    name: [
+        { required: true, message: '请填写指标名称', trigger: 'blur' },
+        { min: 1, max: 256, message: '指标名称长度范围1-256个字符', trigger: 'blur' },
+    ],
+    id: [
+        { required: true, message: '请填写指标id', trigger: 'blur' },
+        { min: 1, max: 12, message: '指标id长度范围1-12个字符', trigger: 'blur' },
+    ],
+    pid: [
+        { required: true, message: '请填写指标父id', trigger: 'blur' },
+        { min: 1, max: 12, message: '指标父id长度范围1-12个字符', trigger: 'blur' },
+    ],
+    sort: [
+        { min: 0, max: 12, message: '指标序号长度范围0-12个字符', trigger: 'blur' },
+    ],
+    score: [
+        { required: true, message: '请填写指标总分', trigger: 'blur' },
+    ],
+    definition: [
+        { required: false, message: '请填写指标定义', trigger: 'blur' },
+    ],
+    method: [
+        { required: false, message: '请填写评审方法', trigger: 'blur' },
+    ],
+    scoreRule: [
+        { required: false, message: '请填写计分细则', trigger: 'blur' },
+    ]
+})
+
+// 需要添加的叶子节点的校验
+const leafRuleFields = ['definition', 'method', 'scoreRule']
+
+const submitForm = async (formEl: FormInstance | undefined) => {
+    if (!formEl) return
+    // 处理叶子节点验证
+    await leafRulesChange(formEl)
+
+    await formEl.validate((valid, fields) => {
+        if (valid) {
+            ruleForm.dept = deptInfoRef.value.states.selectedLabel
+            ruleForm.op = opInfoRef.value.states.selectedLabel
+            saveTargetDict(ruleForm).then((res: any) => {
+                if (res) {
+                    nextTick(() => {
+                        qeryTargetDictTree()
+
+                        if (!isShowForm.value) {
+                            isShowForm.value = true
+                        }
+                    })
+                } else {
+                    qeryTargetDictTree()
+                    return
+                }
+            });
+
+        } else {
+            return
+        }
+    })
+}
+
+const resetForm = (formEl: FormInstance | undefined) => {
+    if (!formEl) return
+
+    if (isShowForm.value) {
+        isShowForm.value = false
+    }
+
+    formEl.resetFields()
+
+    sqlForm.startTime = ''
+    sqlForm.endTime = ''
+    sqlForm.childResult = ''
+    sqlForm.momResult = ''
+    sqlForm.calcResult = ''
+}
+
+const changeNode = async (formEl: FormInstance | undefined) => {
+    if (!formEl) return
+    await leafRulesChange(formEl)
+}
+
+// 叶子节点校验
+const leafRulesChange = async (formEl: FormInstance | undefined) => {
+    if (!formEl) return
+    // 父节点
+    if (ruleForm.isLeaf === '0') {
+        // 取消叶子节点的字典值校验
+        leafRuleFields.forEach(e => {
+            if (rules[e]) {
+                rules[e][0].required = false
+            }
+        })
+        formEl.clearValidate(leafRuleFields)
+    } else { // 叶子节点
+        // 增加叶子节点的字典值校验
+        leafRuleFields.forEach(e => {
+            if (rules[e]) {
+                rules[e][0].required = true
+            }
+        })
+    }
+}
+
+const editForm = (formEl: FormInstance | undefined) => {
+    if (!formEl) return
+    if (isShowForm.value) {
+        isShowForm.value = false
+        if ('1' === ruleForm.isLeaf) {
+            changeNode(formEl)
+        }
+    }
+}
+
+// ------  指标字典新增,修改保存表单结束  ------
+
+// ------  接收树页面传来的数据 -------
+const treeNodeClick = (data: any, node: any, obj: any) => {
+    if (node.data) {
+
+        sqlForm.startTime = ''
+        sqlForm.endTime = ''
+        sqlForm.childResult = ''
+        sqlForm.momResult = ''
+        sqlForm.calcResult = ''
+
+        queryParam.id = node.data.id
+        queryParam.pid = node.data.pid
+        selectTargetDict(queryParam)
+            .then((res: any) => {
+                if (res) {
+                    nextTick(() => {
+                        isShowForm.value = true
+                        ruleForm = clone(res[0])
+                        ruleFormRef.value?.resetFields()
+                        ruleFormRef.value?.clearValidate()
+                        leafRulesChange(ruleFormRef.value)
+                    })
+                }
+            });
+
+
+    }
+}
+
+// ------------------------- sql编辑 -----------------------
+const sqlEdit = (formEl: FormInstance | undefined) => {
+    if (!formEl) return
+    if (ruleForm.id === '') {
+        ElMessage({
+            type: "info",
+            message: "指标信息不全,请确认!",
+            duration: 2500,
+            showClose: true,
+        });
+        return
+    }
+    if (ruleForm.isLeaf === '0') {
+        ElMessage({
+            type: "info",
+            message: "不是基础指标,不需要编写sql,请确认!",
+            duration: 2500,
+            showClose: true,
+        });
+        return
+    }
+
+    isSqlEdit.value = true
+    sqlEditData.value = ruleForm
+
+}
+// --------------- sql编写结束 ------------
+
+// --------------- sql运行 ----------------
+const sqlExecute = (formEl: FormInstance | undefined) => {
+    if (!formEl) return
+    // 验证是否填写完整
+    if (ruleForm.id === '') {
+        ElMessage({
+            type: "info",
+            message: "指标信息不全,请确认!",
+            duration: 2500,
+            showClose: true,
+        });
+        return
+    }
+    if (ruleForm.isLeaf === '0') {
+        ElMessage({
+            type: "info",
+            message: "不是基础指标,不需要执行sql,请确认!",
+            duration: 2500,
+            showClose: true,
+        });
+        return
+    }
+
+    if (ruleForm.calcChild === '') {
+        ElMessage({
+            type: "info",
+            message: "未编写sql,请联系管理员编写!",
+            duration: 2500,
+            showClose: true,
+        });
+        return
+    }
+
+    if (sqlForm.startTime === '' || sqlForm.endTime === '') {
+        ElMessage({
+            type: "info",
+            message: "时间条件未选择,请确认!",
+            duration: 2500,
+            showClose: true,
+        });
+        return
+    }
+
+    sqlForm.id = ruleForm.id
+    sqlForm.pid = ruleForm.pid
+    sqlForm.calcChild = ruleForm.calcChild
+    sqlForm.calcMom = ruleForm.calcMom
+    targetSqlExecute(sqlForm)
+        .then((res: any) => {
+            let r = JSON.parse(JSON.stringify(res))
+            sqlForm.childResult = r.r1
+            sqlForm.momResult = r.r2
+            sqlForm.calcResult = r.r3
+
+        });
+
+}
+
+</script>
+<style lang="scss" scoped deep>
+.hd-cl {
+    margin-bottom: 1px !important;
+}
+</style>

+ 380 - 0
src/views/target-management/target-home/TargetHomePage.vue

@@ -0,0 +1,380 @@
+<template>
+    <div style="background-color: #fff;">
+        <div class="cl-dv">
+            <div class="cl-sn">
+                <el-card class="el-cd1" shadow="hover">
+                    <template #header>
+                        <div>
+                            <span>本年度责任指标</span>
+                        </div>
+                    </template>
+                    <div>
+                        <i class="iconfont icon-zhantie"></i> 99 / 100
+                    </div>
+                </el-card>
+            </div>
+            <div class="cl-sn">
+                <el-card class="el-cd2" shadow="hover">
+                    <template #header>
+                        <div>
+                            <span>本年度填报指标</span>
+                        </div>
+                    </template>
+                    <div>
+                        <i class="iconfont icon-zhantie"></i> 99 / 100
+                    </div>
+                </el-card>
+            </div>
+            <div class="cl-sn">
+                <el-card class="el-cd3" shadow="hover">
+                    <template #header>
+                        <div>
+                            <span>本年度指标总分</span>
+                        </div>
+                    </template>
+                    <div>
+                        <i class="iconfont icon-zhantie"></i> 998 / 1000 分
+                    </div>
+                </el-card>
+            </div>
+            <div class="cl-sn">
+                <el-card class="el-cd4" shadow="hover">
+                    <template #header>
+                        <div>
+                            <span>本年度责任指标不合格项</span>
+                        </div>
+                    </template>
+                    <div>
+                        <i class="iconfont icon-zhantie"></i> 123
+                    </div>
+                </el-card>
+            </div>
+        </div>
+        <div style="margin-top: 5px;">
+            <el-row :gutter="24">
+                <el-col :span="12">
+                    <div style="width: 100%; height: 400px" id="main"></div>
+                </el-col>
+                <el-col :span="12">
+                    <div style="width: 100%; height: 400px" id="rcpie"></div>
+                </el-col>
+            </el-row>
+        </div>
+        <div style="margin-top: 5px; calc(100% - 450);">
+            <page-layer>
+                <template #header height="55px;">
+                    <el-date-picker v-model="dateRange" type="monthrange" range-separator="至" start-placeholder="开始月份"
+                        end-placeholder="结束月份" style="width: 320px"></el-date-picker>
+                    <el-cascader v-model="queryData.dataInfo" :options="targetTreeData" style="width: 720px"
+                        :props="{ value: 'id', label: 'label', children: 'children', expandTrigger: 'hover' }"
+                        @change="handleChange" :clearable="true" :filterable="true" placeholder="请选择指标">
+                    </el-cascader>
+                    <el-button type="primary" icon="Search" @click="query" style="margin-left: 10px">查询</el-button>
+                </template>
+                <template #main>
+                    <el-tabs type="border-card" v-model="queryData.selectType" @tab-click="handleClick">
+                        <el-tab-pane label="数据" name="first">
+                            <el-table :data="targetInfos" :height="tableHeight" border highlight-current-row
+                                row-key="childKey" stripe>
+                                <el-table-column type="index" label="序号" align="center"
+                                    header-align="center"></el-table-column>
+                                <el-table-column label="指标名称" prop="t_name" align="left" header-align="center"
+                                    width="160"></el-table-column>
+                                <el-table-column label="评审方法" prop="t_method" align="left" header-align="center" width="180"
+                                    show-overflow-tooltip></el-table-column>
+                                <el-table-column label="计分细则" prop="t_rule" align="left" header-align="center" width="280"
+                                    show-overflow-tooltip></el-table-column>
+                                <el-table-column label="分数" prop="t_score" align="right" header-align="center"
+                                    width="80"></el-table-column>
+                                <el-table-column label="指标结果" prop="t_result" header-align="center">
+                                    <el-table-column label="2019年" prop="t_y1" align="right"
+                                        header-align="center"></el-table-column>
+                                    <el-table-column label="2020年" prop="t_y2" align="right"
+                                        header-align="center"></el-table-column>
+                                    <el-table-column label="2021年" prop="t_y3" align="right"
+                                        header-align="center"></el-table-column>
+                                    <el-table-column label="2022年" prop="t_y4" align="right"
+                                        header-align="center"></el-table-column>
+                                </el-table-column>
+                                <el-table-column label="负责人" prop="t_manager" align="center"
+                                    header-align="center"></el-table-column>
+                                <el-table-column label="完成状态" prop="t_state" align="center"
+                                    header-align="center"></el-table-column>
+                            </el-table>
+                        </el-tab-pane>
+                    </el-tabs>
+                </template>
+            </page-layer>
+        </div>
+    </div>
+</template>
+<script setup name="TargetHomePage">
+import PageLayer from '@/layout/PageLayer.vue'
+import { useStore } from 'vuex'
+import { ElMessage } from 'element-plus'
+import { ref, reactive, onMounted, nextTick } from 'vue'
+import { highBarsUtils, highBarsNiceUtils } from '@/utils/high-charts'
+import { getDateRangeFormatDate, formatDatetime } from '@/utils/date'
+import { clone } from '../../../utils/clone'
+import { selectTargetDictTree } from '../../../api/target-management/target-dict'
+
+const dateRange = ref([])
+const targetInfos = ref([])
+const storeU = useStore()
+const windowSize = storeU.state.app.windowSize
+const tableHeight = windowSize.h - 620
+const dateS = getDateRangeFormatDate(dateRange.value)
+const targetTreeData = ref()
+const queryData = reactive({
+    startTime: dateS.startTime,
+    endTime: dateS.endTime,
+    targetType: 't1',
+    selectType: 'first',
+    dataInfo: null,
+})
+
+const handleChange = (value) => {
+    console.log(value)
+}
+
+const queryParam = reactive({
+    id: '', // 指标编码
+    name: '', // 指标名称
+    pid: '', // 父级编码
+    sort: '', // 指标序号
+    type: '', // 对接类型
+    state: '', // 状态
+    openTime: '', // 启用时间
+    deptId: '', // 责任科室id
+    source: '', // 数据来源
+    calcChild: '', // 计算分子sql
+    calcMom: '', // 计算分母sql
+    isLeaf: '', //是否叶子节点(0:否, 1:是)
+})
+
+const qeryTargetDictTree = () => {
+    queryParam.id = '';
+    queryParam.pid = '';
+    selectTargetDictTree(queryParam)
+        .then((res) => {
+            targetTreeData.value = clone(res[0].children)
+        });
+}
+
+const handleClick = (tab, event) => {
+    if (!dateRange.value) {
+        ElMessage({
+            message: '请选择时间范围!',
+            type: 'warning',
+            duration: 2500,
+            showClose: true,
+        })
+        return
+    }
+
+    if (!queryData.dataInfo) {
+        ElMessage({
+            message: '请选择指标!',
+            type: 'warning',
+            duration: 2500,
+            showClose: true,
+        })
+        return
+    }
+
+    queryData.setlType = queryData.dataInfo[0]
+    queryData.insurType = queryData.dataInfo[1]
+
+    queryData.startTime = formatDatetime(dateRange.value[0])
+    queryData.endTime = formatDatetime(dateRange.value[1])
+
+    // 查询哪个tab页面
+    queryData.selectType = tab.props.name
+
+    if (queryData.selectType === 'first') {
+        targetInfos.value = [
+            {
+                t_name: '核定床位数', t_method: '核定床位数(≥500张)', t_rule: '核定床位数(≥500张)记1分',
+                t_score: 1, t_y1: '3', t_y2: '8', t_y3: '12', t_y4: '24', t_manager: 'xxx', t_state: '已完成'
+            },
+            {
+                t_name: '实际开放床位数', t_method: '实际开放床位数(≥500张)', t_rule: '实际开放床位数(≥500张)记3分',
+                t_score: 1, t_y1: '90', t_y2: '124', t_y3: '145', t_y4: '165', t_manager: 'xxx', t_state: '已完成'
+            },
+            {
+                t_name: '平均床位使用率', t_method: '平均床位使用率(≥93%)', t_rule: '平均床位使用率(≥93%)记6分',
+                t_score: 1, t_y1: '93%', t_y2: '90%', t_y3: '96%', t_y4: '98%', t_manager: 'xxx', t_state: '已完成'
+            }
+        ]
+    }
+
+}
+
+onMounted(() => {
+
+    nextTick(async () => {
+        qeryTargetDictTree()
+    })
+
+    let Tnames = ['资源配置与运行数据', '医疗服务能力与医院质量安全指标', '重点专业质量控制指标', '单病种(术种)质量控制指标', '重点医疗技术临床应用质量控制指标']
+    let Xnames = ['2019', '2020', '2021', '2022', '2023']
+    let infoData = [{
+        name: '资源配置与运行数据',
+        data: [240, 270, 280, 290, 300]
+    },
+    {
+        name: '医疗服务能力与医院质量安全指标',
+        data: [260, 280, 270, 230, 270]
+    },
+    {
+        name: '重点专业质量控制指标',
+        data: [240, 230, 270, 280, 270]
+    },
+    {
+        name: '单病种(术种)质量控制指标',
+        data: [100, 90, 100, 90, 110]
+    },
+    {
+        name: '重点医疗技术临床应用质量控制指标',
+        data: [25, 27, 22, 28, 30]
+    }]
+    let unit = '分'
+    let titleName = '单位:' + unit
+    let name = '指标得分情况统计'
+    let statusInfos = {
+        zflag: false, // 柱子是否显示数据
+        toolBoxFlag: false, // 是否显示下载,切换标签
+    }
+
+    highBarsUtils(main, name, Tnames, Xnames, infoData, titleName, unit, 1, statusInfos)
+
+    highBarsNiceUtils(rcpie)
+})
+
+const query = () => {
+    if (!dateRange.value) {
+        ElMessage({
+            message: '请选择时间范围!',
+            type: 'warning',
+            duration: 2500,
+            showClose: true,
+        })
+        return
+    }
+
+    if (!queryData.dataInfo) {
+        ElMessage({
+            message: '请选择指标!',
+            type: 'warning',
+            duration: 2500,
+            showClose: true,
+        })
+        return
+    }
+
+    if (queryData.selectType === 'first') {
+        targetInfos.value = [
+            {
+                t_name: '核定床位数', t_method: '核定床位数(≥500张)', t_rule: '核定床位数(≥500张)记1分',
+                t_score: 1, t_y1: '3', t_y2: '8', t_y3: '12', t_y4: '24', t_manager: 'xxx', t_state: '已完成'
+            },
+            {
+                t_name: '实际开放床位数', t_method: '实际开放床位数(≥500张)', t_rule: '实际开放床位数(≥500张)记3分',
+                t_score: 1, t_y1: '90', t_y2: '124', t_y3: '145', t_y4: '165', t_manager: 'xxx', t_state: '已完成'
+            },
+            {
+                t_name: '平均床位使用率', t_method: '平均床位使用率(≥93%)', t_rule: '平均床位使用率(≥93%)记6分',
+                t_score: 1, t_y1: '93%', t_y2: '90%', t_y3: '96%', t_y4: '98%', t_manager: 'xxx', t_state: '已完成'
+            }
+        ]
+    }
+
+
+}
+
+function initTargetOptions() {
+    return [
+        {
+            value: 't1',
+            label: '第一章 资源配置与运行数据指标(300分)',
+            children: [
+                {
+                    value: 'a1',
+                    label: '床位配置(10分)',
+                },
+                {
+                    value: 'a2',
+                    label: '卫生技术人员配备(60分)',
+                },
+                {
+                    value: 'a3',
+                    label: '相关科室资源配置(60分)',
+                },
+                {
+                    value: 'a4',
+                    label: '运行指标(150分)',
+                },
+                {
+                    value: 'a5',
+                    label: '科研指标(20分)',
+                }
+            ],
+        },
+        {
+            value: 't2',
+            label: '第二章 医疗服务能力与医院质量安全指标(280分)',
+            children: [
+                {
+                    value: 'b1',
+                    label: '医疗服务能力(80分)',
+                },
+                {
+                    value: 'b2',
+                    label: '医院质量指标(80分)',
+                },
+                {
+                    value: 'b3',
+                    label: '医疗安全指标(年度医院获得性指标)(120分)',
+                },
+            ],
+        },
+    ]
+}
+</script>
+<style lang="scss" scoped>
+.cl-dv {
+    display: flex;
+    padding: 5px;
+    border-radius: 5px;
+    justify-content: space-evenly;
+
+    .cl-sn {
+        width: calc(100% / 4);
+        margin: 0 5px;
+
+        .el-cd1 {
+            background-color: blue;
+            color: #fff;
+            border-bottom: 0px solid blue;
+        }
+
+        .el-cd2 {
+            background-color: blueviolet;
+            color: #fff;
+            border-bottom: 0px solid blueviolet;
+        }
+
+        .el-cd3 {
+            background-color: #049481;
+            color: #fff;
+            border-bottom: 0px solid #049481;
+        }
+
+        .el-cd4 {
+            background-color: brown;
+            color: #fff;
+            border-bottom: 0px solid brown;
+        }
+    }
+}
+</style>