li.shaoyi 11 ヶ月 前
コミット
e163fa1ffb

+ 2 - 1
src/hooks/countdown/index.ts

@@ -13,7 +13,7 @@ export function useCountDown(defaultTime: number) {
         intervalId = window.setInterval(() => {
             state.time--
             if (state.time < 0) {
-                state.time = defaultTime
+                stop()
                 callback()
             }
         }, 1000)
@@ -21,6 +21,7 @@ export function useCountDown(defaultTime: number) {
 
     const stop = () => {
         clearInterval(intervalId)
+        state.time = defaultTime
         state.status = 0
     }
 

+ 19 - 6
src/packages/pc/views/marketrun/monitor/account/index.vue

@@ -9,7 +9,8 @@
                     </el-select>
                 </el-form-item>
                 <el-form-item prop="risk">
-                    {{ t('marketrun.monitor.account.risk') }}<el-input-number v-model="queryParams.risk" :placeholder="t('common.pleaseenter')" />%
+                    {{ t('marketrun.monitor.account.risk') }}<el-input-number v-model="queryParams.risk"
+                        :placeholder="t('common.pleaseenter')" />%
                 </el-form-item>
                 <el-form-item :label="t('marketrun.monitor.account.searchtype')" prop="searchtype">
                     <el-select v-model="queryParams.searchtype">
@@ -21,14 +22,19 @@
                     </el-select>
                 </el-form-item>
                 <el-form-item :label="t('marketrun.monitor.account.puserid')" prop="puserid">
-                    <app-select-member v-model="queryParams.puserid" usertype="2,3" :placeholder="t('marketrun.monitor.account.tips2')" />
+                    <app-select-member v-model="queryParams.puserid" usertype="2,3"
+                        :placeholder="t('marketrun.monitor.account.tips2')" />
                 </el-form-item>
                 <el-form-item>
                     {{ t('marketrun.monitor.account.tips1') }} {{ countDown.time }})
                 </el-form-item>
                 <el-form-item>
-                    <el-button type="primary" @click="countDown.stop" v-if="countDown.status.value">{{ t('marketrun.monitor.account.stop') }}</el-button>
-                    <el-button type="primary" @click="startCountDown" v-else>{{ t('marketrun.monitor.account.start') }}</el-button>
+                    <el-button type="primary" @click="countDown.stop" v-if="countDown.status.value">
+                        {{ t('marketrun.monitor.account.stop') }}
+                    </el-button>
+                    <el-button type="primary" @click="startCountDown" :disabled="loading" v-else>
+                        {{ t('marketrun.monitor.account.start') }}
+                    </el-button>
                 </el-form-item>
             </el-form>
         </template>
@@ -38,7 +44,7 @@
 </template>
 
 <script lang="ts" setup>
-import { ref, computed } from 'vue'
+import { ref, computed, onUnmounted } from 'vue'
 import { ElMessage, FormInstance } from 'element-plus'
 import { useCountDown } from '@/hooks/countdown'
 import { useRequest } from '@/hooks/request'
@@ -60,10 +66,13 @@ const queryParams = ref<Model.MarketRunInvestorReq>({
 
 const { data } = useRequest(marketRunInitInvestor)
 
-const { dataList, run } = useRequest(marketRunInvestor, {
+const { dataList, loading, run } = useRequest(marketRunInvestor, {
     params: queryParams.value,
     onError: (err) => {
         ElMessage.error(err)
+    },
+    onFinally: () => {
+        startCountDown()
     }
 })
 
@@ -111,4 +120,8 @@ const tableColumns = computed<Model.TableColumn[]>(() => {
 const startCountDown = () => {
     countDown.start(() => run(queryParams.value))
 }
+
+onUnmounted(() => {
+    countDown.stop()
+})
 </script>

+ 15 - 4
src/packages/pc/views/marketrun/monitor/liquidation/index.vue

@@ -4,8 +4,12 @@
         <app-table :data="dataList" :columns="tableColumns">
             <template #headerLeft>
                 <div>{{ t('marketrun.monitor.liquidation.countDown') }}{{ countDown.time }}</div>
-                <el-button type="primary" @click="countDown.stop" v-if="countDown.status.value">{{ t('marketrun.monitor.liquidation.stop') }}</el-button>
-                <el-button type="primary" @click="startCountDown" v-else>{{ t('marketrun.monitor.liquidation.start') }}</el-button>
+                <el-button type="primary" @click="countDown.stop" v-if="countDown.status.value">
+                    {{ t('marketrun.monitor.liquidation.stop') }}
+                </el-button>
+                <el-button type="primary" @click="startCountDown" :disabled="loading" v-else>
+                    {{ t('marketrun.monitor.liquidation.start') }}
+                </el-button>
             </template>
             <template #footer>
                 <app-pagination :total="total" v-model:page-size="pageSize" v-model:page-index="pageIndex"
@@ -16,7 +20,7 @@
 </template>
 
 <script lang="ts" setup>
-import { shallowRef } from 'vue'
+import { shallowRef, onUnmounted } from 'vue'
 import { ElMessage } from 'element-plus'
 import { formatDate } from '@/filters'
 import { getBuyOrSellName } from '@/constants/order'
@@ -30,13 +34,16 @@ import { i18n } from '@/stores'
 const { global: { t } } = i18n
 const countDown = useCountDown(10)
 
-const { dataList, total, pageSize, pageIndex, run } = useRequest(marketRunCutposition, {
+const { dataList, total, loading, pageSize, pageIndex, run } = useRequest(marketRunCutposition, {
     params: {
         pageNum: 1,
         pageSize: 20
     },
     onError: (err) => {
         ElMessage.error(err)
+    },
+    onFinally: () => {
+        startCountDown()
     }
 })
 
@@ -52,4 +59,8 @@ const tableColumns = shallowRef<Model.TableColumn[]>([
 const startCountDown = () => {
     countDown.start(() => run())
 }
+
+onUnmounted(() => {
+    countDown.stop()
+})
 </script>

+ 61 - 0
src/packages/pc/views/marketrun/monitor/marketer/components/positionsumm/details/index.vue

@@ -0,0 +1,61 @@
+<!-- 市场运行管理-监控管理-做市会员风险监控-持仓汇总-持仓单查询 -->
+<template>
+    <app-drawer title="持仓单查询" width="1200" v-model:show="show">
+        <app-table :data="dataList" :columns="tableColumns">
+            <template #headerLeft>
+                <span>资金账户:{{ record.accountid }}</span>
+            </template>
+        </app-table>
+        <template #footer>
+            <el-button @click="onCancel">{{ t('operation.close') }}</el-button>
+        </template>
+    </app-drawer>
+</template>
+
+<script lang="ts" setup>
+import { shallowRef, PropType } from 'vue'
+import { ElMessage } from 'element-plus'
+import { useRequest } from '@/hooks/request'
+import { queryHolderDetailMonitor } from '@/services/api/market'
+import AppDrawer from '@pc/components/base/drawer/index.vue'
+import AppTable from '@pc/components/base/table/index.vue'
+import { i18n } from '@/stores'
+
+const props = defineProps({
+    record: {
+        type: Object as PropType<Model.MarketRunAccpageRsp>,
+        required: true
+    }
+})
+
+const { global: { t } } = i18n
+
+const show = shallowRef(true)
+
+const { dataList } = useRequest(queryHolderDetailMonitor, {
+    params: {
+        accountid: props.record.accountid,
+        goodsid: props.record.goodsid
+    },
+    onError: (err) => {
+        ElMessage.error(err)
+    }
+})
+
+const tableColumns = shallowRef<Model.TableColumn[]>([
+    { field: 'tradeid', label: '成交单号' },
+    { field: 'tradedate', label: '交易日' },
+    { field: 'accountNameId', label: '账户' },
+    { field: 'marketname', label: '市场' },
+    { field: 'goodsCodeName', label: '商品' },
+    { field: 'buyorsell', label: '方向' },
+    { field: 'holderqty', label: '持仓数量' },
+    { field: 'holderprice', label: '持仓价格' },
+    { field: 'holderamount', label: '持仓金额' },
+    { field: 'tradetime', label: '交易时间' },
+])
+
+const onCancel = () => {
+    show.value = false
+}
+</script>

+ 96 - 0
src/packages/pc/views/marketrun/monitor/marketer/components/positionsumm/index.vue

@@ -0,0 +1,96 @@
+<!-- 市场运行管理-监控管理-做市会员风险监控-持仓汇总 -->
+<template>
+    <app-drawer title="账户持仓汇总监控" width="1200" v-model:show="show">
+        <app-table :data="dataList" :columns="tableColumns">
+            <template #headerLeft>
+                <span>资金账户:{{ record.accountid }}</span>
+            </template>
+            <!-- 操作 -->
+            <template #operate="{ row }">
+                <el-button size="small" icon="Search" @click="showComponent('Details', row)" circle plain />
+            </template>
+        </app-table>
+        <template #footer>
+            <el-button @click="onCancel">{{ t('operation.close') }}</el-button>
+        </template>
+        <component ref="componentRef" :is="componentMap.get(componentId)" v-bind="{ record: selectedItem }"
+            @closed="closeComponent" v-if="componentId" />
+    </app-drawer>
+</template>
+
+<script lang="ts" setup>
+import { shallowRef, PropType, defineAsyncComponent, onUnmounted } from 'vue'
+import { ElMessage } from 'element-plus'
+import { useCountDown } from '@/hooks/countdown'
+import { useRequest } from '@/hooks/request'
+import { useComponent } from '@/hooks/component'
+import { marketRunAccpage } from '@/services/api/market'
+import AppDrawer from '@pc/components/base/drawer/index.vue'
+import AppTable from '@pc/components/base/table/index.vue'
+import { i18n } from '@/stores'
+
+const props = defineProps({
+    record: {
+        type: Object as PropType<Model.MarketRunMemberRiskRsp>,
+        required: true
+    }
+})
+
+const componentMap = new Map<string, unknown>([
+    ['Details', defineAsyncComponent(() => import('./details/index.vue'))], // 详情
+])
+
+const { global: { t } } = i18n
+
+const show = shallowRef(true)
+const selectedItem = shallowRef<Model.MarketRunAccpageRsp>()
+const countDown = useCountDown(10)
+
+const { componentRef, componentId, openComponent, closeComponent } = useComponent()
+
+const { dataList, run } = useRequest(marketRunAccpage, {
+    params: {
+        accountid: props.record.accountid
+    },
+    onError: (err) => {
+        ElMessage.error(err)
+    },
+    onFinally: () => {
+        startCountDown()
+    }
+})
+
+const tableColumns = shallowRef<Model.TableColumn[]>([
+    { field: 'accountid', label: '资金账户/账号/名称' },
+    { field: 'parentname', label: '所属' },
+    { field: 'goodsname', label: '商品' },
+    { field: 'buy_hold_qty', label: '持仓数量(买)' },
+    { field: 'buy_hold_value', label: '持仓金额(买)' },
+    { field: 'buy_avg_price', label: '持仓均价(买)' },
+    { field: 'buy_float_pl', label: '持仓损益(买)' },
+    { field: 'sell_hold_qty', label: '持仓数量(卖)' },
+    { field: 'sell_hold_value', label: '持仓金额(卖)' },
+    { field: 'sell_avg_price', label: '持仓均价(卖)' },
+    { field: 'sell_float_pl', label: '持仓损益(卖)' },
+    { field: 'total_float_pl', label: '持仓损益(总)' },
+    { field: 'quote_price_last', label: '最新价' },
+    { field: 'operate', label: '操作', fixed: 'right' }
+])
+
+const showComponent = (code: string, row?: Model.MarketRunAccpageRsp) => {
+    selectedItem.value = row
+    openComponent(code)
+}
+
+const startCountDown = () => {
+    countDown.start(() => run())
+}
+
+const onCancel = () => {
+    show.value = false
+}
+
+onUnmounted(() => {
+    countDown.stop()
+})
+</script>

+ 81 - 1
src/packages/pc/views/marketrun/monitor/marketer/index.vue

@@ -1,7 +1,87 @@
 <!-- 市场运行管理-监控管理-做市会员风险监控 -->
 <template>
-    <app-view></app-view>
+    <app-view>
+        <template #header>
+            <el-form ref="formRef" class="el-form--filter" :model="queryParams">
+                <el-form-item prop="orderbytype">
+                    <el-select v-model="queryParams.orderbytype">
+                        <el-option label="风险率" :value="0" />
+                    </el-select>
+                </el-form-item>
+                <el-form-item prop="risk">
+                    监控当前风险率><el-input-number v-model="queryParams.risk" placeholder="请输入" />%
+                </el-form-item>
+                <el-form-item>
+                    (默认风险率>50%;每10秒刷新一次,下次刷新: {{ countDown.time }})
+                </el-form-item>
+                <el-form-item>
+                    <el-button type="primary" @click="countDown.stop" v-if="countDown.status.value">停止监控</el-button>
+                    <el-button type="primary" @click="startCountDown" :disabled="loading" v-else>开始监控</el-button>
+                </el-form-item>
+            </el-form>
+        </template>
+        <app-table :data="dataList" :columns="tableColumns">
+            <!-- 操作 -->
+            <template #operate="{ row }">
+                <app-operation size="small" :data-list="getActionButtons()"
+                    @click="(code: string) => openComponent(code, row)" circle />
+            </template>
+        </app-table>
+        <component :is="componentMap.get(componentId)" v-bind="{ record }" @closed="closeComponent"
+            v-if="componentId" />
+    </app-view>
 </template>
 
 <script lang="ts" setup>
+import { ref, onUnmounted } from 'vue'
+import { ElMessage, FormInstance } from 'element-plus'
+import { useCountDown } from '@/hooks/countdown'
+import { useOperation } from '@/hooks/operation'
+import { useRequest } from '@/hooks/request'
+import { marketRunMemberRisk } from '@/services/api/market'
+import AppTable from '@pc/components/base/table/index.vue'
+import AppOperation from '@pc/components/base/operation/index.vue'
+
+const formRef = ref<FormInstance>()
+const countDown = useCountDown(10)
+
+const queryParams = ref<Model.MarketRunInvestorReq>({
+    orderbytype: 0,
+    risk: 50
+})
+
+const { componentMap, componentId, record, openComponent, closeComponent, getActionButtons } = useOperation<Model.MarketRunMemberRiskRsp>()
+
+const { dataList, loading, run } = useRequest(marketRunMemberRisk, {
+    params: queryParams.value,
+    onError: (err) => {
+        ElMessage.error(err)
+    },
+    onFinally: () => {
+        startCountDown()
+    }
+})
+
+const tableColumns: Model.TableColumn[] = [
+    { field: 'accountid', label: '账户' },
+    { field: 'tradestatus', label: '账户状态' },
+    { field: 'accountname', label: '会员名称' },
+    { field: 'freezemargin', label: '当前冻结资金' },
+    { field: 'usedmargin', label: '当前占用保证金', width: 140 },
+    { field: 'balance', label: '当前净值' },
+    { field: 'availmargin', label: '可用资金' },
+    { field: 'totalfrozen', label: '总冻结' },
+    { field: 'totalfloatpl', label: '浮动损益' },
+    { field: 'curriskrate', label: '当前风险率(%)' },
+    { field: 'currisklv', label: '当前风险等级' },
+    { field: 'operate', label: '操作', fixed: 'right' }
+]
+
+const startCountDown = () => {
+    countDown.start(() => run(queryParams.value))
+}
+
+onUnmounted(() => {
+    countDown.stop()
+})
 </script>

+ 28 - 0
src/services/api/market/index.ts

@@ -1,5 +1,8 @@
 import httpClient from '@/services/http'
 import { CommonFetchOptions } from '@/services/http/types'
+import { useUserStore } from '@/stores'
+
+const userStore = useUserStore()
 
 /**
  * 市场运行管理-->监控管理-->在线用户查询-->获取列表
@@ -34,4 +37,29 @@ export function marketRunInvestor(options: CommonFetchOptions<{ request: Model.M
  */
 export function marketRunInitInvestor(options: CommonFetchOptions<{ response: Model.MarketRunInitInvestorRsp; }> = {}) {
     return httpClient.commonRequest('/marketRun/initInvestor', 'get', options)
+}
+
+/**
+ * 市场运行管理-->监控管理-->做市会员风险监控-->获取列表
+ */
+export function marketRunMemberRisk(options: CommonFetchOptions<{ request: Model.MarketRunMemberRiskReq; response: Model.MarketRunMemberRiskRsp[]; }>) {
+    options.data = {
+        orgztypes: userStore.userInfo.orgztypes,
+        ...options.data
+    }
+    return httpClient.commonRequest('/marketRun/memberRisk', 'get', options)
+}
+
+/**
+ * 市场运行管理-->监控管理-->做市会员风险监控-->账户持仓汇总监控-->获取列表
+ */
+export function marketRunAccpage(options: CommonFetchOptions<{ request: Model.MarketRunAccpageReq; response: Model.MarketRunAccpageRsp[]; }>) {
+    return httpClient.commonRequest('/marketRun/accpage', 'get', options)
+}
+
+/**
+ * 市场运行管理-->监控管理-->做市会员风险监控-->账户持仓汇总监控-->持仓明细
+ */
+export function queryHolderDetailMonitor(options: CommonFetchOptions<{ request: Model.HolderDetailMonitorReq; response: Model.HolderDetailMonitorRsp[]; }>) {
+    return httpClient.commonRequest('/marketRun/queryHolderDetailMonitor', 'get', options)
 }

+ 105 - 0
src/types/model/market.d.ts

@@ -75,4 +75,109 @@ declare namespace Model {
         isshowsafe: string; // 是否按安全度风控
         isshowshouxin: string; // 是否显示授信金额
     }
+
+    /** 市场运行管理-->监控管理-->做市会员风险监控-->获取列表 请求 */
+    interface MarketRunMemberRiskReq {
+        orderbytype?: number; // 类型
+        orgztypes?: string; // 管理员所属机构角色类型
+        puserid?: number; // 所属机构
+        risk?: number; // 监控当前风险率
+        searchtype?: number; // 查询类型
+    }
+
+    /** 市场运行管理-->监控管理-->做市会员风险监控-->获取列表 响应 */
+    interface MarketRunMemberRiskRsp {
+        accountid: number; // 账户
+        accountname: string; // 会员名称
+        availmargin: number; // 可用资金
+        balance: number; // 当前净值
+        currisklv: number; // 当前风险等级
+        curriskrate: number; // 当前风险率(%)
+        freezemargin: number; // 当前冻结资金
+        totalfloatpl: number; // 浮动盈亏
+        totalfrozen: number; // 总冻结
+        tradestatus: number; // 账户状态
+        usedmargin: number; // 当前占用保证金
+    }
+
+    /** 市场运行管理-->监控管理-->做市会员风险监控-->账户持仓汇总监控-->获取列表 请求 */
+    interface MarketRunAccpageReq {
+        accountid: number;
+    }
+
+    /** 市场运行管理-->监控管理-->做市会员风险监控-->账户持仓汇总监控-->获取列表 响应 */
+    interface MarketRunAccpageRsp {
+        accountid: number; // 账户ID 查询条件 --查询条件
+        buy_avg_price: number; // 持仓均价(买)
+        buy_float_pl: number; // 浮动盈亏(买)
+        buy_hold_qty: number; // 持仓头寸(买)
+        buy_hold_value: number; // 持仓金额(买)
+        decimalplace: number; // 报价小数位
+        excludeaccountids: string; // 排除账户ID --查询条件
+        goodsid: number; // 商品ID
+        goodsname: string;
+        margin: number; // 占用保证金
+        orderby: number; // 排序方式: 1-总损益顺序 2-总损益倒序 --查询条件
+        pageNo: number;
+        pageSize: number;
+        parentname: string; // 上级机构 --查询条件
+        quote_price_buy: number; // 实时行情(买)
+        quote_price_last: number; // 实时行情
+        quote_price_sell: number; // 实时行情(卖)
+        sell_avg_price: number; // 持仓均价(卖)
+        sell_float_pl: number; // 浮动盈亏(卖)
+        sell_hold_qty: number; // 持仓头寸(卖)
+        sell_hold_value: number; // 持仓金额(卖)
+        total_float_pl: number; // 浮动盈亏(总)
+        trademode: number; // 交易模式
+        username: string; // 用户名称 --查询条件
+    }
+
+    /** 市场运行管理-->监控管理-->做市会员风险监控-->账户持仓汇总监控-->持仓明细 请求 */
+    interface HolderDetailMonitorReq {
+        accountid: number;
+        goodsid: number;
+    }
+
+    /** 市场运行管理-->监控管理-->做市会员风险监控-->账户持仓汇总监控-->持仓明细 响应 */
+    interface HolderDetailMonitorRsp {
+        accountNameId: string; // 账户
+        actuallYpl: number; // 实际盈亏 trademode = 18、26 / 浮动损益 ishis = 1
+        actuallYplS: number; // 浮动损益
+        agreeUnit: number;
+        buyorsell: number; // 方向
+        defercharge: number; // 递延费 ishis = 1
+        expiredate: string; // 行权日 trademode = 18、26
+        expiretype: number; // 行权日类型 trademode = 18、26
+        goodsCodeName: string; // 商品代码/名称
+        goodscode: string;
+        goodsid: number;
+        histradedate: string; // 历史交易日 ishis = 1
+        holderamount: number; // 持仓金额
+        holderdays: number; // T+N
+        holderprice: number; // 持仓价格
+        holderqty: number; // 持仓数量
+        isConfirmExercise: number;
+        isPreExercise: number;
+        ishis: number; // 查询类型 1历史 0当前
+        marketname: string; // 市场
+        memberusername: string; // 所属会员
+        openprice: number; // 订立价格/行权价
+        openqty: number; // 订立数量
+        optiontype: number; // 期权类型 trademode = 18、26
+        parentusername: string; // 所属上级/所属营销中心 trademode = 18、26
+        preExercisePrice: number;
+        premium: number; // 定货金 trademode = 18、26
+        premiumAmount: number; // 定货金总额 trademode = 18、26
+        realTimeYpl: number; // 实时盈亏 trademode = 18、26
+        reckonpl: number; // 结算损益 ishis = 1
+        reckonprice: number; // 结算价 ishis = 1
+        refgoodscode: string;
+        tradeamount: number; // 订立金额
+        tradedate: string; // 交易日
+        tradeid: string; // 成交单号
+        trademode: number;
+        tradetime: string; // 交易时间
+        usertype: number; // 账户类型
+    }
 }