li.shaoyi 4 年之前
父节点
当前提交
d5ac5856d9

+ 1 - 1
public/config/app.config.json

@@ -1,3 +1,3 @@
 {
-    "apiUrl": "http://192.168.31.139:8080/cfg?key=test_139"
+    "apiUrl": "http://192.168.31.137:8080/cfg?key=test_137"
 }

+ 0 - 95
src/common/components/countDown/index.vue

@@ -1,95 +0,0 @@
-<template>
-    <div class="countDown">
-        <span class="text" :style="{ backgroundColor: bgColor, color: color }">{{ day }}</span>
-        <span :style="{ color: textColor }">天</span>
-        <span class="text" :style="{ backgroundColor: bgColor, color: color }">{{ hour }}</span>
-        <span :style="{ color: textColor }">时</span>
-        <span class="text" :style="{ backgroundColor: bgColor, color: color }">{{ minute }}</span>
-        <span :style="{ color: textColor }">分</span>
-        <span class="text" :style="{ backgroundColor: bgColor, color: color }">{{ second }}</span>
-        <span :style="{ color: textColor }">秒</span>
-    </div>
-</template>
-
-<script lang="ts">
-    import { defineComponent, ref, reactive, toRaw, watch, watchEffect} from 'vue';
-
-     export default defineComponent({
-        props: {
-            countTime: {
-                default: 10000000,
-            },
-            bgColor: {
-                default: '#000000',
-            },
-            color: {
-                default: '#FFFFFF',
-            },
-            textColor: {
-                default: '#7a8a94',
-            },
-        },
-        setup(props, context) {
-            const day = ref<string>('00');
-            const hour = ref<string>('00');
-            const minute = ref<string>('00');
-            const second = ref<string>('00');
-            const count = ref<number>(0)
-            const interval = ref<any>(null)
-            function start() {
-                 interval.value = setInterval(() => {
-                    count.value =count.value  - 1000;
-                    if (count.value  <= 0) {
-                        second.value = '00';
-                        clearInterval(interval);
-                        timeDown();
-                        return;
-                    }
-                    //天数
-                    day.value = parseInt(count.value / (24 * 60 * 60 * 1000))
-                        .toString()
-                        .padStart(2, 0);
-                    //小时数
-                    hour.value = parseInt((count.value - day.value  * 24 * 60 * 60 * 1000) / (60 * 60 * 1000))
-                        .toString()
-                        .padStart(2, 0);
-                    //分钟数
-                    const n = count.value  % (60 * 60 * 1000);
-                    minute.value = parseInt(n / (60 * 1000))
-                        .toString()
-                        .padStart(2, 0);
-                    //秒数
-                    const n2 = n % (60 * 1000);
-                    second.value = parseInt(n2 / 1000)
-                        .toString()
-                        .padStart(2, 0);
-                }, 1000);
-            }
-            function timeDown() {
-                context.emit('timeDown')
-            }
-            watchEffect(() => {
-
-                props.countTime
-            })
-            watch(props.countTime, (props.countTime, prevCount) => {
-
-            })
-        }
-     })
-</script>
-
-<style lang="scss">
-    .countDown {
-        display: inline-block;
-    }
-    .text {
-        display: inline-block;
-        width: 28px;
-        height: 30px;
-        line-height: 30px;
-        text-align: center;
-        font-size: 16px;
-        border-radius: 3px;
-    }
-</style>

+ 51 - 7
src/common/components/echart/echart-base/setup.ts

@@ -1,4 +1,4 @@
-import { onActivated, onDeactivated, onUnmounted, SetupContext } from "vue";
+import { onActivated, onDeactivated, onUnmounted, SetupContext, onMounted } from "vue";
 import { debounce } from "@/utils/time"
 import { getTheme, ThemeEnum } from '@/common/config/theme';
 import * as echarts from 'echarts'
@@ -14,12 +14,7 @@ const createIframe = (parent: HTMLElement): HTMLIFrameElement => {
     return iframe;
 }
 
-type UseEchart = {
-    setOptions: (options: echarts.EChartsOption[], notMerge?: boolean) => void,
-    showLoading: (loading: boolean) => void,
-}
-
-export function useEchart(el: HTMLElement): UseEchart {
+export function useEchart(el: HTMLElement) {
     const iframe = createIframe(el);
     const echartMap: echarts.ECharts[] = [];
 
@@ -73,14 +68,63 @@ export function useEchart(el: HTMLElement): UseEchart {
         }, 50);
     };
 
+    // 键盘上下左右键控制图表
+    const onKeyup = (e: KeyboardEvent) => {
+        echartMap.forEach((chart) => {
+            const datazoom = chart.getOption().dataZoom as echarts.DataZoomComponentOption[];
+            if (datazoom && datazoom.length) {
+                const start = datazoom[0].start!;
+                const end = datazoom[0].end!;
+                switch (e.key) {
+                    case 'ArrowLeft':
+                        if (start > 0) {
+                            chart.setOption({
+                                dataZoom: [
+                                    {
+                                        start: start - 1,
+                                        end: end - 1,
+                                    }
+                                ]
+                            });
+                        }
+                        break;
+                    case 'ArrowUp':
+                        console.log('上');
+                        break;
+                    case 'ArrowRight':
+                        if (end < 100) {
+                            chart.setOption({
+                                dataZoom: [
+                                    {
+                                        start: start + 1,
+                                        end: end + 1,
+                                    }
+                                ]
+                            });
+                        }
+                        break;
+                    case 'ArrowDown':
+                        console.log('下');
+                        break;
+                    default:
+                        console.log(e);
+                }
+            }
+        });
+    };
+
     const addEventListener = () => {
         // 监听 iframe 变化重置图表尺寸
         iframe.contentWindow?.addEventListener('resize', onresize);
+        // 监听键盘事件
+        document.addEventListener('keyup', onKeyup);
     }
 
     const removeEventListener = () => {
         // 移除 iframe 监听事件
         iframe.contentWindow?.removeEventListener('resize', onresize);
+        // 移除键盘监听事件
+        document.removeEventListener('keyup', onKeyup);
     }
 
     addEventListener();

+ 46 - 60
src/common/components/echart/echart-kline/index.vue

@@ -245,51 +245,56 @@ export default defineComponent({
             }
 
             const diffTime = newTime.valueOf() - lastTime.valueOf(); // 计算时间差
-            // 判断时间差是否大于周期时间
-            if (diffTime > cycleMilliseconds) {
-                lastTime.add(cycleMilliseconds, 'ms');
-                // 添加历史行情
-                source.push({
-                    date: lastTime.format('YYYY-MM-DD HH:mm:ss'),
-                    open: newPrice,
-                    close: newPrice,
-                    lowest: newPrice,
-                    highest: newPrice,
-                    ma5: '-',
-                    ma10: '-',
-                    ma15: '-',
-                    vol: 0,
-                    macd: '-',
-                    dif: '-',
-                    dea: '-',
-                    k: '-',
-                    d: '-',
-                    j: '-',
-                    cci: '-',
-                });
-                historyIndexs.push(lastIndex + 1); // 添加历史行情索引
+
+            if (diffTime > cycleMilliseconds * 2) {
+                // 时间间隔超过两个周期,重新请求历史数据
             } else {
-                const lastData = source[lastIndex];
-                if (lastData.lowest > newPrice) {
-                    lastData.lowest = newPrice; //更新最低价
-                }
-                if (lastData.highest < newPrice) {
-                    lastData.highest = newPrice; //更新最高价
+                // 判断时间差是否大于周期时间
+                if (diffTime > cycleMilliseconds) {
+                    lastTime.add(cycleMilliseconds, 'ms');
+                    // 添加历史行情
+                    source.push({
+                        date: lastTime.format('YYYY-MM-DD HH:mm:ss'),
+                        open: newPrice,
+                        close: newPrice,
+                        lowest: newPrice,
+                        highest: newPrice,
+                        ma5: '-',
+                        ma10: '-',
+                        ma15: '-',
+                        vol: 0,
+                        macd: '-',
+                        dif: '-',
+                        dea: '-',
+                        k: '-',
+                        d: '-',
+                        j: '-',
+                        cci: '-',
+                    });
+                    historyIndexs.push(lastIndex + 1); // 添加历史行情索引
+                } else {
+                    const lastData = source[lastIndex];
+                    if (lastData.lowest > newPrice) {
+                        lastData.lowest = newPrice; //更新最低价
+                    }
+                    if (lastData.highest < newPrice) {
+                        lastData.highest = newPrice; //更新最高价
+                    }
+                    lastData.close = newPrice; //更新收盘价
                 }
-                lastData.close = newPrice; //更新收盘价
-            }
 
-            calcMA('ma5', 5);
-            calcMA('ma10', 10);
-            calcMA('ma15', 15);
-            calcMACD();
-            calcKDJ();
-            clacCCI();
+                calcMA('ma5', 5);
+                calcMA('ma10', 10);
+                calcMA('ma15', 15);
+                calcMACD();
+                calcKDJ();
+                clacCCI();
 
-            // 延迟图表更新,减少卡顿
-            debounce(() => {
-                updateOptions(props.seriesType);
-            }, 1000);
+                // 延迟图表更新,减少卡顿
+                debounce(() => {
+                    updateOptions(props.seriesType);
+                }, 1000);
+            }
         };
 
         // 监听行情最新价推送
@@ -335,25 +340,6 @@ export default defineComponent({
             });
         });
 
-        // document.onkeydown = (e) => {
-        //     switch (e.key) {
-        //         case '37':
-        //             console.log('左');
-        //             break;
-        //         case '38':
-        //             console.log('上');
-        //             break;
-        //         case '39':
-        //             console.log('右');
-        //             break;
-        //         case '40':
-        //             console.log('下');
-        //             break;
-        //         default:
-        //             console.log(e.key);
-        //     }
-        // };
-
         return {
             loading,
             isEmpty,

+ 5 - 2
src/common/components/echart/echart-timeline/setup.ts

@@ -55,7 +55,11 @@ export function handleEchart() {
 
     // 计算涨跌幅百分比,涨跌幅=(今日收盘价-昨日收盘价)/昨日收盘价*100%
     const calcRatio = (val: number) => {
-        const result = (Number(val) - chartData.value.yestclose) / chartData.value.yestclose * 100;
+        const num = Number(val);
+        if (isNaN(num)) {
+            return "-";
+        }
+        const result = (num - chartData.value.yestclose) / chartData.value.yestclose * 100;
         return toDecimalFull(result) + '%';
     }
 
@@ -123,7 +127,6 @@ export function handleEchart() {
                 axisLabel: {
                     showMinLabel: true,
                     showMaxLabel: true,
-                    interval: 50,
                 }
             },
             yAxis: [

+ 91 - 0
src/router/dynamic.ts

@@ -0,0 +1,91 @@
+import { RouteRecordRaw } from 'vue-router'
+import router from '@/router'
+import { OperationTabMenu } from '@/services/go/commonService/interface';
+import APP from '@/services';
+
+interface OperationMenu {
+    title: string,
+    code: string,
+    path: string,
+    component: string,
+    sort: number,
+    requireAuth: boolean,
+    isshow: boolean,
+    url?: string,
+    remark?: string,
+    children?: OperationMenu[],
+    auth?: {
+        label: string,
+        code: string,
+        requireAuth: boolean,
+        isshow: boolean,
+        remark?: string,
+    }[]
+}
+
+/**
+ * 添加404页面
+ */
+const addNotFound = () => {
+    router.addRoute({
+        path: '/:pathMatch(.*)*',
+        name: '404',
+        component: () => import('@/views/error-page/404.vue'),
+    })
+}
+
+/**
+ * 动态添加路由
+ */
+const addRoutes = (routes: OperationMenu[], parentName = ""): void => {
+    routes.forEach((item) => {
+        if (item.path && item.isshow && !item.url) {
+            let component;
+            switch (item.component) {
+                case 'Layout':
+                    component = () => import('@/layout/index.vue');
+                    break;
+                case 'Main':
+                    component = () => import('@/layout/components/main.vue');
+                    break;
+                default:
+                    const componentString = item.component.replace(/^\/+/, ''); // 过滤字符串前面所有 '/' 字符
+                    const componentPath = componentString.replace(/\.\w+$/, ''); // 过滤后缀名,为了让 import 加入 .vue ,不然会有警告提示...
+                    component = () => import('@/' + componentPath + '.vue');
+            }
+
+            const route: RouteRecordRaw = {
+                path: item.path,
+                name: item.code,
+                component,
+                meta: {
+                    title: item.title,
+                    auth: item.auth ?? [],
+                    remark: item.remark,
+                },
+            }
+
+            parentName ? router.addRoute(parentName, route) : router.addRoute(route);
+
+            if (item.children && item.children.length) {
+                addRoutes(item.children, item.code);
+            }
+        }
+    })
+};
+
+/**
+ * 注册路由
+ */
+export const registerRoutes = (): Promise<boolean> => {
+    const routerMap: OperationMenu[] = APP.get('menus');
+    return new Promise((resolve, reject) => {
+        addNotFound();
+        if (routerMap.length) {
+            addRoutes(routerMap);
+            resolve(true);
+        } else {
+            reject(false);
+        }
+    })
+}

+ 17 - 7
src/router/index.ts

@@ -8,6 +8,7 @@ import { isLogin, login } from '@/services/bus/login';
 import { localStorageUtil } from '@/utils/storage';
 import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router';
 import eventBus from '../utils/eventBus';
+import { registerRoutes } from './dynamic';
 
 const routes: Array<RouteRecordRaw> = [
     {
@@ -2020,12 +2021,6 @@ const routes: Array<RouteRecordRaw> = [
         name: 'test',
         component: () => import('@/views/test/index.vue'),
     },
-    {
-        // VueRouter 匹配规则是从上往下 建议把*放最后
-        path: '/:pathMatch(.*)*',
-        name: '404',
-        component: () => import('@/views/error-page/404.vue'),
-    },
 ];
 
 const router = createRouter({
@@ -2033,17 +2028,32 @@ const router = createRouter({
     routes,
 });
 
+// 防止加载动态路由无限死循环
+let routerComplete = false;
+
 // 路由拦截
 router.beforeEach((to, from, next) => {
     // 前往登录页时 直接走登出流程
     if (to.fullPath === '/login') {
+        routerComplete = false;
         eventBus.$emit('logout');
         next();
     } else {
         // 前往其他页 判断是否是登录状态
         if (isLogin()) {
-            return next();
+            if (routerComplete) {
+                return next();
+            } else {
+                // 注册动态路由
+                registerRoutes().then(() => {
+                    routerComplete = true;
+                    next({ ...to, replace: true });
+                }).catch(() => {
+                    // 404?
+                })
+            }
         } else {
+            routerComplete = false;
             if (!getLoadIsComplete()) { // 没有加载对应的资料,表示第一次启动项目
                 console.log('to', to);
                 const { ACCOUNT, PASSWORD } = to.query

+ 1 - 2
src/services/go/commonService/index.ts

@@ -96,10 +96,9 @@ export function GetPCMenus(): Promise<string> {
     const obj = isOemByEnum(OemType.pingan) ? { name: getOem() } : {}
     const param = {
         loginID: geLoginID_number(),
-        clientType: 0, // 终端类型,0:PC 1:Mobile
     };
     Object.assign(param, obj)
-    return commonSearch_go('/Common/GetClientMenus', param)
+    return commonSearch_go('/Common/GetPCWebMenus', param)
         .then((res) => {
             APP.set('menus', res);
             console.log('交易端菜单', res);

+ 117 - 3
src/services/go/ermcp/goodsInfo/index.ts

@@ -11,7 +11,8 @@ import {
     ErmcpDeliveryGoodsDetailEx,
     ErmcpDeliveryGoodsReq,
     ErmcpDeliveryGoodsRsp, ErmcpMiddleGoodsChangeLog, ErmcpMiddleGoodsModel,
-    Goods
+    Goods,
+    Ermcp3MiddleGoodsDetail2
 } from './interface';
 
 /**
@@ -59,8 +60,121 @@ export function QueryGoodsbrand(): Promise<Ermcp3Brand[]> {
  */
 export function QueryDeliveryGoodsDetail(): Promise<ErmcpDeliveryGoodsDetailEx[]> {
     return commonSearch_go('/Ermcp3/QueryDeliveryGoodsDetail', { userid: getUserId(), usertype: getUserAccountType() }).then(res => {
-        APP.set('DeliveryGoodsList', res)
-        return res
+        const result: ErmcpDeliveryGoodsDetailEx[] = [];
+        // 新接口数据结构转化
+        res.forEach((item: any) => {
+            const data = {
+                agreeunit: item.unitid,
+                areauserid: item.areauserid,
+                auditflag: 0, // 作废
+                categoryid: 0, //作废
+                deliverygoodscode: item.deliverygoodscode,
+                deliverygoodsid: item.deliverygoodsid,
+                deliverygoodsname: item.deliverygoodsname,
+                deliverygoodstype: 0, // 作废
+                dgstatus: item.dgstatus,
+                enumdicname: '', // 作废
+                goodsunitid: 0, // 作废
+                isvalid: item.isvalid,
+                qtydecimalplace: 0, // 作废
+                remark: item.remark,
+                standardqty: 0, // 作废
+                standardqtyrange: 0, // 作废
+            }
+
+            const gblist = item.bdlst.map((e: any) => {
+                return {
+                    areauserid: 0, //作废
+                    brandid: e.brandid,
+                    brandname: e.brandname,
+                    deliverygoodsid: 0, //作废
+                }
+            })
+
+            const gmlist = item.wdlst.map((e: any) => {
+                return {
+                    areauserid: 0, //作废
+                    convertfactor: 0, //作废
+                    createtime: '', //作废
+                    creatorid: 0, //作废
+                    deliverygoodsid: e.deliverygoodsid,
+                    enumdicname: e.enumdicname,
+                    isvalid: 0, //作废
+                    minivalue: 0, //作废
+                    minivaluedp: 0, //作废
+                    realminivalue: 0, //作废
+                    realminivaluedp: 0,
+                    remark: '', //作废
+                    unitid: e.unitid,
+                    updatetime: '', //作废
+                    wrstandardcode: e.wrstandardcode,
+                    wrstandardid: e.wrstandardid,
+                    wrstandardname: e.wrstandardname,
+                    //vatrate: e.vatrate // 新增-增值税率
+                }
+            })
+
+            const mgList: Ermcp3MiddleGoodsDetail2[] = [];
+            item.wdlst.forEach((e: any) => {
+                e.mglst.forEach((v: any) => {
+                    mgList.push({
+                        convertratio: v.convertratio,
+                        gplist: v.GPLST.map((t: any) => {
+                            return {
+                                convertratio: t.convertratio,
+                                enumdicname: t.enumdicname,
+                                exexchangecode: t.exexchangecode,
+                                glist: t.GDLST.map((m: any) => {
+                                    return {
+                                        agreeunit: m.agreeunit,
+                                        enumdicname: m.enumdicname,
+                                        exexchangecode: '', // 作废
+                                        goodscode: m.goodscode,
+                                        goodsid: m.goodsid,
+                                        goodsname: m.goodsname,
+                                    }
+                                }),
+                                goodsgroupid: t.goodsgroupid,
+                                goodsgroupname: t.goodsgroupname,
+                                goodsunitid: t.goodunitid,
+                                middlegoodsid: 0, //作废
+                            }
+                        }),
+                        mg: {
+                            areauserid: 0, //作废
+                            createtime: '', //作废
+                            enumdicname: v.enumdicname, //作废
+                            evaluateratio: 0, //作废
+                            goodsgroupid: 0, //作废
+                            goodsunitid: 0, //作废
+                            isvalid: 0, //作废
+                            middlegoodscode: v.middlegoodscode, //作废
+                            middlegoodsid: v.middlegoodsid, //作废
+                            middlegoodsname: v.middlegoodsname, //作废
+                            modifytime: '', //作废
+                            needhedgeratio: 0, //作废
+                            qtydecimalplace: 0, //作废
+                            relatedgoodsid: 0, //作废
+                            relatedgoodstype: 0, //作废
+                            remark: '', //作废
+                            //costratio:v.costratio, // 新增-成本权重
+                            //deliverygoodsid:v.deliverygoodsid, // 新增-现货商品id
+                            //unitid:v.unitid // 新增-单位id
+                        },
+                    })
+                });
+            });
+
+            result.push({
+                data,
+                gblist,
+                gmlist,
+                mgList,
+            })
+        });
+
+        APP.set('DeliveryGoodsList', result)
+        return result
     }).catch((err) => {
         throw new Error(`查询现货商品详情: ${err}`);
     });

+ 28 - 37
src/views/information/custom/list/checkpending/index.vue

@@ -1,42 +1,33 @@
 <template>
-  <!-- 客户信息: 正常 -->
-  <div class="custom_info_checkpending"
-       :loading="loading">
-    <filterCustomTable @search="updateColumn">
-      <BtnList :btnList="commonBtn" />
-    </filterCustomTable>
-    <contextMenu :contextMenuList="forDataBtn">
-      <a-table :columns="columns"
-               class="srcollYTable"
-               :scroll="{ x: '100%', y: 'calc(100vh - 163px)' }"
-               :pagination="false"
-               :expandedRowKeys="expandedRowKeys"
-               :customRow="Rowclick"
-               rowKey="key"
-               :data-source="tableList">
-        <!-- 额外的展开行 -->
-        <template #expandedRowRender="{  }">
-          <BtnList :btnList="forDataBtn" />
-        </template>
-        <template #userinfotype="{ text }">
-          <a>{{ text === 2 ? '企业' : '个人' }}</a>
-        </template>
-        <!-- 客户名称 -->
-        <template #customername="{ record }">
-          <a>{{ record.userinfotype === 2 ? record.customername :  record.username }}</a>
-        </template>
+    <!-- 客户信息: 正常 -->
+    <div class="custom_info_checkpending" :loading="loading">
+        <filterCustomTable @search="updateColumn">
+            <BtnList :btnList="commonBtn" />
+        </filterCustomTable>
+        <contextMenu :contextMenuList="forDataBtn">
+            <a-table :columns="columns" class="srcollYTable" :scroll="{ x: '100%', y: 'calc(100vh - 163px)' }" :pagination="false" :expandedRowKeys="expandedRowKeys" :customRow="Rowclick" rowKey="key" :data-source="tableList">
+                <!-- 额外的展开行 -->
+                <template #expandedRowRender="{}">
+                    <BtnList :btnList="forDataBtn" />
+                </template>
+                <template #userinfotype="{ text }">
+                    <a>{{ text === 2 ? '企业' : '个人' }}</a>
+                </template>
+                <!-- 客户名称 -->
+                <template #customername="{ record }">
+                    <a>{{ record.userinfotype === 2 ? record.customername : record.username }}</a>
+                </template>
 
-        <template #status="{ text }">
-          <a>{{ getStatusName(text) }}</a>
-        </template>
-        <template #cardtype="{ text }">
-          <a>{{ getCardTypeEnumItemName(text) }}</a>
-        </template>
-      </a-table>
-    </contextMenu>
-    <Middle :selectedRow="selectedRow"
-            @refresh="queryTable" />
-  </div>
+                <template #status="{ text }">
+                    <a>{{ getStatusName(text) }}</a>
+                </template>
+                <template #cardtype="{ text }">
+                    <a>{{ getCardTypeEnumItemName(text) }}</a>
+                </template>
+            </a-table>
+        </contextMenu>
+        <Middle :selectedRow="selectedRow" @refresh="queryTable" />
+    </div>
 </template>
 
 <script lang="ts">

+ 25 - 22
src/views/market/spot_trade/components/goods-chart/chart/index.less

@@ -38,28 +38,31 @@
                 margin-left: 20px;
             }
 
-            .ant-radio-button-wrapper {
-                height          : 22px;
-                line-height     : 20px;
-                color           : #7a8a94;
-                border-color    : var(--tab-border-color, #22292c) !important;
-                background-color: transparent;
-
-                &:not(:first-child)::before {
-                    background-color: var(--tab-border-color, #22292c) !important;
-                }
-            }
-
-            .ant-radio-button-wrapper-checked {
-                color           : var(--tab-checked-color, #0866b8);
-                background-color: var(--tab-checked-bgcolor, #0e2f4c);
-
-                &:not(.ant-radio-button-wrapper-disabled)::before {
-                    background-color: var(--tab-border-color, #22292c) !important;
-                }
-
-                &:not(.ant-radio-button-wrapper-disabled):focus-within {
-                    box-shadow: none;
+            display         : inline-block;
+            background-color: transparent;
+            line-height     : normal;
+            border-bottom   : 0;
+            border          : 1px solid var(--tab-border-color, #22292c);
+            border-radius   : 1.02px;
+            border-right    : 0;
+            overflow        : hidden;
+            margin-top      : 0;
+
+            .ant-menu-item {
+                height       : 22px;
+                line-height  : 22px;
+                color        : #7a8a94;
+                border-bottom: 0;
+                border-right : 1px solid var(--tab-border-color, #22292c);
+                margin-top   : 0;
+                top          : 0;
+                padding      : 0 16px;
+
+                &-active,
+                &-selected {
+                    color           : var(--tab-checked-color, #0866b8);
+                    background-color: var(--tab-checked-bgcolor, #0e2f4c);
+                    border-bottom   : 0;
                 }
             }
         }

+ 141 - 167
src/views/market/spot_trade/components/goods-chart/chart/index.vue

@@ -1,167 +1,133 @@
 <template>
-  <!-- 交易图表  -->
-  <div class="chart-container">
-    <div class="chart-content">
-      <div class="chart-content__header">
-        <a-radio-group class="chart-content__tabs"
-                       v-model:value="activeCycleType">
-          <template v-for="item in chartType"
-                    :key="item.type">
-            <a-radio-button :value="item.type">{{ item.name }}</a-radio-button>
-          </template>
-        </a-radio-group>
-        <a-radio-group class="chart-content__tabs"
-                       v-model:value="activeSeriesType"
-                       v-show="activeCycleType !== CycleType.time">
-          <a-radio-button value="MACD">MACD</a-radio-button>
-          <a-radio-button value="VOL">VOL</a-radio-button>
-          <a-radio-button value="KDJ">KDJ</a-radio-button>
-          <a-radio-button value="CCI">CCI</a-radio-button>
-        </a-radio-group>
-      </div>
-      <echart-time class="chart-content__main"
-                   :quote-data="selectedRow"
-                   v-if="activeCycleType === CycleType.time"></echart-time>
-      <echart-kline class="chart-content__main"
-                    :quote-data="selectedRow"
-                    :cycle-type="activeCycleType"
-                    :series-type="activeSeriesType"
-                    v-else></echart-kline>
-      <div class="chart-content__footer"></div>
-    </div>
-    <div class="chart-slider">
-      <div class="chart-slider__button"></div>
-    </div>
-    <div class="chart-tips">
-      <div>
-        <div class="chart-tips__nav">
-          <div class="content content--left">{{ selectedRow.goodscode }}</div>
-          <div class="content content--right">{{ selectedRow.goodsname }}</div>
-        </div>
-        <div class="chart-tips__last">
-          <div
-               :class="['content content--left', handleQuotePriceColor(selectedRow.last, selectedRow.presettle)]">
-            {{ selectedRow.last }}</div>
-          <div class="content content--right">
-            <span
-                  :class="handleQuotePriceColor(selectedRow.last, selectedRow.presettle)">{{ quoteChange(selectedRow) }}</span>
-            <span
-                  :class="handleQuotePriceColor(selectedRow.last, selectedRow.presettle)">{{ quoteAmplitude(selectedRow) }}</span>
-          </div>
+    <!-- 交易图表  -->
+    <div class="chart-container">
+        <div class="chart-content">
+            <div class="chart-content__header">
+                <a-menu class="chart-content__tabs" v-model:selectedKeys="activeCycleName" mode="horizontal" @click="changeCycleType">
+                    <a-menu-item v-for="item in chartType" :key="item.name">{{ item.label }}</a-menu-item>
+                </a-menu>
+                <a-menu class="chart-content__tabs" v-model:selectedKeys="activeSeriesType" mode="horizontal" v-show="activeCycleType !== CycleType.time">
+                    <a-menu-item key="MACD">MACD</a-menu-item>
+                    <a-menu-item key="VOL">VOL</a-menu-item>
+                    <a-menu-item key="KDJ">KDJ</a-menu-item>
+                    <a-menu-item key="CCI">CCI</a-menu-item>
+                </a-menu>
+            </div>
+            <echart-time class="chart-content__main" :quote-data="selectedRow" v-if="activeCycleType === CycleType.time"></echart-time>
+            <echart-kline class="chart-content__main" :quote-data="selectedRow" :cycle-type="activeCycleType" :series-type="activeSeriesType[0]" v-else></echart-kline>
+            <div class="chart-content__footer"></div>
         </div>
-        <div class="chart-tips__volume">
-          <a-row>
-            <a-col :span="8">卖一</a-col>
-            <a-col :class="handleQuotePriceColor(selectedRow.ask, selectedRow.presettle)"
-                   :span="8">{{ selectedRow.ask }}</a-col>
-            <a-col :class="handleQuotePriceColor(selectedRow.askvolume, selectedRow.presettle)"
-                   :span="8">{{ selectedRow.askvolume }}</a-col>
-          </a-row>
-          <a-row>
-            <a-col :span="8">买一</a-col>
-            <a-col :class="handleQuotePriceColor(selectedRow.bid, selectedRow.presettle)"
-                   :span="8">{{ selectedRow.bid }}</a-col>
-            <a-col :class="handleQuotePriceColor(selectedRow.bidvolume, selectedRow.presettle)"
-                   :span="8">{{ selectedRow.bidvolume }}</a-col>
-          </a-row>
+        <div class="chart-slider">
+            <div class="chart-slider__button"></div>
         </div>
-      </div>
-      <div class="chart-tips__tik">
-        <div class="row-header">
-          <h4>分时成交</h4>
-          <a-row>
-            <a-col :span="8">时间</a-col>
-            <a-col :span="8">价格</a-col>
-            <a-col :span="8">现量</a-col>
-          </a-row>
+        <div class="chart-tips">
+            <div>
+                <div class="chart-tips__nav">
+                    <div class="content content--left">{{ selectedRow.goodscode }}</div>
+                    <div class="content content--right">{{ selectedRow.goodsname }}</div>
+                </div>
+                <div class="chart-tips__last">
+                    <div :class="['content content--left', handleQuotePriceColor(selectedRow.last, selectedRow.presettle)]"> {{ selectedRow.last }}</div>
+                    <div class="content content--right">
+                        <span :class="handleQuotePriceColor(selectedRow.last, selectedRow.presettle)">{{ quoteChange(selectedRow) }}</span>
+                        <span :class="handleQuotePriceColor(selectedRow.last, selectedRow.presettle)">{{ quoteAmplitude(selectedRow) }}</span>
+                    </div>
+                </div>
+                <div class="chart-tips__volume">
+                    <a-row>
+                        <a-col :span="8">卖一</a-col>
+                        <a-col :class="handleQuotePriceColor(selectedRow.ask, selectedRow.presettle)" :span="8">{{ selectedRow.ask }}</a-col>
+                        <a-col :class="handleQuotePriceColor(selectedRow.askvolume, selectedRow.presettle)" :span="8">{{ selectedRow.askvolume }}</a-col>
+                    </a-row>
+                    <a-row>
+                        <a-col :span="8">买一</a-col>
+                        <a-col :class="handleQuotePriceColor(selectedRow.bid, selectedRow.presettle)" :span="8">{{ selectedRow.bid }}</a-col>
+                        <a-col :class="handleQuotePriceColor(selectedRow.bidvolume, selectedRow.presettle)" :span="8">{{ selectedRow.bidvolume }}</a-col>
+                    </a-row>
+                </div>
+            </div>
+            <div class="chart-tips__tik">
+                <div class="row-header">
+                    <h4>分时成交</h4>
+                    <a-row>
+                        <a-col :span="8">时间</a-col>
+                        <a-col :span="8">价格</a-col>
+                        <a-col :span="8">现量</a-col>
+                    </a-row>
+                </div>
+                <div class="row-content">
+                    <a-row v-for="(item, index) in tradedList" :key="index + '11'">
+                        <a-col :span="8">{{ formatTime(item.TS, 'hm') }}</a-col>
+                        <a-col :class="handleQuotePriceColor(item.PE, selectedRow.presettle)" :span="8">{{ item.PE }}</a-col>
+                        <a-col :class="handleQuotePriceColor(item.Vol, selectedRow.presettle)" :span="8">{{ item.Vol }}</a-col>
+                    </a-row>
+                </div>
+            </div>
+            <div class="chart-tips__info">
+                <a-row>
+                    <a-col :span="4">最新</a-col>
+                    <a-col :class="handleQuotePriceColor(selectedRow.last, selectedRow.presettle)" :span="8">{{ selectedRow.last }}</a-col>
+                    <a-col :span="4">均价</a-col>
+                    <a-col :class="handleQuotePriceColor(selectedRow.averageprice, selectedRow.presettle)" :span="8">{{ selectedRow.averageprice }}</a-col>
+                </a-row>
+                <a-row>
+                    <a-col :span="4">涨跌</a-col>
+                    <a-col :class="handleQuotePriceColor(selectedRow.last, selectedRow.presettle)" :span="8">{{ quoteChange(selectedRow) }}</a-col>
+                    <a-col :span="4">今开</a-col>
+                    <a-col :class="handleQuotePriceColor(selectedRow.opened, selectedRow.presettle)" :span="8">{{ selectedRow.opened }}</a-col>
+                </a-row>
+                <a-row>
+                    <a-col :span="4">涨幅</a-col>
+                    <a-col :class="handleQuotePriceColor(selectedRow.last, selectedRow.presettle)" :span="8">{{ quoteAmplitude(selectedRow) }}</a-col>
+                    <a-col :span="4">最高</a-col>
+                    <a-col :class="handleQuotePriceColor(selectedRow.highest, selectedRow.presettle)" :span="8">{{ selectedRow.highest }}</a-col>
+                </a-row>
+                <a-row>
+                    <a-col :span="4">总量</a-col>
+                    <a-col :span="8">{{ selectedRow.totalvolume }}</a-col>
+                    <a-col :span="4">最低</a-col>
+                    <a-col :class="handleQuotePriceColor(selectedRow.lowest, selectedRow.presettle)" :span="8">{{ selectedRow.lowest }}</a-col>
+                </a-row>
+                <a-row>
+                    <a-col :span="4">金额</a-col>
+                    <a-col :span="8" style="color: #0d96ff">{{ changeUnit(selectedRow.totalturnover) }}</a-col>
+                    <a-col :span="4">量比</a-col>
+                    <a-col :span="8">{{ '--' }}</a-col>
+                </a-row>
+                <a-row>
+                    <a-col :span="4">涨停</a-col>
+                    <a-col class="red1" :span="8">{{ selectedRow.limitup }}</a-col>
+                    <a-col :span="4">跌停</a-col>
+                    <a-col class="green" :span="8">{{ selectedRow.limitdown }}</a-col>
+                </a-row>
+                <a-row>
+                    <a-col :span="4">外盘</a-col>
+                    <a-col :span="8">{{ selectedRow.totalbidvolume }}</a-col>
+                    <a-col :span="4">内盘</a-col>
+                    <a-col :span="8">{{ selectedRow.totalaskvolume }}</a-col>
+                </a-row>
+                <a-row>
+                    <a-col :span="4">持仓</a-col>
+                    <a-col :span="8">{{ selectedRow.holdvolume }}</a-col>
+                    <a-col :span="4">结算</a-col>
+                    <a-col :span="8">{{ selectedRow.settle }}</a-col>
+                </a-row>
+                <a-row>
+                    <a-col :span="4">仓差</a-col>
+                    <a-col :span="8">{{ '--' }}</a-col>
+                    <a-col :span="4">昨结</a-col>
+                    <a-col :span="8">{{ selectedRow.presettle }}</a-col>
+                </a-row>
+                <a-row>
+                    <a-col :span="4">日增</a-col>
+                    <a-col :span="8">{{ '--' }}</a-col>
+                    <a-col :span="4">开平</a-col>
+                    <a-col :span="8">{{ '--' }}</a-col>
+                </a-row>
+            </div>
+            <div @click="watchMore" class="watchMore">查看更多</div>
         </div>
-        <div class="row-content">
-          <a-row v-for="(item, index) in tradedList"
-                 :key="index + '11'">
-            <a-col :span="8">{{ formatTime(item.TS, 'hm') }}</a-col>
-            <a-col :class="handleQuotePriceColor(item.PE, selectedRow.presettle)"
-                   :span="8">{{ item.PE }}</a-col>
-            <a-col :class="handleQuotePriceColor(item.Vol, selectedRow.presettle)"
-                   :span="8">{{ item.Vol }}</a-col>
-          </a-row>
-        </div>
-      </div>
-      <div class="chart-tips__info">
-        <a-row>
-          <a-col :span="4">最新</a-col>
-          <a-col :class="handleQuotePriceColor(selectedRow.last, selectedRow.presettle)"
-                 :span="8">{{ selectedRow.last }}</a-col>
-          <a-col :span="4">均价</a-col>
-          <a-col :class="handleQuotePriceColor(selectedRow.averageprice, selectedRow.presettle)"
-                 :span="8">{{ selectedRow.averageprice }}</a-col>
-        </a-row>
-        <a-row>
-          <a-col :span="4">涨跌</a-col>
-          <a-col :class="handleQuotePriceColor(selectedRow.last, selectedRow.presettle)"
-                 :span="8">{{ quoteChange(selectedRow) }}</a-col>
-          <a-col :span="4">今开</a-col>
-          <a-col :class="handleQuotePriceColor(selectedRow.opened, selectedRow.presettle)"
-                 :span="8">{{ selectedRow.opened }}</a-col>
-        </a-row>
-        <a-row>
-          <a-col :span="4">涨幅</a-col>
-          <a-col :class="handleQuotePriceColor(selectedRow.last, selectedRow.presettle)"
-                 :span="8">{{ quoteAmplitude(selectedRow) }}</a-col>
-          <a-col :span="4">最高</a-col>
-          <a-col :class="handleQuotePriceColor(selectedRow.highest, selectedRow.presettle)"
-                 :span="8">{{ selectedRow.highest }}</a-col>
-        </a-row>
-        <a-row>
-          <a-col :span="4">总量</a-col>
-          <a-col :span="8">{{ selectedRow.totalvolume }}</a-col>
-          <a-col :span="4">最低</a-col>
-          <a-col :class="handleQuotePriceColor(selectedRow.lowest, selectedRow.presettle)"
-                 :span="8">{{ selectedRow.lowest }}</a-col>
-        </a-row>
-        <a-row>
-          <a-col :span="4">金额</a-col>
-          <a-col :span="8"
-                 style="color: #0d96ff">{{ changeUnit(selectedRow.totalturnover) }}</a-col>
-          <a-col :span="4">量比</a-col>
-          <a-col :span="8">{{ '--' }}</a-col>
-        </a-row>
-        <a-row>
-          <a-col :span="4">涨停</a-col>
-          <a-col class="red1"
-                 :span="8">{{ selectedRow.limitup }}</a-col>
-          <a-col :span="4">跌停</a-col>
-          <a-col class="green"
-                 :span="8">{{ selectedRow.limitdown }}</a-col>
-        </a-row>
-        <a-row>
-          <a-col :span="4">外盘</a-col>
-          <a-col :span="8">{{ selectedRow.totalbidvolume }}</a-col>
-          <a-col :span="4">内盘</a-col>
-          <a-col :span="8">{{ selectedRow.totalaskvolume }}</a-col>
-        </a-row>
-        <a-row>
-          <a-col :span="4">持仓</a-col>
-          <a-col :span="8">{{ selectedRow.holdvolume }}</a-col>
-          <a-col :span="4">结算</a-col>
-          <a-col :span="8">{{ selectedRow.settle }}</a-col>
-        </a-row>
-        <a-row>
-          <a-col :span="4">仓差</a-col>
-          <a-col :span="8">{{ '--' }}</a-col>
-          <a-col :span="4">昨结</a-col>
-          <a-col :span="8">{{ selectedRow.presettle }}</a-col>
-        </a-row>
-        <a-row>
-          <a-col :span="4">日增</a-col>
-          <a-col :span="8">{{ '--' }}</a-col>
-          <a-col :span="4">开平</a-col>
-          <a-col :span="8">{{ '--' }}</a-col>
-        </a-row>
-      </div>
-      <div @click="watchMore"
-           class="watchMore">查看更多</div>
     </div>
-  </div>
 </template>
 
 <script lang="ts">
@@ -192,8 +158,9 @@ export default defineComponent({
     },
     setup(props, context) {
         const { visible, cancel } = _closeModal(context);
+        const activeCycleName = ref<string[]>(['time']);
         const activeCycleType = ref<CycleType>(CycleType.time);
-        const activeSeriesType = ref('MACD');
+        const activeSeriesType = ref<string[]>(['MACD']);
 
         function watchMore() {
             context.emit('update', ComponentType.marketContent);
@@ -202,15 +169,20 @@ export default defineComponent({
 
         // 周期类型
         const chartType = [
-            { name: '分时', type: CycleType.time },
-            { name: '1分钟', type: CycleType.minutes },
-            { name: '5分钟', type: CycleType.minutes5 },
-            { name: '30分钟', type: CycleType.minutes30 },
-            { name: '60分钟', type: CycleType.minutes60 },
-            { name: '4小时', type: CycleType.Hours4 },
-            { name: '日 K', type: CycleType.days },
+            { label: '分时', name: 'time', value: CycleType.time },
+            { label: '1分钟', name: 'minutes', value: CycleType.minutes },
+            { label: '5分钟', name: 'minutes5', value: CycleType.minutes5 },
+            { label: '30分钟', name: 'minutes30', value: CycleType.minutes30 },
+            { label: '60分钟', name: 'minutes60', value: CycleType.minutes60 },
+            { label: '4小时', name: 'Hours4', value: CycleType.Hours4 },
+            { label: '日 K', name: 'days', value: CycleType.days },
         ];
 
+        // 切换图表周期类型
+        const changeCycleType = (e: { key: string }) => {
+            activeCycleType.value = chartType.find((item) => item.name === e.key)!.value;
+        };
+
         // Tik列表
         const { list: tradedList } = useQueryData<QueryHistoryTikDatasRsp>(QueryHistoryTikDatas, {
             goodsCode: goodscode,
@@ -247,6 +219,7 @@ export default defineComponent({
             chartType,
             tradedList,
             CycleType,
+            activeCycleName,
             activeCycleType,
             activeSeriesType,
             changeUnit,
@@ -255,6 +228,7 @@ export default defineComponent({
             quoteChange,
             quoteAmplitude,
             handleQuotePriceColor,
+            changeCycleType,
         };
     },
 });