marymelisa 4 лет назад
Родитель
Сommit
31fc287fc4

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

@@ -1,3 +1,3 @@
 {
-    "apiUrl": "http://192.168.31.114:8080/cfg?key=test_114"
+    "apiUrl": "http://192.168.31.175:8080/cfg?key=test_175"
 }

+ 18 - 0
public/config/readMe.txt

@@ -6,3 +6,21 @@ http://192.168.31.114:8080/cfg?key=test_114
 李倩:http://192.168.31.220:8080/cfg?key=test_220
 
 http://192.168.30.211:8080/cfg?key=test_211
+
+透传  "apiUrl": "http://192.168.31.175:8080/cfg?key=test_175"
+账号 110000000001
+    199990000012
+    199990000013
+    188880000001
+    199990000002
+    199990000003
+    199990000004
+    199990000005
+    199990000006
+    199990000007
+    199990000008
+    199990000009
+    199990000010
+    199990000011
+    199990000001
+    188880000002

+ 131 - 129
src/App.vue

@@ -1,151 +1,153 @@
 <template>
-    <a-spin :tip="tip" :spinning="spinning" size="large">
-        <router-view />
-    </a-spin>
+  <a-spin :tip="tip"
+          :spinning="spinning"
+          size="large">
+    <router-view />
+  </a-spin>
 </template>
 
 <script lang="ts">
-    import { defineComponent, ref, watchEffect, provide } from 'vue';
-    import { globalDataRefresh } from '@/services/bus/index';
-    import { notice } from '@/services/bus/system';
-    import eventBus from '@/utils/eventBus/index';
-    import TimerUtils from '@/utils/tool/timerUtil';
-    import Router from '@/router';
-    import APP from '@/services';
-    import { Modal } from 'ant-design-vue';
-    import { setLoadComplete } from '@/setup/methods/index';
-    import { isLogin, logout } from '@/services/bus/login';
-    let lastTime = new Date().getTime();
+import { defineComponent, ref, watchEffect, provide } from 'vue';
+import { globalDataRefresh } from '@/services/bus/index';
+import { notice } from '@/services/bus/system';
+import eventBus from '@/utils/eventBus/index';
+import TimerUtils from '@/utils/tool/timerUtil';
+import Router from '@/router';
+import APP from '@/services';
+import { Modal } from 'ant-design-vue';
+import { setLoadComplete } from '@/setup/methods/index';
+import { isLogin, logout } from '@/services/bus/login';
+let lastTime = new Date().getTime();
 
-    // 设置太久没有操作界面,自动退出界面功能
-    function setOvertime() {
-        window.addEventListener('mousemove', () => {
-            lastTime = new Date().getTime(); //更新当前时间
-        });
-        const mimut = 30;
-        const timeOut = mimut * 60 * 1000; //设置超时时间: 5分钟
-        TimerUtils.setInterval(
-            () => {
-                const currentTime = new Date().getTime();
-                if (currentTime - lastTime > timeOut) {
-                    //判断是否超时
-                    if (isLogin()) {
-                        Modal.info({
-                            title: '系统提示:',
-                            content: `您已超过${mimut}分钟没有进行任何操作,已自动退出登录!`,
-                            okType: 'primary',
-                            okText: '确定',
-                            keyboard: false,
-                        });
-                        logout();
-                        APP.closeServer();
-                        Router.replace('/login');
-                    }
+// 设置太久没有操作界面,自动退出界面功能
+function setOvertime() {
+    window.addEventListener('mousemove', () => {
+        lastTime = new Date().getTime(); //更新当前时间
+    });
+    const mimut = 30;
+    const timeOut = mimut * 60 * 1000; //设置超时时间: 5分钟
+    TimerUtils.setInterval(
+        () => {
+            const currentTime = new Date().getTime();
+            if (currentTime - lastTime > timeOut) {
+                //判断是否超时
+                if (isLogin()) {
+                    Modal.info({
+                        title: '系统提示:',
+                        content: `您已超过${mimut}分钟没有进行任何操作,已自动退出登录!`,
+                        okType: 'primary',
+                        okText: '确定',
+                        keyboard: false,
+                    });
+                    logout();
+                    APP.closeServer();
+                    Router.replace('/login');
                 }
-            },
-            timeOut,
-            'overtimeInterval'
-        );
-    }
-
-    export default defineComponent({
-        name: 'app',
-        components: {},
-        setup() {
-            let spinning = ref<boolean>(false);
-            const tip = ref<string>('');
+            }
+        },
+        timeOut,
+        'overtimeInterval'
+    );
+}
 
-            // 登出状态展示
-            eventBus.$onOnly('logout', () => {
-                tip.value = '跳转中...';
-                spinning.value = true;
-                TimerUtils.setTimeout(
-                    () => {
-                        spinning.value = false;
-                        APP.closeServer();
-                    },
-                    1000,
-                    'logoutTimer'
-                );
-            });
-            // 登录成功
-            eventBus.$onOnly('loginSuccess', setOvertime);
-            // 监听路由的变化
-            watchEffect(() => Router.currentRoute && provide('current-route', Router.currentRoute));
+export default defineComponent({
+    name: 'app',
+    components: {},
+    setup() {
+        let spinning = ref<boolean>(false);
+        const tip = ref<string>('');
 
-            // 监听刷新事件
-            window.addEventListener(
-                'load',
+        // 登出状态展示
+        eventBus.$onOnly('logout', () => {
+            tip.value = '跳转中...';
+            spinning.value = true;
+            TimerUtils.setTimeout(
                 () => {
-                    tip.value = '数据初始化...';
-                    lastTime = new Date().getTime(); //更新当前时间
-                    spinning.value = true;
-                    // 注册全局loadComplete事件 保证loadComplete变量及时更新
-                    setLoadComplete(false);
-                    globalDataRefresh()
-                        .then((res) => {
-                            setLoadComplete(true);
-                            eventBus.$emit('loadComplete');
-                            spinning.value = false;
-                        })
-                        .catch((err) => {
-                            console.error(err);
-                            spinning.value = false;
-                        });
+                    spinning.value = false;
+                    APP.closeServer();
                 },
-                true
+                1000,
+                'logoutTimer'
             );
+        });
+        // 登录成功
+        // eventBus.$onOnly('loginSuccess', setOvertime);
+        // 监听路由的变化
+        watchEffect(() => Router.currentRoute && provide('current-route', Router.currentRoute));
+
+        // 监听刷新事件
+        window.addEventListener(
+            'load',
+            () => {
+                tip.value = '数据初始化...';
+                lastTime = new Date().getTime(); //更新当前时间
+                spinning.value = true;
+                // 注册全局loadComplete事件 保证loadComplete变量及时更新
+                setLoadComplete(false);
+                globalDataRefresh()
+                    .then((res) => {
+                        setLoadComplete(true);
+                        eventBus.$emit('loadComplete');
+                        spinning.value = false;
+                    })
+                    .catch((err) => {
+                        console.error(err);
+                        spinning.value = false;
+                    });
+            },
+            true
+        );
 
-            setOvertime();
-            // 订阅交易通知
-            notice((msg: string) => {
-                Modal.info({
-                    title: '系统提示:',
-                    content: `${msg},请重新登录。`,
-                    okType: 'primary',
-                    okText: '确定',
-                    keyboard: false,
-                    onOk() {
-                        Router.replace('/login');
-                    },
-                });
+        // setOvertime();
+        // 订阅交易通知
+        notice((msg: string) => {
+            Modal.info({
+                title: '系统提示:',
+                content: `${msg},请重新登录。`,
+                okType: 'primary',
+                okText: '确定',
+                keyboard: false,
+                onOk() {
+                    Router.replace('/login');
+                },
             });
+        });
 
-            return {
-                tip,
-                spinning,
-            };
-        },
-    });
+        return {
+            tip,
+            spinning,
+        };
+    },
+});
 </script>
 
 <style lang="less">
-    #app {
-        width: 100%;
-        height: auto;
-        min-height: 100%;
-        font-family: Avenir, Helvetica, Arial, sans-serif;
-        -webkit-font-smoothing: antialiased;
-        -moz-osx-font-smoothing: grayscale;
-        text-align: center;
-        color: #2c3e50;
-        background-color: #fffefe;
-        display: flex;
-        justify-content: center;
-        overflow-y: hidden;
-        img {
-            cursor: pointer;
-        }
+#app {
+    width: 100%;
+    height: auto;
+    min-height: 100%;
+    font-family: Avenir, Helvetica, Arial, sans-serif;
+    -webkit-font-smoothing: antialiased;
+    -moz-osx-font-smoothing: grayscale;
+    text-align: center;
+    color: #2c3e50;
+    background-color: #fffefe;
+    display: flex;
+    justify-content: center;
+    overflow-y: hidden;
+    img {
+        cursor: pointer;
     }
+}
 
-    #nav {
-        padding: 30px;
-        a {
-            font-weight: bold;
-            color: #2c3e50;
-            &.router-link-exact-active {
-                color: #42b983;
-            }
+#nav {
+    padding: 30px;
+    a {
+        font-weight: bold;
+        color: #2c3e50;
+        &.router-link-exact-active {
+            color: #42b983;
         }
     }
+}
 </style>

+ 42 - 3
src/assets/styles/index.css

@@ -34,18 +34,23 @@
   overflow: hidden;
 }
 /*滚动条样式*/
+::-webkit-scrollbar {
+  width: 10px;
+  height: 10px;
+}
 ::-webkit-scrollbar-thumb {
   border-radius: 10px;
+  background-color: #272E32;
 }
 ::-webkit-scrollbar-button {
-  background-color: transparent;
+  background-color: #171A1B;
 }
 ::-webkit-scrollbar-track-piece {
-  background-color: transparent;
+  background-color: #171A1B;
 }
 ::-webkit-scrollbar-corner,
 .el-input::-webkit-scrollbar-corner {
-  background-color: transparent;
+  background-color: #171A1B;
 }
 html {
   font-family: system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
@@ -247,3 +252,37 @@ body {
 .pointer {
   cursor: pointer;
 }
+.ant-table-wrapper .ant-table-thead tr th {
+  background: #212629;
+  color: #556772;
+  font-size: 14px;
+  font-family: Adobe Heiti Std;
+}
+.ant-table-wrapper .ant-table-thead > tr:first-child > th:last-child,
+.ant-table-wrapper .ant-table-thead > tr:first-child > th:first-child {
+  border-radius: 0px;
+}
+.ant-table-wrapper .ant-table-tbody > tr:hover:not(.ant-table-expanded-row):not(.ant-table-row-selected) > td {
+  background: #172b56;
+}
+.ant-table-wrapper .ant-table-body tr td {
+  background-color: #0E0E0F;
+  color: white;
+  cursor: pointer;
+}
+.ant-table-wrapper .ant-table-bordered .ant-table-thead > tr > th,
+.ant-table-wrapper .ant-table-bordered .ant-table-tbody > tr > td {
+  padding: 0;
+  height: 34px;
+  line-height: 34px;
+  border-color: #161a1c;
+  font-family: Adobe Heiti Std;
+  font-size: 16px;
+}
+.ant-table-wrapper .ant-table-fixed {
+  width: max-content !important;
+  color: #e5e5e5;
+  background: #0e0e0f;
+  border-top-color: #0e0e0f !important;
+  border-left-color: #161a1c !important;
+}

+ 43 - 0
src/assets/styles/index.less

@@ -245,3 +245,46 @@ body {
 .pointer {
     cursor: pointer;
 }
+
+.ant-table-wrapper {
+    .ant-table-thead {
+        tr th {
+            background: #212629;
+            color: #556772;
+            font-size: 14px;
+            font-family: Adobe Heiti Std;
+        }
+
+       
+        > tr:first-child {
+            > th:last-child, > th:first-child {
+                border-radius: 0px;
+                
+            }
+        }
+    }
+    
+    .ant-table-tbody > tr:hover:not(.ant-table-expanded-row):not(.ant-table-row-selected) > td {
+        background: #172b56;
+    }
+    .ant-table-body tr td {
+        background-color: #0E0E0F;
+        color: white;
+        cursor: pointer;
+    }
+    .ant-table-bordered .ant-table-thead > tr > th, .ant-table-bordered .ant-table-tbody > tr > td {
+        padding: 0;
+        height: 34px;
+        line-height: 34px;
+        border-color: #161a1c;
+        font-family: Adobe Heiti Std;
+        font-size: 16px;
+    }
+    .ant-table-fixed {
+        width: max-content !important;
+        color: #e5e5e5;
+        background: #0e0e0f;
+        border-top-color: #0e0e0f !important;
+        border-left-color: #161a1c !important;
+    }
+}

+ 1 - 0
src/assets/styles/variables.less

@@ -25,6 +25,7 @@
 @m-blue0: #3a87f7;
 @m-blue1: #4885eb;
 @m-blue2: #3270d2;
+@m-blue3: #172B56;
 @body-bg: #e9eef3;
 @m-white0: #ffffff;
 @m-green0: #1FF195;

+ 4 - 3
src/components/firstMenu/index.vue

@@ -56,9 +56,8 @@ export default defineComponent({
     border-bottom: none;
 }
 .first-menu {
-    .flex();
-    flex: 1;
-    justify-content: space-between;
+    width: 100%;
+    height: 40px;
     border-bottom: 1px solid @m-blue0 !important;
     background-color: @m-black1;
     .a-menu_container {
@@ -67,6 +66,8 @@ export default defineComponent({
         height: 34px;
         line-height: 34px;
         .ant-menu-item {
+            height: 34px;
+            line-height: 34px;
             background: linear-gradient(0deg, #343d46 0%, #38444f 100%);
             margin-left: 3px;
             font-size: 16px;

+ 37 - 52
src/components/quoteTable/index.vue

@@ -1,18 +1,18 @@
 <template>
-    <div class="quoteTable" @contextmenu.prevent="onContextMenu">
-        <a-table
-            class="quote-table"
-            :columns="columns"
-            :data-source="dataSource"
-            bordered
-            :pagination="false"
-            :scroll="{ x: true, y: 600 }">
-            <template #action>
-                <a>action</a>
-            </template>
-        </a-table>
-        <contextMenu :contextMenu="context" @update="updateContextMenu"/>
-    </div>
+  <div @contextmenu.prevent="onContextMenu" class="quoteTable">
+    <a-table class="quote-table"
+             :columns="columns"
+             :data-source="dataSource"
+             bordered
+             :pagination="false"
+             :scroll="{ x: true, y: 600 }">
+      <template #action>
+        <a>action</a>
+      </template>
+    </a-table>
+    <contextMenu :contextMenu="context"
+                 @update="updateContextMenu" />
+  </div>
 </template>
 <script lang="ts">
 import { defineComponent, reactive, PropType } from 'vue';
@@ -26,7 +26,7 @@ function handleContextMenu(props: any) {
         show: false,
         menuList: [],
         selectedData: null,
-    })
+    });
     function onContextMenu(value: MouseEvent) {
         const target = value.target as any;
         // 获取点击表格的 tr  所在的 索引位置
@@ -34,18 +34,18 @@ function handleContextMenu(props: any) {
         const { clientX, clientY } = value;
         Object.assign(context.position, { clientX, clientY });
         context.show = true;
-        context.selectedData = props.dataSource[index]
+        context.selectedData = props.dataSource[index];
     }
     // 关闭右键弹窗
     function updateContextMenu(value: boolean) {
-        context.show = value
+        context.show = value;
     }
-    return { context, onContextMenu, updateContextMenu }
+    return { context, onContextMenu, updateContextMenu };
 }
 
 export default defineComponent({
     components: {
-        contextMenu
+        contextMenu,
     },
     props: {
         columns: {
@@ -59,7 +59,7 @@ export default defineComponent({
         contextMenuList: {
             default: [],
             type: Object as PropType<MenuItem[]>,
-        }
+        },
     },
     setup(props) {
         const { context, onContextMenu, updateContextMenu } = handleContextMenu(props);
@@ -75,45 +75,30 @@ export default defineComponent({
 <style lang="less">
 .quoteTable {
     width: 100%;
+    max-height: calc(100% - 68px);
     flex: 1;
-    .quote-table {
-        width: 100%;
-        height: 100%;
+}
+.quote-table {
+    height: 100%;
+    .ant-spin-nested-loading {
+        .ant-spin-container {
+
+        }
+    }
+    .ant-table td {
+        white-space: nowrap;
     }
-    .ant-table td { white-space: nowrap; }
     .ant-table-thead {
-        tr th {
-            background: #212629;
-            color: #556772;
-            font-size: 14px;
-            font-family: Adobe Heiti Std;
-        }
         .ant-table-fixed-columns-in-body {
             width: 100px;
         }
     }
-    .ant-table-tbody .ant-table-row-hover td {
-        background: #172B56!important;
-    }
-    .ant-table-fixed {
-        width: max-content !important;
-        color: #E5E5E5;
-        background: #0E0E0F;
-        border-top-color: #0E0E0F !important;
-        border-left-color: #161a1c !important;
-
-    }
-    .ant-table-tbody > tr:hover:not(.ant-table-expanded-row):not(.ant-table-row-selected) > td {
-        background: #172B56;
-    }
-    .ant-table-bordered .ant-table-thead > tr > th, .ant-table-bordered .ant-table-tbody > tr > td {
-        padding: 0;
-        height: 34px;
-        line-height: 34px;
-        border-color: #161a1c;
-        font-family: Adobe Heiti Std;
-        font-size: 16px;
+    .ant-table-fixed,.ant-table-body {
+        .ant-table-row-hover {
+            td.ant-table-row-cell-break-word {
+                background-color: @m-blue3 !important;
+            }
+        }
     }
-
 }
 </style>;

+ 0 - 17
src/components/secondeMenu/index.vue

@@ -159,23 +159,6 @@ export default defineComponent({
 <style lang="less">
 .second_menu {
     height: 100%;
-    // .left-menu {
-    //     height: 100%;
-    //     .menu-item_title {
-    //         margin-left: 10px;
-    //     }
-    // }
-    
-    // .ant-avatar-icon {
-    //     background-color: @m-grey1;
-    //     cursor: pointer;
-    // }
-    // .m-layout-left {
-    //     background: @m-black0;
-    //     .ant-layout-sider-trigger {
-    //     background: @m-black0;
-    // }
-    // }
     .m-layout-left {
         height: 100%;
         background: @m-black4;

+ 12 - 0
src/goServiceAPI/ermcp/index.ts

@@ -0,0 +1,12 @@
+import { getLongTypeLoginID } from '@/services/bus/login';
+import { commonSearch_go } from '../index';
+import * as type from './interface';
+
+/**
+ * 获取目标登录账号当前对冲账号在线状态
+ * @returns GetErmcpOutAccountStatus[]
+ */
+export function GetErmcpOutAccountStatus(): Promise<type.GetErmcpOutAccountStatus[]> {
+    const id = getLongTypeLoginID();
+    return commonSearch_go('/Ermcp/GetErmcpOutAccountStatus', { loginID: Number(id) })
+}

+ 21 - 0
src/goServiceAPI/ermcp/interface.ts

@@ -0,0 +1,21 @@
+export interface GetErmcpOutAccountStatus {
+    accountcurrecnygroup: string;
+    accountcurrency: string;
+    accountid: number;
+    appid: string;
+    authcode: string;
+    brokerid: string;
+    channeladdress: string;
+    channelid: number;
+    connectflag: number;
+    exchangeratecurrencygroup: string;
+    fcid: number;
+    fcname: string;
+    hedgeaccountcode: string;
+    hedgeaccountpwd: string;
+    hedgeaccounttype: number;
+    limit: number;
+    marketid: number;
+    status: number;
+    userproductinfo: string;
+}

+ 100 - 0
src/layout/bottom.vue

@@ -0,0 +1,100 @@
+<template>
+  <section class="layout-bottom">
+    <CapitalInfo class="capital-info-container"></CapitalInfo>
+    <main>
+        <firstMenu :list="list"
+            :value="'value'"
+            @selectMenu="selectMenu" />
+        <quoteTable :columns="columns"
+                :dataSource="data"
+                />
+        <!-- <thirdMenu></thirdMenu> -->
+    </main>
+  </section>
+</template>
+<script lang="ts">
+import { defineComponent } from 'vue';
+import SecondMenu from '@/components/secondeMenu/index.vue';
+import CapitalInfo from '@/components/capitalInfo/index.vue';
+import thirdMenu from '@/components/thirdMenu/index.vue';
+import quoteTable from '@/components/quoteTable/index.vue';
+import { MenuItem } from '@/components/contextMenu/interface';
+
+const columns = [
+    { title: '序号', width: 100, dataIndex: 'name', key: 'name', fixed: 'left', align: 'center' },
+    { title: '品种', width: 100, dataIndex: 'age', key: 'age', fixed: 'left', align: 'center' },
+    { title: '种类', dataIndex: 'address', key: '1', width: 200, align: 'center' },
+    { title: '品牌', dataIndex: 'address', key: '2', width: 200, align: 'center' },
+    { title: '数量', dataIndex: 'address', key: '3', width: 200, align: 'center' },
+    { title: '价格', dataIndex: 'address', key: '4', width: 200, align: 'center' },
+    { title: '仓库', dataIndex: 'address', key: '5', width: 200, align: 'center' },
+    { title: '所在地', dataIndex: 'address', key: '6', width: 200, align: 'center' },
+    { title: '挂牌方', dataIndex: 'address', key: '7', width: 'auto', align: 'center' },
+    // {
+    //     title: 'Action',
+    //     key: 'operation',
+    //     fixed: 'right',
+    //     align: 'center',
+    //     width: 100,
+    //     slots: { customRender: 'action' },
+    // },
+];
+
+interface DataItem {
+    key: number;
+    name: string;
+    age: number;
+    address: string;
+}
+
+const data: DataItem[] = [];
+for (let i = 0; i < 100; i++) {
+    data.push({
+        key: i,
+        name: `Edrward ${i}`,
+        age: 32,
+        address: `London Park no. ${i}`,
+    });
+}
+
+function handleMenu() {
+    const list = [
+        { key: '1', value: '仓单贸易' },
+        { key: '2', value: '拍卖' },
+    ];
+    function selectMenu(item: any) {
+        console.log(item);
+    }
+    return { list, selectMenu };
+}
+
+export default defineComponent({
+    name: 'layout-top',
+    components: {
+        CapitalInfo,
+        thirdMenu,
+        quoteTable
+    },
+    setup() {
+        const { list, selectMenu } = handleMenu();
+        return {
+            columns,
+            data,
+            list,
+            selectMenu,
+        };
+    },
+});
+</script>
+<style lang="less">
+.layout-bottom {
+    display: flex;
+    .capital-info-container {
+        width: 180px;
+    }
+    main {
+        flex: 1;
+        background: rgb(14, 14, 15);
+    }
+}
+</style>

+ 25 - 191
src/layout/index.vue

@@ -1,117 +1,37 @@
 <template>
-    <a-layout class="layout">
-        <a-layout-header class="m-layout-header">
-            <div>深圳市多元世纪信息技术股份有限公司</div>
-            <div class="m-layout-header-right">
-                <div>
-                    <span>{{ username }}(2500000001),您好!</span>
-                </div>
-                <div class="relative">
-                    <a-input-search ref="userNameInput"  class="searchInput" placeholder="请输入代码/名称" @pressEnter="search" >
-                    </a-input-search>
-                    <!-- <a-icon type="search" /> -->
-                </div>
-                <div class="news-container">
-                    <a-badge dot @click="chooseSetMenu('notice')">
-                        <svg class="icon svg-icon" aria-hidden="true">
-                            <use xlink:href="#icon-xiaoxi"></use>
-                        </svg>
-                    </a-badge>
-                </div>
-                <div>
-                    <a-popover v-model:visible="visible" trigger="click" placement="bottomRight">
-                        <template #content>
-                            <div v-for="item in setMenu" @click="chooseSetMenu(item.path)" :key="item.path">{{item.name}}</div>
-                        </template>
-                        <a-avatar :size="24">
-                            <template #icon>
-                                <UserOutlined />
-                            </template>
-                        </a-avatar>
-                    </a-popover>
-                    <Setting />
-                </div>
-            </div>
-        </a-layout-header>
-        <a-layout class="middleLayout">
-            <SecondMenu></SecondMenu>
-            <a-layout-content class="contentBar">
-                <!-- <router-view /> -->
-                <WarehouseTrade></WarehouseTrade>
-            </a-layout-content>
-        </a-layout>
-        <div class="sliderLayout">
-            <div class="shortLine"></div>
-        </div>
-        <a-layout class="bottomLayout">
-            <a-layout-sider class="m-layout-left" width="180">
-                <!-- 这里左边需要加上资金信息 capital-info -->
-                <CapitalInfo></CapitalInfo>
-            </a-layout-sider>
-            <a-layout-content :style="{ background: '#0E0E0F' }">
-            </a-layout-content>
-        </a-layout>
-    </a-layout>
+  <div class="layout">
+    <LayoutTop @chooseMenu="chooseMenu" />
+    <template v-if="isShowBottomPart">
+      <div class="sliderLayout">
+        <div class="shortLine"></div>
+      </div>
+      <LayoutBottom />
+    </template>
+  </div>
 </template>
 <script lang="ts">
-import { UserOutlined } from '@ant-design/icons-vue';
-import { defineComponent, ref, provide } from 'vue';
-import Setting from '@/views/setting/index.vue';
-import CapitalInfo from '@/components/capitalInfo/index.vue';
-import SecondMenu from '@/components/secondeMenu/index.vue';
-import WarehouseTrade from '@/views/market/warehouseTrade/index.vue';
-import APP from '@/services';
+import LayoutTop from './top.vue';
+import LayoutBottom from './bottom.vue';
+import { defineComponent, ref } from 'vue';
 
-// 设置
-const setFn = () => {
-    const visible = ref<boolean>(false);
-    const chooseSetupItem = ref<string>('');
-    provide('setting', chooseSetupItem);
-    const setMenu = [
-        { name: '修改密码', path: 'password' },
-        { name: '收货地址', path: 'addresss' },
-        // {name: '发票', path: 'setup-password'},
-        { name: '手机号码绑定/解绑', path: 'phone' },
-        { name: '关于我们', path: 'aboutUs' },
-        { name: '退出', path: 'logout' },
-    ];
-    function chooseSetMenu(path: string) {
-        chooseSetupItem.value = path;
-        console.log(path);
-        visible.value = false;
+// 控制下半部分是否显示
+function submitBottomIsShow() {
+    const isShowBottomPart = ref<boolean>(true);
+    function chooseMenu(value: boolean) {
+        isShowBottomPart.value = value;
     }
+    return { isShowBottomPart, chooseMenu };
+}
 
-    return { visible, setMenu, chooseSetMenu };
-};
-// 搜索
-const onSearch = () => {
-    function search(value: string) {
-        console.log(value);
-    }
-    return {  search }
-};
 export default defineComponent({
     name: 'layout',
     components: {
-        Setting,
-        UserOutlined,
-        CapitalInfo,
-        SecondMenu,
-        WarehouseTrade,
+        LayoutTop,
+        LayoutBottom,
     },
     setup() {
-        const { visible, setMenu, chooseSetMenu } = setFn();
-        const username = APP.get('username');
-        const { search } = onSearch(); 
-        const searchName = ref<string[]>(['']);
-        return {
-            visible,
-            setMenu,
-            chooseSetMenu,
-            username,
-            search,
-            searchName,
-        };
+        const { isShowBottomPart, chooseMenu } = submitBottomIsShow();
+        return { isShowBottomPart, chooseMenu };
     },
 });
 </script>
@@ -121,107 +41,21 @@ export default defineComponent({
     width: 100%;
     height: 100%;
     flex-direction: column;
-    .m-layout-header {
-        width: 100%;
-        height: 40px;
-        line-height: 40px;
-        background: @m-grey0;
-        color: @m-grey1;
-        padding: 0 20px;
-        .flex();
-        justify-content: space-between;
-        .searchInput.ant-input-affix-wrapper {
-            width: 240px;
-            height: 30px;
-            line-height: 30px;
-            font-size: 14px;
-            background: @m-grey9;
-            border: 0;
-            vertical-align: middle;
-            padding-left: 40px;
-            position: relative;
-            .rounded-corners(15px);
-            .ant-input {
-                background: @m-grey9;
-                color: @m-white0;
-            }
-            .ant-input-suffix {
-                margin-left: -215px;
-                .ant-input-search-icon {
-                    color: @m-grey10;
-                }
-
-            }
-        }
-        // .relative {
-        //     position: relative;
-        //     .a-icon {
-        //         font-size: 14px;
-        //         .position(absolute, 50%, auto, auto, 10px);
-        //         margin-top: -7px;
-        //         color: @m-grey10;
-        //         z-index: 10;
-        //     }
-        // }
-        .m-layout-header-right {
-            .flex();
-            .news-container {
-                padding-left: 10px;
-                padding-right: 16px;
-                .ant-badge {
-                    margin-top: 7px;
-                    cursor: pointer;
-                    > svg {
-                        font-size: 24px;
-                    }
-                    .ant-badge-dot {
-                        box-shadow: 0 0 0 1px @m-red0;
-                    }
-                }
-            }
-
-            .ant-avatar-icon {
-                margin-top: -3px;
-            }
-        }
-    }
-    .contentBar {
-        background: @m-black2;
-        overflow-y: hidden;
-    }
-    .middleLayout {
-        flex: 1;
-        width: 100%;
-        .inlineflex;
-        border-bottom: 1px solid @m-black2;
-        .m-layout-left {
-            position: relative;
-        }
-        .ant-layout-sider-trigger {
-            position: absolute;
-        }
-    }
     .sliderLayout {
         width: 100%;
         height: 4px;
-        background: #242A2E;
+        background: #242a2e;
         border-top: 1px solid @m-grey5;
         border-bottom: 1px solid @m-grey5;
         position: relative;
         .shortLine {
             width: 30px;
             height: 2px;
-            background: #4B5861;
+            background: #4b5861;
             border-radius: 1px;
             .position(absolute, 50%, auto, auto, 50%);
             transform: translate(-50%, -50%);
         }
     }
-    .bottomLayout {
-        width: 100%;
-        flex: none;
-        height: @bottomHeight;
-        .inlineflex;
-    }
 }
 </style>

+ 415 - 0
src/layout/top.vue

@@ -0,0 +1,415 @@
+<template>
+  <a-layout class="layout-top">
+        <a-layout-header class="m-layout-header">
+            <div>深圳市多元世纪信息技术股份有限公司</div>
+            <div class="m-layout-header-right">
+                <div>
+                    <span>{{ username }}(2500000001),您好!</span>
+                </div>
+                <div class="relative">
+                    <a-input-search ref="userNameInput"  class="searchInput" placeholder="请输入代码/名称" @pressEnter="search" >
+                    </a-input-search>
+                    <!-- <a-icon type="search" /> -->
+                </div>
+                <div class="news-container">
+                    <a-badge dot @click="chooseSetMenu('notice')">
+                        <svg class="icon svg-icon" aria-hidden="true">
+                            <use xlink:href="#icon-xiaoxi"></use>
+                        </svg>
+                    </a-badge>
+                </div>
+                <div>
+                    <a-popover v-model:visible="visible" trigger="click" placement="bottomRight">
+                        <template #content>
+                            <div v-for="item in setMenu" @click="chooseSetMenu(item.path)" :key="item.path">{{item.name}}</div>
+                        </template>
+                        <a-avatar :size="24">
+                            <template #icon>
+                                <UserOutlined />
+                            </template>
+                        </a-avatar>
+                    </a-popover>
+                    <Setting />
+                </div>
+            </div>
+        </a-layout-header>
+        <a-layout class="middleLayout">
+            <a-layout-sider class="m-layout-left"
+                width="180"
+                v-model:collapsed="collapsed"
+                @collapse="collapse"
+                collapsible>
+                <a-menu theme="dark"
+                    mode="inline"
+                    class="left-menu"
+                    v-model:selectedKeys="selectedKeys"
+                    v-model:openKeys="openKeys"
+                    @click="menuClick">
+                    <a-sub-menu v-for="item in menuList"
+                        :key="item.code">
+                        <template #title>
+                            <span>
+                                <svg class="icon svg-icon"
+                                    aria-hidden="true">
+                                <use :xlink:href="fontIcon(item.code)"></use>
+                                </svg>
+                                <span class="menu-item_title"
+                                    v-show="!collapsed">{{ item.title }}</span>
+                            </span>
+                        </template>
+                        <a-menu-item :key="subItem.code"
+                            v-for="subItem in item.children">
+                            <span>{{ subItem.title }}</span>
+                        </a-menu-item>
+                    </a-sub-menu>
+                </a-menu>
+            </a-layout-sider>
+            <a-layout-content :style="{ background: '#0E0E0F', flex: 1 }">
+                <router-view />
+            </a-layout-content>
+    </a-layout>
+  </a-layout>
+</template>
+<script lang="ts">
+import { UserOutlined } from '@ant-design/icons-vue';
+import { defineComponent, ref, provide, unref } from 'vue';
+import Setting from '@/views/setting/index.vue';
+import CapitalInfo from '@/components/capitalInfo/index.vue';
+import SecondMenu from '@/components/secondeMenu/index.vue';
+import APP from '@/services';
+import { initData } from '@/setup/methods/index';
+import { useRouter } from 'vue-router';
+
+// 菜单栏
+const handleMenu = () => {
+    const collapsed = ref<boolean>(false);
+    const selectedKeys = ref<string[]>(['1-1']);
+    const openKeys = ref<string[]>(['1']);
+    const preOpenKeys = ref<string[]>(['1']);
+    // const menuList = APP.getRef('menus');
+    const menuList = [
+        {
+          key: '1',
+          title: '市场',
+          code: 'market',
+          children: [
+            {
+              key: '1-1',
+              title: '现货贸易',
+              code: ''
+            },
+          ],
+        },
+        {
+          key: '2',
+          title: '查询',
+          code: 'search',
+          children: [
+            {
+              key: '2-1',
+              title: '单据记录',
+              code: ''
+            },
+            {
+              key: '2-2',
+              title: '资金流水',
+              code: ''
+            },
+            {
+              key: '2-3',
+              title: '出入库',
+              code: ''
+            },
+            {
+              key: '2-4',
+              title: '登录日志',
+              code: ''
+            },
+          ],
+        },
+        {
+          key: '3',
+          title: '报表',
+          code: 'report'
+        },
+      ];
+    const router = useRouter();
+    // 控制菜单是否隐藏
+    function collapse(collapsed: boolean) {
+        if (collapsed) {
+            preOpenKeys.value = openKeys.value;
+            openKeys.value = [];
+        } else {
+            openKeys.value = preOpenKeys.value;
+        }
+    }
+
+    function menuClick(value: any) {
+        router.push(value.key);
+    }
+    // 一级菜单图标
+    function fontIcon(code: string): string {
+        let result = 'icon-jinrongfenxi';
+        switch (code) {
+            case 'market':
+                result = 'icon-jinrongfenxi';
+                break;
+            case 'info':
+                result = 'icon-zhangdan';
+                break;
+            case 'business':
+                result = 'icon-renwu';
+                break;
+            case 'manage':
+                result = 'icon-quanxian';
+                break;
+            case 'search':
+                result = 'icon-chazhaojilu';
+                break;
+            case 'report':
+                result = 'icon-bingtu';
+                break;
+        }
+        return '#' + result;
+    }
+    return { collapsed, selectedKeys, menuList, openKeys, collapse, menuClick, fontIcon };
+};
+
+// 设置
+const setFn = () => {
+    const visible = ref<boolean>(false);
+    const chooseSetupItem = ref<string>('');
+    provide('setting', chooseSetupItem);
+    const setMenu = [
+        // { name: '修改密码', path: 'password' },
+        // { name: '收货地址', path: 'addresss' },
+        // // {name: '发票', path: 'setup-password'},
+        // { name: '手机号码绑定/解绑', path: 'phone' },
+        // { name: '关于我们', path: 'aboutUs' },
+        { name: '退出', path: 'logout' },
+    ];
+    function chooseSetMenu(path: string) {
+        chooseSetupItem.value = path;
+        console.log(path);
+        visible.value = false;
+    }
+
+    return { visible, setMenu, chooseSetMenu };
+};
+// 搜索
+const onSearch = () => {
+    function search(value: string) {
+        console.log(value);
+    }
+    return { search };
+};
+// 配置是否显示下半部分
+function setShowBottomPart(code: string): boolean {
+    const unShow = ['outaccount_status'];
+    return !unShow.includes(code);
+}
+export default defineComponent({
+    name: 'layout-top',
+    components: {
+        Setting,
+        UserOutlined,
+        CapitalInfo,
+        SecondMenu,
+    },
+    setup(props, context) {
+        const { collapsed, selectedKeys, openKeys, menuList, collapse, menuClick, fontIcon } = handleMenu();
+        const router = useRouter();
+
+        initData(() => {
+            // 处理路由跳转到菜单栏里第一个队员的页面
+            const list = unref(menuList);
+            if (list.length && list[0].children && list[0].children.length) {
+                const code = list[0].children[0].code;
+                selectedKeys.value = [code];
+                openKeys.value = [list[0].code];
+                context.emit('chooseMenu', setShowBottomPart(code));
+                router.push(code);
+            }
+        });
+        const { visible, setMenu, chooseSetMenu } = setFn();
+        const username = APP.get('username');
+        const { search } = onSearch();
+        const searchName = ref<string[]>(['']);
+        return {
+            collapsed,
+            collapse,
+            selectedKeys,
+            openKeys,
+            menuClick,
+            username,
+            menuList,
+            visible,
+            setMenu,
+            chooseSetMenu,
+            fontIcon,
+        };
+    },
+});
+</script>
+<style lang="less">
+.layout-top {
+    .flex;
+    width: 100%;
+    height: 100%;
+    flex-direction: column;
+    .m-layout-header {
+        width: 100%;
+        height: 40px;
+        line-height: 40px;
+        background: @m-grey0;
+        color: @m-grey1;
+        padding: 0 20px;
+        .flex();
+        justify-content: space-between;
+        .searchInput.ant-input-affix-wrapper {
+            width: 240px;
+            height: 30px;
+            line-height: 30px;
+            font-size: 14px;
+            background: @m-grey9;
+            border: 0;
+            vertical-align: middle;
+            padding-left: 40px;
+            position: relative;
+            .rounded-corners(15px);
+            .ant-input {
+                background: @m-grey9;
+                color: @m-white0;
+            }
+            .ant-input-suffix {
+                margin-left: -215px;
+                .ant-input-search-icon {
+                    color: @m-grey10;
+                }
+
+            }
+        }
+        // .relative {
+        //     position: relative;
+        //     .a-icon {
+        //         font-size: 14px;
+        //         .position(absolute, 50%, auto, auto, 10px);
+        //         margin-top: -7px;
+        //         color: @m-grey10;
+        //         z-index: 10;
+        //     }
+        // }
+        .m-layout-header-right {
+            .flex();
+            .news-container {
+                padding-left: 10px;
+                padding-right: 16px;
+                .ant-badge {
+                    margin-top: 7px;
+                    cursor: pointer;
+                    > svg {
+                        font-size: 24px;
+                    }
+                    .ant-badge-dot {
+                        box-shadow: 0 0 0 1px @m-red0;
+                    }
+                }
+            }
+
+            .ant-avatar-icon {
+                margin-top: -3px;
+            }
+        }
+    }
+
+    .middleLayout {
+        flex: 1;
+        width: 100%;
+        .inlineflex;
+        border-bottom: 1px solid @m-black2;
+        .m-layout-left {
+            height: 100%;
+            background: @m-black4;
+            .ant-layout-sider-children {
+                ul.ant-menu.ant-menu-inline {
+                    li.ant-menu-submenu {
+                        padding-bottom: 0;
+                        .ant-menu-submenu-title {
+                            color: @m-grey2;
+                            font-size: 16px;
+                            height: 60px;
+                            line-height: 60px;
+                            margin-top: 0;
+                            margin-bottom: 0;
+                            padding: 5px 0;
+                            .icon {
+                                font-size: 20px;
+                            }
+                            .menu-item_title {
+                                display: inline-block;
+                                font-size: 16px;
+                                margin-left: 15px;
+                            }
+                        }
+                        .ant-menu-sub {
+                            .ant-menu-item {
+                                padding-left: 60px !important;
+                                margin-top: 5px;
+                                margin-bottom: 5px;
+                            }
+                        }
+                    }
+                    li.ant-menu-submenu-open {
+                        .ant-menu-submenu-title {
+                            color: @m-white0;
+                            .icon {
+                                color: @m-white0;
+                            }
+                        }
+                        .ant-menu-sub {
+                            .ant-menu-item.ant-menu-item-selected {
+                                background-color: @m-blue0;
+                            }
+                        }
+                    }
+                }
+            }
+            .ant-layout-sider-trigger {
+                width: 100%;
+                height: 40px;
+                line-height: 40px;
+                background: @m-black0;
+                position: absolute;
+            }
+        }
+        .ant-menu-vertical {
+            .ant-menu-submenu-vertical {
+                height: 60px;
+                line-height: 60px;
+                padding: 5px 0;
+                .ant-menu-submenu-title {
+                    height: 50px;
+                    line-height: 50px;
+                    .icon {
+                        font-size: 20px;
+                    }
+                }
+            }
+            .ant-menu-submenu {
+                .ant-menu-submenu-title {
+                    .menu-item_title {
+                        display: none;
+                    }
+                }
+            }
+        }
+    }
+
+    .bottomLayout {
+        width: 100%;
+        flex: none;
+        height: @bottomHeight;
+        .inlineflex;
+    }
+}
+</style>

+ 5 - 0
src/router/index.ts

@@ -39,6 +39,11 @@ const routes: Array<RouteRecordRaw> = [
                 name: 'warehouseTrade',
                 component: () => import('@/views/market/warehouseTrade/index.vue'),
             },
+            {
+                path: '/outaccount_status',
+                name: 'accountStatus',
+                component: () => import('@/views/account/accountStatus.vue'),
+            },
 
         ],
     },

+ 1 - 0
src/utils/tool/timerUtil.ts

@@ -5,6 +5,7 @@ export interface IntervalTimerNames {
     quoteDay: string; // 定时轮休盘面
     pollingNotice: string; //通知公告轮询
     overtimeInterval: string; // 超时,如果太久没有操作界面,则退出登录
+    accountStauts: string; // 账号状态
 }
 export interface TimeoutTimerNames {
     logoutTimer: string; //登出1s延时器

+ 137 - 0
src/views/account/accountStatus.vue

@@ -0,0 +1,137 @@
+<template>
+  <div class="account-status">
+    <firstMenu :list="menulist"
+               :value="'value'"
+               @selectMenu="selectMenu" />
+    <div class="tip">最新更新时间:{{updatedTime}}</div>
+    <a-table :columns="columns"
+             :data-source="list"
+             :pagination="false"
+             bordered>
+      <template #status="{ text }">
+        <span :class="[text ? 'success-satus' : 'error-status']">{{ text ? '正常' : '断开' }}</span>
+      </template>
+    </a-table>
+  </div>
+</template>
+
+<script lang="ts">
+import { defineComponent, ref, onUnmounted } from 'vue';
+import { initData } from '@/setup/methods/index';
+import { message } from 'ant-design-vue';
+import firstMenu from '@/components/firstMenu/index.vue';
+import { GetErmcpOutAccountStatus } from '@/goServiceAPI/ermcp/index';
+import { GetErmcpOutAccountStatus as GetErmcpOutAccountStatusType } from '@/goServiceAPI/ermcp/interface';
+import TimerUtils from '@/utils/tool/timerUtil';
+import moment from 'moment';
+
+function getAccountList() {
+    interface ListType extends GetErmcpOutAccountStatusType {
+        index: number;
+        key: string;
+    }
+    const columns = [
+        {
+            title: '序号',
+            dataIndex: 'index',
+            align: 'center',
+            width: 200,
+        },
+        {
+            title: '资金账号',
+            align: 'center',
+            dataIndex: 'accountid',
+            width: 400,
+        },
+        {
+            title: '期货公司',
+            align: 'center',
+            dataIndex: 'fcname',
+            width: 500,
+        },
+        {
+            title: '连接状态',
+            align: 'center',
+            dataIndex: 'status',
+            width: 340,
+            slots: { customRender: 'status' },
+        },
+    ];
+    const list = ref<ListType[]>([]);
+    // 更新时间
+    function getTime(): string {
+        return moment().format('YYYY-MM-DD HH:mm:ss');
+    }
+    const updatedTime = ref<string>(getTime());
+    // 获取列表
+    function getAccountStatusList() {
+        return GetErmcpOutAccountStatus()
+            .then((res) => {
+                list.value = res.map((e: GetErmcpOutAccountStatusType, index: number) => {
+                    return { ...e, index: index + 1, key: String(index) };
+                });
+                updatedTime.value = getTime();
+                return 'ok';
+            })
+            .catch((e) => {
+                message.error(e.message);
+            });
+    }
+    // 定时轮询
+    function setLoop() {
+        TimerUtils.setInterval(getAccountStatusList, 10000, 'accountStauts');
+    }
+    return { columns, list, getAccountStatusList, setLoop, updatedTime };
+}
+
+function handleMenu() {
+    const menulist = [{ key: '1', value: '账号状态' }];
+    function selectMenu(item: any) {
+        console.log(item);
+    }
+    return { menulist, selectMenu };
+}
+
+export default defineComponent({
+    name: 'account-status',
+    components: {
+        firstMenu,
+    },
+    setup() {
+        const { columns, list, getAccountStatusList, setLoop, updatedTime } = getAccountList();
+        const { menulist, selectMenu } = handleMenu();
+        initData(async () => {
+            await getAccountStatusList();
+            setLoop();
+        });
+        onUnmounted(() => {
+            TimerUtils.clearInterval('accountStauts');
+        });
+        return { columns, list, menulist, selectMenu, updatedTime };
+    },
+});
+</script>
+
+<style lang="less">
+.account-status {
+    .ant-table-wrapper {
+        margin-left: 1px;
+        .ant-table-body > table {
+            border: none;
+        }
+        .ant-table {
+            width: 100%;
+        }
+    }
+    .success-satus {
+        color: #1ff195;
+    }
+    .error-status {
+        color: #ff2b2b;
+    }
+    .tip {
+        padding: 10px 0;
+        color: #364048;
+    }
+}
+</style>;

+ 38 - 7
swagger-to-ts/swagger.ts

@@ -1,10 +1,41 @@
 interface HttpRespone {code: number;msg: string;page: number;pagesize: number;total: number;}export interface Enum// 已签约信息
 message BankAccountSign {
-code	:string;//ID
-isshow	:boolean;//是否显示
-rulekey	:string;//对应权限主键,对应FUNCMENULIST表RESOURCECODE
-sort	:number;//排序
-title	:string;//标题
-type	:number;//类型,1:菜单 2:按钮
-}
+ accountcurrecnygroup: :string;
+//,
+  accountcurrency: :string;
+//,
+  accountid: number;
+//,
+  appid: :string;
+//,
+  authcode: :string;
+//,
+  brokerid: :string;
+//,
+  channeladdress: :string;
+//,
+  channelid: number;
+//,
+  connectflag: number;
+//,
+  exchangeratecurrencygroup: :string;
+//,
+  fcid: number;
+//,
+  fcname: :string;
+//,
+  hedgeaccountcode: :string;
+//,
+  hedgeaccountpwd: :string;
+//,
+  hedgeaccounttype: number;
+//,
+  limit:number;
+//: number;
+//,
+  marketid: number;
+//,
+  status: number;
+//,
+  userproductinfo: :string;//}
 export interface QueryMarketGoodsRespone extends HttpRespone{data: Enum[];}

+ 19 - 17
swagger-to-ts/swagger.txt

@@ -1,20 +1,22 @@
 // 已签约信息
 message BankAccountSign {
-code	string
-ID
-
-isshow	boolean
-是否显示
-
-rulekey	string
-对应权限主键,对应FUNCMENULIST表RESOURCECODE
-
-sort	integer
-排序
-
-title	string
-标题
-
-type	integer
-类型,1:菜单 2:按钮
+ "accountcurrecnygroup": "string",
+  "accountcurrency": "string",
+  "accountid": 0,
+  "appid": "string",
+  "authcode": "string",
+  "brokerid": "string",
+  "channeladdress": "string",
+  "channelid": 0,
+  "connectflag": 0,
+  "exchangeratecurrencygroup": "string",
+  "fcid": 0,
+  "fcname": "string",
+  "hedgeaccountcode": "string",
+  "hedgeaccountpwd": "string",
+  "hedgeaccounttype": 0,
+  "limitnumber": 0,
+  "marketid": 0,
+  "status": 0,
+  "userproductinfo": "string"
 }