Selaa lähdekoodia

增加订单单据功能

Handy_Cao 2 vuotta sitten
vanhempi
commit
7b8f18e9ff
23 muutettua tiedostoa jossa 1285 lisäystä ja 8 poistoa
  1. 1 1
      public/config/appconfig.json
  2. 5 0
      src/packages/mobile/router/index.ts
  3. 13 0
      src/packages/mobile/views/goods/detail/components/delisting/Index.less
  4. 139 0
      src/packages/mobile/views/goods/detail/components/delisting/index.vue
  5. 13 0
      src/packages/mobile/views/goods/detail/components/listing/Index.less
  6. 133 0
      src/packages/mobile/views/goods/detail/components/listing/index.vue
  7. 108 0
      src/packages/mobile/views/goods/detail/index.vue
  8. 2 2
      src/packages/mobile/views/goods/list/Index.vue
  9. 14 0
      src/packages/mobile/views/order/list/Index.vue
  10. 79 0
      src/packages/mobile/views/order/list/components/goodsorder/detail/Index.vue
  11. 122 0
      src/packages/mobile/views/order/list/components/goodsorder/list/Index.vue
  12. 56 0
      src/packages/mobile/views/order/list/components/goodstrade/detail/Index.vue
  13. 96 0
      src/packages/mobile/views/order/list/components/goodstrade/list/Index.vue
  14. 54 0
      src/packages/mobile/views/order/list/components/hisgoodsorder/detail/Index.vue
  15. 143 0
      src/packages/mobile/views/order/list/components/hisgoodsorder/list/Index.vue
  16. 56 0
      src/packages/mobile/views/order/list/components/hisgoodstrade/detail/Index.vue
  17. 143 0
      src/packages/mobile/views/order/list/components/hisgoodstrade/list/Index.vue
  18. 2 0
      src/packages/mobile/views/order/position/Index.vue
  19. 0 0
      src/packages/mobile/views/order/position/components/goods/close/Index.vue
  20. 0 0
      src/packages/mobile/views/order/position/components/goods/delivery/Index.vue
  21. 101 0
      src/packages/mobile/views/order/position/components/goods/list/Index.vue
  22. 2 2
      src/packages/mobile/views/swap/detail/components/delisting/Index.vue
  23. 3 3
      src/packages/mobile/views/swap/detail/components/listing/Index.vue

+ 1 - 1
public/config/appconfig.json

@@ -1,5 +1,5 @@
 {
   "version": "1.0.0",
   "versionCode": "100000",
-  "apiUrl": "http://192.168.31.204:8080/cfg?key=test_204"
+  "apiUrl": "http://192.168.31.158:18240/cfg?key=dev_104"
 }

+ 5 - 0
src/packages/mobile/router/index.ts

@@ -168,6 +168,11 @@ const routes: Array<RouteRecordRaw> = [
         name: 'goods-list',
         component: () => import('../views/goods/list/Index.vue'),
       },
+      {
+        path: 'detail',
+        name: 'goods-detail',
+        component: () => import('../views/goods/detail/Index.vue'),
+      },
     ],
   },
   {

+ 13 - 0
src/packages/mobile/views/goods/detail/components/delisting/Index.less

@@ -0,0 +1,13 @@
+.goods-delisting {
+    &__form {
+        .van-stepper {
+            display: flex;
+            align-items: center;
+            width: 100%;
+  
+            &__input {
+                flex: 1;
+            }
+        }
+    }
+  }

+ 139 - 0
src/packages/mobile/views/goods/detail/components/delisting/index.vue

@@ -0,0 +1,139 @@
+<template>
+    <app-popup :title="'摘牌'" v-model:show="showModal" :refresh="refresh">
+        <Form class="goods-delisting__form" ref="formRef" @submit="onSubmit" v-if="props">
+            <Field label="交易账户">
+                <template #input>
+                    <span>{{ accountStore.accountId }}</span>
+                </template>
+            </Field>
+            <Field label="订单商品">
+                <template #input>
+                    <span>{{ item.goodscode }}/{{ item.goodsname }}</span>
+                </template>
+            </Field>
+            <Field label="挂牌方">
+                <template #input>
+                    <span>{{ selectedRow.username }}</span>
+                </template>
+            </Field>
+            <Field label="挂牌价格">
+                <template #input>
+                    <span>{{ selectedRow.orderprice }}</span>
+                </template>
+            </Field>
+            <Field label="剩余数量">
+                <template #input>
+                    <span>{{ selectedRow.orderqty }}</span>
+                </template>
+            </Field>
+            <Field label="摘牌方向">
+                <template #input>
+                    <span>{{ getBuyOrSellName(selectedRow.buyorsell) }}</span>
+                </template>
+            </Field>
+            <Field label="挂牌类型">
+                <template #input>
+                    <RadioGroup v-model="buildType" direction='horizontal'>
+                        <Radio :name="1">订立</Radio>
+                        <Radio :name="2">转让</Radio>
+                    </RadioGroup>
+                </template>
+            </Field>
+            <Field name="OrderQty" :rules="formRules.OrderQty" label="摘牌数量">
+                <template #input>
+                    <Stepper v-model="formData.OrderQty" input-width="100" theme="round" button-size="22" :min="0" :step="0.01" :max="selectedRow.orderqty" :auto-fixed="false" />
+                </template>
+            </Field>
+        </Form>
+        <template #footer>
+            <Button type="primary" block round @click="formRef?.submit">{{ tabIndex === 0 ? '卖出' : '买入' }}</Button>
+        </template>
+    </app-popup>
+</template>
+
+<script lang="ts" setup>
+import { shallowRef, PropType } from 'vue'
+import { Form, FormInstance, Button, Field, RadioGroup, Radio, FieldRule, Stepper} from 'vant'
+import { useAccountStore, useFuturesStore } from '@/stores'
+import { EBuildType, EDelistingType, EListingSelectType, EOrderOperateType, EPriceMode, EValidType } from '@/constants/client'
+import { useOrder } from '@/business/trade'
+import { fullloading, dialog } from '@/utils/vant'
+
+import AppPopup from '@mobile/components/base/popup/index.vue'
+import { getBuyOrSellName } from '@/constants/order'
+
+const accountStore = useAccountStore()
+const { formData, formSubmit} = useOrder()
+
+/// 挂牌类型
+const buildType = shallowRef(EBuildType.BUILDTYPE_OPEN)
+
+const props = defineProps({
+    selectedRow: {
+        type: Object as PropType<Model.WrTradeOrderDetailRsp>,
+        required: true
+    },
+    item: {
+        type: Object as PropType<Model.QuoteGoodsListRsp>,
+        required: true
+    },
+    tabIndex: {
+        type: Number,
+        required: true
+    }
+})
+
+const formRef = shallowRef<FormInstance>()
+const showModal = shallowRef(true)
+const refresh = shallowRef(false) // 是否刷新父组件数据
+
+// 表单验证规则
+const formRules: { [key in keyof Proto.OrderReq]?: FieldRule[] } = {
+    OrderQty: [{
+        message: '请输入摘牌数量',
+        validator: () => {
+            return !!formData.OrderQty
+        }
+    }],
+}
+
+// 提交挂牌
+const onSubmit = () => {
+    const { goodsid, orderid } = props.selectedRow
+    /// 获取对应的市场ID
+    formData.MarketID = useFuturesStore().getGoods(goodsid).value?.marketid ?? 0
+    formData.PriceMode = EPriceMode.PRICEMODE_MARKET
+    formData.RelatedID = orderid
+    formData.BuyOrSell = props.selectedRow.buyorsell,
+    formData.GoodsID = goodsid
+    formData.ListingSelectType = EListingSelectType.LISTINGSELECTTYPE_DELISTING
+    formData.DelistingType = EDelistingType.DELISTINGTYPE_SELECTED
+    formData.BuildType = EBuildType.BUILDTYPE_OPEN
+    formData.ValidType = EValidType.VALIDTYPE_DR
+    formData.OperateType = EOrderOperateType.ORDEROPERATETYPE_NORMAL
+    formData.TriggerType = 0
+    formData.ServiceTime = ""
+    formData.ValidTime = ""
+    formData.BuildType = buildType.value
+
+    fullloading((hideLoading) => {
+        formSubmit().then(() => {
+            hideLoading()
+            dialog('挂牌提交成功。').then(() => closed(true))
+        }).catch((err) => {
+            hideLoading(err, 'fail')
+        })
+    })
+}
+
+// 关闭弹窗
+const closed = (isRefresh = false) => {
+    refresh.value = isRefresh
+    showModal.value = false
+}
+
+// 暴露组件属性给父组件调用
+defineExpose({
+    closed,
+})
+</script>

+ 13 - 0
src/packages/mobile/views/goods/detail/components/listing/Index.less

@@ -0,0 +1,13 @@
+.goods-listing {
+    &__form {
+        .van-stepper {
+            display: flex;
+            align-items: center;
+            width: 100%;
+
+            &__input {
+                flex: 1;
+            }
+        }
+    }
+}

+ 133 - 0
src/packages/mobile/views/goods/detail/components/listing/index.vue

@@ -0,0 +1,133 @@
+<template>
+    <app-popup class="goods-listing" :title="'挂牌'" v-model:show="showModal" :refresh="refresh">
+        <Form class="goods-listing__form" ref="formRef" @submit="onSubmit">
+            <Tabs class="van-tabs--list" v-model:active="buyOrSell" :swipe-threshold="2">
+                <Tab title="挂牌买入" />
+                <Tab title="挂牌卖出" />
+            </Tabs>
+            <Field label="交易账户">
+                <template #input>
+                    <span>{{ accountStore.accountId }}</span>
+                </template>
+            </Field>
+            <Field label="订单商品">
+                <template #input>
+                    <span>{{ item.goodscode }}/{{ item.goodsname }}</span>
+                </template>
+            </Field>
+            <Field label="挂牌类型">
+                <template #input>
+                    <RadioGroup v-model="buildType" direction='horizontal'>
+                        <Radio :name="1">订立</Radio>
+                        <Radio :name="2">转让</Radio>
+                    </RadioGroup>
+                </template>
+            </Field>
+            <Field name="OrderPrice" :rules="formRules.OrderPrice" label="价格">
+                <template #input>
+                    <Stepper v-model="formData.OrderPrice" input-width="100" theme="round" button-size="22" :auto-fixed="false" :step="0.01" />
+                </template>
+            </Field>
+            <Field name="OrderQty" :rules="formRules.OrderQty" label="数量">
+                <template #input>
+                    <Stepper v-model="formData.OrderQty" input-width="100" theme="round" button-size="22" :auto-fixed="false" integer />
+                </template>
+            </Field>
+        </Form>
+        <template #footer>
+            <Button type="primary" block round @click="formRef?.submit">确定</Button>
+        </template>
+    </app-popup>
+</template>
+
+<script lang="ts" setup>
+import { shallowRef, PropType } from 'vue'
+import { Form, FormInstance, Button, FieldRule, Field, Tab, Tabs, Stepper, Radio, RadioGroup } from 'vant'
+import { useOrder } from '@/business/trade'
+import { fullloading, dialog } from '@/utils/vant'
+import { useAccountStore, useFuturesStore } from '@/stores'
+import { EPriceMode, EListingSelectType, EDelistingType, EBuildType, EValidType, EOrderOperateType } from '@/constants/client'
+
+import AppPopup from '@mobile/components/base/popup/index.vue'
+
+const accountStore = useAccountStore()
+
+const formRef = shallowRef<FormInstance>()
+const showModal = shallowRef(true)
+const refresh = shallowRef(true) // 是否刷新父组件数据
+/// 挂牌类型
+const buildType = shallowRef(EBuildType.BUILDTYPE_OPEN)
+const { formData, formSubmit } = useOrder()
+
+
+const props = defineProps({
+    item: {
+        type: Object as PropType<Model.QuoteGoodsListRsp>,
+        required: true
+    },
+    tabIndex: {
+        type: Number,
+        required: true
+    }
+})
+
+/// 买卖方向
+const buyOrSell = shallowRef(props.tabIndex)
+
+// 提交挂牌
+const onSubmit = () => {
+    /// 买卖方向
+    const { goodsid } = props.item ?? {}
+    /// 获取对应的市场ID
+    formData.MarketID = useFuturesStore().getGoods(goodsid).value?.marketid ?? 0
+    formData.BuyOrSell = buyOrSell.value,
+    formData.PriceMode = EPriceMode.PRICEMODE_LIMIT
+    formData.MarketMaxSub = 0.0 
+    formData.GoodsID = goodsid
+    formData.ListingSelectType = EListingSelectType.LISTINGSELECTTYPE_LISTING
+    formData.DelistingType = EDelistingType.DELISTINGTYPE_SELECTED
+    formData.BuildType = EBuildType.BUILDTYPE_OPEN
+    formData.ValidType = EValidType.VALIDTYPE_DR
+    formData.OperateType = EOrderOperateType.ORDEROPERATETYPE_NORMAL
+    formData.TriggerType = 0
+    formData.ServiceTime = ""
+    formData.ValidTime = ""
+    formData.BuildType = buildType.value
+
+    fullloading((hideLoading) => {
+        formSubmit().then(() => {
+            hideLoading()
+            dialog('挂牌提交成功。').then(() => closed(true))
+        }).catch((err) => {
+            hideLoading(err, 'fail')
+        })
+    })
+}
+
+// 表单验证规则
+const formRules: { [key in keyof Proto.OrderReq]?: FieldRule[] } = {
+    OrderPrice: [{
+        message: '请输入价格',
+        validator: () => {
+            return !!formData.OrderPrice
+        }
+    }],
+    OrderQty: [{
+        message: '请输入挂牌数量',
+        validator: () => {
+            return !!formData.OrderQty
+        }
+    }],
+}
+
+// 关闭弹窗
+const closed = (isRefresh = true) => {
+    refresh.value = isRefresh
+    showModal.value = false
+}
+
+// 暴露组件属性给父组件调用
+defineExpose({
+    closed,
+})
+</script>

+ 108 - 0
src/packages/mobile/views/goods/detail/index.vue

@@ -0,0 +1,108 @@
+<template>
+    <app-view>
+        <template #header>
+            <app-navbar title="订单挂牌大厅" >
+                <template #right>
+                    <div class="button-more" @click="onListing">
+                        <span>挂牌</span>
+                    </div>
+                </template>
+            </app-navbar>
+            <div>
+                <span>{{ item.goodsname }}/{{ item.goodscode }}</span>
+                <span>--</span>
+            </div>
+        </template>
+        <Tabs v-model:active="tabIndex" @click="onTabChange">
+            <Tab title="买大厅" />
+            <Tab title="卖大厅" />
+        </Tabs>
+        <app-pull-refresh ref="pullRefreshRef" v-model:loading="loading" v-model:error="error" v-model:pageIndex="pageIndex"
+        :page-count="pageCount" @refresh="onTabChange">
+            <div class="trade-section sell" v-if="dataList.length">
+                <app-list :columns="columns" :data-list="dataList">
+                    <template #username="{ row }">
+                        <span >{{ row.userid }}/{{ row.username }}</span>
+                    </template>
+                    <template #operate="{ row }">
+                        <Button size="small" type="primary" round @click="onDelisting(row)">{{ tabIndex === 0 ? '卖出' : '买入' }}</Button>
+                    </template>
+                </app-list>
+            </div>
+        </app-pull-refresh>
+        <component ref="componentRef" :is="componentMap.get(componentId)" v-bind="{ selectedRow, tabIndex, item }" @closed="closeComponent"
+            v-if="componentId" />
+    </app-view>
+</template>
+
+<script lang="ts" setup>
+import { shallowRef, defineAsyncComponent } from 'vue'
+import { Tab, Tabs, Button, showToast } from 'vant'
+import { useRequest } from '@/hooks/request'
+import { useNavigation } from '@/hooks/navigation'
+import { useComponent } from '@/hooks/component'
+import AppList from '@mobile/components/base/list/index.vue'
+import { queryWrTradeOrderDetail } from '@/services/api/transfer'
+import { useLoginStore } from '@/stores'
+import AppPullRefresh from '@mobile/components/base/pull-refresh/index.vue'
+
+const componentMap = new Map<string, unknown>([
+    ['delisting', defineAsyncComponent(() => import('./components/delisting/Index.vue'))],
+    ['listing', defineAsyncComponent(() => import('./components/listing/Index.vue'))],
+])
+
+const loginStore = useLoginStore()
+
+const { getParamString } = useNavigation()
+const { componentRef, componentId, openComponent, closeComponent } = useComponent()
+const item: Model.QuoteGoodsListRsp = JSON.parse(getParamString('item')?.toString() || '{}')
+const tabIndex = shallowRef(0)
+const selectedRow = shallowRef<Model.WrTradeOrderDetailRsp>()
+const error = shallowRef(false)
+const dataList = shallowRef<Model.WrTradeOrderDetailRsp[]>([])
+
+const { pageIndex, loading, run, pageCount } = useRequest(queryWrTradeOrderDetail, {
+    params: {
+        pagesize: 20,
+        goodsid: item.goodsid,
+        buyorsell: tabIndex.value
+    },
+    onSuccess: (res) => {
+        if (pageIndex.value === 1) {
+            dataList.value = []
+        }
+        dataList.value.push(...res.data)
+    },
+    onError: () => {
+        error.value = true
+    }
+})
+
+const onTabChange = () => {
+    run({
+        buyorsell: tabIndex.value
+    })
+}
+
+const columns: Model.TableColumn[] = [
+    { prop: 'orderprice', label: '价格' },
+    { prop: 'orderqty', label: '数量' },
+    { prop: 'username', label: '挂牌方' },
+    { prop: 'operate', label: '摘牌' },
+]
+
+const onDelisting = (row: Model.WrTradeOrderDetailRsp) => {
+    selectedRow.value = row
+    /// 不能与自己成交
+    if (row.userid === loginStore.userId) {
+        showToast('不能与自己成交')
+        return
+    }
+    openComponent('delisting')
+}
+
+const onListing = () => {
+    openComponent('listing')
+}
+
+</script>

+ 2 - 2
src/packages/mobile/views/goods/list/Index.vue

@@ -5,7 +5,7 @@
         </template>
         <app-list :columns="columns" :data-list="tableList">
             <template #goodsname="{ row }">
-                <span @click="$router.push({ name: 'swap-detail', params: { item: JSON.stringify(row) } })">{{ row.goodsname }}</span>
+                <span @click="$router.push({ name: 'goods-detail', params: { item: JSON.stringify(row) } })">{{ row.goodsname }}</span>
             </template>
             <!-- 当前价 -->
             <template #last="{ row }">
@@ -64,7 +64,7 @@ const { dataList } = useRequest(queryQuoteGoodsList, {
 
 const tableList = computed(() => {
     return dataList.value.map((item) => {
-        const quote = futuresStore.getQuoteInfo(item.refgoodscode)
+        const quote = futuresStore.getQuoteInfo(item.goodscode)
         const { goodsname, lastColor, openedColor, lowestColor, highestColor, last, presettle, rise, change, amplitude, highest, lowest, opened } = quote.value ?? {}
         return {
             ...item,

+ 14 - 0
src/packages/mobile/views/order/list/Index.vue

@@ -26,8 +26,10 @@
                 <component :is="componentMap.get('swaptrade')" />
             </Tab>
             <Tab title="订单委托">
+                <component :is="componentMap.get('goodsorder')" />
             </Tab>
             <Tab title="订单成交">
+                <component :is="componentMap.get('goodstrade')" />
             </Tab>
             <Tab title="挂牌委托">
             </Tab>
@@ -50,10 +52,14 @@ const componentMap = new Map<string, unknown>([
     ['presale', defineAsyncComponent(() => import('./components/presale/list/Index.vue'))], // 预售认购
     ['swaporder', defineAsyncComponent(() => import('./components/swaporder/list/Index.vue'))], // 掉期委托
     ['swaptrade', defineAsyncComponent(() => import('./components/swaptrade/list/Index.vue'))], // 掉期成交
+    ['goodsorder', defineAsyncComponent(() => import('./components/goodsorder/list/Index.vue'))], // 订单委托
+    ['goodstrade', defineAsyncComponent(() => import('./components/goodstrade/list/Index.vue'))], // 订单成交
     ['transferorder', defineAsyncComponent(() => import('./components/transferorder/list/Index.vue'))], // 转让委托
     ['transfertrade', defineAsyncComponent(() => import('./components/transfertrade/list/Index.vue'))], // 转让成交
     ['hisswaporder', defineAsyncComponent(() => import('./components/hisswaporder/list/Index.vue'))], // 历史掉期委托
     ['hisswaptrade', defineAsyncComponent(() => import('./components/hisswaptrade/list/Index.vue'))], // 历史掉期成交
+    ['hisgoodsorder', defineAsyncComponent(() => import('./components/hisgoodsorder/list/Index.vue'))], // 历史订单委托
+    ['hisgoodstrade', defineAsyncComponent(() => import('./components/hisgoodstrade/list/Index.vue'))], // 历史订单成交
 ])
 
 const onMoreClick = () => {
@@ -72,6 +78,14 @@ const onMoreClick = () => {
             showComponent('hisswaptrade')
             break
         }
+        case 5: {
+            showComponent('hisgoodsorder')
+            break
+        }
+        case 6: {
+            showComponent('hisgoodstrade')
+            break
+        }
     }
 }
 

+ 79 - 0
src/packages/mobile/views/order/list/components/goodsorder/detail/Index.vue

@@ -0,0 +1,79 @@
+<!-- 我的订单- 订单委托 - 详情 -->
+<template>
+    <app-modal direction="right" height="100%" v-model:show="showModal" :refresh="refresh">
+        <app-view class="g-form">
+            <template #header>
+                <app-navbar title="详细" @back="closed" />
+            </template>
+            <div v-if="props" class="order-detail__container g-form__container">
+                <CellGroup title="订单委托信息">
+                    <Cell title="商品代码/名称" :value="selectedRow.goodscode + '/' + selectedRow.goodsname" />
+                    <Cell title="方向" :value="getBuyOrSellName(selectedRow.buyorsell)" />
+                    <Cell title="委托数量" :value="formatDecimal(selectedRow.orderqty)" />
+                    <Cell title="委托价格" :value="formatDecimal(selectedRow.orderprice)" />
+                    <Cell title="成交数量" :value="formatDecimal(selectedRow.tradeqty)" />
+                    <Cell title="委托状态" :value="getWRTradeOrderStatusName(selectedRow.orderstatus)" />
+                    <Cell title="委托时间" :value="formatDate(selectedRow.ordertime)" />
+                    <Cell title="委托单号" :value="selectedRow.orderid" />
+                </CellGroup>
+            </div>
+            <template #footer v-if="selectedRow.orderstatus === 3 || selectedRow.orderstatus === 7">
+                <Button type="primary" block round @click="onCancelSumit">撤销</Button>
+            </template>
+        </app-view>
+    </app-modal>
+</template>
+
+<script lang="ts" setup>
+import { shallowRef, PropType } from 'vue'
+import AppModal from '@/components/base/modal/index.vue'
+import { CellGroup, Cell, Button } from 'vant'
+import { getBuyOrSellName, getWRTradeOrderStatusName } from '@/constants/order'
+import { formatDate, formatDecimal } from '@/filters'
+import { useCancelOrder } from '@/business/trade'
+import { dialog, fullloading } from '@/utils/vant'
+
+const showModal = shallowRef(true)
+// 是否刷新父组件数据
+const refresh = shallowRef(false)
+const { cancelSubmit, formData } = useCancelOrder()
+
+const props = defineProps({
+    selectedRow: {
+        type: Object as PropType<Model.TradeOrderDetailRsp>,
+        required: true,
+    }
+})
+
+const onCancelSumit = () => {
+    dialog({
+        message: '确认要撤销吗?',
+        showCancelButton: true,
+    }).then(() => {
+        /// 市场ID
+        formData.Header = { MarketID: props.selectedRow.marketid }
+        formData.OldOrderId = props.selectedRow.orderid
+
+        /// loding....
+        fullloading((hideLoading) => {
+            cancelSubmit().then(() => {
+                hideLoading('撤销成功')
+                closed(true)
+            }).catch((err) => {
+                hideLoading(err, 'fail')
+            })
+        })
+    })
+}
+
+// 关闭弹窗
+const closed = (isRefresh = false) => {
+    refresh.value = isRefresh
+    showModal.value = false
+}
+
+// 暴露组件属性给父组件调用
+defineExpose({
+    closed,
+})
+</script>

+ 122 - 0
src/packages/mobile/views/order/list/components/goodsorder/list/Index.vue

@@ -0,0 +1,122 @@
+<!-- 我的订单-订单委托 -->
+<template>
+    <app-pull-refresh ref="pullRefreshRef" v-model:loading="loading" v-model:error="error" v-model:pageIndex="pageIndex"
+        :page-count="pageCount" @refresh="run">
+        <div class="g-order-list">
+            <div class="g-order-list__box" v-for="(item, index) in dataList" :key="index">
+                <div class="g-order-list__titlebar">
+                    <div class="left">
+                        <h5>{{ item.goodscode }}/{{ item.goodsname }}</h5>
+                    </div>
+                    <div class="right">
+                        <span>{{ item.orderid }}</span>
+                    </div>
+                </div>
+                <div class="g-order-list__content">
+                    <ul>
+                        <li>
+                            <span>时间:</span>
+                            <span>{{ formatDate(item.ordertime, 'HH:mm:ss') }}</span>
+                        </li>
+                        <li>
+                            <span>方向:</span>
+                            <span>{{ getBuyOrSellName(item.buyorsell) }}</span>
+                        </li>
+                        <li>
+                            <span>委托数量:</span>
+                            <span>{{ formatDecimal(item.orderqty) }}</span>
+                        </li>
+                        <li>
+                            <span>委托价格:</span>
+                            <span>{{ formatDecimal(item.orderprice) }}</span>
+                        </li>
+                        <li>
+                            <span>成交数量:</span>
+                            <span>{{ formatDecimal(item.tradeqty) }}</span>
+                        </li>
+                        <li>
+                            <span>委托状态:</span>
+                            <span>{{ getWRTradeOrderStatusName(item.orderstatus) }}</span>
+                        </li>
+                    </ul>
+                </div>
+                <div class="g-order-list__btnbar">
+                    <Button size="small" @click="showComponent('detail', item)" round>详情</Button>
+                    <Button size="small" v-if="(item.orderstatus === 3 || item.orderstatus === 7)"
+                        @click="onCancelSumit(item)" round>撤销</Button>
+                </div>
+            </div>
+        </div>
+        <component ref="componentRef" v-bind="{ selectedRow }" :is="componentMap.get(componentId)" @closed="closeComponent"
+            v-if="componentId" />
+    </app-pull-refresh>
+</template>
+
+<script lang="ts" setup>
+import { shallowRef, defineAsyncComponent } from 'vue'
+import { Button } from 'vant'
+import { useComponent } from '@/hooks/component'
+import { useRequest } from '@/hooks/request'
+import { queryTradeOrderDetail } from '@/services/api/order'
+import { getBuyOrSellName, getWRTradeOrderStatusName } from '@/constants/order'
+import { formatDate, formatDecimal } from '@/filters'
+import { useCancelOrder } from '@/business/trade'
+import { dialog } from '@/utils/vant'
+import { fullloading } from '@/utils/vant'
+
+import AppPullRefresh from '@mobile/components/base/pull-refresh/index.vue'
+
+const componentMap = new Map<string, unknown>([
+    ['detail', defineAsyncComponent(() => import('../detail/Index.vue'))]
+])
+
+const { cancelSubmit, formData } = useCancelOrder()
+const dataList = shallowRef<Model.TradeOrderDetailRsp[]>([])
+const selectedRow = shallowRef<Model.TradeOrderDetailRsp>()
+const error = shallowRef(false)
+const pullRefreshRef = shallowRef()
+
+const { componentRef, componentId, openComponent, closeComponent } = useComponent(() => {
+    pullRefreshRef.value?.refresh()
+})
+
+const { loading, pageIndex, pageCount, run } = useRequest(queryTradeOrderDetail, {
+    params: {
+        pagesize: 20,
+        tradeMode: '50'
+    },
+    onSuccess: (res) => {
+        if (pageIndex.value === 1) {
+            dataList.value = []
+        }
+        dataList.value.push(...res.data)
+    },
+    onError: () => {
+        error.value = true
+    }
+})
+
+const onCancelSumit = (item: Model.TradeOrderDetailRsp) => {
+    dialog({
+        message: '确认要撤销吗?',
+        showCancelButton: true,
+    }).then(() => {
+        formData.Header = { MarketID: item.marketid }
+        formData.OldOrderId = item.orderid
+
+        /// loding....
+        fullloading((hideLoading) => {
+            cancelSubmit().then(() => {
+                hideLoading('撤销成功')
+            }).catch((err) => {
+                hideLoading(err, 'fail')
+            })
+        })
+    })
+}
+
+const showComponent = (componentName: string, row: Model.TradeOrderDetailRsp) => {
+    selectedRow.value = row
+    openComponent(componentName)
+}
+</script>

+ 56 - 0
src/packages/mobile/views/order/list/components/goodstrade/detail/Index.vue

@@ -0,0 +1,56 @@
+<!-- 我的订单- 掉期成交 - 详情 -->
+<template>
+    <app-modal direction="right" height="100%" v-model:show="showModal" :refresh="refresh">
+        <app-view class="g-form">
+            <template #header>
+                <app-navbar title="详细" @back="closed" />
+            </template>
+            <div v-if="props" class="order-detail__container g-form__container">
+                <CellGroup title="掉期成交信息">
+                    <Cell title="商品代码/名称" :value="selectedRow.goodscode+'/'+selectedRow.goodsname"/>
+                    <Cell title="方向" :value="getBuyOrSellName(selectedRow.buyorsell)" />
+                    <Cell title="类型" :value="getBuildTypeName(selectedRow.buildtype)" />
+                    <Cell title="成交数量" :value="formatDecimal(selectedRow.tradeqty)" />
+                    <Cell title="成交价格" :value="formatDecimal(selectedRow.tradeprice)" />
+                    <Cell title="手续费" :value="formatDecimal(selectedRow.charge)" />
+                    <Cell title="平仓损益" :value="formatDecimal(selectedRow.closepl)" />
+                    <Cell title="对手方" :value="selectedRow.matchaccountid" />
+                    <Cell title="成交时间" :value="formatDate(selectedRow.tradetime)" />
+                    <Cell title="成交单号" :value="selectedRow.tradeid" />
+                </CellGroup>
+            </div>
+            <div v-else>
+                <Empty />
+            </div>
+        </app-view>
+    </app-modal>
+</template>
+
+<script lang="ts" setup>
+import { shallowRef, PropType } from 'vue'
+import { CellGroup, Cell } from 'vant'
+import { formatDate, formatDecimal } from '@/filters'
+import AppModal from '@/components/base/modal/index.vue'
+import { getBuyOrSellName, getBuildTypeName } from '@/constants/order'
+
+const showModal = shallowRef(true)
+const refresh = shallowRef(false) // 是否刷新父组件数据
+
+const props = defineProps({
+    selectedRow: {
+        type: Object as PropType<Model.TradeDetailRsp>,
+        required: true,
+    }
+})
+
+// 关闭弹窗
+const closed = (isRefresh = false) => {
+    refresh.value = isRefresh
+    showModal.value = false
+}
+
+// 暴露组件属性给父组件调用
+defineExpose({
+    closed,
+})
+</script>

+ 96 - 0
src/packages/mobile/views/order/list/components/goodstrade/list/Index.vue

@@ -0,0 +1,96 @@
+<!-- 我的订单-订单成交 -->
+<template>
+    <app-pull-refresh ref="pullRefreshRef" v-model:loading="loading" v-model:error="error" v-model:pageIndex="pageIndex"
+        :page-count="pageCount" @refresh="run">
+        <div class="g-order-list">
+            <div class="g-order-list__box" v-for="(item, index) in dataList" :key="index">
+                <div class="g-order-list__titlebar">
+                    <div class="left">
+                        <h5>{{ item.goodscode }}/{{ item.goodsname }}</h5>
+                    </div>
+                    <div class="right">
+                        <span>{{ item.tradeid }}</span>
+                    </div>
+                </div>
+                <div class="g-order-list__content">
+                    <ul>
+                        <li>
+                            <span>时间:</span>
+                            <span>{{ formatDate(item.tradetime, 'HH:mm:ss') }}</span>
+                        </li>
+                        <li>
+                            <span>类型:</span>
+                            <span>{{ getBuildTypeName(item.buildtype) }}{{ getBuyOrSellName(item.buyorsell) }}</span>
+                        </li>
+                        <li>
+                            <span>成交价格:</span>
+                            <span>{{ formatDecimal(item.tradeprice) }}</span>
+                        </li>
+                        <li>
+                            <span>手续费:</span>
+                            <span>{{ formatDecimal(item.charge)}}</span>
+                        </li>
+                        <li>
+                            <span>成交数量:</span>
+                            <span>{{ formatDecimal(item.tradeqty) }}</span>
+                        </li>
+                        <li>
+                            <span>平仓盈亏:</span>
+                            <span>{{ formatDecimal(item.closepl) }}</span>
+                        </li>
+                    </ul>
+                </div>
+                <div class="g-order-list__btnbar">
+                    <Button size="small" @click="showComponent('detail', item)" round>详情</Button>
+                </div>
+            </div>
+        </div>
+        <component ref="componentRef" v-bind="{ selectedRow }" :is="componentMap.get(componentId)" @closed="closeComponent"
+            v-if="componentId" />
+    </app-pull-refresh>
+</template>
+
+<script lang="ts" setup>
+import { shallowRef, defineAsyncComponent } from 'vue'
+import { Button } from 'vant'
+import { useComponent } from '@/hooks/component'
+import { useRequest } from '@/hooks/request'
+import { queryTradeDetail } from '@/services/api/order'
+import AppPullRefresh from '@mobile/components/base/pull-refresh/index.vue'
+import { getBuyOrSellName, getBuildTypeName } from '@/constants/order'
+import { formatDate, formatDecimal } from '@/filters'
+
+const componentMap = new Map<string, unknown>([
+    ['detail', defineAsyncComponent(() => import('../detail/Index.vue'))],
+])
+
+const dataList = shallowRef<Model.TradeDetailRsp[]>([])
+const selectedRow = shallowRef<Model.TradeDetailRsp>()
+const error = shallowRef(false)
+const pullRefreshRef = shallowRef()
+
+const { componentRef, componentId, openComponent, closeComponent } = useComponent(() => {
+    pullRefreshRef.value?.refresh()
+})
+
+const { loading, pageIndex, pageCount, run } = useRequest(queryTradeDetail, {
+    params: {
+        pagesize: 20,
+        tradeMode: '50'
+    },
+    onSuccess: (res) => {
+        if (pageIndex.value === 1) {
+            dataList.value = []
+        }
+        dataList.value.push(...res.data)
+    },
+    onError: () => {
+        error.value = true
+    }
+})
+
+const showComponent = (componentName: string, row: Model.TradeDetailRsp) => {
+    selectedRow.value = row
+    openComponent(componentName)
+}
+</script>

+ 54 - 0
src/packages/mobile/views/order/list/components/hisgoodsorder/detail/Index.vue

@@ -0,0 +1,54 @@
+<!-- 我的订单- 历史订单订单 - 详情 -->
+<template>
+    <app-modal direction="right" height="100%" v-model:show="showModal" :refresh="refresh">
+        <app-view class="g-form">
+            <template #header>
+                <app-navbar title="详细" @back="closed" />
+            </template>
+            <div v-if="props" class="order-detail__container g-form__container">
+                <CellGroup title="掉期订单信息">
+                    <Cell title="商品代码/名称" :value="selectedRow.goodscode+'/'+selectedRow.goodsname"/>
+                    <Cell title="方向" :value="getBuyOrSellName(selectedRow.buyorsell)" />
+                    <Cell title="委托数量" :value="formatDecimal(selectedRow.orderqty)" />
+                    <Cell title="委托价格" :value="formatDecimal(selectedRow.orderprice)" />
+                    <Cell title="成交数量" :value="formatDecimal(selectedRow.tradeqty)" />
+                    <Cell title="委托状态" :value="getWRTradeOrderStatusName(selectedRow.orderstatus)" />
+                    <Cell title="委托时间" :value="formatDate(selectedRow.ordertime)" />
+                    <Cell title="委托单号" :value="selectedRow.orderid" />
+                </CellGroup>
+            </div>
+            <div v-else>
+                <Empty />
+            </div>
+        </app-view>
+    </app-modal>
+</template>
+
+<script lang="ts" setup>
+import { shallowRef, PropType } from 'vue'
+import AppModal from '@/components/base/modal/index.vue'
+import { CellGroup, Cell } from 'vant'
+import { getBuyOrSellName, getWRTradeOrderStatusName } from '@/constants/order'
+import { formatDate, formatDecimal } from '@/filters'
+
+const showModal = shallowRef(true)
+const refresh = shallowRef(false) // 是否刷新父组件数据
+
+const props = defineProps({
+    selectedRow: {
+        type: Object as PropType<Model.TradeOrderDetailRsp>,
+        required: true,
+    }
+})
+
+// 关闭弹窗
+const closed = (isRefresh = false) => {
+    refresh.value = isRefresh
+    showModal.value = false
+}
+
+// 暴露组件属性给父组件调用
+defineExpose({
+    closed,
+})
+</script>

+ 143 - 0
src/packages/mobile/views/order/list/components/hisgoodsorder/list/Index.vue

@@ -0,0 +1,143 @@
+<!-- 我的订单- 订单订单 - 委托 -->
+<template>
+    <app-modal direction="right" height="100%" v-model:show="showModal" :refresh="refresh">
+        <app-view class="g-form">
+            <template #header>
+                <app-navbar title="历史订单委托" @back="closed" />
+            </template>
+            <Cell title="查询日期" :value="date" @click="show = true" is-link></Cell>
+            <app-pull-refresh ref="pullRefreshRef" v-model:loading="loading" v-model:error="error" v-model:pageIndex="pageIndex"
+        :page-count="pageCount" @refresh="run">
+                <div class="g-order-list">
+                    <div class="g-order-list__box" v-for="(item, index) in dataList" :key="index">
+                        <div class="g-order-list__titlebar">
+                            <div class="left">
+                                <h5>{{ item.goodscode }}/{{ item.goodsname }}</h5>
+                            </div>
+                            <div class="right">
+                                <span>{{ item.orderid }}</span>
+                            </div>
+                        </div>
+                        <div class="g-order-list__content">
+                            <ul>
+                                <li>
+                                    <span>时间:</span>
+                                    <span>{{ formatDate(item.ordertime, 'YY/MM/DD HH:mm:ss') }}</span>
+                                </li>
+                                <li>
+                                    <span>方向:</span>
+                                    <span>{{ getBuyOrSellName(item.buyorsell) }}</span>
+                                </li>
+                                <li>
+                                    <span>委托数量:</span>
+                                    <span>{{ item.orderqty }}</span>
+                                </li>
+                                <li>
+                                    <span>委托价格:</span>
+                                    <span>{{ item.orderprice}}</span>
+                                </li>
+                                <li>
+                                    <span>成交数量:</span>
+                                    <span>{{ item.tradeqty }}</span>
+                                </li>
+                                <li>
+                                    <span>委托状态:</span>
+                                    <span>{{ getWRTradeOrderStatusName(item.orderstatus) }}</span>
+                                </li>
+                            </ul>
+                        </div>
+                        <div class="g-order-list__btnbar">
+                            <Button size="small" @click="showComponent('detail', item)" round>详情</Button>
+                        </div>
+                    </div>
+                </div>
+                <component ref="componentRef" v-bind="{ selectedRow }" :is="componentMap.get(componentId)" @closed="closeComponent"
+                    v-if="componentId" />
+            </app-pull-refresh>
+            <Calendar :show="show" type="range" :max-date="new Date()" :min-date="moment().subtract(1, 'years').toDate()"
+            @close="onClose" @confirm="onConfirm" />
+        </app-view>
+    </app-modal>
+</template>
+
+<script lang="ts" setup>
+import { shallowRef, ref, reactive, defineAsyncComponent } from 'vue'
+import { useRequest } from '@/hooks/request'
+import { queryHisTradeOrderDetail } from '@/services/api/order'
+import { getBuyOrSellName, getWRTradeOrderStatusName } from '@/constants/order'
+import { formatDate } from '@/filters'
+import { useComponent } from '@/hooks/component'
+import { Button, Calendar, Cell } from 'vant'
+import moment from 'moment'
+import AppModal from '@/components/base/modal/index.vue'
+import AppPullRefresh from '@mobile/components/base/pull-refresh/index.vue'
+
+const dataList = shallowRef<Model.HisTradeOrderDetailRsp[]>([])
+const showModal = shallowRef(true)
+/// 是否显示日历
+const show = shallowRef(false)
+/// 显示日期
+const date = ref('')
+const selectedRow = shallowRef<Model.HisTradeOrderDetailRsp>()
+const error = shallowRef(false)
+const pullRefreshRef = shallowRef()
+const refresh = shallowRef(false) // 是否刷新父组件数据
+
+const { componentRef, componentId, openComponent, closeComponent } = useComponent(() => {
+    pullRefreshRef.value?.refresh()
+})
+
+const componentMap = new Map<string, unknown>([
+    ['detail', defineAsyncComponent(() => import('../detail/Index.vue'))],
+])
+
+const formData = reactive<Model.HisTradeOrderDetailReq>({
+    tradeMode: '50',
+})
+
+const { loading, pageIndex, pageCount, run } = useRequest(queryHisTradeOrderDetail, {
+    manual: true,
+    params: {
+        ...formData
+    },
+    onSuccess: (res) => {
+        if (pageIndex.value === 1) {
+            dataList.value = []
+        }
+        dataList.value.push(...res.data)
+    },
+    onError: () => {
+        error.value = true
+    }
+})
+
+const showComponent = (componentName: string, row: Model.HisTradeOrderDetailRsp) => {
+    selectedRow.value = row
+    openComponent(componentName)
+}
+
+const onClose = () => {
+    show.value = false
+}
+
+const onConfirm = (values: Date[]) => {
+    const [start, end] = values;
+    show.value = false
+    formData.startDate = formatDate(start.toString(), 'YYYYMMDD')
+    formData.endDate = formatDate(end.toString(), 'YYYYMMDD')
+    date.value = formData.startDate + '-' + formData.endDate
+    /// 查询
+    pullRefreshRef.value?.refresh()
+}
+
+// 关闭弹窗
+const closed = (isRefresh = false) => {
+    refresh.value = isRefresh
+    showModal.value = false
+}
+
+// 暴露组件属性给父组件调用
+defineExpose({
+    closed,
+})
+</script>

+ 56 - 0
src/packages/mobile/views/order/list/components/hisgoodstrade/detail/Index.vue

@@ -0,0 +1,56 @@
+<!-- 我的持仓- 历史订单成交 - 平仓 -->
+<template>
+    <app-modal direction="right" height="100%" v-model:show="showModal" :refresh="refresh">
+        <app-view class="g-form">
+            <template #header>
+                <app-navbar title="详细" @back="closed" />
+            </template>
+            <div v-if="props" class="order-detail__container g-form__container">
+                <CellGroup title="掉期订单信息">
+                    <Cell title="商品代码/名称" :value="selectedRow.goodscode+'/'+selectedRow.goodsname"/>
+                    <Cell title="方向" :value="getBuyOrSellName(selectedRow.buyorsell)" />
+                    <Cell title="类型" :value="getBuildTypeName(selectedRow.buildtype)" />
+                    <Cell title="成交数量" :value="formatDecimal(selectedRow.tradeqty)" />
+                    <Cell title="成交价格" :value="formatDecimal(selectedRow.tradeprice)" />
+                    <Cell title="手续费" :value="formatDecimal(selectedRow.charge)" />
+                    <Cell title="平仓损益" :value="formatDecimal(selectedRow.closepl)" />
+                    <Cell title="对手方" :value="selectedRow.matchaccountid" />
+                    <Cell title="成交时间" :value="formatDate(selectedRow.tradetime)" />
+                    <Cell title="成交单号" :value="selectedRow.tradeid" />
+                </CellGroup>
+            </div>
+            <div v-else>
+                <Empty />
+            </div>
+        </app-view>
+    </app-modal>
+</template>
+
+<script lang="ts" setup>
+import { shallowRef, PropType } from 'vue'
+import { CellGroup, Cell } from 'vant'
+import AppModal from '@/components/base/modal/index.vue'
+import { formatDate, formatDecimal } from '@/filters'
+import { getBuyOrSellName, getBuildTypeName } from '@/constants/order'
+
+const showModal = shallowRef(true)
+const refresh = shallowRef(false) // 是否刷新父组件数据
+
+const props = defineProps({
+    selectedRow: {
+        type: Object as PropType<Model.HisTradeDetailRsp>,
+        required: true,
+    }
+})
+
+// 关闭弹窗
+const closed = (isRefresh = false) => {
+    refresh.value = isRefresh
+    showModal.value = false
+}
+
+// 暴露组件属性给父组件调用
+defineExpose({
+    closed,
+})
+</script>

+ 143 - 0
src/packages/mobile/views/order/list/components/hisgoodstrade/list/Index.vue

@@ -0,0 +1,143 @@
+<!-- 我的订单- 订单订单 - 成交 -->
+<template>
+    <app-modal direction="right" height="100%" v-model:show="showModal" :refresh="refresh">
+        <app-view class="g-form">
+            <template #header>
+                <app-navbar title="历史订单成交" @back="closed" />
+            </template>
+            <Cell title="查询日期" :value="date" @click="show = true" is-link></Cell>
+            <app-pull-refresh ref="pullRefreshRef" v-model:loading="loading" v-model:error="error" v-model:pageIndex="pageIndex"
+        :page-count="pageCount" @refresh="run">
+                <div class="g-order-list">
+                    <div class="g-order-list__box" v-for="(item, index) in dataList" :key="index">
+                        <div class="g-order-list__titlebar">
+                            <div class="left">
+                                <h5>{{ item.goodscode }}/{{ item.goodsname }}</h5>
+                            </div>
+                            <div class="right">
+                                <span>{{ item.tradeid }}</span>
+                            </div>
+                        </div>
+                        <div class="g-order-list__content">
+                            <ul>
+                                <li>
+                                    <span>时间:</span>
+                                    <span>{{ formatDate(item.tradetime, 'YY/MM/DD HH:mm:ss') }}</span>
+                                </li>
+                                <li>
+                                    <span>类型:</span>
+                                    <span>{{ getBuildTypeName(item.buildtype) }}{{ getBuyOrSellName(item.buyorsell) }}</span>
+                                </li>
+                                <li>
+                                    <span>成交价格:</span>
+                                    <span>{{ item.tradeprice }}</span>
+                                </li>
+                                <li>
+                                    <span>手续费:</span>
+                                    <span>{{ item.charge}}</span>
+                                </li>
+                                <li>
+                                    <span>成交数量:</span>
+                                    <span>{{ item.tradeqty }}</span>
+                                </li>
+                                <li>
+                                    <span>平仓盈亏:</span>
+                                    <span>{{ item.closepl }}</span>
+                                </li>
+                            </ul>
+                        </div>
+                        <div class="g-order-list__btnbar">
+                            <Button size="small" @click="showComponent('detail', item)" round>详情</Button>
+                        </div>
+                    </div>
+                </div>
+                <component ref="componentRef" v-bind="{ selectedRow }" :is="componentMap.get(componentId)" @closed="closeComponent"
+                    v-if="componentId" />
+            </app-pull-refresh>
+            <Calendar :show="show" type="range" :max-date="new Date()" :min-date="moment().subtract(1, 'years').toDate()"
+            @close="onClose" @confirm="onConfirm" />
+        </app-view>
+    </app-modal>
+</template>
+
+<script lang="ts" setup>
+import { shallowRef, ref, reactive, defineAsyncComponent } from 'vue'
+import { useRequest } from '@/hooks/request'
+import { queryHisTradeDetail } from '@/services/api/order'
+import { getBuyOrSellName, getBuildTypeName } from '@/constants/order'
+import { formatDate } from '@/filters'
+import { useComponent } from '@/hooks/component'
+import { Button, Calendar, Cell } from 'vant'
+import moment from 'moment'
+import AppModal from '@/components/base/modal/index.vue'
+import AppPullRefresh from '@mobile/components/base/pull-refresh/index.vue'
+
+const dataList = shallowRef<Model.HisTradeDetailRsp[]>([])
+const showModal = shallowRef(true)
+/// 是否显示日历
+const show = shallowRef(false)
+/// 显示日期
+const date = ref('')
+const selectedRow = shallowRef<Model.HisTradeDetailRsp>()
+const error = shallowRef(false)
+const pullRefreshRef = shallowRef()
+const refresh = shallowRef(false) // 是否刷新父组件数据
+
+const { componentRef, componentId, openComponent, closeComponent } = useComponent(() => {
+    pullRefreshRef.value?.refresh()
+})
+
+const componentMap = new Map<string, unknown>([
+    ['detail', defineAsyncComponent(() => import('../detail/Index.vue'))],
+])
+
+const formData = reactive<Model.HisTradeDetailReq>({
+    tradeMode: '50'
+})
+
+const { loading, pageIndex, pageCount, run } = useRequest(queryHisTradeDetail, {
+    manual: true,
+    params: {
+        ...formData
+    },
+    onSuccess: (res) => {
+        if (pageIndex.value === 1) {
+            dataList.value = []
+        }
+        dataList.value.push(...res.data)
+    },
+    onError: () => {
+        error.value = true
+    }
+})
+
+const showComponent = (componentName: string, row: Model.HisTradeDetailRsp) => {
+    selectedRow.value = row
+    openComponent(componentName)
+}
+
+const onClose = () => {
+    show.value = false
+}
+
+const onConfirm = (values: Date[]) => {
+    const [start, end] = values;
+    show.value = false
+    formData.startDate = formatDate(start.toString(), 'YYYYMMDD')
+    formData.endDate = formatDate(end.toString(), 'YYYYMMDD')
+    date.value = formData.startDate + '-' + formData.endDate
+    /// 查询
+    pullRefreshRef.value?.refresh()
+}
+
+// 关闭弹窗
+const closed = (isRefresh = false) => {
+    refresh.value = isRefresh
+    showModal.value = false
+}
+
+// 暴露组件属性给父组件调用
+defineExpose({
+    closed,
+})
+</script>

+ 2 - 0
src/packages/mobile/views/order/position/Index.vue

@@ -14,6 +14,7 @@
                 <component :is="componentMap.get('swap')" />
             </Tab>
             <Tab title="订单持仓">
+                <component :is="componentMap.get('goods')" />
             </Tab>
             <Tab title="现货持仓">
                 <component :is="componentMap.get('spot')" />
@@ -31,6 +32,7 @@ const componentMap = new Map<string, unknown>([
     ['transfer', defineAsyncComponent(() => import('./components/transfer/list/Index.vue'))], // 转让持仓
     ['spot', defineAsyncComponent(() => import('./components/spot/list/Index.vue'))], // 现货持仓
     ['swap', defineAsyncComponent(() => import('./components/swap/list/Index.vue'))], // 掉期持仓
+    ['goods', defineAsyncComponent(() => import('./components/goods/list/Index.vue'))], // 订单持仓
 ])
 
 const active = shallowRef(0)

+ 0 - 0
src/packages/mobile/views/order/position/components/goods/close/Index.vue


+ 0 - 0
src/packages/mobile/views/order/position/components/goods/delivery/Index.vue


+ 101 - 0
src/packages/mobile/views/order/position/components/goods/list/Index.vue

@@ -0,0 +1,101 @@
+<!-- 我的持仓-掉期持仓 -->
+<template>
+    <app-pull-refresh ref="pullRefreshRef" v-model:loading="loading" v-model:error="error" v-model:pageIndex="pageIndex"
+        :page-count="pageCount" @refresh="run">
+        <div class="g-order-list">
+            <div class="g-order-list__box" v-for="(item, index) in dataList" :key="index">
+                <div class="g-order-list__titlebar">
+                    <div class="left">
+                        <h4>{{ item.goodscode }}/{{ item.goodsname }}</h4>
+                        <span>--</span>
+                    </div>
+                    <div class="right">
+                        <span>{{ getBuyOrSellName(item.buyorsell) }}</span>
+                    </div>
+                </div>
+                <div class="g-order-list__content">
+                    <ul>
+                        <li>
+                            <span>持有数量:</span>
+                            <span>{{ formatDecimal(item.curpositionqty) }}</span>
+                        </li>
+                        <li>
+                            <span>持仓均价:</span>
+                            <span>{{ item.averageprice === 0.0 ? '--' : formatDecimal(item.averageprice) }}</span>
+                        </li>
+                        <li>
+                            <span>冻结数量:</span>
+                            <span>{{ formatDecimal(item.frozenqty) }}</span>
+                        </li>
+                        <li>
+                            <span>持仓金额:</span>
+                            <span>{{ formatDecimal(item.curholderamount) }}</span>
+                        </li>
+                        <li>
+                            <span>可用数量:</span>
+                            <span>{{ formatDecimal(item.enableqty) }}</span>
+                        </li>
+                        <li>
+                            <span>参考损益:</span>
+                            <span>--</span>
+                        </li>
+                    </ul>
+                </div>
+                <div class="g-order-list__btnbar">
+                    <Button size="small" @click="showComponent('close', item)" round>平仓</Button>
+                    <Button size="small" v-if="userStore.userType === 5" @click="showComponent('delivery', item)" round>交收</Button>
+                </div>
+            </div>
+        </div>
+        <component ref="componentRef" v-bind="{ selectedRow }" :is="componentMap.get(componentId)" @closed="closeComponent"
+            v-if="componentId" />
+    </app-pull-refresh>
+</template>
+
+<script lang="ts" setup>
+import { shallowRef, defineAsyncComponent } from 'vue'
+import { Button } from 'vant'
+import { useComponent } from '@/hooks/component'
+import { useRequest } from '@/hooks/request'
+import { queryTradePosition } from '@/services/api/order'
+import AppPullRefresh from '@mobile/components/base/pull-refresh/index.vue'
+import { getBuyOrSellName } from '@/constants/order'
+import { formatDecimal } from '@/filters'
+import { useUserStore } from '@/stores'
+
+const componentMap = new Map<string, unknown>([
+    ['close', defineAsyncComponent(() => import('../close/Index.vue'))],
+    ['delivery', defineAsyncComponent(() => import('../delivery/Index.vue'))]
+])
+
+const userStore = useUserStore()
+const dataList = shallowRef<Model.TradePositionRsp[]>([])
+const selectedRow = shallowRef<Model.TradePositionRsp>()
+const error = shallowRef(false)
+const pullRefreshRef = shallowRef()
+
+const { componentRef, componentId, openComponent, closeComponent } = useComponent(() => {
+    pullRefreshRef.value?.refresh()
+})
+
+const { loading, pageIndex, pageCount, run } = useRequest(queryTradePosition, {
+    params: {
+        pagesize: 20,
+        tradeMode: '50'
+    },
+    onSuccess: (res) => {
+        if (pageIndex.value === 1) {
+            dataList.value = []
+        }
+        dataList.value.push(...res.data)
+    },
+    onError: () => {
+        error.value = true
+    }
+})
+
+const showComponent = (componentName: string, row: Model.TradePositionRsp) => {
+    selectedRow.value = row
+    openComponent(componentName)
+}
+</script>

+ 2 - 2
src/packages/mobile/views/swap/detail/components/delisting/Index.vue

@@ -36,12 +36,12 @@
             </Field>
             <Field name="OrderQty" :rules="formRules.OrderQty" label="挂牌数量">
                 <template #input>
-                    <Stepper v-model="formData.OrderQty" theme="round" button-size="22" :min="0" :step="0.01" :max="selectedRow.orderqty" :auto-fixed="false" />
+                    <Stepper v-model="formData.OrderQty" input-width="100" theme="round" button-size="22" :min="0" :step="0.01" :max="selectedRow.orderqty" :auto-fixed="false" />
                 </template>
             </Field>
             <Field name="OrderPrice" v-if="priceMove === 2" :rules="formRules.OrderPrice" label="摘牌价格">
                 <template #input>
-                    <Stepper v-model="formData.OrderPrice" theme="round" button-size="22" :min="0" :auto-fixed="false" />
+                    <Stepper v-model="formData.OrderPrice" input-width="100" theme="round" button-size="22" :min="0" :auto-fixed="false" />
                 </template>
             </Field>
             <Field label="估算金额" v-if="priceMove === 3">

+ 3 - 3
src/packages/mobile/views/swap/detail/components/listing/Index.vue

@@ -20,12 +20,12 @@
             </Field>
             <Field name="OrderPrice" :rules="formRules.OrderPrice" label="挂牌价格" v-if="priceMove === 2">
                 <template #input>
-                    <Stepper v-model="formData.OrderPrice" theme="round" button-size="22" :auto-fixed="false" :step="0.01" />
+                    <Stepper v-model="formData.OrderPrice" input-width="100" theme="round" button-size="22" :auto-fixed="false" :step="0.01" />
                 </template>
             </Field>
             <Field name="MarketMaxSub" :rules="formRules.MarketMaxSub" label="点差" v-if="priceMove === 3">
                 <template #input>
-                    <Stepper v-model="formData.MarketMaxSub" theme="round" button-size="22" :auto-fixed="false" :step="0.01" />
+                    <Stepper v-model="formData.MarketMaxSub" input-width="100" theme="round" button-size="22" :auto-fixed="false" :step="0.01" />
                 </template>
             </Field>
             <Field label="估算价格" v-if="priceMove === 3">
@@ -40,7 +40,7 @@
             </Field>
             <Field name="OrderQty" :rules="formRules.OrderQty" label="挂牌数量">
                 <template #input>
-                    <Stepper v-model="formData.OrderQty" theme="round" button-size="22" :auto-fixed="false" integer />
+                    <Stepper v-model="formData.OrderQty" input-width="100" theme="round" button-size="22" :auto-fixed="false" integer />
                 </template>
             </Field>
             <Field label="挂牌金额" v-if="priceMove === 2">