Explorar o código

上线ETA1.2.2

jwyu hai 11 meses
pai
achega
e39af5bc2b

+ 66 - 0
src/api/modules/dataSource.js

@@ -0,0 +1,66 @@
+import http from "@/api/http.js"
+
+// 数据源管理模块
+const apiDataSource={
+    //获取数据源列表列配置项
+    //列表类型ColumnType:1数据源明细表,2数据源统计表,3删除指标列表,4指标信息变更表"
+    GLTableColOpts:params=>{
+        return http.get('/data_stat/source_column',params)
+    },
+
+    //编辑自定义列
+    GLTableColEdit:params=>{
+        return http.post('/data_stat/source_column/edit',params)
+    },
+
+    //数据源明细表
+    GLDetailTableList:params=>{
+        return http.get('/data_stat/edb_update_stat',params)
+    },
+
+    //数据源统计
+    GLStatisticTableList:params=>{
+        return http.get('/data_stat/source_stat',params)
+    },
+
+    //删除指标列表数据
+    GLDelTableList:params=>{
+        return http.get('/data_stat/edb_delete_log',params)
+    },
+
+    //指标信息变更列表数据
+    GLEdbInfoTableList:params=>{
+        return http.get('/data_stat/edb_update_log',params)
+    },
+
+    //刷新失败指标详情
+    GLRefreshFailDetail:params=>{
+        return http.get('data_stat/edb_update_stat/failed',params)
+    },
+
+    // 新增/编辑终端账号
+    accountSave:params=>{
+        return http.post('/data_stat/terminal/save',params)
+    },
+
+    //终端账号列表
+    accountList:params=>{
+        return http.get('/data_stat/terminal/list',params)
+    },
+
+    //启用/禁用终端账号
+    accountSet:params=>{
+        return http.post('/data_stat/terminal/status/set',params)
+    },
+
+    // 获取终端编码数据
+    terminalCodeArr:params=>{
+        return http.get('/data_stat/terminal/code',{})
+    }
+    
+
+}
+
+export {
+    apiDataSource
+}

BIN=BIN
src/assets/img/data_m/icon01.png


BIN=BIN
src/assets/img/data_m/move_ico2.png


BIN=BIN
src/assets/img/data_m/set_icon.png


+ 19 - 0
src/routes/modules/dataSource.js

@@ -0,0 +1,19 @@
+const home = r => require.ensure([], () => r(require('@/views/Home.vue')), 'Home'); //主页
+
+export default [
+    //
+    {
+        path: "/",
+        component: home,
+        name: "数据报表管理",
+        hidden: false,
+        icon_path: require("@/assets/img/home/data_ic.png"),
+        children: [
+            {
+                path: "dataSourceGL",
+                name: "数据源管理",
+                component: () => import("@/views/dataSource_manage/dataSourceListGL.vue"),
+            },
+        ]
+    }
+]

+ 6 - 0
src/routes/modules/oldRoutes.js

@@ -323,6 +323,12 @@ export default [
         name: "外部链接配置",
         hidden: true,
       },
+      {
+        path: "dataSourceAccountList",
+        component: () => import("@/views/dataSource_manage/accountList.vue"),
+        name: "数据源终端管理",
+        hidden: true,
+      },
     ],
   },
   // 外部链接

+ 6 - 1
src/utils/buttonConfig.js

@@ -232,8 +232,13 @@ export const dataSourcePermission = {
     /*--------EIA  STEO报告---- */
     eiaData_export:'eiaData:export',
     /*--------国家统计局---- */
-    gjtjjData_export:'gjtjjData:export'
+    gjtjjData_export:'gjtjjData:export',
 
+    /*--------数据报表管理---- */
+    /*--------数据源终端管理---- */
+    dataSource_account_add:'dataSourceAccount:add',//新增终端账号
+    dataSource_account_edit:'dataSourceAccount:edit',//编辑
+    dataSource_account_enable:'dataSourceAccount:enable',//禁用/启用
 }
 
 /*

+ 162 - 0
src/views/dataSource_manage/accountList.vue

@@ -0,0 +1,162 @@
+<template>
+    <div class="account-list-page">
+
+        <el-button 
+            type="primary" 
+            @click="showEditAccount=true;activeTermId=0;initData={}"
+            v-permission="permissionBtn.dataSourcePermission.dataSource_account_add"
+        >新增终端账号</el-button>
+        <el-table
+            style="margin-top:30px"
+            :data="tableData"
+            border
+        >
+            <el-table-column
+                v-for="col in tableColOpts"
+                :key="col.key"
+                :label="col.name"
+                :prop="col.key"
+                :sortable="col.sortable"
+                align="center"
+            >
+                <template slot-scope="scope">
+                    <span 
+                        v-if="col.key==='Status'"
+                        :style="{color:scope.row.Status===1?'':'#FF0000'}"
+                    >{{scope.row.Status===1?'启用':'禁用'}}</span>
+                    <span v-else>{{scope.row[col.key]}}</span>
+                </template>
+            </el-table-column>
+            <el-table-column label="操作" align="center" width="100">
+                <template slot-scope="scope">
+                    <span 
+                        style="color:#409EFF;cursor: pointer;" 
+                        @click="handleEditAccount(scope.row)"
+                        v-permission="permissionBtn.dataSourcePermission.dataSource_account_edit"
+                    >编辑</span>
+                    <span 
+                        style="color:#409EFF;cursor: pointer;" 
+                        @click="handleSetAccountStatus(scope.row,2)" 
+                        v-if="scope.row.Status===1"
+                        v-permission="permissionBtn.dataSourcePermission.dataSource_account_enable"
+                    >禁用</span>
+                    <span 
+                        style="color:#409EFF;cursor: pointer;" 
+                        @click="handleSetAccountStatus(scope.row,1)" 
+                        v-if="scope.row.Status===2"
+                        v-permission="permissionBtn.dataSourcePermission.dataSource_account_enable"
+                    >启用</span>
+                </template>
+            </el-table-column>
+            <div slot="empty">
+                <tableNoData text="暂无数据"/>
+            </div>
+        </el-table>
+
+        <!-- 新增/编辑终端账号 -->
+        <EditAccount 
+            v-model="showEditAccount" 
+            :TerminalId="activeTermId" 
+            :initData="initData"
+            @change="getAccountList"
+        />
+    </div>
+</template>
+
+<script>
+import EditAccount from './components/EditAccount.vue'
+import {apiDataSource} from '@/api/modules/dataSource.js'
+export default {
+    components:{EditAccount},
+    data() {
+        return {
+            tableData:[],
+            tableColOpts:[
+                {
+                    name:'终端编码',
+                    key:'TerminalCode',
+                },
+                {
+                    name:'终端名称',
+                    key:'Name',
+                },
+                {
+                    name:'文件夹路径',
+                    key:'DirPath',
+                },
+                {
+                    name:'终端地址',
+                    key:'ServerUrl',
+                },
+                {
+                    name:'终端token',
+                    key:'Value',
+                },
+                {
+                    name:'数据源类型',
+                    key:'Source',
+                },
+                {
+                    name:'状态',
+                    key:'Status',
+                },
+                {
+                    name:'指标数据量',
+                    key:'Num',
+                },
+                {
+                    name:'更新时间',
+                    key:'ModifyTime',
+                    sortable:true
+                },
+            ],
+
+            showEditAccount:false,
+            activeTermId:0,
+            initData:{},
+        }
+    },
+    created() {
+        this.getAccountList()
+    },
+    methods: {
+        async getAccountList(){
+            const res=await apiDataSource.accountList({})
+            if(res.Ret===200){
+                const arr=res.Data.List||[]
+                this.tableData=arr
+            }
+        },
+
+        // 点击编辑账号
+        handleEditAccount(e){
+            this.activeTermId=e.TerminalId
+            this.initData=e
+            this.showEditAccount=true
+        },
+
+        // 启用/禁用账号
+        handleSetAccountStatus(e,status){
+            apiDataSource.accountSet({
+                TerminalId:e.TerminalId,
+                Status:status
+            }).then(res=>{
+                if(res.Ret===200){
+                    this.$message.success('操作成功')
+                    this.getAccountList()
+                }
+            })
+        }
+    },
+}
+</script>
+
+<style lang="scss" scoped>
+.account-list-page{
+    padding: 30px;
+    border-radius: 4px;
+    border: 1px solid #DCDFE6; 
+    background-color: #fff;
+    min-height: calc(100vh - 260px);
+}
+</style>

+ 177 - 0
src/views/dataSource_manage/components/DelEDBTable.vue

@@ -0,0 +1,177 @@
+<template>
+    <div class="del-table-wrap">
+        <div>
+            <img src="~@/assets/img/data_m/set_icon.png" alt="" style="cursor: pointer;float:right" @click="showSetTableCols=true">
+        </div>
+        <el-table
+            v-loading="tableLoading"
+            ref="tableIns"
+            :data="tableData"
+            border
+            @sort-change="handleTableSortChange"
+        >
+            <el-table-column
+                v-for="col in tableColOpts"
+                :key="col.ColumnKey"
+                :column-key="col.ColumnKey"
+                :label="col.ColumnName"
+                :prop="col.ColumnKey"
+                :sortable="col.IsSort===1?'custom':false"
+                align="center"
+                :width="getColWidth(col.ColumnKey)"
+            >
+                <template slot="header" slot-scope="scope">
+                    <span>{{col.ColumnName}}</span>
+                    <el-tooltip 
+                        effect="dark" 
+                        :content="getTableHeadTips(col.ColumnKey)" 
+                        placement="top-start"
+                    >
+                        <i class="el-icon-info" v-if="tipsKeysArr.includes(col.ColumnKey)"></i>
+                    </el-tooltip>
+                </template>
+            </el-table-column>
+            <div slot="empty">
+                <tableNoData text="暂无数据"/>
+            </div>
+        </el-table>
+        <el-pagination
+          layout="total,prev,pager,next,jumper"
+          background
+          @current-change="handleCurrentChange"
+          :page-size="pageSize"
+          :total="total"
+          style="float: right;margin-top:20px"
+        />
+        <!-- 自定义列表 -->
+        <SetTableCols v-model="showSetTableCols" :ColumnType="3" @change="handleTableColChange"/>
+    </div>
+</template>
+
+<script>
+import {apiDataSource} from '@/api/modules/dataSource'
+import SetTableCols from './SetTableCols.vue'
+export default {
+    components:{SetTableCols},
+    data() {
+        return {
+            tipsKeysArr:['EdbNameSource','ErDataUpdateDate'], 
+            tableLoading:false,
+            tableColOpts:[],
+            tableData:[],
+            pageSize:15,
+            page:1,
+            total:0,
+            filterState:{
+                sortKey:'',
+                sortType:'',
+            },
+
+            showSetTableCols:false,
+        }
+    },
+    created() {
+        this.getTableColOpts()
+    },
+    methods: {
+        //获取表格数据
+        getTableList(){
+            this.tableLoading=true
+            apiDataSource.GLDelTableList({
+                CurrentIndex:this.page,
+                PageSize:this.pageSize,
+                SortParam:this.filterState.sortKey,
+                SortType:this.filterState.sortType,
+                CreateTime:''
+            }).then(res=>{
+                this.tableLoading=false
+                if(res.Ret===200){
+                    const arr=res.Data.List||[]
+                    this.tableData=arr
+                    this.total=res.Data.Paging.Totals
+                }
+            })
+        },
+
+        handleCurrentChange(e){
+            this.page=e
+            this.getTableList()
+        },
+
+        // 获取表格列配置项
+        getTableColOpts(){
+            this.tableColOpts=[]
+            this.tableLoading=true
+            apiDataSource.GLTableColOpts({ColumnType:3}).then(res=>{
+                if(res.Ret===200){
+                    const arr=res.Data.List||[]
+                    this.tableColOpts=arr.filter(item=>item.IsShow===1)
+                    this.$nextTick(()=>{
+                        // this.$refs.tableIns.doLayout()
+                        this.tableLoading=false
+                    })
+                    this.getTableList()
+                }
+            })
+        },
+
+        handleTableColChange(){
+            this.getTableColOpts()
+        },
+
+        handleShowSetTableCol(){
+            this.showSetTableCols=true
+        },
+
+        // 筛选项刷新列表
+        handleRefreshList(){
+            this.page=1
+            this.getTableList()
+        },
+
+        // 排序
+        handleTableSortChange({column, prop, order}){
+            console.log(column, prop, order);
+            this.filterState.sortKey=prop
+            this.filterState.sortType=order==='descending'?'desc':order==='ascending'?'asc':''
+            this.handleRefreshList()
+        },
+
+        // table说明文案
+        getTableHeadTips(key){
+            const tipsMap={
+                EdbNameSource:'指标在数据源的全称',
+                ErDataUpdateDate:'指标数据发生变化的最早日期',
+            }
+            return tipsMap[key]
+        },
+
+        // 设置列的宽度
+        getColWidth(key){
+            const widthMap={
+                DataUpdateTime:'150px',
+                ErDataUpdateDate:'200px',
+                StartDate:'150px',
+                LatestDate:'150px',
+                CreateTime:'150px'
+            }
+
+            return widthMap[key]
+        }
+    },
+}
+</script>
+
+<style lang="scss" scoped>
+.del-table-wrap{
+    .top-wrap{
+        display: flex;
+        justify-content: flex-end;
+        margin-bottom: 30px;
+        .set-icon{
+            width: 40px;
+            cursor: pointer;
+        }
+    }
+}
+</style>

+ 313 - 0
src/views/dataSource_manage/components/DetailTable.vue

@@ -0,0 +1,313 @@
+<template>
+    <div class="detail-table-wrap">
+        <div class="top-wrap">
+        <div class="filter-box">
+            <el-select
+                v-model="filterState.terminalCode"
+                placeholder="终端编码"
+                multiple
+                clearable
+                collapse-tags
+                style="width:250px"
+                @change="handleRefreshList"
+            >
+                <el-option
+                    v-for="item in terminalCodeOpts"
+                    :key="item.TerminalCode"
+                    :label="item.Name"
+                    :value="item.TerminalCode"
+                />
+            </el-select> 
+            <el-cascader
+                v-model="filterState.user"
+                placeholder="创建人"
+                :options="sysUserOpts"
+                :props="props"
+                collapse-tags
+                :show-all-levels="false"
+                clearable
+                @change="handleRefreshList"
+                filterable
+                style="width:250px"
+            />
+            <el-select
+                v-model="filterState.frequency"
+                placeholder="频度"
+                multiple
+                clearable
+                collapse-tags
+                style="width:250px"
+                @change="handleRefreshList"
+            >
+                <el-option
+                    v-for="item in frequencyOpt"
+                    :key="item"
+                    :label="item"
+                    :value="item"
+                />
+            </el-select>
+            <el-input
+                placeholder="指标ID/指标名称"
+                prefix-icon="el-icon-search"
+                v-model="filterState.keyword"
+                clearable
+                style="width:250px"
+                @input="handleRefreshList"
+            />
+        </div>
+        <img src="~@/assets/img/data_m/set_icon.png" alt="" style="cursor: pointer;" @click="showSetTableCols=true">
+        </div>
+        <el-table
+            v-loading="tableLoading"
+            ref="tableIns"
+            :data="tableData"
+            border
+            @sort-change="handleTableSortChange"
+        >
+            <el-table-column
+                v-for="col in tableColOpts"
+                :key="col.ColumnKey"
+                :column-key="col.ColumnKey"
+                :label="col.ColumnName"
+                :prop="col.ColumnKey"
+                :sortable="col.IsSort===1?'custom':false"
+                align="center"
+                :width="getColWidth(col.ColumnKey)"
+            >
+                <template slot="header" slot-scope="scope">
+                    <span>{{col.ColumnName}}</span>
+                    <el-tooltip 
+                        effect="dark" 
+                        :content="getTableHeadTips(col.ColumnKey)" 
+                        placement="top-start"
+                    >
+                        <i class="el-icon-info" v-if="tipsKeysArr.includes(col.ColumnKey)"></i>
+                    </el-tooltip>
+                </template>
+                <template slot-scope="scope">
+                    <span v-if="col.ColumnKey==='IsAdd'">{{scope.row.IsAdd===1?'是':'否'}}</span>
+                    <span v-else-if="col.ColumnKey==='NeedRefresh'">{{scope.row.NeedRefresh===1?'是':'否'}}</span>
+                    <span v-else-if="col.ColumnKey==='HasRefresh'">{{scope.row.HasRefresh===1?'是':'否'}}</span>
+                    <span v-else-if="col.ColumnKey==='DataUpdateResult'">{{scope.row.DataUpdateResult===1?'是':'否'}}</span>
+                    
+                    <span v-else>{{scope.row[col.ColumnKey]}}</span>
+                </template>
+            </el-table-column>
+            <div slot="empty">
+                <tableNoData text="暂无数据"/>
+            </div>
+        </el-table>
+        <el-pagination
+          layout="total,prev,pager,next,jumper"
+          background
+          @current-change="handleCurrentChange"
+          :page-size="pageSize"
+          @size-change="handleSizeChange"
+          :total="total"
+          style="float: right;margin-top:20px"
+        />
+        <!-- 自定义列表 -->
+        <SetTableCols v-model="showSetTableCols" :ColumnType="1" @change="handleTableColChange"/>
+    </div>
+</template>
+
+<script>
+import {apiDataSource} from '@/api/modules/dataSource'
+import {frequencyOpt} from '../utils/config'
+import SetTableCols from './SetTableCols.vue'
+import { departInterence } from "@/api/api.js";
+export default {
+    components:{SetTableCols},
+    data() {
+        return {
+            tipsKeysArr:['EdbNameSource','DataUpdateTime','ErDataUpdateDate','NeedRefresh','HasRefresh','UpdateTime'],
+            frequencyOpt,
+            terminalCodeOpts:[],
+            sysUserOpts:[],
+            props: {
+                value: "AdminId",
+                label: "RealName",
+                children: "ChildrenList",
+                multiple: true,
+                emitPath:false
+            },
+            filterState:{
+                frequency:'',
+                keyword:'',
+                sortKey:'',
+                sortType:'',
+                terminalCode:'',
+                user:[],
+                dateVal:this.$moment().format('YYYY-MM-DD')||''
+            },
+            checkAll:false,
+            tableColOpts:[],
+            tableData:[],
+            pageSize:15,
+            page:1,
+            total:0,
+            tableLoading:false,
+
+            showSetTableCols:false,
+
+        }
+    },
+    created() {
+        this.getTableColOpts()
+        this.getTerminalCodeOpts()
+        this.getSysUserList()
+    },
+    methods: {
+        //获取表格数据
+        getTableList(){
+            this.tableLoading=true
+            apiDataSource.GLDetailTableList({
+                CurrentIndex:this.page,
+                PageSize:this.pageSize,
+                SortParam:this.filterState.sortKey,
+                SortType:this.filterState.sortType,
+                CreateTime:this.filterState.dateVal,
+                TerminalCode:this.filterState.terminalCode?this.filterState.terminalCode.join(','):'',
+                SysUserId:this.filterState.user?this.filterState.user.join(','):'',
+                Frequency:this.filterState.frequency?this.filterState.frequency.join(','):'',
+                KeyWord:this.filterState.keyword
+            }).then(res=>{
+                this.tableLoading=false
+                if(res.Ret===200){
+                    const arr=res.Data.List||[]
+                    this.tableData=arr
+                    this.total=res.Data.Paging.Totals
+                }
+            })
+        },
+
+        handleCurrentChange(e){
+            this.page=e
+            this.getTableList()
+        },
+
+        // 筛选项刷新列表
+        handleRefreshList(){
+            this.page=1
+            this.getTableList()
+        },
+
+        // 获取表格列配置项
+        getTableColOpts(){
+            this.tableLoading=true
+            this.tableColOpts=[]
+            apiDataSource.GLTableColOpts({ColumnType:1}).then(res=>{
+                if(res.Ret===200){
+                    const arr=res.Data.List||[]
+                    this.tableColOpts=arr.filter(item=>item.IsShow===1)
+                    this.$nextTick(()=>{
+                        // this.$refs.tableIns.doLayout()
+                        this.tableLoading=false
+                    })
+                    this.getTableList()
+                    
+                }
+            })
+        },
+
+        // 表格配置项变更
+        handleTableColChange(){
+            this.getTableColOpts()
+        },
+
+        // 排序
+        handleTableSortChange({column, prop, order}){
+            console.log(column, prop, order);
+            this.filterState.sortKey=prop
+            this.filterState.sortType=order==='descending'?'desc':order==='ascending'?'asc':''
+            this.handleRefreshList()
+        },
+
+        // 获取终端编码数据
+        getTerminalCodeOpts(){
+            apiDataSource.terminalCodeArr().then(res=>{
+                if(res.Ret===200){
+                    this.terminalCodeOpts=res.Data.List||[]
+                }
+            })
+        },
+
+        // 获取所有系统用户
+        async getSysUserList() {
+            const res = await departInterence.getQuestionAdminList();
+            if (res.Ret === 200) {
+                this.sysUserOpts = res.Data.List||[];
+            }
+        },
+
+        handleShowSetTableCol(){
+            this.showSetTableCols=true
+        },
+
+        // table说明文案
+        getTableHeadTips(key){
+            const tipsMap={
+                EdbNameSource:'指标在数据源的全称',
+                DataUpdateTime:'指标最近一次数据发生变化的时间',
+                ErDataUpdateDate:'指标数据发生变化的最早日期',
+                NeedRefresh:'该指标今日是否设置了定时刷新任务',
+                HasRefresh:'该指标是否发起了刷新任务',
+                UpdateTime:'指标最近一次执行刷新任务的时间'
+            }
+            return tipsMap[key]
+        },
+
+        // 设置列的宽度
+        getColWidth(key){
+            const widthMap={
+                EdbNameSource:'120px',
+                DataUpdateTime:'120px',
+                ErDataUpdateDate:'200px',
+                NeedRefresh:'200px',
+                HasRefresh:'200px',
+                SourceUpdateTime:'120px',
+                DataUpdateResult:'120px',
+                SourceUpdateFailedReason:'120px'
+            }
+
+            return widthMap[key]
+        }
+    },
+}
+</script>
+
+<style lang="scss">
+.detail-table-wrap{
+    .top-wrap{
+        .el-cascader__search-input{
+            min-width: 30px;
+        }
+    }
+}
+
+</style>
+<style lang="scss" scoped>
+.top-wrap{
+    display: flex;
+    justify-content: space-between;
+    align-items: flex-start;
+    margin-bottom: 30px;
+    .filter-box{
+        margin-right: 100px;
+        display: flex;
+        flex-wrap: wrap;
+        align-items: center;
+        gap: 10px 20px;
+    }
+    .right-opt-box{
+        display: flex;
+        align-items: center;
+        gap: 20px;
+        .set-icon{
+            width: 40px;
+            cursor: pointer;
+        }
+    }
+}
+
+</style>

+ 183 - 0
src/views/dataSource_manage/components/EDBInfoChangeTable.vue

@@ -0,0 +1,183 @@
+<template>
+    <div class="edbinfo-table-wrap">
+        <div>
+            <img src="~@/assets/img/data_m/set_icon.png" alt="" style="cursor: pointer;float:right" @click="showSetTableCols=true">
+        </div>
+        <el-table
+            v-loading="tableLoading"
+            ref="tableIns"
+            :data="tableData"
+            border
+            @sort-change="handleTableSortChange"
+        >
+            <el-table-column
+                v-for="col in tableColOpts"
+                :key="col.ColumnKey"
+                :column-key="col.ColumnKey"
+                :label="col.ColumnName"
+                :prop="col.ColumnKey"
+                :sortable="col.IsSort===1?'custom':false"
+                align="center"
+                :width="getColWidth(col.ColumnKey)"
+            >
+                <template slot="header" slot-scope="scope">
+                    <span>{{col.ColumnName}}</span>
+                    <el-tooltip 
+                        effect="dark" 
+                        :content="getTableHeadTips(col.ColumnKey)" 
+                        placement="top-start"
+                    >
+                        <i class="el-icon-info" v-if="tipsKeysArr.includes(col.ColumnKey)"></i>
+                    </el-tooltip>
+                </template>
+            </el-table-column>
+            <div slot="empty">
+                <tableNoData text="暂无数据"/>
+            </div>
+        </el-table>
+        <el-pagination
+          layout="total,prev,pager,next,jumper"
+          background
+          @current-change="handleCurrentChange"
+          :page-size="pageSize"
+          @size-change="handleSizeChange"
+          :total="total"
+          style="float: right;margin-top:20px"
+        />
+        <!-- 自定义列表 -->
+        <SetTableCols v-model="showSetTableCols" :ColumnType="4" @change="handleTableColChange"/>
+    </div>
+</template>
+
+<script>
+import {apiDataSource} from '@/api/modules/dataSource'
+import SetTableCols from './SetTableCols.vue'
+export default {
+    components:{SetTableCols},
+    data() {
+        return {
+            tipsKeysArr:['EdbNameSource','EdbName','ErDataUpdateDate'],
+            tableLoading:false,
+            tableColOpts:[],
+            tableData:[],
+            pageSize:15,
+            page:1,
+            total:0,
+            tableLoading:false,
+            filterState:{
+                dateVal:this.$moment().format('YYYY-MM-DD')||'',
+                sortKey:'',
+                sortType:'',
+            },
+
+            showSetTableCols:false,
+        }
+    },
+    created() {
+        this.getTableColOpts()
+    },
+    methods: {
+        //获取表格数据
+        getTableList(){
+            this.tableLoading=true
+            apiDataSource.GLEdbInfoTableList({
+                CurrentIndex:this.page,
+                PageSize:this.pageSize,
+                SortParam:this.filterState.sortKey,
+                SortType:this.filterState.sortType,
+                CreateTime:this.filterState.dateVal,
+            }).then(res=>{
+                this.tableLoading=false
+                if(res.Ret===200){
+                    const arr=res.Data.List||[]
+                    this.tableData=arr
+                    this.total=res.Data.Paging.Totals
+                }
+            })
+        },
+
+        handleCurrentChange(e){
+            this.page=e
+            this.getTableList()
+        },
+
+        // 筛选项刷新列表
+        handleRefreshList(){
+            this.page=1
+            this.getTableList()
+        },
+
+        // 获取表格列配置项
+        getTableColOpts(){
+            this.tableColOpts=[]
+            this.tableLoading=true
+            apiDataSource.GLTableColOpts({ColumnType:4}).then(res=>{
+                if(res.Ret===200){
+                    const arr=res.Data.List||[]
+                    this.tableColOpts=arr.filter(item=>item.IsShow===1)
+                    this.$nextTick(()=>{
+                        // this.$refs.tableIns.doLayout()
+                        this.tableLoading=false
+                    })
+                    this.getTableList()
+                }
+            })
+        },
+
+        handleTableColChange(){
+            this.getTableColOpts()
+        },
+
+        handleShowSetTableCol(){
+            this.showSetTableCols=true
+        },
+
+        // 排序
+        handleTableSortChange({column, prop, order}){
+            console.log(column, prop, order);
+            this.filterState.sortKey=prop
+            this.filterState.sortType=order==='descending'?'desc':order==='ascending'?'asc':''
+            this.handleRefreshList()
+        },
+
+        // table说明文案
+        getTableHeadTips(key){
+            const tipsMap={
+                EdbNameSource:'指标在数据源的全称',
+                EdbName:'指标在ETA指标库保存的指标名称',
+                ErDataUpdateDate:'指标数据发生变化的最早日期',
+            }
+            return tipsMap[key]
+        },
+
+        // 设置列的宽度
+        getColWidth(key){
+            const widthMap={
+                EdbName:'150px',
+                DataUpdateTime:'150px',
+                ErDataUpdateDate:'200px',
+                StartDate:'150px',
+                LatestDate:'150px',
+                CreateTime:'150px',
+                EdbNameSource:'150px'
+            }
+
+            return widthMap[key]
+        }
+    },
+}
+</script>
+
+<style lang="scss" scoped>
+.edbinfo-table-wrap{
+    .top-wrap{
+        display: flex;
+        justify-content: flex-end;
+        margin-bottom: 30px;
+        .set-icon{
+            width: 40px;
+            cursor: pointer;
+        }
+    }
+}
+</style>

+ 158 - 0
src/views/dataSource_manage/components/EditAccount.vue

@@ -0,0 +1,158 @@
+<template>
+    <el-dialog
+      :title="TerminalId?'编辑终端账号':'新增终端账号'"
+      :visible.sync="show"
+      :modal-append-to-body="false"
+      :close-on-click-modal="false"
+      :center="true"
+      v-dialogDrag
+      custom-class="dialogclass"
+      width="540px"
+      @close="handleClose"
+    >
+        <el-form 
+            :model="formState" 
+            :rules="rules" 
+            ref="formIns" 
+            label-width="120px" 
+            class="demo-ruleForm"
+        >
+            <el-form-item label="终端名称" prop="name">
+                <el-input placeholder="请输入终端名称" v-model="formState.name" style="width:300px"></el-input>
+            </el-form-item>
+            <el-form-item label="文件夹路径" prop="dirUrl">
+                <el-input placeholder="请输入文件夹路径" v-model="formState.dirUrl"  style="width:300px" :disabled="TerminalId"></el-input>
+            </el-form-item>
+            <el-form-item label="终端地址" prop="url">
+                <el-input placeholder="请输入终端地址" v-model="formState.url"  style="width:300px"></el-input>
+            </el-form-item>
+            <el-form-item label="终端token" prop="token">
+                <el-input placeholder="请输入终端token" v-model="formState.token"  style="width:300px"></el-input>
+            </el-form-item>
+            <el-form-item label="数据源类型" prop="type">
+                <el-select 
+                    v-model="formState.type" 
+                    placeholder="请选择数据源类型"
+                    style="width:300px"
+                    :disabled="TerminalId"
+                >
+                    <el-option 
+                        v-for="item in dataSourceOpt"
+                        :key="item.EdbSourceId"
+                        :label="item.SourceName"
+                        :value="item.EdbSourceId"
+                    />
+                </el-select>
+            </el-form-item>
+            <el-form-item label="指标数据量" prop="num">
+                <el-input placeholder="请输入指标数据量" type="number" min="0" v-model.number="formState.num"  style="width:300px"></el-input>
+            </el-form-item>
+        </el-form>
+        <div style="text-align:center;margin:30px 0">
+            <el-button type="primary" plain @click="handleClose">取消</el-button>
+            <el-button type="primary" @click="handleSave">确定</el-button>
+        </div>
+    </el-dialog>
+</template>
+
+<script>
+import {apiDataSource} from '@/api/modules/dataSource.js'
+import {dataBaseInterface} from '@/api/api.js'
+export default {
+    model:{
+        prop:"show",
+        event:'close'
+    },
+    props:{
+        show:{
+            type:Boolean,
+            default:false
+        },
+        TerminalId:{
+            type:Number,
+            default:0
+        },
+        initData:{
+            type:Object,
+            default:{}
+        }
+    },
+    watch: {
+        show(n,o){
+            if(n&&this.TerminalId){
+                console.log('aa');
+                console.log(this.initData);
+                this.formState.name=this.initData.Name
+                this.formState.url=this.initData.ServerUrl
+                this.formState.dirUrl=this.initData.DirPath
+                this.formState.type=this.initData.Source
+                this.formState.num=this.initData.Num
+                this.formState.token=this.initData.Value
+            }
+            if(!n){
+                this.formState.name=''
+                this.formState.url=''
+                this.formState.dirUrl=''
+                this.formState.type=''
+                this.formState.num=''
+                this.formState.token=''
+            }
+        }
+    },
+    data() {
+        return {
+            dataSourceOpt:[],
+            formState:{
+                name:'',
+                url:'',
+                token:'',
+                dirUrl:'',
+                type:'',
+                num:''
+            }
+        }
+    },
+    created() {
+        this.getTargetSource()
+    },
+    methods: {
+        handleClose(){
+            this.$emit('close', false)
+        },
+
+        async handleSave(){
+            const params={
+                TerminalId:this.TerminalId||0,
+                Source:Number(this.formState.type),//终端类型
+                Name:this.formState.name,
+                ServerUrl:this.formState.url,
+                DirPath:this.formState.dirUrl,
+                Num:Number(this.formState.num),
+                Value:this.formState.token
+            }
+            console.log(params);
+            const res=await apiDataSource.accountSave(params)
+            if(res.Ret===200){
+                this.$message.success('保存成功')
+                this.$emit('change')
+                this.handleClose()
+            }
+        },
+
+        // 获取数据源类型
+        getTargetSource(){
+			this.dataSourceOpt = []
+			dataBaseInterface.getDataSource({IsBase:1}).then(res=>{
+				if(res.Ret!==200) return
+				if(res.Data){
+					this.dataSourceOpt = res.Data||[]
+				}
+			})
+		}
+    },
+}
+</script>
+
+<style>
+
+</style>

+ 137 - 0
src/views/dataSource_manage/components/GLRefreshFailDetail.vue

@@ -0,0 +1,137 @@
+<template>
+    <el-dialog
+        title="更新失败指标详情"
+        :visible.sync="show"
+        :close-on-click-modal="false"
+        :append-to-body="true"
+        :center="true"
+        v-dialogDrag
+        width="645px"
+        @close="handleClose"
+    >
+        <div class="gl-refresh-fail-detail-wrap">
+            <div style="margin-bottom:20px">
+                <span>终端名称:{{info.Name}}</span>
+                <span style="display:inline-block;margin-left:20px">文件夹路径:{{info.DirPath}}</span>
+            </div>
+            <div style="display:flex;justify-content: space-between;">
+                <div>
+                    <span>已成功刷新指标数:{{info.UpdateSuccessNum}}</span>
+                    <span>更新失败指标数:{{info.UpdateFailedNum}}</span>
+                </div>
+                <div style="display:flex;align-items:center;color:#409EFF;cursor: pointer;" @click="showBZ=true">
+                    <img src="~@/assets/img/data_m/icon01.png" alt="">
+                    <span>排查步骤</span>
+                </div>
+            </div>
+            <el-table
+                :data="info.List"
+                border
+                height="500"
+            >
+                <el-table-column
+                    label="频度"
+                    prop="Frequency"
+                    align="center"
+                >
+                </el-table-column>
+                <el-table-column
+                    label="数量"
+                    prop="Num"
+                    align="center"
+                >
+                </el-table-column>
+                <el-table-column
+                    label="原因"
+                    prop="SourceUpdateFailedReason"
+                    align="center"
+                >
+                </el-table-column>
+                <div slot="empty">
+                    <tableNoData text="暂无数据"/>
+                </div>
+            </el-table>
+        </div>
+
+        <!-- 排查步骤说明 -->
+        <el-dialog
+            title="排查步骤"
+            :visible.sync="showBZ"
+            :close-on-click-modal="false"
+            :center="true"
+            v-dialogDrag
+            :append-to-body="true"
+            width="500px"
+        > 
+            <div style="padding-bottom:30px;line-height:2;color:#333">
+                <div>1、在钢联终端上,用指标编码查询下是否存在该指标,避免因为指标编码变更的原因导致刷新失败。</div>
+                <div>2、核实钢联终端账号处于登录状态。</div>
+                <div>3、打开Excel,如果“钢联数据2.0”插件不存在,则需要先退出所有Excel和WPS,在钢联终端:最上面的导航栏选择工具->Excel插件修复->点击一键修复,完成钢联数据2.0插件安装。</div>
+                <div>4、打开Excel,选中“钢联数据2.0”插件,查看登录状态是否正常。</div>
+                <div>5、打开文件目录下的一个Excel,选中“钢联数据2.0”插件,点击“更新所有页”按钮后,等待十几秒,查看Excel左下角是否提示额度超限。</div>
+            </div>
+        </el-dialog>
+    </el-dialog>
+    
+</template>
+
+<script>
+import {apiDataSource} from '@/api/modules/dataSource.js'
+export default {
+    model:{
+        prop:"show",
+        event:'close'
+    },
+    props:{
+        show:{
+            type:Boolean,
+            default:false
+        },
+        TerminalCode:{
+            type:String,
+            default:''
+        },
+        date:{
+            type:String,
+            default:''
+        }
+    },
+    watch: {
+      show(n){
+          if(n){
+              this.getDetail()
+          }
+      }  
+    },
+    data() {
+        return {
+            info:{},
+            showBZ:false
+        }
+    },
+    methods: {
+        handleClose(){
+            this.$emit('close', false)
+        },
+
+        getDetail(){
+            apiDataSource.GLRefreshFailDetail({
+                TerminalCode:this.TerminalCode,
+                CreateTime:this.date
+            }).then(res=>{
+                if(res.Ret===200){
+                    this.info=res.Data
+                }
+            })
+        }
+    },
+}
+</script>
+
+<style lang='scss'>
+.gl-refresh-fail-detail-wrap{
+    color: #333;
+    padding-bottom: 30px;
+}
+
+</style>

+ 123 - 0
src/views/dataSource_manage/components/SetTableCols.vue

@@ -0,0 +1,123 @@
+<template>
+    <el-dialog
+      title="自定义列"
+      :visible.sync="show"
+      :modal-append-to-body="false"
+      :close-on-click-modal="false"
+      :center="true"
+      v-dialogDrag
+      custom-class="dialogclass"
+      width="550px"
+      @close="handleClose"
+    >
+        <draggable
+            v-model="list"
+            class="list-wrap"
+            animation="300"
+            tag="div"
+            handle=".drag"
+        >
+            <div class="list-item" v-for="item in list" :key="item.ColumnKey">
+                <el-checkbox v-model="item.checked" :disabled="item.IsMust===1">
+                    <span class="name" :style="{color:item.IsMust===1?'#C0C4CC':''}">{{item.ColumnName}}</span>
+                </el-checkbox>
+                <img class="drag" src="~@/assets/img/data_m/move_ico2.png" alt="">
+            </div>
+        </draggable>
+        <div style="text-align:center;margin:30px 0">
+            <el-button type="primary" plain @click="handleClose">取消</el-button>
+            <el-button type="primary" @click="handleSave">确定</el-button>
+        </div>
+    </el-dialog>
+</template>
+
+<script>
+import draggable from 'vuedraggable';
+import {apiDataSource} from '@/api/modules/dataSource'
+export default {
+    components:{draggable},
+    model:{
+        prop:"show",
+        event:'close'
+    },
+    props:{
+        show:{
+            type:Boolean,
+            default:false
+        },
+        ColumnType:{//1数据源明细表,2数据源统计表,3删除指标列表,4指标信息变更表"
+            type:Number,
+            default:0
+        }
+    },
+    watch: {
+        show(n){
+            if(n){
+                this.getTableColOpts()
+            }
+        }  
+    },
+    data() {
+        return {
+            list:[]
+        }
+    },
+    methods: {
+        // 获取表格列配置项
+        getTableColOpts(){
+            apiDataSource.GLTableColOpts({ColumnType:this.ColumnType}).then(res=>{
+                if(res.Ret===200){
+                    const arr=res.Data.List||[]
+                    this.list=arr.map(item=>{
+                        return {
+                            ...item,
+                            checked:item.IsShow===1?true:false
+                        }
+                    })
+                }
+            })
+        },
+
+        handleSave(){
+            const list=this.list.map(item=>{
+                return {
+                    Id:item.Id,
+                    IsShow:item.checked?1:0
+                }
+            })
+            apiDataSource.GLTableColEdit({
+                list:list
+            }).then(res=>{
+                if(res.Ret===200){
+                    this.$message.success('保存成功')
+                    this.$emit('change')
+
+                    this.handleClose()
+                }
+            })
+        },
+
+        handleClose(){
+            this.$emit('close', false)
+        }
+    },
+}
+</script>
+
+<style lang="scss" scoped>
+.list-wrap{
+    .list-item{
+        padding: 10px 0;
+        border-bottom: 1px solid #000;
+        display: flex;
+        justify-content: space-between;
+        .name{
+            font-size: 16px;
+            color: #000;
+        }
+        .drag{
+            cursor: move;
+        }
+    }
+}
+</style>

+ 186 - 0
src/views/dataSource_manage/components/StatisticTable.vue

@@ -0,0 +1,186 @@
+<template>
+    <div class="statistic-table-wrap">
+        <div>
+            <img src="~@/assets/img/data_m/set_icon.png" alt="" style="cursor: pointer;float:right" @click="showSetTableCols=true">
+        </div>
+        <el-table
+            v-loading="tableLoading"
+            ref="tableIns"
+            :data="tableData"
+            border
+        >
+            <el-table-column
+                v-for="col in tableColOpts"
+                :key="col.ColumnKey"
+                :column-key="col.ColumnKey"
+                :label="col.ColumnName"
+                :prop="col.ColumnKey"
+                align="center"
+                :width="getColWidth(col.ColumnKey)"
+            >
+                <template slot="header" slot-scope="scope">
+                    <span>{{col.ColumnName}}</span>
+                    <el-tooltip 
+                        effect="dark" 
+                        :content="getTableHeadTips(col.ColumnKey)" 
+                        placement="top-start"
+                    >
+                        <i class="el-icon-info" v-if="tipsKeysArr.includes(col.ColumnKey)"></i>
+                    </el-tooltip>
+                </template>
+                <template slot-scope="scope">
+                    <span 
+                        v-if="col.ColumnKey==='UpdateFailedNum'" 
+                        style="color:#409EFF;cursor: pointer;"
+                        @click="handleShowFail(scope.row)"
+                    >{{scope.row.UpdateFailedNum}}</span>
+                    <span v-else>{{scope.row[col.ColumnKey]}}</span>
+                </template>
+            </el-table-column>
+            <div slot="empty">
+                <tableNoData text="暂无数据"/>
+            </div>
+        </el-table>
+        <el-pagination
+          layout="total,prev,pager,next,jumper"
+          background
+          @current-change="handleCurrentChange"
+          :page-size="pageSize"
+          @size-change="handleSizeChange"
+          :total="total"
+          style="float: right;margin-top:20px"
+        />
+        <!-- 自定义列表 -->
+        <SetTableCols v-model="showSetTableCols" :ColumnType="2" @change="handleTableColChange"/>
+
+        <!-- 刷新失败详情 -->
+        <GLRefreshFailDetail v-model="showFail" :TerminalCode="TerminalCode" :date="filterState.dateVal"/>
+    </div>
+</template>
+
+<script>
+import {apiDataSource} from '@/api/modules/dataSource'
+import SetTableCols from './SetTableCols.vue'
+import GLRefreshFailDetail from './GLRefreshFailDetail.vue'
+export default {
+    components:{SetTableCols,GLRefreshFailDetail},
+    data() {
+        return {
+            tipsKeysArr:['NeedRefreshNum','HasRefreshNum','RefreshSuccessNum','RefreshFailedNum','UpdateFailedNum','UpdateSuccessNum'],
+            tableColOpts:[],
+            tableData:[],
+            pageSize:15,
+            page:1,
+            total:0,
+            filterState:{
+                dateVal:this.$moment().format('YYYY-MM-DD')||''
+            },
+
+            showSetTableCols:false,
+            tableLoading:false,
+
+            showFail:false,
+            TerminalCode:''
+        }
+    },
+    created() {
+        this.getTableColOpts()
+    },
+    methods: {
+        //获取表格数据
+        getTableList(){
+            this.tableLoading=true
+            apiDataSource.GLStatisticTableList({
+                CurrentIndex:this.page,
+                PageSize:this.pageSize,
+                CreateTime:this.filterState.dateVal,
+            }).then(res=>{
+                this.tableLoading=false
+                if(res.Ret===200){
+                    const arr=res.Data.List||[]
+                    this.tableData=arr
+                    this.total=res.Data.Paging.Totals
+                }
+            })
+        },
+
+        handleCurrentChange(e){
+            this.page=e
+            this.getTableList()
+        },
+
+        // 筛选项刷新列表
+        handleRefreshList(){
+            this.page=1
+            this.getTableList()
+        },
+
+        // 获取表格列配置项
+        getTableColOpts(){
+            this.tableLoading=true
+            this.tableColOpts=[]
+            apiDataSource.GLTableColOpts({ColumnType:2}).then(res=>{
+                if(res.Ret===200){
+                    this.tableColOpts=res.Data.List||[]
+                    this.$nextTick(()=>{
+                        // this.$refs.tableIns.doLayout()
+                        this.tableLoading=false
+                    })
+                    this.getTableList()
+                }
+            })
+        },
+
+        handleTableColChange(){
+            this.getTableColOpts()
+        },
+
+        handleShowSetTableCol(){
+            this.showSetTableCols=true
+        },
+
+        handleShowFail(e){
+            this.TerminalCode=e.TerminalCode
+            this.showFail=true
+        },
+
+        // table说明文案
+        getTableHeadTips(key){
+            const tipsMap={
+                NeedRefreshNum:'今日该终端需定时刷新的指标数量',
+                HasRefreshNum:'今日该终端发起刷新任务的指标数量',
+                RefreshSuccessNum:'今日该终端刷新成功的指标数量',
+                RefreshFailedNum:'今日该终端刷新失败的指标数量',
+                UpdateFailedNum:'今日该终端成功发起刷新任务,但指标数据未变化的指标数量',
+                UpdateSuccessNum:' 今日该终端数据发生变化的指标数量'
+            }
+            return tipsMap[key]
+        },
+
+        // 设置列的宽度
+        getColWidth(key){
+            const widthMap={
+                NeedUpdateNum:'200px',
+                HasUpdateNum:'200px',
+                UpdateSuccessNum:'200px'
+            }
+
+            return widthMap[key]
+        }
+    },
+}
+</script>
+
+<style lang="scss" scoped>
+.statistic-table-wrap{
+    .top-wrap{
+        display: flex;
+        justify-content: flex-end;
+        margin-bottom: 30px;
+        .set-icon{
+            width: 40px;
+            cursor: pointer;
+        }
+    }
+}
+</style>

+ 108 - 0
src/views/dataSource_manage/dataSourceListGL.vue

@@ -0,0 +1,108 @@
+<template>
+    <div class="data-source-list-page">
+        <div class="top-wrap">
+            <ul class="nav-box">
+                <li 
+                    :class="['nav-item',item.key===activeNav?'active':'']" 
+                    v-for="item in navOpt" 
+                    :key="item.key"
+                    @click="activeNav=item.key"
+                >{{item.name}}</li>
+            </ul>
+            <div>
+                <el-date-picker
+                    v-model="time"
+                    type="date"
+                    placeholder="选择日期"
+                    value-format="yyyy-MM-dd"
+                    :clearable="false"
+                    @change="handleDateChange"
+                    style="width:200px"
+                    v-if="activeNav!='DelEDBTable'"
+                />
+            </div>
+        </div>
+        <div class="main-box">
+            <component :is='activeNav' ref="comIns"></component>
+        </div>
+    </div>
+</template>
+
+<script>
+import DelEDBTable from './components/DelEDBTable.vue'
+import DetailTable from './components/DetailTable.vue'
+import EDBInfoChangeTable from './components/EDBInfoChangeTable.vue'
+import StatisticTable from './components/StatisticTable.vue'
+export default {
+    components:{DelEDBTable,DetailTable,EDBInfoChangeTable,StatisticTable},
+    watch: {
+        activeNav(n){
+            this.time=this.$moment().format('YYYY-MM-DD')
+        }  
+    },
+    data() {
+        return {
+            navOpt:[
+                {name:'数据源明细表',key:'DetailTable'},
+                {name:'数据源统计表',key:'StatisticTable'},
+                {name:'删除指标表',key:'DelEDBTable'},
+                {name:'指标信息变更表',key:'EDBInfoChangeTable'}
+            ],
+            activeNav:'DetailTable',
+            time:this.$moment().format('YYYY-MM-DD')||''
+        }
+    },
+    methods: {
+        handleShowSetTableCol(){
+            this.$refs.comIns.handleShowSetTableCol()
+        },
+
+        handleDateChange(){
+            this.$refs.comIns.filterState.dateVal=this.time
+            this.$refs.comIns.handleRefreshList()
+        }
+    },
+}
+</script>
+
+<style lang="scss" scoped>
+.data-source-list-page{
+    .top-wrap{
+        padding: 20px 30px;
+        border-radius: 4px;
+        border: 1px solid #DCDFE6; 
+        background-color: #fff;
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        .nav-box{
+            display: flex;
+            border: 1px solid #DCDFE6;
+            border-radius: 4px;
+            overflow: hidden;
+            &:last-child{
+                border-right: none;
+            }
+            .nav-item{
+                padding: 10px;
+                color: #666;
+                border-right: 1px solid #DCDFE6;
+                cursor: pointer;
+                &.active{
+                    background-color: #0052D9;
+                    color: #fff;
+                }
+            }
+        }
+    }
+    .main-box{
+        margin-top: 30px;
+        padding: 30px;
+        border-radius: 4px;
+        border: 1px solid #DCDFE6; 
+        background-color: #fff;
+        min-height: calc(100vh - 380px);
+        padding-bottom: 80px;
+    }
+}
+</style>

+ 4 - 0
src/views/dataSource_manage/utils/config.js

@@ -0,0 +1,4 @@
+export const frequencyOpt=['日度','周度','旬度','月度','季度','年度']
+
+export const refreshFrequencyOpt=['每工作日','周一','周二','周三','周四','周五','周六','周日','每月',]
+