jwyu 1 år sedan
förälder
incheckning
6c15f09ad6

+ 2 - 2
.env.development

@@ -1,5 +1,5 @@
-# 接口地址http://8.136.199.33:8610/v1   https://rddptest.hzinsights.com/adminapi
-VITE_APP_API_URL="http://8.136.199.33:8610/v1"
+# 接口地址http://8.136.199.33:8610/v1   http://8.136.199.33:7778/adminapi
+VITE_APP_API_URL="http://8.136.199.33:7778/adminapi"
 # 路由根地址
 # 路由根地址
 VITE_APP_BASE_URL="/"
 VITE_APP_BASE_URL="/"
 # 打包输入文件名
 # 打包输入文件名

+ 1 - 1
index.html

@@ -4,7 +4,7 @@
     <meta charset="UTF-8" />
     <meta charset="UTF-8" />
     <link rel="icon" type="image/x-icon" href="/fa.ico"/>
     <link rel="icon" type="image/x-icon" href="/fa.ico"/>
     <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, viewport-fit=cover">
     <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, viewport-fit=cover">
-    <title>移动ETA</title>
+    <title>ETA投研平台</title>
     <link href='/froala_editor.pkgd.min.css' rel='stylesheet' type='text/css' />
     <link href='/froala_editor.pkgd.min.css' rel='stylesheet' type='text/css' />
   </head>
   </head>
   <body>
   <body>

+ 88 - 0
src/api/dataEDB.js

@@ -0,0 +1,88 @@
+//ETA指标库
+import { get,post } from "./index";
+
+export default{
+    /**
+     * ETA指标列表
+     */
+    edbList(params){
+        return get('/datamanage/classify/edb_info/list?ClassifyId=535',params)
+    },
+
+    /**
+     * ETA指标库分类列表
+     */
+    edbClassifyList(){
+        return get('/datamanage/classify/items/v3',{})
+    },
+
+    /**
+     * 新增ETA指标库分类
+     * @param ClassifyName
+     * @param Level
+     * @param ParentId
+     */
+    edbClassifyAdd(params){
+        return post('/datamanage/classify/add',params)
+    },
+
+    /**
+     * 编辑ETA指标库分类
+     * @param ClassifyName
+     * @param ClassifyId
+     */
+    edbClassifyEdit(params){
+        return post('/datamanage/classify/edit',params)
+    },
+
+    /**
+     * 删除ETA指标库分类检测
+     * @param ClassifyId
+     * @param EdbInfoId
+     */
+    edbClassifyDeleteCheck(params){
+        return post('/datamanage/classify/delete/check',params)
+    },
+
+    /**
+     * 删除ETA指标库分类(包含指标的删除)
+     * @param ClassifyId
+     * @param EdbInfoId
+     */
+    edbClassifyDelete(params){
+        return post('/datamanage/classify/delete',params)
+    },
+
+    /**
+     * 移动ETA指标库分类
+     * @param ClassifyId
+     * @param ParentClassifyId
+     * @param PrevClassifyId
+     * @param NextClassifyId
+     */
+    edbClassifyMove(params){
+        return post('/datamanage/edb_classify/move',params)
+    },
+
+    /**
+     * 基础指标详情
+     * @param EdbInfoId
+     */
+    getBaseEdbInfo(params){
+        return get('/datamanage/edb_info/detail',params)
+    },
+
+    /**
+     * 基础指标编辑
+     * @param EdbInfoId
+     * @param ClassifyId
+     * @param EdbName
+     * @param Frequency
+     * @param Unit
+     */
+    editBaseEdbInfo(params){
+        return post('/datamanage/edb_info/edit',params)
+    }
+
+
+}

BIN
src/assets/imgs/chartETA/icon_chartETA_logo.png


BIN
src/assets/imgs/dataEDB/icon_menu.png


BIN
src/assets/imgs/dataEDB/icon_opt.png


BIN
src/assets/imgs/myETA/icon_myETA_logo.png


BIN
src/assets/imgs/ppt/ppt_icon_en.png


BIN
src/assets/imgs/ppt/ppt_icon_zh.png


BIN
src/assets/imgs/report/report_icon.png


BIN
src/assets/imgs/report/report_icon_en.png


BIN
src/assets/imgs/tabbar/home-s.png


BIN
src/assets/imgs/tabbar/home.png


BIN
src/assets/imgs/tabbar/icon_EDB.png


BIN
src/assets/imgs/tabbar/icon_PPT.png


BIN
src/assets/imgs/tabbar/icon_chart.png


BIN
src/assets/imgs/tabbar/icon_dataSource.png


BIN
src/assets/imgs/tabbar/icon_myChart.png


BIN
src/assets/imgs/tabbar/icon_preEDB.png


BIN
src/assets/imgs/tabbar/icon_report.png


BIN
src/assets/imgs/tabbar/icon_table.png


BIN
src/assets/imgs/tabbar/user-s.png


BIN
src/assets/imgs/tabbar/user.png


+ 1 - 1
src/assets/styles/common.scss

@@ -18,7 +18,7 @@ html,body,#app{
     }
     }
 }
 }
 
 
-div{
+div,ul,li{
     box-sizing: border-box;
     box-sizing: border-box;
 }
 }
 
 

+ 13 - 0
src/router/dataEDB.js

@@ -0,0 +1,13 @@
+// ETA指标库模块
+export const dataEDBRoutes=[
+    {
+        path:"/dataEDB/index",
+        name:"DataEDBIndex",
+        component: () => import("@/views/dataEDB/Index.vue"),
+        meta: { 
+            title: "ETA指标库",
+            keepAlive:true,
+            hasBackTop:true,
+        },
+    },
+]

+ 3 - 0
src/router/index.js

@@ -17,6 +17,7 @@ import {myETARoutes} from './myETA'
 import {reportRoutes} from './report'
 import {reportRoutes} from './report'
 import {reportEnRoutes} from './reportEn'
 import {reportEnRoutes} from './reportEn'
 import {chartETARoutes} from './chartETA'
 import {chartETARoutes} from './chartETA'
+import {dataEDBRoutes} from './dataEDB'
 
 
 const routes = [
 const routes = [
   	{
   	{
@@ -67,6 +68,8 @@ const routes = [
 			...reportEnRoutes,
 			...reportEnRoutes,
             //ETA图库模块
             //ETA图库模块
             ...chartETARoutes,
             ...chartETARoutes,
+			//ETA指标库模块
+			...dataEDBRoutes,
 		]
 		]
 	},
 	},
 	
 	

+ 383 - 0
src/views/dataEDB/Index.vue

@@ -0,0 +1,383 @@
+<script setup name="DataEDBIndex">
+import {reactive,ref, watch} from 'vue'
+import apiDataEDB from '@/api/dataEDB'
+import EDBClassify from './components/EDBClassify.vue'
+import EditBaseEDB from './components/EditBaseEDB.vue'
+import {useEDBDelete} from './hooks/useEDBDelete'
+import { showToast } from 'vant'
+
+const {edbClassifyDelete} =useEDBDelete()
+
+const listState = reactive({
+    list:[],
+    page:1,
+    pageSize:15,
+    finished:false,
+    loading:false,
+    total:0,
+    activeClassifyName:'',//当前选中的分类名称
+    activeClassifyId:0,
+})
+async function getEDBList(){
+    const res=await apiDataEDB.edbList()
+    if(res.Ret===200){
+        listState.loading=false
+        if(!res.Data){
+            listState.finished=true
+            listState.total=0
+            return
+        }
+        
+        listState.finished=true
+        const arr=res.Data.EdbInfoList||[]
+        listState.list=[...listState.list,...arr]
+        listState.total=20
+    }
+}
+getEDBList()
+// 触底加载
+function onLoad(){
+    listState.page++
+    getEDBList()
+}
+// 刷新列表
+function refreshEBDList(){
+
+}
+
+//基础操作
+const showActionPop=ref(false)
+function handleSelectActionOpt(e){
+    console.log(e);
+}
+
+// 分类弹窗
+const showClassifyPop=ref(false)
+watch(
+    ()=>showClassifyPop.value,
+    (n)=>{
+        if(!n){
+            listState.page=1
+            listState.list=[]
+            listState.finished=false
+            listState.total=0
+            getEDBList()
+        }
+    }
+)
+function handleSelectClassifyChange(e){
+    listState.activeClassifyName=e.selectClassifyNameStr
+    listState.activeClassifyId=e.selectClassifyId
+}
+
+// 单个指标操作数据
+const edbOptState=reactive({
+    show:false,
+    data:null,
+})
+watch(
+    ()=>edbOptState.show,
+    (n)=>{
+        if(!n){
+            edbOptState.data=null
+        }
+    }
+)
+function handleShowEdbOpt(item){
+    edbOptState.data=item
+
+    edbOptState.show=true
+}
+// 控制指标操作中的计算指标查看
+function seeComputeEDBInfo(data){
+    return data?.EdbType===2&&![58,59,67,68].includes(data?.Source)
+}
+
+
+const activeEditEDBData=ref(null)//当前编辑的指标项数据
+const showEditBaseEDB=ref(false)// 显示编辑基础指标
+// 指标操作
+function handleEDBOpt(type,data){
+    // 编辑
+    if(type==='edit'){
+        activeEditEDBData.value=data
+        // 基础指标
+        if(data.EdbType===1 || [58,59,67,68].includes(data.Source)){
+            showEditBaseEDB.value=true
+        }
+        // 计算指标
+        if(data.EdbType === 2 && ![27,40,58,59].includes(data.Source)){
+            showToast('待开发,计算指标请在pc端操作')
+        }
+    }
+    // 删除
+    if(type==='delete'){
+        edbClassifyDelete(data).then((res)=>{
+            if(res===true){
+                refreshEBDList()
+            }
+        })
+    }
+
+    edbOptState.show=false
+}
+//编辑基础指标信息成功回调
+function handleEditBaseEdbSuccess(e){
+    // 更新列表中指标的名称
+    listState.list.forEach(item=>{
+        if(item.EdbInfoId===e.EdbInfoId){
+            item.ClassifyName=e.EdbName
+        }
+    })
+}
+
+</script>
+
+<template>
+    <div class="dataEDB-index-page">
+        <div class="top-sticky-box">
+            <div class="search-box">
+                <van-search 
+                    shape="round" 
+                    readonly 
+                    placeholder="请输入指标ID/指标名称"
+                    style="flex:1;padding-left:0"
+                    @click-input="$router.push('/chartETA/search')"
+                />
+                <div class="lang-icon icon">
+                    <img v-if="true" src="@/assets/imgs/chartETA/lang-icon.png" alt="">
+                    <img v-if="false" src="@/assets/imgs/chartETA/langEn-icon.png" alt="">
+                </div>
+            </div>
+            <div class="count-box">
+                <div class="con">
+                    <div class="van-ellipsis label">{{listState.activeClassifyName||'全部'}}</div>
+                    <span class="num">共70个指标</span>
+                </div>
+                <img class="menu-icon" src="@/assets/imgs/dataEDB/icon_menu.png" alt="" @click="showClassifyPop=true">
+            </div>
+        </div>
+        <div class="edb-list-wrap">
+            <van-list
+                v-model:loading="listState.loading"
+                :finished="listState.finished"
+                :finished-text="listState.list.length>0?'没有更多了':'暂无数据'"
+                :immediate-check="false"
+                @load="onLoad"
+            >
+                <img v-if="listState.list.length==0&&listState.finished" class="list-empty-img" src="https://hzstatic.hzinsights.com/static/ETA_mobile/empty_img.png" alt="">
+                <ul class="edb-list">
+                    <li class="edb-item" v-for="item in listState.list" :key="item.EdbInfoId">
+                        <div class="van-multi-ellipsis--l2 name">{{item.ClassifyName}}</div>
+                        <van-image
+                            class="img"
+                            src=""
+                        />
+                        <div>
+                            <span class="time">{{item.StartDate}}</span>
+                            <svg 
+                                class="opt-icon" 
+                                xmlns="http://www.w3.org/2000/svg" 
+                                width="28" 
+                                height="28" 
+                                viewBox="0 0 28 28" 
+                                fill="none"
+                                @click="handleShowEdbOpt(item)"
+                            >
+                                <rect width="28" height="28" rx="4" :fill="item.EdbInfoId===edbOptState.data?.EdbInfoId?'#0052D9':'none'"/>
+                                <path d="M14 19.25C14.9625 19.25 15.75 20.0375 15.75 21C15.75 21.9625 14.9625 22.75 14 22.75C13.0375 22.75 12.25 21.9625 12.25 21C12.25 20.0375 13.0375 19.25 14 19.25ZM12.25 14C12.25 14.9625 13.0375 15.75 14 15.75C14.9625 15.75 15.75 14.9625 15.75 14C15.75 13.0375 14.9625 12.25 14 12.25C13.0375 12.25 12.25 13.0375 12.25 14ZM12.25 7C12.25 7.9625 13.0375 8.75 14 8.75C14.9625 8.75 15.75 7.9625 15.75 7C15.75 6.0375 14.9625 5.25 14 5.25C13.0375 5.25 12.25 6.0375 12.25 7Z" :fill="item.EdbInfoId===edbOptState.data?.EdbInfoId?'#fff':'#333333'"/>
+                            </svg>
+                        </div>
+                    </li>
+                </ul>
+            </van-list>
+        </div>
+        
+    </div>
+
+    <!-- 悬浮操作按钮 -->
+    <div class="fixed-opt-btn" @click="showActionPop=true">
+        <svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 48 48" fill="none">
+            <path fill-rule="evenodd" clip-rule="evenodd" d="M43.4855 12.7505L25.4062 2.31235C24.536 1.80995 23.4639 1.80995 22.5937 2.31235L4.5144 12.7505V33.6267C4.5144 34.6315 5.05046 35.5599 5.92065 36.0623L24 46.5005L42.0793 36.0623C42.9495 35.5599 43.4855 34.6315 43.4855 33.6267V12.7505ZM23.997 22.2665L9.01233 13.6153L24 4.96245L38.9859 13.6158L23.997 22.2665ZM25.5 24.8665L40.485 16.2149V33.5165L25.5 42.1666V24.8665ZM22.5 24.8665V42.1667L7.51198 33.5165V16.2132L22.5 24.8665Z" fill="white"/>
+        </svg>
+    </div>
+
+    <!-- 基础操作弹窗 -->
+    <van-action-sheet
+        teleport="body"
+        v-model:show="showActionPop"
+        cancel-text="取消"
+        close-on-click-action
+        :actions="[
+            {
+                name:'添加指标'
+            },
+            {
+                name:'计算指标'
+            },
+            {
+                name:'替换指标'
+            }
+        ]"
+        @select="handleSelectActionOpt"
+    >
+    </van-action-sheet>
+
+    <!-- 分类弹窗 -->
+    <EDBClassify v-model="showClassifyPop" @change="handleSelectClassifyChange"/>
+
+    <!-- 指标的操作 -->
+    <van-action-sheet
+        teleport="body"
+        v-model:show="edbOptState.show"
+        cancel-text="取消"
+        close-on-click-action
+    >
+        <template #default>
+            <ul class="edb-opt-list">
+                <!-- 计算指标查看 -->
+                <!-- <li class="item" v-if="seeComputeEDBInfo(edbOptState.data)">查看</li> -->
+                <li class="item color-blue" v-if="edbOptState.data?.Button.OpButton" @click="handleEDBOpt('edit',edbOptState.data)">编辑</li>
+                <li class="item color-red" v-if="edbOptState.data?.Button.DeleteButton" @click="handleEDBOpt('delete',edbOptState.data)">删除</li>
+                <li class="item" v-if="edbOptState.data?.Button.MoveButton">移动至</li>
+                <li class="item" v-if="edbOptState.data?.Button.ShowEdbRelation">关联指标</li>
+                <li class="item" v-if="edbOptState.data?.Button.ShowChartRelation">关联图表</li>
+            </ul>
+        </template>
+    </van-action-sheet>
+
+    <!-- 编辑基础指标 -->
+    <EditBaseEDB 
+        v-model="showEditBaseEDB" 
+        :edbInfoId="activeEditEDBData?.EdbInfoId"
+        @success="handleEditBaseEdbSuccess"
+    />
+</template>
+
+<style lang="scss" scoped>
+.dataEDB-index-page{
+    min-height: 100vh;
+    background-color: $page-bg-grey;
+}
+.fixed-opt-btn{
+    width: var(--van-back-top-size);
+    height: var(--van-back-top-size);
+    position: fixed;
+    right: var(--van-back-top-right);
+    bottom: calc(var(--van-back-top-bottom) + var(--van-back-top-size) + 10px);
+    background-color: $theme-color;
+    border-radius: 50%;
+    box-shadow: 0px 6px 28px 4px rgba(0, 0, 0, 0.05), 0px 16px 20px 2px rgba(0, 0, 0, 0.06), 0px 10px 10px -6px rgba(0, 0, 0, 0.1);
+    svg{
+        width: 40px;
+        height: 40px;
+        position: absolute;
+        top: 50%;
+        left: 50%;
+        transform: translate(-50%,-50%);
+    }
+}
+.top-sticky-box{
+    top: 0;
+    left: 0;
+    right: 0;
+    z-index: 99;
+    position: sticky;
+    background-color: #fff;
+    .search-box{
+        display: flex;
+        align-items: center;
+        padding: 20px $page-padding;
+        border-bottom: 1px solid $border-color;
+        :deep(.van-search){
+            padding: 0;
+        }
+        .lang-icon{
+            margin-left: 10px;
+            width: 70px;
+            height:70px;
+            background-color: #F2F3FF;
+            border-radius: 50%;
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            img{
+                width:45px;
+                height:45px;
+            }
+        }
+    }
+    .count-box{
+        display: flex;
+        align-items: center;
+        padding: 20px $page-padding;
+        .con{
+            flex: 1;
+            display: flex;
+            overflow: hidden;
+            .lable{
+                flex: 1;
+            }
+            .num{
+                color: $font-grey_999;
+                margin-left: 12px;
+                flex-shrink: 0;
+            }
+        }
+        .menu-icon{
+            width: 48px;
+            height: 48px;
+            flex-shrink: 0;
+            margin-left: 10px;
+        }
+    }
+}
+.edb-list-wrap{
+    padding: 32px $page-padding;
+    .edb-list{
+        display: flex;
+        justify-content: space-between;
+        flex-wrap: wrap;
+        gap: 30px 0;
+        .edb-item{
+            width: 326px;
+            border-radius: 8px;
+            background: #FFF;
+            box-shadow: 0px 0px 6px 1px rgba(0, 0, 0, 0.08);
+            padding: 10px;
+            .name{
+                min-height: 70px;
+            }
+            .img{
+                width: 100%;
+                height: 220px;
+                margin: 14px 0;
+            }
+            .time{
+                font-size: 24px;
+            }
+            .opt-icon{
+                float: right;
+                width: 28px;
+                height: 28px;
+            }
+        }
+    }
+    
+}
+.edb-opt-list{
+    .item{
+        font-size: 14PX;
+        text-align: center;
+        line-height: 44PX;
+        border-bottom: 1px solid $border-color;
+    }
+    .color-blue{
+        color: $theme-color;
+    }
+    .color-red{
+        color: $theme-red;
+    }
+}
+
+</style>

+ 494 - 0
src/views/dataEDB/components/EDBClassify.vue

@@ -0,0 +1,494 @@
+<script setup>
+import {reactive, ref,watch} from 'vue'
+import { useWindowSize } from '@vueuse/core'
+import apiDataEDB from '@/api/dataEDB'
+import { showDialog , showToast } from 'vant';
+import {useEDBDelete} from '../hooks/useEDBDelete'
+
+const {edbClassifyDelete}=useEDBDelete()
+const { width } = useWindowSize()
+
+const props=defineProps({
+    modelValue:{
+        type:Boolean,
+        default:false
+    }
+})
+
+const emits=defineEmits(['update:modelValue','change'])
+
+// 关闭弹窗
+function handleClose(){
+    emits('update:modelValue',false)
+}
+
+// 当前点击了哪些分类
+let selectClassifyNameStr=''
+let selectClassifyId=0
+function handleSelectClassify(level1,level2,level3){
+    // console.log(level1,level2,level3);
+    if(level1){
+        selectClassifyId=level1.ClassifyId
+        selectClassifyNameStr=`${level1.ClassifyName}`
+    }
+    if(level2){
+        selectClassifyId=level2.ClassifyId
+        selectClassifyNameStr=`${level1.ClassifyName}/${level2.ClassifyName}`
+    }
+    if(level3){
+        selectClassifyId=level3.ClassifyId
+        selectClassifyNameStr=`${level1.ClassifyName}/${level2.ClassifyName}/${level3.ClassifyName}`
+    }
+    emits('change',{selectClassifyNameStr,selectClassifyId})
+}
+
+// 设置显示的分类名称(中英文)
+function getClassifyItemName(item){
+    return item.ClassifyName
+}
+
+// 获取分类数据
+const classifyList=ref([])
+async function getEDBClassifyList(){
+    const res=await apiDataEDB.edbClassifyList()
+    if(res.Ret===200){
+        classifyList.value=res.Data.AllNodes||[]
+    }
+}
+getEDBClassifyList()
+
+const openClassify=ref([])//当前展开的分类
+
+// 分类操作数据
+const classifyState=reactive({
+    show:false,
+    title:'',
+    name:'',//输入框中的值
+    placeholderText:'',
+    type:'add',//新增、编辑
+    level:1,//1新增/编辑一级目录,2新增/编辑二级目录
+    level1Text:'',
+    level2Text:'',
+    parentId:0,
+    classifyId:0,
+})
+watch(
+    ()=>classifyState.show,
+    (n)=>{
+        if(!n){
+            classifyState.title=''
+            classifyState.name=''
+            classifyState.placeholderText=''
+            classifyState.type='add'
+            classifyState.level=1
+            classifyState.level1Text=''
+            classifyState.level2Text=''
+            classifyState.parentId=0
+            classifyState.classifyId=0
+        }
+    }
+)
+function handleAddLevel1(){
+    classifyState.title='添加一级目录'
+    classifyState.placeholderText='请输入一级分类名称'
+    classifyState.show=true
+}
+async function handleConfirmClassifyState(){
+    let params={}
+    if(classifyState.type==='add'){
+        params={
+            ClassifyName:classifyState.name,
+            Level:classifyState.level,
+            ParentId:classifyState.parentId
+        }
+    }else{
+        params={
+            ClassifyName:classifyState.name,
+            ClassifyId:classifyState.classifyId
+        }
+    }
+    const res=classifyState.type==='add'?await apiDataEDB.edbClassifyAdd(params):await apiDataEDB.edbClassifyEdit(params)
+    if(res.Ret===200){
+        getEDBClassifyList()
+        classifyState.show=false
+    }
+}
+
+// 显示分类操作按钮数据
+const classifyOptState=reactive({
+    show:false,
+    actions:[],
+    level:1,//点击的是几级
+    level1Data:null,
+    level2Data:null,
+    level3Data:null
+})
+watch(
+    ()=>classifyOptState.show,
+    (n)=>{
+        if(!n){
+            classifyOptState.actions=[]
+            classifyOptState.level=1
+            classifyOptState.level1Data=null
+            classifyOptState.level2Data=null
+            classifyOptState.level3Data=null
+        }
+    }
+)
+// 显示分类的具体操作选项
+function handleShowClassifyOpt(level,level1,level2,level3){
+    const optArr=[
+        {name:'重命名',type:'edit'},
+        {name:'删除',type:'delete',color:"#C54322"}
+    ]
+    if(level===1){
+        // 判断操作权限
+        if(level1.Button.AddButton){//添加权限
+            optArr.unshift({name:'添加二级目录',type:'add'})
+        }
+        if(!level1.Button.OpButton){//编辑权限
+            optArr=optArr.filter(item=>item.type!='edit')
+        }
+        if(!level1.Button.DeleteButton){//删除
+            optArr=optArr.filter(item=>item.type!='delete')
+        }
+    }else if(level===2){
+        // 判断操作权限
+        if(level2.Button.AddButton){//添加权限
+            optArr.unshift({name:'添加三级目录',type:'add'})
+        }
+        if(level2.Button.MoveButton){//移动权限
+            optArr.push({name:'移动至',type:'move'})
+        }
+        if(!level2.Button.OpButton){//编辑权限
+            optArr=optArr.filter(item=>item.type!='edit')
+        }
+        if(!level2.Button.DeleteButton){//删除
+            optArr=optArr.filter(item=>item.type!='delete')
+        }
+    }else if(level===3){
+        // 判断操作权限
+        if(level3.Button.MoveButton){//移动权限
+            optArr.push({name:'移动至',type:'move'})
+        }
+        if(!level3.Button.OpButton){//编辑权限
+            optArr=optArr.filter(item=>item.type!='edit')
+        }
+        if(!level3.Button.DeleteButton){//删除
+            optArr=optArr.filter(item=>item.type!='delete')
+        }
+    }
+    classifyOptState.actions=optArr
+    classifyOptState.level=level
+    classifyOptState.level1Data=level1
+    classifyOptState.level2Data=level2
+    classifyOptState.level3Data=level3
+    classifyOptState.show=true
+}
+function handleSelectOpt(e){
+    if(e.type==='add'){
+        classifyState.title=e.name
+        classifyState.placeholderText='请输入分类名称'
+        classifyState.type='add'
+        classifyState.level1Text=classifyOptState.level1Data?.ClassifyName
+        classifyState.level2Text=classifyOptState.level2Data?.ClassifyName
+        if(classifyOptState.level===1){
+            classifyState.parentId=classifyOptState.level1Data?.ClassifyId
+            classifyState.level=1
+        }
+        if(classifyOptState.level===2){
+            classifyState.parentId=classifyOptState.level2Data?.ClassifyId
+            classifyState.level=2
+        }
+        classifyState.show=true
+    }
+    if(e.type==='edit'){
+        classifyState.title='重命名'
+        classifyState.placeholderText='请输入分类名称'
+        classifyState.type='edit'
+        classifyState.level=classifyOptState.level
+        if(classifyOptState.level===1){
+            classifyState.classifyId=classifyOptState.level1Data?.ClassifyId
+            classifyState.name=classifyOptState.level1Data?.ClassifyName
+        }else if(classifyOptState.level===2){
+            classifyState.level1Text=classifyOptState.level1Data?.ClassifyName
+            classifyState.classifyId=classifyOptState.level2Data?.ClassifyId
+            classifyState.name=classifyOptState.level2Data?.ClassifyName
+        }else if(classifyOptState.level===3){
+            classifyState.level1Text=classifyOptState.level1Data?.ClassifyName
+            classifyState.level2Text=classifyOptState.level2Data?.ClassifyName
+            classifyState.classifyId=classifyOptState.level3Data?.ClassifyId
+            classifyState.name=classifyOptState.level3Data?.ClassifyName
+        }
+        classifyState.show=true
+    }
+    if(e.type==='delete'){
+        let data=null
+        if(classifyOptState.level===1){
+            data=classifyOptState.level1Data
+        }else if(classifyOptState.level===2){
+            data=classifyOptState.level2Data
+        }else if(classifyOptState.level===3){
+            data=classifyOptState.level3Data
+        }
+        edbClassifyDelete(data).then(res=>{
+            console.log(res===true);
+            if(res===true){
+                getEDBClassifyList()
+            }
+        })
+    }
+    if(e.type==='move'){
+        classifyMoveState.selectValue=''
+        classifyMoveState.tabIndex=0
+        if(classifyOptState.level===2){
+            //移动二级
+            classifyMoveState.options=classifyList.value.map(item=>{
+                return {
+                    ...item,
+                    Children:null
+                }
+            })
+            classifyMoveState.classifyId=classifyOptState.level2Data.ClassifyId
+            classifyMoveState.moveLevel=2
+        }
+        if(classifyOptState.level===3){
+            //移动三级
+            classifyMoveState.options=classifyList.value.map(item=>{
+                const children=item.Children.map(_item=>{
+                    return {
+                        ..._item,
+                        Children:null
+                    }
+                })
+                return {
+                    ...item,
+                    Children:children
+                }
+            })
+            classifyMoveState.classifyId=classifyOptState.level3Data.ClassifyId
+            classifyMoveState.moveLevel=3
+        }
+        
+        classifyMoveState.show=true
+    }
+    classifyOptState.show=false
+}
+
+// 移动分类数据
+const classifyMoveState=reactive({
+    show:false,
+    selectValue:'',
+    options:[],
+    classifyId:0,//要移动的分类id
+    tabIndex:0,//当前选择了哪一级的分类
+    moveLevel:2,//要移动的分类是哪级
+})
+function handleSelectMoveClassifyChange({value,selectedOptions,tabIndex}){
+    classifyMoveState.tabIndex=tabIndex
+}
+function handleConfirmMove(){
+    if(!classifyMoveState.selectValue){
+        showToast('请选择要移动至的分类')
+        return
+    }
+    if(classifyMoveState.moveLevel===3&&classifyMoveState.tabIndex!=1){
+        showToast('请选择要移动至的二级分类')
+        return
+    }
+    let NextClassifyId=0
+    if(classifyMoveState.moveLevel===2){
+        const index=classifyMoveState.options.findIndex(e=>e.ClassifyId===classifyMoveState.selectValue)
+        console.log(index);
+        NextClassifyId=classifyList.value[index].Children[0]?.ClassifyId
+    }else if(classifyMoveState.moveLevel===3){
+        let index1=0,index2=0;
+        classifyMoveState.options.forEach((e,idx)=>{
+            e.Children?.forEach((e2,idx2)=>{
+                if(e2.ClassifyId===classifyMoveState.selectValue){
+                    index1=idx
+                    index2=idx2
+                }
+            })
+        })
+        NextClassifyId=classifyList.value[index1].Children[index2].Children[0]?.ClassifyId
+    }
+    // console.log(NextClassifyId);
+    apiDataEDB.edbClassifyMove({
+        ClassifyId:classifyMoveState.classifyId,
+        ParentClassifyId:classifyMoveState.selectValue,
+        PrevClassifyId:0,
+        NextClassifyId:NextClassifyId
+    }).then(res=>{
+        if(res.Ret===200){
+            showToast('移动成功')
+            getEDBClassifyList()
+            classifyMoveState.show=false
+        }
+    })
+}
+</script>
+
+<template>
+    <van-popup 
+        :show="props.modelValue"
+        position="right"
+        closeable
+        :style="{width:width>650?'400px':'100%',height:'100%'}"
+        @click-close-icon="handleClose"
+    >
+        <div class="edb-classify-wrap">
+            <div class="top-box"></div>
+            <div class="classify-box">
+                <van-collapse v-model="openClassify" :border="false">
+                    <van-collapse-item
+                        v-for="level1 in classifyList"
+                        :key="level1.ClassifyId"
+                        :name="level1.ClassifyId"
+                        :is-link="false"
+                        :border="false"
+                    >
+                        <template #title>
+                            <div class="van-ellipsis" @click="handleSelectClassify(level1)">
+                                <van-icon :name="openClassify.includes(level1.ClassifyId)?'arrow-down':'arrow'" style="margin-right:4px"/>
+                                <span>{{getClassifyItemName(level1)}}</span>
+                            </div>
+                        </template>
+                        <template #value>
+                            <img style="width:22px;height:22px" src="@/assets/imgs/dataEDB/icon_opt.png" alt="" @click.stop="handleShowClassifyOpt(1,level1)">
+                        </template>
+                        <div class="level2-box">
+                            <van-collapse-item
+                                v-for="level2 in level1.Children"
+                                :key="level2.ClassifyId"
+                                :name="level2.ClassifyId"
+                                :is-link="false"
+                                :border="false"
+                            >
+                                <template #title>
+                                    <div class="van-ellipsis" @click="handleSelectClassify(level1,level2)">
+                                        <van-icon :name="openClassify.includes(level2.ClassifyId)?'arrow-down':'arrow'" style="margin-right:4px"/>
+                                        <span>{{getClassifyItemName(level2)}}</span>
+                                    </div>
+                                </template>
+                                <template #value>
+                                    <img style="width:22px;height:22px" src="@/assets/imgs/dataEDB/icon_opt.png" alt="" @click.stop="handleShowClassifyOpt(2,level1,level2)">
+                                </template>
+                                <div class="level3-box">
+                                    <van-collapse-item
+                                        v-for="level3 in level2.Children"
+                                        :key="level3.ClassifyId"
+                                        :title="getClassifyItemName(level3)" 
+                                        :name="level3.ClassifyId"
+                                        :is-link="false"
+                                        disabled
+                                        :border="false"
+                                    >
+                                        <template #title>
+                                            <div class="van-ellipsis" @click="handleSelectClassify(level1,level2,level3)">
+                                                <span>{{getClassifyItemName(level3)}}</span>
+                                            </div>
+                                        </template>
+                                        <template #value>
+                                            <img style="width:22px;height:22px" src="@/assets/imgs/dataEDB/icon_opt.png" alt="" @click.stop="handleShowClassifyOpt(3,level1,level2,level3)">
+                                        </template>
+                                    </van-collapse-item>
+                                </div>
+                            </van-collapse-item>
+                        </div>
+                    </van-collapse-item>
+                </van-collapse>
+            </div>
+            <div class="bot-btn-box">
+                <van-button type="primary" block @click="handleAddLevel1">添加一级目录</van-button>
+            </div>
+        </div>
+    </van-popup>
+
+    <!-- 分类操作选项 -->
+    <van-action-sheet
+        v-model:show="classifyOptState.show"
+        :actions="classifyOptState.actions"
+        cancel-text="取消"
+        @select="handleSelectOpt"
+    />
+
+    <!-- 创建/编辑分类 -->
+    <van-dialog 
+        v-model:show="classifyState.show" 
+        :title="classifyState.title" 
+        show-cancel-button
+        @confirm="handleConfirmClassifyState"
+    >
+        <div class="edit-classify-wrap">
+            <p v-if="classifyState.level1Text" style="margin-bottom:8px">一级目录:{{classifyState.level1Text}}</p>
+            <p v-if="classifyState.level2Text" style="margin-bottom:8px">二级目录:{{classifyState.level2Text}}</p>
+            <input class="input-box" type="text" :placeholder="classifyState.placeholderText" v-model="classifyState.name">
+        </div>
+    </van-dialog>
+
+    <van-popup 
+        v-model:show="classifyMoveState.show" 
+        round 
+        position="bottom"
+    >
+        <van-cascader
+            v-model="classifyMoveState.selectValue"
+            title="移动至"
+            :options="classifyMoveState.options"
+            :field-names="{text:'ClassifyName',value:'ClassifyId',children:'Children'}"
+            @close="classifyMoveState.show = false"
+            @change="handleSelectMoveClassifyChange"
+        />
+        <div style="width:300px;margin:0 auto;padding:20px 0">
+            <van-button type="primary" round block @click="handleConfirmMove">确定</van-button>
+        </div>
+    </van-popup>
+</template>
+
+<style lang="scss" scoped>
+.edb-classify-wrap{
+    height: 100%;
+    display: flex;
+    flex-direction: column;
+    .top-box{
+        height: calc(var(--van-popup-close-icon-margin) + 50px);
+        background-color: #fff;
+        flex-shrink: 0;
+    }
+    .classify-box{
+        flex: 1;
+        overflow-y: auto;
+        :deep(.van-cell__title){
+            flex: 2;
+            overflow: hidden;
+            white-space: nowrap;
+            text-overflow: ellipsis;
+            color: #333;
+        }
+        :deep(.van-collapse-item__content){
+            padding-right: 0;
+            padding-top: 0;
+            padding-bottom: 0;
+        }
+    }
+    .bot-btn-box{
+        padding: 48px;
+        flex-shrink: 0;
+    }
+    
+}
+
+.edit-classify-wrap{
+    padding: 32px 48px;
+    .input-box{
+        width: 100%;
+        box-sizing: border-box;
+        display: block;
+        padding: 24px 32px;
+        background-color: #f6f6f6;
+        border-radius: 12px;
+    }
+}
+
+</style>

+ 251 - 0
src/views/dataEDB/components/EditBaseEDB.vue

@@ -0,0 +1,251 @@
+<script setup>
+import {watch,ref, reactive, computed} from 'vue'
+import apiDataEDB from '@/api/dataEDB'
+import {edbFrequencyOpts,edbUnitOpts} from '../util/config'
+import { showToast } from 'vant'
+
+const props=defineProps({
+    modelValue:{
+        type:Boolean,
+        default:false
+    },
+    edbInfoId:{
+        type:Number,
+        default:0
+    },//当前指标id
+})
+const emits=defineEmits(['update:modelValue','success'])
+
+const edbNameInputFocus=ref(false)//指标名称输入框聚焦状态
+
+const formState=reactive({
+    name:'',
+    classify:'',
+    frequency:'',
+    unit:''
+})
+// 获取指标详情
+async function getEDBInfo(){
+    const res=await apiDataEDB.getBaseEdbInfo({EdbInfoId:props.edbInfoId})
+    if(res.Ret===200){
+        formState.name=res.Data.EdbName
+        formState.classify=res.Data.ClassifyId
+        formState.frequency=res.Data.Frequency
+        formState.unit=res.Data.Unit
+
+        getEdbClassifyList()
+    }
+}
+watch(
+    ()=>props.modelValue,
+    ()=>{
+        props.modelValue && getEDBInfo()
+    }
+)
+
+function handleClose(){
+    emits('update:modelValue',false)
+}
+
+// 获取指标库分类
+const edbClassifyList=ref([])
+function getEdbClassifyList(){
+    apiDataEDB.edbClassifyList().then(res=>{
+        if(res.Ret===200){
+            edbClassifyList.value=res.Data.AllNodes||[]
+        }
+    })
+}
+const showSelectClassify=ref(false)
+const selectClassifyNameStr=computed(()=>{
+    if(!formState.classify) return ''
+    let str=''
+    edbClassifyList.value.forEach(level1=>{
+        level1.Children?.forEach(level2=>{
+            level2.Children?.forEach(level3=>{
+                if(level3.ClassifyId===formState.classify){
+                    str=`${level1.ClassifyName}/${level2.ClassifyName}/${level3.ClassifyName}`
+                }
+            })
+        })
+    })
+    return str
+
+})
+
+// 选择频率
+const showSelectFrequency=ref(false)
+const frequencyOpts=edbFrequencyOpts.map(item=>{
+    return {
+        text:item,
+        value:item
+    }
+})
+function onConfirmSelectFrequency(e){
+    formState.frequency=e.selectedValues[0]
+    showSelectFrequency.value=false
+}
+
+// 选择单位
+const showSelectUnit=ref(false)
+const unitOpts=edbUnitOpts.map(item=>{return{text:item,value:item}})
+function onConfirmSelectUnit(e){
+    formState.unit=e.selectedValues[0]
+    showSelectUnit.value=false
+}
+
+// 保存编辑
+async function handleSave(){
+    const params={
+        EdbInfoId:props.edbInfoId,
+        ClassifyId:formState.classify,
+        EdbName:formState.name,
+        Frequency:formState.frequency,
+        Unit:formState.unit
+    }
+    if(!params.EdbName){
+        showToast('指标名称不能为空')
+        return
+    }
+    if(!params.ClassifyId){
+        showToast('目录名称不能为空')
+        return
+    }
+    if(!params.Frequency){
+        showToast('频率不能为空')
+        return
+    }
+    if(!params.Unit){
+        showToast('单位不能为空')
+        return
+    }
+    const res=await apiDataEDB.editBaseEdbInfo(params)
+    if(res.Ret===200){
+        showToast(res.Msg)
+        emits('update:modelValue')
+        emits('success',params)
+    }
+}
+
+</script>
+
+<template>
+    <van-popup 
+        :show="props.modelValue"
+        position="bottom"
+        style="width:100%;height:100%"
+    >
+        <div class="edit-baseEDB-wrap">
+            <van-field 
+                v-model="formState.name" 
+                label="指标名称" 
+                placeholder="指标名称"
+                input-align="right"
+                @focus="edbNameInputFocus=true"
+                @blur="edbNameInputFocus=false"
+            >
+                <template #right-icon>
+                    <svg class="edit-icon" xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 48 48" fill="none">
+                        <path d="M23.4 13.2L34.8 24.6L19.4 40H8V28.6L23.4 13.2ZM23.4 19L12 30.4V36H17.6L29 24.6L23.4 19ZM28.8 8L40 19.4L36.6 22.8L25.2 11.4L28.8 8Z" :fill="edbNameInputFocus?'#0052D9':'#333333'"/>
+                    </svg>
+                </template>
+            </van-field>
+            <van-field 
+                :modelValue="selectClassifyNameStr"
+                readonly
+                label="所属目录" 
+                placeholder="请选择所属目录"
+                input-align="right"
+                right-icon="arrow"
+                @click-input="showSelectClassify=true"
+            />
+            <van-field 
+                :modelValue="formState.frequency"
+                readonly
+                label="频率" 
+                placeholder="请选择频率"
+                input-align="right"
+                right-icon="arrow"
+                @click-input="showSelectFrequency=true"
+            />
+            <van-field 
+                :modelValue="formState.unit"
+                readonly
+                label="单位" 
+                placeholder="请选择单位"
+                input-align="right"
+                right-icon="arrow"
+                @click-input="showSelectUnit=true"
+            />
+
+            <div class="btn-box">
+                <van-button @click="handleClose">取消</van-button>
+                <van-button type="primary" @click="handleSave">保存</van-button>
+            </div>
+            
+        </div>
+    </van-popup>
+
+    <!-- 选择分类 -->
+    <van-popup 
+        v-model:show="showSelectClassify" 
+        round 
+        position="bottom"
+    >
+        <van-cascader
+            v-model="formState.classify"
+            title="选择目录"
+            :options="edbClassifyList"
+            :field-names="{text:'ClassifyName',value:'ClassifyId',children:'Children'}"
+            @close="showSelectClassify = false"
+        />
+    </van-popup>
+
+    <!-- 选择频率 -->
+    <van-popup 
+        v-model:show="showSelectFrequency" 
+        round 
+        position="bottom"
+    >
+        <van-picker
+            title="请选择频率"
+            :columns="frequencyOpts"
+            @cancel="showSelectFrequency=false"
+            @confirm="onConfirmSelectFrequency"
+        />
+    </van-popup>
+
+    <!-- 选择单位 -->
+    <van-popup 
+        v-model:show="showSelectUnit" 
+        round 
+        position="bottom"
+    >
+        <van-picker
+            title="选择单位"
+            :columns="unitOpts"
+            @cancel="showSelectUnit=false"
+            @confirm="onConfirmSelectUnit"
+        />
+    </van-popup>
+</template>
+
+<style lang="scss" scoped>
+.edit-baseEDB-wrap{
+    .edit-icon{
+        width: 48px;
+        height: 48px;
+    }
+    :deep(.van-field__right-icon){
+        width: 60px;
+    }
+    .btn-box{
+        margin-top: 50PX;
+        text-align: center;
+        .van-button{
+            width: 150PX;
+            margin: 0 10PX;
+        }
+    }
+}
+</style>

+ 63 - 0
src/views/dataEDB/hooks/useEDBDelete.js

@@ -0,0 +1,63 @@
+// 目录或者指标的删除
+import apiDataEDB from '@/api/dataEDB'
+import { showDialog , showToast } from 'vant';
+
+
+export function useEDBDelete(){
+    // 删除分类
+    async function handleClassifyDelete(data){
+        const res=await apiDataEDB.edbClassifyDelete({
+            ClassifyId:data.ClassifyId,
+            EdbInfoId:data.EdbInfoId
+        })
+        if(res.Ret===200){
+            showToast('删除成功')
+            return true
+        }
+    }
+
+    async function edbClassifyDelete(data){
+        const res=await apiDataEDB.edbClassifyDeleteCheck({
+            ClassifyId:data.ClassifyId,
+            EdbInfoId:data.EdbInfoId
+        })
+        if(res.Ret===200){
+            if([1,3,4].includes(res.Data.DeleteStatus)){
+                let message=res.Data.TipsMsg
+                if(res.Data.DeleteStatus === 1) message='该目录关联指标不可删除'
+                if(res.Data.DeleteStatus === 3) message='当前指标已用作画图,不可删除'
+                showDialog({
+                    title: '删除失败',
+                    message: message,
+                    confirmButtonText:'知道了'
+                })
+                
+            }else if(res.Data.DeleteStatus === 0 && !data.EdbCode){
+                await showDialog({
+                    title: '提示',
+                    message: '确定删除当前目录吗?',
+                    showCancelButton:true,
+                })
+                return  handleClassifyDelete(data)
+            }else if(res.Data.DeleteStatus === 0 && data.EdbCode){
+                await showDialog({
+                    title: '提示',
+                    message: '删除后指标和指标值均不可使用,确认删除吗?',
+                    showCancelButton:true,
+                })
+                return handleClassifyDelete(data)
+            }else if(res.Data.DeleteStatus === 2){
+                await showDialog({
+                    title: '提示',
+                    message: '确认删除当前目录及包含的子目录吗?',
+                    showCancelButton:true,
+                })
+                return handleClassifyDelete(data)
+            }
+        }
+    }
+
+    return {
+        edbClassifyDelete
+    }
+}

+ 20 - 0
src/views/dataEDB/util/config.js

@@ -0,0 +1,20 @@
+//指标频率配置项
+export const edbFrequencyOpts=['日度','周度','旬度','月度','季度','年度']
+
+// 指标单位配置项
+export const edbUnitOpts=[
+    '无',
+    '万吨',
+    '亿元',
+    '元',
+    '元/吨',
+    '元/湿吨',
+    '千克',
+    '吨',
+    '短吨',
+    '美元/吨',
+    '万平方米',
+    '美元/桶',
+    '美分/加仑',
+    '手'
+]

+ 167 - 61
src/views/tabbar/Home.vue

@@ -1,9 +1,10 @@
 <script setup>
 <script setup>
-import {ref} from 'vue'
+import {ref,computed} from 'vue'
 import { useRouter } from "vue-router";
 import { useRouter } from "vue-router";
 import {apiMenuList} from '@/api/user'
 import {apiMenuList} from '@/api/user'
 import {getStaticImg} from '@/hooks/common'
 import {getStaticImg} from '@/hooks/common'
 import {useCachedViewsStore} from '@/store/modules/cachedViews'
 import {useCachedViewsStore} from '@/store/modules/cachedViews'
+import { showToast } from 'vant';
 
 
 const cachedViewsStore=useCachedViewsStore()
 const cachedViewsStore=useCachedViewsStore()
 cachedViewsStore.removeCaches(-1)
 cachedViewsStore.removeCaches(-1)
@@ -11,6 +12,10 @@ cachedViewsStore.removeCaches(-1)
 const router=useRouter()
 const router=useRouter()
 
 
 function goNext(path){
 function goNext(path){
+    if(!path){
+        showToast('功能开发中,敬请期待!')
+        return
+    }
     const routerEl=router.resolve({path})
     const routerEl=router.resolve({path})
     window.open(routerEl.href,'_blank')
     window.open(routerEl.href,'_blank')
 }
 }
@@ -19,94 +24,169 @@ if(!localStorage.getItem('token')){
     router.replace('/login')
     router.replace('/login')
 }
 }
 
 
+const language_version=ref('zh')//语言版本 zh en 
+function languageVersionChange(){
+    if(language_version.value==='zh'){
+        language_version.value='en'
+    }else{
+        language_version.value='zh'
+    }
+}
 /**
 /**
  * name 显示的名称
  * name 显示的名称
  * key 对应接口中的 name
  * key 对应接口中的 name
  * level 说明该菜单在数据中的第几级查找
  * level 说明该菜单在数据中的第几级查找
+ * type 类型 zh中文 en英文
  */
  */
 const menuConfig=[
 const menuConfig=[
     {
     {
         name:'中文研报',
         name:'中文研报',
+        des:'研报一体化管理',
         key:'研报列表',
         key:'研报列表',
+        type:'zh',
         level:2,
         level:2,
         path:'/report/list',
         path:'/report/list',
-        icon:getStaticImg('report/report_icon.png'),
+        icon:getStaticImg('tabbar/icon_report.png'),
+        backgroundColor:'#FFFBF6',
         show:false
         show:false
     },
     },
     {
     {
-        name:'英文研报',
+        name:'English Research Report',
+        des:'Integrated Research Report Management',
         key:'英文研报',
         key:'英文研报',
+        type:'en',
         level:2,
         level:2,
         path:'/reportEn/list',
         path:'/reportEn/list',
-        icon:getStaticImg('report/report_icon_en.png'),
+        icon:getStaticImg('tabbar/icon_report.png'),
+        backgroundColor:'#FFFBF6',
         show:false
         show:false
     },
     },
     {
     {
         name:'智能PPT',
         name:'智能PPT',
+        des:"支持共享协作编辑",
         key:'智能ppt',
         key:'智能ppt',
+        type:'zh',
         level:1,
         level:1,
         path:'/ppt/index',
         path:'/ppt/index',
-        icon:getStaticImg('ppt/ppt_icon_zh.png'),
+        icon:getStaticImg('tabbar/icon_PPT.png'),
+        backgroundColor:'#FFF5F3',
         show:false
         show:false
     },
     },
     {
     {
-        name:'英文PPT',
+        name:'PPT in English',
+        des:'Support for collaborative editing',
         key:'英文ppt',
         key:'英文ppt',
+        type:'en',
         level:1,
         level:1,
         path:'/ppten/index',
         path:'/ppten/index',
-        icon:getStaticImg('ppt/ppt_icon_en.png'),
+        icon:getStaticImg('tabbar/icon_PPT.png'),
+        backgroundColor:'#FFF5F3',
         show:false
         show:false
     },
     },
     {
     {
-        name:'My ETA',
-        key:'My ETA',
+        name:'数据源',
+        des:'数据对接与整合',
+        key:'数据源',
+        type:'zh',
         level:1,
         level:1,
-        path:'/myETA/index',
-        icon:getStaticImg('myETA/icon_myETA_logo.png'),
+        path:'',
+        icon:getStaticImg('tabbar/icon_dataSource.png'),
+        backgroundColor:'#F8F9FF',
+        show:false
+    },
+    {
+        name:'指标库',
+        des:'数据归类与分析',
+        key:'ETA指标库',
+        type:'zh',
+        level:1,
+        path:'/dataEDB/index',
+        icon:getStaticImg('tabbar/icon_EDB.png'),
+        backgroundColor:'#F5FAFF',
+        show:false
+    },
+    {
+        name:'预测指标',
+        des:'模型预测趋势',
+        key:'ETA预测指标',
+        type:'zh',
+        level:1,
+        path:'',
+        icon:getStaticImg('tabbar/icon_preEDB.png'),
+        backgroundColor:'#FFF5F3',
         show:false
         show:false
     },
     },
     {
     {
         name:'ETA图库',
         name:'ETA图库',
+        des:'数据可视化平台',
         key:'ETA图库',
         key:'ETA图库',
+        type:'zh',
         level:1,
         level:1,
         path:'/chartETA/list',
         path:'/chartETA/list',
-        icon:getStaticImg('chartETA/icon_chartETA_logo.png'),
+        icon:getStaticImg('tabbar/icon_chart.png'),
+        backgroundColor:'#F8F9FF',
         show:false
         show:false
-    }
+    },
+    {
+        name:'My ETA',
+        des:'图表收藏',
+        key:'My ETA',
+        type:'zh',
+        level:1,
+        path:'/myETA/index',
+        icon:getStaticImg('tabbar/icon_myChart.png'),
+        backgroundColor:'#F5FAFF',
+        show:false
+    },
+    {
+        name:'ETA表格',
+        des:'快速建立平衡表',
+        key:'ETA表格',
+        type:'zh',
+        level:1,
+        path:'',
+        icon:getStaticImg('tabbar/icon_table.png'),
+        backgroundColor:'#FFFBF6',
+        show:false
+    },
 ]
 ]
-const menuOpts=ref([])
+const menuOpts=computed(()=>{
+    // 过滤中英文
+    let arr=menuConfig.filter(item=>item.type===language_version.value)
+    
+    // 根据菜单数据权限过滤
+    arr.forEach(item=>{
+        if(item.level===1){
+            resMenuList.value.forEach(f=>{
+                if(f.name.trim()===item.key){
+                    item.show=true
+                }
+            })
+        }
+        if(item.level===2){
+            resMenuList.value.forEach(f=>{
+                f.children.forEach(s=>{
+                    if(s.name.trim()===item.key){
+                        item.show=true
+                    }
+                })
+            })
+        }
+    })
+
+    arr=arr.filter(item=>item.show)
+    return arr||[]
+})
 
 
 // 获取菜单权限数据
 // 获取菜单权限数据
+const resMenuList=ref([])
 async function getMenuList(){
 async function getMenuList(){
     menuConfig.forEach(item=>{
     menuConfig.forEach(item=>{
         item.show=false
         item.show=false
     })
     })
     const res=await apiMenuList()
     const res=await apiMenuList()
     if(res.Ret===200){
     if(res.Ret===200){
-        if(res.Data.List){
-            const arr=res.Data.List
-            menuConfig.forEach(item=>{
-                if(item.level===1){
-                    arr.forEach(f=>{
-                        if(f.name.trim()===item.key){
-                            item.show=true
-                        }
-                    })
-                }
-                if(item.level===2){
-                    arr.forEach(f=>{
-                        f.children.forEach(s=>{
-                            if(s.name.trim()===item.key){
-                                item.show=true
-                            }
-                        })
-                    })
-                }
-            })
-            menuOpts.value=menuConfig.filter(item=>item.show)
-        }else{
-            menuOpts.value=[]
-        }
+        resMenuList.value=res.Data.List||[]
     }
     }
 }
 }
 getMenuList()
 getMenuList()
@@ -115,23 +195,27 @@ getMenuList()
 
 
 <template>
 <template>
     <div class="home-page">
     <div class="home-page">
+        <img 
+            class="top-img"
+            :src="language_version==='zh'?'https://hzstatic.hzinsights.com/static/ETA_mobile/tabbar_home_topimg_en.png':'https://hzstatic.hzinsights.com/static/ETA_mobile/tabbar_home_topimg_zh.png'" 
+            alt=""
+            @click="languageVersionChange"
+        >
+
         <div class="list">
         <div class="list">
             <div 
             <div 
                 v-for="item in menuOpts"
                 v-for="item in menuOpts"
                 :key="item.name"
                 :key="item.name"
-                class="item-box" 
+                :class="['item-box',item.type==='en'?'item-box_en':'']"
+                :style="{backgroundColor:item.backgroundColor}"
                 @click="goNext(item.path)"
                 @click="goNext(item.path)"
             >
             >
-                <img :src="item.icon" alt="">
-                <div>{{item.name}}</div>
+                <img class="icon" :src="item.icon" alt="">
+                <div class="content">
+                    <div class="name">{{item.name}}</div>
+                    <div class="des">{{item.des}}</div>
+                </div>
             </div>
             </div>
-            
-            <div class="item-box" style="border:none;height:0"></div>
-            <div class="item-box" style="border:none;height:0"></div>
-            <div class="item-box" style="border:none;height:0"></div>
-            <div class="item-box" style="border:none;height:0"></div>
-            <div class="item-box" style="border:none;height:0"></div>
-            <div class="item-box" style="border:none;height:0"></div>
         </div>
         </div>
         
         
     </div>
     </div>
@@ -140,28 +224,50 @@ getMenuList()
 <style lang="scss" scoped>
 <style lang="scss" scoped>
 .home-page{
 .home-page{
     padding: 30px 34px;
     padding: 30px 34px;
+    .top-img{
+        display: block;
+        width: 100%;
+        margin-bottom: 40px;
+    }
     .list{
     .list{
         display: flex;
         display: flex;
-        justify-content: space-between;
+        gap: 20px;
         flex-wrap: wrap;
         flex-wrap: wrap;
         .item-box{
         .item-box{
-            width: 326px;
-            height: 326px;
-            margin-bottom: 20px;
+            width: 331px;
+            min-height: 228px;
+            padding: 40px 20px;
             display: flex;
             display: flex;
-            flex-direction: column;
             justify-content: center;
             justify-content: center;
             align-items: center;
             align-items: center;
-            font-size: 32px;
-            border: 1px solid $border-color;
             border-radius: 32px;
             border-radius: 32px;
-            filter: drop-shadow(3px 4px 12px rgba(0, 0, 0, 0.08));
-            img{
-                width: 140px;
-                height: 140px;
-                margin-bottom: 40px;
+            .icon{
+                width: 90px;
+                height: 90px;
+                margin-right: 12px;
+            }
+            .content{
+                .name{
+                    font-size: 36px;
+                    font-weight: 600;
+                }
+                .des{
+                    font-size: 24px;
+                    color: $font-grey_999;
+                    margin-top: 12px;
+                }
+            }
+        }
+        .item-box_en{
+            flex-direction: column;
+            justify-content: flex-start;
+            align-items: flex-start;
+            .icon{
+                width: 48px;
+                height: 48px;
+                margin-bottom: 12px;
+                margin-right: 0;
             }
             }
-
         }
         }
     }
     }
 }
 }

+ 5 - 5
src/views/tabbar/Index.vue

@@ -79,8 +79,8 @@ function goPage(item){
             align-items: center;
             align-items: center;
             height: 100%;
             height: 100%;
             .icon{
             .icon{
-                width: 40px;
-                height: 40px;
+                width: 48px;
+                height: 48px;
             }
             }
             .text{
             .text{
                 font-size: 20px;
                 font-size: 20px;
@@ -95,9 +95,9 @@ function goPage(item){
         .tabbar-item-con{
         .tabbar-item-con{
             background-color: #F2F3FF;
             background-color: #F2F3FF;
             border-radius: 112px;
             border-radius: 112px;
-            .text{
-                color: $theme-color;
-            }
+            // .text{
+            //     color: $theme-color;
+            // }
         }
         }
     }
     }
 }
 }