Pārlūkot izejas kodu

Merge branch 'eta1.8.2'

cxmo 11 mēneši atpakaļ
vecāks
revīzija
941e6dce36

+ 4 - 2
src/api/api.js

@@ -15,7 +15,8 @@ import {
   fwmtInterface,
   guangqiInterface,
   icpiInterface,
-  coalWordInterface
+  coalWordInterface,
+  bloombergInterface
 } from './modules/thirdBaseApi';
 
 //手工指标 手工数据 手工数据权限
@@ -122,7 +123,8 @@ export {
   fwmtInterface,
   guangqiInterface,
   icpiInterface,
-  coalWordInterface
+  coalWordInterface,
+  bloombergInterface
 };
 
 //老接口 研报 ppt等

+ 58 - 1
src/api/modules/thirdBaseApi.js

@@ -910,6 +910,62 @@ const coalWordInterface={
 		return http.get('/entry/data/mtjh/frequency',params)
 	},
 }
+/* 彭博数据源 */
+const bloombergInterface={
+    /**
+     * 数据列表
+     * @param {Object} params 
+     * @param {Number} params.PageSize
+     * @param {Number} params.CurrentIndex
+     * @param {String} params.Frequency
+     * @param {String} params.Keywords
+     * @param {Boolean} params.ListAll
+     * @param {Number} params.SortField
+     * @param {Number} params.SortRule
+     * @returns 
+     */
+    getTableList:params=>{
+        return http.get('/datamanage/bloomberg_source/list',params)
+    },
+    /**
+     * 指标重名校验
+     * @param {Object[]} params
+     * @param {String} params[].EdbCode //指标编码
+     * @param {String} params[].EdbName //指标名称
+     * @returns 
+     */
+    edbNameCheck:params=>{
+        return http.post('/datamanage/bloomberg_source/name_check',params)
+    },
+    /**
+     * 添加指标校验
+     * @param {Object} params 
+     * @param {Object} params.Frequency
+     * @param {Object} params.Keywords
+     * @param {Object} params.SortField
+     * @param {Object} params.SortRule
+     * @param {Boolean} params.ListAll
+     * @param {String[]} params.IndexCodes
+     * @returns 
+     */
+    edbAddCheck:params=>{
+        return http.post('/datamanage/bloomberg_source/add_check',params)
+    },
+    /**
+     * 批量新增指标
+     * @param {Object[]} params 
+     * @param {String} params[].EdbCode
+     * @param {String} params[].EdbName
+     * @param {String} params[].Frequency
+     * @param {String} params[].Unit
+     * @param {Number} params[].ClassifyId
+     * @returns 
+     */
+    edbBatchAdd:params=>{
+        return http.post('/datamanage/bloomberg_source/batch_add',params)
+    },
+
+}
 
 export { 
 	lzDataInterface,
@@ -926,5 +982,6 @@ export {
   fwmtInterface,
 	guangqiInterface,
 	icpiInterface,
-	coalWordInterface
+	coalWordInterface,
+    bloombergInterface
 }

+ 8 - 0
src/lang/modules/DataSources/En.js

@@ -193,6 +193,14 @@ export default {
     col_status_irr:'Updates dependent on external sources may experience irregular delays',
     haved_all_msg:'All indicators added this time are already in the indicator library, please do not add them again!',
     haved_some_msg:'The following indicators already exist in the indicator library and will be automatically filtered out!'
+  },
+
+  /* 彭博数据源 */
+  BloombergPage:{
+    operation_prompt:'Operation Prompt',
+    add_edb_hint:'Max 30 indicators for bulk add!',
+    add_edb_check_hint1:'Incomplete Indicator Info',
+    add_edb_check_hint2:'Indicator name exists, please re-enter'
   }
   
 }

+ 8 - 0
src/lang/modules/DataSources/Zh.js

@@ -192,5 +192,13 @@ export default {
     col_status_irr:'更新依赖外部会有不定期延迟',
     haved_all_msg:'本次添加的指标均已在指标库中,请勿重复添加!',
     haved_some_msg:'指标库中已存在以下指标,会自动过滤!'
+  },
+
+  /* 彭博数据源 */
+  BloombergPage:{
+    operation_prompt:'操作提示',
+    add_edb_hint:'批量添加指标数量不得超过30个!',
+    add_edb_check_hint1:'指标信息未填写完整',
+    add_edb_check_hint2:'指标名称已存在,请重新填写'
   }
 }

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

@@ -245,6 +245,12 @@ export default [
         name: "煤炭江湖",
         hidden: false
       },
+      {
+        path: "bloomberg",
+        component: () => import("@/views/dataEntry_manage/thirdBase/bloombergSource.vue"),
+        name: "Bloomberg",
+        hidden: false
+      },
     ],
   },
 ];

+ 2 - 0
src/utils/buttonConfig.js

@@ -262,6 +262,8 @@ export const dataSourcePermission = {
     /*--------煤炭江湖---- */
     coalWordData_view:'coalWord:view', // 查看
     coalWordData_export:'coalWord:export', // 导出
+    /*--------彭博数据源--- */
+    Bloomberg_add2edb:'Bloomberg:add2edb',//添加指标库
 }
 
 /*

+ 569 - 0
src/views/dataEntry_manage/thirdBase/bloombergSource.vue

@@ -0,0 +1,569 @@
+<template>
+    <div class="bloomberg-source-wrap">
+        <div class="page-header">
+            <div class="header-select-box">
+                <!-- 频度 -->
+                <el-select v-model="selectOption.frequenceSelect" 
+                    :placeholder="$t('Edb.InputHolderAll.input_fre')" 
+                    @change="selectOptionChange('frequenceSelect')"
+                    clearable 
+                    style="width:240px">
+                    <el-option v-for="i in frequencyList" :key="i"
+                            :label="i" :value="i"
+                        />
+                </el-select>
+                <!-- 指标ID/名称 -->
+                <el-input 
+                    v-model="selectOption.keywordSelect" 
+                    prefix-icon="el-icon-search"
+                    :placeholder="$t('Edb.InputHolderAll.input_name_orid')" 
+                    @input="selectOptionChange('keywordSelect')"
+                    clearable 
+                    style="width:360px"></el-input>
+                <!-- 列表全选 -->
+                <el-checkbox 
+                    :indeterminate="isIndeterminate" 
+                    v-model="isCheckAll" 
+                    @change="listCheckAllChange">{{ $t('YsDataPage.label_all_check') }}</el-checkbox>
+            </div>
+            <!-- 添加到指标库 -->
+            <el-button v-permission="permissionBtn.dataSourcePermission.Bloomberg_add2edb" :disabled="total===0"
+                type="primary" @click="handleCheckDialogShow(false,{})">{{ $t('YsDataPage.add_base_btn') }}</el-button>
+        </div>
+        <div class="page-table">
+            <el-table :data="tableData" border
+                ref="edbDataRef"
+                @selection-change="selectionChange"
+                @select="selectHandle" 
+                @select-all="selectAllHandle"
+                @sort-change="handleSortChange"
+            >
+                <!-- 多选 -->
+                <el-table-column
+                    align="center"
+                    type="selection"
+                    width="55">
+                </el-table-column>
+                <el-table-column
+                    v-for="column in tableColumns" :key="column.key"
+                    :prop="column.key"
+                    :label="column.label"
+                    :sortable="column.sortable?column.sortable:false"
+                    align="center">
+                </el-table-column>
+                <el-table-column :label="$t('Table.column_operations')" align="center">
+                    <template slot-scope="{row}">
+                        <el-button type="text" @click="handleCheckDialogShow(true,row)"
+                        v-if="!row.EdbExist&&permissionBtn.isShowBtn('dataSourcePermission','Bloomberg_add2edb')">{{ $t('YsDataPage.add_base_btn') }}</el-button>
+                    </template>
+                </el-table-column>
+            </el-table>
+            <el-pagination 
+                :current-page="currentPage"
+                :page-size="pageSize"
+                :total="total"
+                @current-change="handleCurrentChange"
+            />
+        </div>
+        <!-- 操作提示弹窗 -->
+        <el-dialog 
+            :title="$t('BloombergPage.operation_prompt')"
+            :visible.sync="isHintDialogShow"
+            :close-on-click-modal="false"
+            :modal-append-to-body="false"
+            @close="isHintDialogShow=false"
+            width="578px"
+            v-dialogDrag
+            center>
+            <div class="hint-dialog-wrap">
+                <p style="margin-bottom: 20px;">{{ hintText }}</p>
+                <ul>
+                    <li v-for="(item,index) in afterAddList" :key="index" class="hint-item" @click="gotoEdbDetail(item)">
+                        {{ index+1 }}、{{ item.IndexName }}({{ item.IndexCode }})
+                    </li>
+                </ul>
+            </div>
+            <div style="text-align: center;margin-bottom: 30px;">
+                    <el-button type="primary" @click="handleCloseDialog">{{$t('Dialog.known')}}</el-button>
+                </div>
+        </el-dialog>
+        <!-- 添加到指标库弹窗 -->
+        <el-dialog 
+            :title="$t('YsDataPage.add_base_btn')"
+            :visible.sync="isAddDialogShow"
+            :close-on-click-modal="false"
+            :modal-append-to-body="false"
+            @close="isAddDialogShow=false"
+            width="900px"
+            top="5vh"
+            v-dialogDrag
+            center>
+            <div class="add-dialog-wrap">
+                <el-form :model="addForm" ref="addFormRef">
+                    <div class="group" v-for="(item,index) in addForm.list" :key="index">
+                        <div class="item-header">
+                            <span @click="item.expand=!item.expand">
+                                {{ item.IndexCode }}
+                                <i :class="item.expand?'el-icon-arrow-up':'el-icon-arrow-down'"></i>
+                            </span>
+                        </div>
+                        <div class="form-wrap" v-show="item.expand">
+                            <el-form-item 
+                                :prop="`list[${index}].IndexName`" 
+                                :rules="[
+                                    {required:true,message:$t('Edb.InputHolderAll.input_name'),trigger: 'blur'},
+                                    {validator:edbNameCheck}
+                                ]">
+                                <el-input v-model="item.IndexName"></el-input>
+                            </el-form-item>
+                            <el-form-item :prop="`list[${index}].Unit`" :rules="{required:true,message:$t('Edb.InputHolderAll.input_unit'),trigger: 'blur'}">
+                                <el-input v-model="item.Unit"
+                                    :placeholder="$t('Edb.InputHolderAll.input_fre')">
+                                </el-input>
+                            </el-form-item>
+                            <el-form-item :prop="`list[${index}].Frequency`" :rules="{required:true,message:$t('Edb.InputHolderAll.input_fre'),trigger: 'blur'}">
+                                <el-select v-model="item.Frequency" :placeholder="$t('Edb.InputHolderAll.input_fre')" >
+                                    <el-option v-for="i in frequencyList" :key="i"
+                                            :label="i" :value="i"
+                                        />
+                                </el-select>
+                            </el-form-item>
+                            <el-form-item :prop="`list[${index}].ClassifyId`" :rules="{required:true,message:$t('Edb.InputHolderAll.input_menu'),trigger: 'blur'}">
+                                <el-cascader v-model="item.ClassifyId"
+                                :placeholder="$t('Edb.InputHolderAll.input_menu')"
+                                :options="edbCatalogList" 
+                                :props="{
+                                    label: 'ClassifyName',
+                                    value: 'ClassifyId',
+                                    children: 'Children',
+                                    checkStrictly: true,
+                                    emitPath:false
+                                }"
+                                ></el-cascader>
+                            </el-form-item>
+                        </div>
+                        
+                    </div>
+                </el-form>
+            </div>
+            <div style="text-align: center;margin-bottom: 30px;">
+                    <el-button @click="isAddDialogShow=false">{{$t('Dialog.cancel_btn')}}</el-button>
+                    <el-button type="primary" @click="handleSaveCheck" :loading="btnLoading">{{$t('Dialog.confirm_save_btn')}}</el-button>
+                </div>
+        </el-dialog>
+    </div>
+</template>
+
+<script>
+import {bloombergInterface,dataBaseInterface} from '@/api/api.js'
+export default {
+    data() {
+        return {
+            selectOption:{
+                frequenceSelect:'',
+                keywordSelect:'',
+                sortParam:'',
+                sortType:''
+            },
+            frequencyList:['日度','周度','旬度','月度','季度','半年度','年度'],
+            tableData:[],
+            tableDataIds:[],
+            currentPage:1,
+            pageSize:10,
+            total:2,
+
+            isIndeterminate:false,
+            isCheckAll:false,//与isIndeterminate一起表示列表全选的状态
+            isSelectAll:false,//是否勾选了列表全选:为true时,selectList是剔除的指标,为false时selectList是已选择的指标
+            selectList:[],//已选择/已剔除的指标id
+            selectionReactCancel:false,//select-事件触发时,为true;该事件触发完成后,为false;
+            
+            isHintDialogShow:false,
+            afterAddList:[],//已添加进指标库的指标
+            beforeAddList:[],//需要添加进指标库的指标
+            edbCatalogList:[],//指标库目录数据
+            isAddDialogShow:false,
+            addForm:{
+                list:[
+                    /* {
+                        IndexName:'',
+                        Unit:'',
+                        Frequency:'',
+                        ClassifyId:''
+                    } */
+                ]
+            },
+            checkedList:[],//重名的指标code
+            btnLoading:false,
+
+        };
+    },
+    computed:{
+        tableColumns(){
+            return [
+                    {key:'IndexCode',label:this.$t('Edb.Detail.e_id')}, //指标ID
+                    {key:'IndexName',label:this.$t('Edb.Detail.e_name')},//指标名称
+                    {key:'Frequency',label:this.$t('Edb.Detail.e_fre')},//频度
+                    {key:'StartDate',label:this.$t('DataBankPage.table_col_start_time'),sortable:true},//指标开始时间
+                    {key:'EndDate',label:this.$t('DataBankPage.table_col_newest_time'),sortable:true},//指标最新时间
+                    {key:'ModifyTime',label:this.$t('Edb.Detail.e_update_time'),sortable:true} //更新时间
+                ]
+        },
+        hintText(){
+            let key = 0
+            if(this.afterAddList.length) key++
+            if(!this.beforeAddList.length) key++
+            return {
+                0:'',
+                1:this.$t('YsDataPage.haved_all_msg'),//本次添加的指标均已在指标库中,请勿重复添加!
+                2:this.$t('YsDataPage.haved_some_msg'),//指标库中已存在以下指标,会自动过滤!
+            }[key]
+        }
+    },
+    methods: {
+        getEdbCatalog() {
+            dataBaseInterface.menuListV3().then(res => {
+            if(res.Ret === 200) {
+                this.edbCatalogList = res.Data.AllNodes || [];
+                this.filterNodes(this.edbCatalogList);
+            }
+            })
+        },
+        // 递归改变目录结构
+        filterNodes(arr) {
+            arr.length && arr.forEach(item => {
+            item.Children.length && this.filterNodes(item.Children)
+            if(!item.Children.length) {
+                item.Children=null
+            }
+            })
+        },
+        getTableData(type){
+            const {frequenceSelect,keywordSelect,sortParam,sortType} = this.selectOption
+            bloombergInterface.getTableList({
+                PageSize:this.pageSize,
+                CurrentIndex:this.currentPage,
+                Frequency:frequenceSelect,
+                Keywords:keywordSelect,
+                SortField:sortParam,
+                SortRule:sortType
+            }).then(res=>{
+                if(res.Ret!==200) return 
+                this.tableData = res.Data.List||[]
+                this.total = res.Data.Paging.Totals
+                if(this.tableData.length>0){
+                    this.tableDataIds = this.tableData.map(it => it.IndexCode)
+                }else{
+                    this.tableDataIds = []
+                }
+                if(type==='optionChange'){
+                    //如果是表格筛选项改变导致重新请求数据
+                    //数据获取完成后,列表全选,表格全选
+                    this.selectList = []
+                    this.listCheckAllChange(true)
+                }else{
+                    //若不是,数据获取完成后,查询列表全选的值
+                    //若当页有数据在selectList内,则勾选/剔除
+                    this.adjustSelection()
+                }
+            })
+            
+        },
+        handleCurrentChange(page){
+            this.currentPage = page
+            this.getTableData()
+        },
+        handleSortChange({prop,order}){
+            console.log('prop',prop,'order',order)
+            const propMap={
+                'StartDate':1,
+                'EndDate':2,
+                'ModifyTime':3
+            }
+            this.selectOption.sortParam = order?propMap[prop]||'':''
+            this.selectOption.sortType = order?order==='ascending'?1:2:''
+            this.selectOptionChange()
+        },
+        //表格筛选项改变时触发
+        selectOptionChange(type){
+            //若是取消筛选,则不进行全选
+            const optionValue = this.selectOption[type]
+            if(!optionValue){
+                this.isSelectAll = false
+                this.selectList = []
+                this.isIndeterminate = false
+                this.isCheckAll = false
+            }
+            this.currentPage = 1
+            this.getTableData(optionValue?'optionChange':'')
+        },
+        //列表全选改变
+        listCheckAllChange(value){
+            this.selectList = []
+            this.isSelectAll = value
+            this.$refs.edbDataRef && this.$refs.edbDataRef.clearSelection()
+            if(value){
+                this.$refs.edbDataRef && this.$refs.edbDataRef.toggleAllSelection()
+            }
+        },
+        selectionChange(){
+            if(this.selectionReactCancel) return 
+            // selectAllHandle的触发在selectionChange后面,将selectionChange的逻辑延迟一下
+            setTimeout(()=>{
+                // 去重
+                let duplicateArr = Array.from(new Set(this.selectList))
+                //isSelectAll为true时,selectList表示需要剔除的项
+                //isSelectAll为false时,selectList表示需要勾选的项
+                //全选
+                if((duplicateArr.length == this.total && (!this.isSelectAll))|| (duplicateArr.length == 0 && this.isSelectAll)){
+                    this.isCheckAll = true
+                    this.isIndeterminate=false
+                //全不选
+                }else if((duplicateArr.length == 0 && (!this.isSelectAll))|| (duplicateArr.length == this.total && this.isSelectAll)){
+                    this.isCheckAll = false
+                    this.isIndeterminate=false
+                //半选
+                }else{
+                    this.isCheckAll = false
+                    this.isIndeterminate=true
+                }
+            },1)
+        },
+        selectHandle(selection,row){
+            if(this.selectionReactCancel) return 
+            let check = false; 
+            if(selection.some(it => it.IndexCode == row.IndexCode)){
+                // 勾选
+                if(this.isSelectAll){
+                    check=false
+                }else{
+                    check=true
+                }
+            }else{
+                // 取消勾选
+                if(this.isSelectAll){
+                    check=true
+                }else{
+                    check=false
+                }
+            }
+            if(check){
+                this.selectList.push(row.IndexCode)
+                }else{
+                this.selectList=this.selectList.filter(it => it!=row.IndexCode)
+            }
+        },
+        selectAllHandle(selection){
+            if(this.selectionReactCancel) return 
+            let check = false; 
+            if(selection && selection.length>0){
+                // 全选
+                if(this.isSelectAll){
+                    check=false
+                }else{
+                    check=true
+                }
+            }else{
+                // 全不选
+                if(this.isSelectAll){
+                    check=true
+                }else{
+                    check=false
+                }
+            }
+            if(check){
+                this.selectList =  [...this.selectList,...this.tableDataIds]
+            }else{
+                this.selectList = this.selectList.filter(it => !this.tableDataIds.includes(it))
+            }
+        },
+        adjustSelection(){
+            this.selectionReactCancel=true
+            if(!this.isSelectAll){
+                this.selectList.map(it =>{
+                    let row = this.tableData.find(da => da.IndexCode==it)
+                    if(row){
+                        setTimeout(()=>{
+                            this.$refs.edbDataRef.toggleRowSelection(row,true)
+                        },10)
+                    }
+                })
+            }else{
+                this.$refs.edbDataRef && this.$refs.edbDataRef.clearSelection()
+                this.$refs.edbDataRef &&this.$refs.edbDataRef.toggleAllSelection()
+                this.selectList.map(it =>{
+                    let row = this.tableData.find(da => da.IndexCode==it)
+                    if(row){
+                        setTimeout(()=>{
+                            this.$refs.edbDataRef.toggleRowSelection(row,false)
+                        },50)
+                    }
+                })
+            }
+            setTimeout(()=>{
+                this.selectionReactCancel=false
+            },50)
+        },
+        handleCheckDialogShow(isSingle=false,data={}){
+            //check
+            const {frequenceSelect,keywordSelect,sortParam,sortType} = this.selectOption
+            bloombergInterface.edbAddCheck({
+                Frequency:frequenceSelect,
+                Keywords:keywordSelect,
+                SortField:sortParam||0,
+                SortRule:sortType||0,
+                ListAll:isSingle?false:this.isSelectAll,
+                IndexCodes:isSingle?[data.IndexCode]:this.selectList
+            }).then(res=>{
+                if(res.Ret!==200) return 
+                const edbList = res.Data||[]
+                this.afterAddList = edbList.filter(i=>i.EdbExist===1)
+                this.beforeAddList = edbList.filter(i=>i.EdbExist===0).map(i=>{return{...i,expand:true}})
+                this.afterAddList.length&&(this.isHintDialogShow=true)
+                !this.afterAddList.length&&this.handleCloseDialog()
+            })
+        },
+        //操作提示弹窗关闭
+        handleCloseDialog(){
+            this.isHintDialogShow = false
+            //判断是否要展示下一个弹窗
+            if(this.beforeAddList.length){
+                this.addForm.list = this.beforeAddList
+                this.isAddDialogShow = true
+            }
+        },
+        //重名校验
+        edbNameCheck(rule,value,callback){
+            if(this.checkedList.includes(value)){
+                callback(this.$t('BloombergPage.add_edb_check_hint2'))
+            }else{
+                callback()
+            }
+        },
+        //保存前校验
+        async handleSaveCheck(){
+            //表单校验
+            try{
+                await this.$refs.addFormRef.validate()
+            }catch(e){
+                return
+            }
+            //重名校验
+            this.checkedList = []
+            bloombergInterface.edbNameCheck(
+                this.addForm.list.map(i=>{return{EdbCode:i.IndexCode,EdbName:i.IndexName}})
+            ).then(res=>{
+                if(res.Ret!==200) return 
+                this.checkedList = res.Data.filter(i=>i.Exist).map(i=>i.EdbName)
+                if(this.checkedList.length){
+                    this.$refs.addFormRef.validate()
+                }else{
+                    this.saveEdb()
+                }
+            })
+        },
+        //批量新增
+        saveEdb(){
+            this.btnLoading = true
+            bloombergInterface.edbBatchAdd(
+                this.addForm.list.map(i=>{
+                    return {
+                        EdbCode:i.IndexCode,
+                        EdbName:i.IndexName,
+                        Frequency:i.Frequency,
+                        Unit:i.Unit,
+                        ClassifyId:i.ClassifyId
+                    }
+                })
+            ).then(res=>{
+                this.btnLoading = false
+                if(res.Ret!==200) return 
+                this.$message.success(this.$t('MsgPrompt.add_msg2'))
+                this.isAddDialogShow = false
+                this.handleCurrentChange(1)
+            })
+        },
+        //跳转至指标详情
+        gotoEdbDetail(data){
+            const {EdbClassifyId,EdbInfoId,EdbUniqueCode} = data||{}
+            const href = this.$router.resolve({
+                path:'/database',
+                query:{
+                    code:EdbUniqueCode,
+                    id:EdbInfoId,
+                    classifyId:EdbClassifyId,
+                }
+            }).href
+            window.open(href,"_blank")
+        }
+    },
+    mounted(){
+        this.getTableData()
+        this.getEdbCatalog()
+    },
+};
+</script>
+
+<style lang="scss">
+.bloomberg-source-wrap{
+    .add-dialog-wrap{
+        .el-form{
+            .group{
+                .item-header{
+                    margin-bottom: 20px;
+                }
+                .form-wrap{
+                    display: flex;
+                    gap:10px;
+                    .el-input{
+                        width: 100%;
+                    }
+                }
+            }
+        }
+    }
+}
+</style>
+<style scoped lang="scss">
+.bloomberg-source-wrap{
+    min-height: calc(100vh - 120px);
+    display: flex;
+    flex-direction: column;
+    background-color: #fff;
+    border:1px solid #C8CDD9;
+    border-radius: 4px;
+    padding:20px;
+    box-sizing: border-box;
+    .page-header{
+        display: flex;
+        justify-content: space-between;
+        .header-select-box{
+            display: flex;
+            gap:20px;
+            align-items: center;
+        }
+    }
+    .page-table{
+        .el-table{
+            margin:20px 0;
+            .el-button--text{
+                padding:0;
+            }
+        }
+        .el-pagination{
+            text-align: right;
+        }
+    }
+    .hint-dialog-wrap{
+        padding-bottom:30px;
+        .hint-item{
+            cursor: pointer;
+            margin-bottom: 10px;
+            &:hover{
+                color:#409EFF;
+                text-decoration: underline;
+            }
+        }
+    }
+}
+</style>