li.shaoyi 2 anni fa
parent
commit
803a2b366c

+ 46 - 0
src/business/presale/index.ts

@@ -0,0 +1,46 @@
+import { shallowRef, reactive } from 'vue'
+import { v4 } from 'uuid'
+import { formatDate } from '@/filters'
+import { ClientType } from '@/constants/client'
+import { BuyOrSell } from '@/constants/order'
+import { order } from '@/services/api/presale'
+import { useLoginStore, useAccountStore } from '@/stores'
+
+const loginStore = useLoginStore()
+const accountStore = useAccountStore()
+
+export function useOrder(selectedRow: Model.PresaleAuctionsRsp) {
+    const loading = shallowRef(false)
+
+    const formData = reactive<Partial<Proto.OrderReq>>({
+        ClientType: ClientType.Web, // 终端类型
+        LoginID: loginStore.loginId, // 登陆账号
+        AccountID: accountStore.accountId, // 交易账号
+        GoodsID: selectedRow.goodsid, // 商品ID
+        MarketID: 48201, // 市场ID
+        ValidType: 1, // 校验类型
+        BuyOrSell: BuyOrSell.Buy, // 买卖方向
+        DelistingType: 2, // 摘牌类型
+    })
+
+    const formSubmit = async () => {
+        try {
+            loading.value = true
+            return await order({
+                data: {
+                    ClientSerialNo: v4(),
+                    ClientOrderTime: formatDate(new Date().toISOString(), 'YYYY-MM-DD HH:mm:ss'),
+                    ...formData,
+                }
+            })
+        } finally {
+            loading.value = false
+        }
+    }
+
+    return {
+        loading,
+        formData,
+        formSubmit,
+    }
+}

+ 5 - 0
src/constants/funcode.ts

@@ -89,4 +89,9 @@ export enum FunCode {
 
     SpotPresalePointPriceReq = 1441877, // 铁合金预售点价请求
     SpotPresalePointPriceRsp = 1441878, // 铁合金预售点价响应
+
+    OrderReq = 196609, // 交易委托请求
+    OrderRsp = 196610, // 交易委托应答
+    CancelOrderReq = 196611, // 撤单请求
+    CancelOrderRsp = 196612, // 撤单应答
 } 

+ 9 - 1
src/packages/mobile/assets/themes/global/global.less

@@ -105,6 +105,9 @@
     }
 }
 
+/* 商品列表 */
+.g-goods-list {}
+
 /* 订单列表 */
 .g-order-list {
     padding: .2rem;
@@ -123,13 +126,17 @@
     &__titlebar {
         display: flex;
         justify-content: space-between;
-        align-items: center;
         margin-bottom: .2rem;
 
         .left {
             h4 {
                 font-weight: bold;
             }
+
+            span {
+                font-size: .24rem;
+                color: #999;
+            }
         }
 
         .right {
@@ -149,6 +156,7 @@
             li {
                 display: flex;
                 justify-content: space-between;
+                line-height: .4rem;
                 width: calc(~"50% - .24rem");
 
                 span {

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

@@ -9,6 +9,7 @@
             <Tab title="线下交收单">
             </Tab>
             <Tab title="现货提货单">
+                <Spot />
             </Tab>
         </Tabs>
     </app-view>
@@ -17,6 +18,7 @@
 <script lang="ts" setup>
 import { shallowRef } from 'vue'
 import { Tab, Tabs } from 'vant'
+import Spot from './components/spot/list/Index.vue'
 
 const active = shallowRef(0)
 </script>

+ 60 - 0
src/packages/mobile/views/order/delivery/components/spot/detail/Index.vue

@@ -0,0 +1,60 @@
+<!-- 交收提货-现货提货单-详情 -->
+<template>
+    <app-modal direction="right" height="100%" v-model:show="showModal">
+        <app-view class="g-form">
+            <template #header>
+                <app-navbar title="现货提货单" @back="closed" />
+            </template>
+            <div class="g-form__container">
+                <CellGroup title="提货信息">
+                    <Cell title="商品代码/名称" :value="selectedRow.wrstandardname" />
+                    <Cell title="仓库" :value="selectedRow.warehousename" />
+                    <Cell title="提货数量" :value="selectedRow.qty" />
+                    <Cell title="提货方式" :value="selectedRow.appointmentmodeldisplay" />
+                    <Cell title="联系人" :value="selectedRow.contactname" />
+                    <Cell title="联系方式" :value="selectedRow.contactnum" />
+                    <Cell title="收货地址" :value="address" v-if="selectedRow.appointmentmodel === 1" />
+                    <Cell title="发票信息" title-style="flex:none" v-if="selectedRow.appointmentremark">
+                        <template #value>
+                            <div style="white-space: pre-line">{{ selectedRow.appointmentremark }}</div>
+                        </template>
+                    </Cell>
+                    <Cell title="申请时间" :value="selectedRow.applytime" />
+                    <Cell title="提货状态" :value="getApplyStatusName(selectedRow.applystatus)" />
+                    <Cell title="提货单号" :value="selectedRow.applyid" />
+                </CellGroup>
+            </div>
+        </app-view>
+    </app-modal>
+</template>
+
+<script lang="ts" setup>
+import { shallowRef, PropType, computed } from 'vue'
+import { CellGroup, Cell } from 'vant'
+import { getApplyStatusName } from '@/constants/order'
+import AppModal from '@/components/base/modal/index.vue'
+
+const props = defineProps({
+    selectedRow: {
+        type: Object as PropType<Model.WrOutInApplyRsp>,
+        required: true,
+    }
+})
+
+const showModal = shallowRef(true)
+
+const address = computed(() => {
+    const { provincename, cityname, districtname, address } = props.selectedRow
+    return [provincename, cityname, districtname, address].join(' ')
+})
+
+// 关闭弹窗
+const closed = () => {
+    showModal.value = false
+}
+
+// 暴露组件属性给父组件调用
+defineExpose({
+    closed,
+})
+</script>

+ 88 - 0
src/packages/mobile/views/order/delivery/components/spot/list/Index.vue

@@ -0,0 +1,88 @@
+<!-- 交收提货-现货提货单 -->
+<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.wrstandardname }}</h4>
+                        <span>{{ item.applyid }}</span>
+                    </div>
+                    <div class="right">
+                        <span>{{ getApplyStatusName(item.applystatus) }}</span>
+                    </div>
+                </div>
+                <div class="g-order-list__content">
+                    <ul>
+                        <li>
+                            <span>数量</span>
+                            <span>{{ item.qty }}</span>
+                        </li>
+                        <li>
+                            <span>类型</span>
+                            <span>{{ item.appointmentmodeldisplay }}</span>
+                        </li>
+                        <li>
+                            <span>仓库</span>
+                            <span>{{ item.warehousename }}</span>
+                        </li>
+                        <li>
+                            <span>时间</span>
+                            <span>{{ formatDate(item.applytime, 'YYYY-MM-DD') }}</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 { formatDate } from '@/filters'
+import { useComponent } from '@/hooks/component'
+import { useRequest } from '@/hooks/request'
+import { getApplyStatusName } from '@/constants/order'
+import { queryWrOutInApply } from '@/services/api/order'
+import AppPullRefresh from '@mobile/components/base/pull-refresh/index.vue'
+
+const componentMap = new Map<string, unknown>([
+    ['detail', defineAsyncComponent(() => import('../detail/Index.vue'))],
+])
+
+const dataList = shallowRef<Model.WrOutInApplyRsp[]>([])
+const selectedRow = shallowRef<Model.WrOutInApplyRsp>()
+const error = shallowRef(false)
+const pullRefreshRef = shallowRef()
+
+const { componentRef, componentId, openComponent, closeComponent } = useComponent(() => {
+    pullRefreshRef.value?.refresh()
+})
+
+const { loading, pageIndex, pageCount, run } = useRequest(queryWrOutInApply, {
+    params: {
+        pagesize: 20,
+    },
+    onSuccess: (res) => {
+        if (pageIndex.value === 1) {
+            dataList.value = []
+        }
+        dataList.value.push(...res.data)
+    },
+    onError: () => {
+        error.value = true
+    }
+})
+
+const showComponent = (componentName: string, row: Model.WrOutInApplyRsp) => {
+    selectedRow.value = row
+    openComponent(componentName)
+}
+</script>

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

@@ -1,7 +1,7 @@
 <template>
     <app-view>
         <template #header>
-            <app-navbar title="我的订单" >
+            <app-navbar title="我的订单">
                 <template #right>
                     <div class="button-more" @click="onMoreClick">
                         <span>更多</span>
@@ -11,6 +11,7 @@
         </template>
         <Tabs class="van-tabs--list" v-model:active="active" :swipe-threshold="4">
             <Tab title="预售认购">
+                <Presale />
             </Tab>
             <Tab title="转让委托">
             </Tab>
@@ -31,8 +32,7 @@
             <Tab title="挂牌成交">
             </Tab>
         </Tabs>
-        <component ref="componentRef" :is="componentMap.get(componentId)" @closed="closeComponent"
-            v-if="componentId" />
+        <component ref="componentRef" :is="componentMap.get(componentId)" @closed="closeComponent" v-if="componentId" />
     </app-view>
 </template>
 
@@ -40,7 +40,7 @@
 import { shallowRef, defineAsyncComponent } from 'vue'
 import { Tab, Tabs } from 'vant'
 import { useComponent } from '@/hooks/component'
-
+import Presale from './components/presale/list/Index.vue'
 import SwapOrder from './components/swaporder/list/Index.vue'
 import SwapTrade from './components/swaptrade/list/Index.vue'
 

+ 7 - 0
src/packages/mobile/views/order/list/components/presale/detail/Index.vue

@@ -0,0 +1,7 @@
+<!-- 我的持仓-预售持仓-详情 -->
+<template>
+    详情
+</template>
+
+<script lang="ts" setup>
+</script>

+ 107 - 0
src/packages/mobile/views/order/list/components/presale/list/Index.vue

@@ -0,0 +1,107 @@
+<!-- 我的订单-预售认购 -->
+<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.goodsname }}</h4>
+                        <span>{{ item.orderid }}</span>
+                    </div>
+                    <div class="right">
+                        <span>{{ item.orderstatus }}</span>
+                    </div>
+                </div>
+                <div class="g-order-list__content">
+                    <ul>
+                        <li>
+                            <span>认购量</span>
+                            <span>{{ item.orderqty }}</span>
+                        </li>
+                        <li>
+                            <span>认购价</span>
+                            <span>{{ item.orderprice }}</span>
+                        </li>
+                        <li>
+                            <span>发售方</span>
+                            <span>{{ item.sellname }}</span>
+                        </li>
+                        <li>
+                            <span>起拍价</span>
+                            <span>{{ item.startprice }}</span>
+                        </li>
+                        <li>
+                            <span>开始日期</span>
+                            <span>{{ item.starttime }}</span>
+                        </li>
+                        <li>
+                            <span>结束日期</span>
+                            <span>{{ item.endtime }}</span>
+                        </li>
+                        <li>
+                            <span>预售价</span>
+                            <span>{{ item.tradeprice }}</span>
+                        </li>
+                        <li>
+                            <span>订单量</span>
+                            <span>{{ item.tradeqty }}</span>
+                        </li>
+                        <li>
+                            <span>日期</span>
+                            <span>{{ item.clientordertime }}</span>
+                        </li>
+                    </ul>
+                </div>
+                <div class="g-order-list__btnbar">
+                    <Button size="small" @click="showComponent('detail', item)" round>详情</Button>
+                    <Button size="small" @click="showComponent('pickup', 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 { queryMineTradeOrderDetails } from '@/services/api/presale'
+import AppPullRefresh from '@mobile/components/base/pull-refresh/index.vue'
+
+const componentMap = new Map<string, unknown>([
+    ['detail', defineAsyncComponent(() => import('../detail/Index.vue'))],
+])
+
+const dataList = shallowRef<Model.MineTradeOrderDetailsRsp[]>([])
+const selectedRow = shallowRef<Model.MineTradeOrderDetailsRsp>()
+const error = shallowRef(false)
+const pullRefreshRef = shallowRef()
+
+const { componentRef, componentId, openComponent, closeComponent } = useComponent(() => {
+    pullRefreshRef.value?.refresh()
+})
+
+const { loading, pageIndex, pageCount, run } = useRequest(queryMineTradeOrderDetails, {
+    params: {
+        pagesize: 20,
+    },
+    onSuccess: (res) => {
+        if (pageIndex.value === 1) {
+            dataList.value = []
+        }
+        dataList.value.push(...res.data)
+    },
+    onError: () => {
+        error.value = true
+    }
+})
+
+const showComponent = (componentName: string, row: Model.MineTradeOrderDetailsRsp) => {
+    selectedRow.value = row
+    openComponent(componentName)
+}
+</script>

+ 96 - 1
src/packages/mobile/views/order/position/components/presale/list/Index.vue

@@ -1,7 +1,102 @@
 <!-- 我的持仓-预售持仓 -->
 <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.goodsname }}</h4>
+                    </div>
+                    <div class="right">
+                        <span>{{ item.handlestatus }}</span>
+                    </div>
+                </div>
+                <div class="g-order-list__content">
+                    <ul>
+                        <li>
+                            <span>认购数量</span>
+                            <span>{{ item.tradeqty }}</span>
+                        </li>
+                        <li>
+                            <span>预售价</span>
+                            <span>{{ item.openprice }}</span>
+                        </li>
+                        <li>
+                            <span>总货款</span>
+                            <span>{{ item.tradeamount }}</span>
+                        </li>
+                        <li>
+                            <span>转让定金比例</span>
+                            <span>{{ item.transferdepositratio }}</span>
+                        </li>
+                        <li>
+                            <span>转让定金</span>
+                            <span>{{ item.transferdeposit }}</span>
+                        </li>
+                        <li>
+                            <span>未付定金</span>
+                            <span>{{ item.depositremain }}</span>
+                        </li>
+                        <li>
+                            <span>发售方</span>
+                            <span>{{ item.sellname }}</span>
+                        </li>
+                        <li>
+                            <span>结束日期</span>
+                            <span>{{ item.endtime }}</span>
+                        </li>
+                    </ul>
+                </div>
+                <div class="g-order-list__btnbar">
+                    <Button size="small" @click="showComponent('detail', item)" round>详情</Button>
+                    <Button size="small" @click="showComponent('pickup', 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 { queryMineCpTradePreSaleResults } from '@/services/api/presale'
+import AppPullRefresh from '@mobile/components/base/pull-refresh/index.vue'
+
+const componentMap = new Map<string, unknown>([
+    ['detail', defineAsyncComponent(() => import('../detail/Index.vue'))],
+])
+
+const dataList = shallowRef<Model.MineCpTradePreSaleResultsRsp[]>([])
+const selectedRow = shallowRef<Model.MineCpTradePreSaleResultsRsp>()
+const error = shallowRef(false)
+const pullRefreshRef = shallowRef()
+
+const { componentRef, componentId, openComponent, closeComponent } = useComponent(() => {
+    pullRefreshRef.value?.refresh()
+})
+
+const { loading, pageIndex, pageCount, run } = useRequest(queryMineCpTradePreSaleResults, {
+    params: {
+        pagesize: 20,
+    },
+    onSuccess: (res) => {
+        if (pageIndex.value === 1) {
+            dataList.value = []
+        }
+        dataList.value.push(...res.data)
+    },
+    onError: () => {
+        error.value = true
+    }
+})
+
+const showComponent = (componentName: string, row: Model.MineCpTradePreSaleResultsRsp) => {
+    selectedRow.value = row
+    openComponent(componentName)
+}
 </script>

+ 1 - 1
src/packages/mobile/views/order/position/components/spot/pickup/Index.vue

@@ -191,7 +191,7 @@ const receiptChange = (item: Model.WrUserReceiptInfoRsp) => {
 const onSubmit = () => {
     fullloading((hideLoading) => {
         applySubmit().then(() => {
-            hideLoading('挂牌成功', 'success')
+            hideLoading('提交成功', 'success')
             closed(true)
         }).catch((err) => {
             hideLoading(err, 'fail')

+ 58 - 3
src/packages/mobile/views/presale/detail/Index.vue

@@ -1,8 +1,63 @@
 <template>
-    <app-view>
-
+    <app-view class="presale-details">
+        <template #header>
+            <app-navbar title="挂牌详情" />
+        </template>
+        <div class="presale-details__content">
+            <Swipe class="banner" :autoplay="5000" indicator-color="white" lazy-render>
+                <SwipeItem v-for="(url, index) in detailBanners" :key="index">
+                    <img :src="url" />
+                </SwipeItem>
+            </Swipe>
+            <div class="goods">
+                <h4 class="goods-title">{{ detail.goodsname }}</h4>
+            </div>
+            <div class="gallery">
+                <Divider>商品详情</Divider>
+                <template v-for="(url, index) in detailImages" :key="index">
+                    <img :src="url" alt="" />
+                </template>
+            </div>
+        </div>
+        <template #footer>
+            <div class="g-form__footer">
+                <Button type="primary" block round @click="openComponent('buy')">我要出价</Button>
+            </div>
+            <component ref="componentRef" :is="componentMap.get(componentId)" v-bind="{ detail }" @closed="closeComponent"
+                v-if="componentId" />
+        </template>
     </app-view>
 </template>
 
 <script lang="ts" setup>
-</script>
+import { computed, defineAsyncComponent } from 'vue'
+import { Swipe, SwipeItem, Divider, Button } from 'vant'
+import { getFileUrl } from '@/filters'
+import { useComponent } from '@/hooks/component'
+import { useNavigation } from '@/hooks/navigation'
+
+const componentMap = new Map<string, unknown>([
+    ['buy', defineAsyncComponent(() => import('./components/buy/index.vue'))], // 挂牌
+])
+
+const { getParamString } = useNavigation()
+const { componentRef, componentId, openComponent, closeComponent } = useComponent()
+const aa = getParamString('item')
+const detail: Model.PresaleAuctionsRsp = JSON.parse(aa.toString() || '{}')
+
+// 商品banner
+const detailBanners = computed(() => {
+    const bannerpicurl = detail.bannerpicurl ?? ''
+    return bannerpicurl?.split(',').map((path) => getFileUrl(path))
+})
+
+// 商品图片列表
+const detailImages = computed(() => {
+    const pictureurls = detail.pictureurls ?? ''
+    return pictureurls.split(',').map((path) => getFileUrl(path))
+})
+</script>
+
+<style lang="less">
+@import './index.less';
+</style>

+ 13 - 0
src/packages/mobile/views/presale/detail/components/buy/index.less

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

+ 101 - 0
src/packages/mobile/views/presale/detail/components/buy/index.vue

@@ -0,0 +1,101 @@
+<template>
+    <app-popup class="supply-demand-listing" title="出价" v-model:show="showModal" :refresh="refresh">
+        <Form class="supply-demand-listing__form" ref="formRef" @submit="onSubmit">
+            <Field label="起拍价">
+                <template #input>
+                    <span>{{ detail.startprice }}</span>
+                </template>
+            </Field>
+            <Field name="OrderPrice" :rules="formRules.OrderPrice" label="认购价">
+                <template #input>
+                    <Stepper v-model="formData.OrderPrice" theme="round" :decimal-length="2" :auto-fixed="false"
+                        button-size="22" />
+                </template>
+            </Field>
+            <Field name="OrderQty" :rules="formRules.OrderQty" label="认购数量">
+                <template #input>
+                    <Stepper v-model="formData.OrderQty" theme="round" button-size="22" :auto-fixed="false" integer />
+                </template>
+            </Field>
+            <Field label="预售定金">
+                <template #input>
+                    <span>{{ detail.presaledepositvalue }}</span>
+                </template>
+            </Field>
+            <Field label="可用资金">
+                <template #input>
+                    <span>{{ accountStore.avaiableMoney.toFixed(2) }}</span>
+                </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, Field, Stepper, Button, FieldRule, FormInstance } from 'vant'
+import { fullloading, dialog } from '@/utils/vant'
+import { useAccountStore } from '@/stores'
+import { useOrder } from '@/business/presale'
+import AppPopup from '@mobile/components/base/popup/index.vue'
+//import AppSelect from '@mobile/components/base/select/index.vue'
+
+const props = defineProps({
+    detail: {
+        type: Object as PropType<Model.PresaleAuctionsRsp>,
+        required: true
+    },
+})
+
+const { formData, formSubmit } = useOrder(props.detail)
+const accountStore = useAccountStore()
+const formRef = shallowRef<FormInstance>()
+const refresh = shallowRef(false) // 是否刷新父组件数据
+const showModal = shallowRef(true)
+
+// 表单验证规则
+const formRules: { [key in keyof Proto.OrderReq]?: FieldRule[] } = {
+    OrderPrice: [{
+        message: '请输入价格',
+        validator: () => {
+            return !!formData.OrderPrice
+        }
+    }],
+    OrderQty: [{
+        message: '请输入数量',
+        validator: () => {
+            return !!formData.OrderQty
+        }
+    }],
+}
+
+// 关闭弹窗
+const closed = (isRefresh = false) => {
+    refresh.value = isRefresh
+    showModal.value = false
+}
+
+// 提交挂牌
+const onSubmit = () => {
+    fullloading((hideLoading) => {
+        formSubmit().then(() => {
+            hideLoading()
+            dialog('提交成功').then(() => closed(true))
+        }).catch((err) => {
+            hideLoading(err, 'fail')
+        })
+    })
+}
+
+// 暴露组件属性给父组件调用
+defineExpose({
+    closed,
+})
+</script>
+
+<style lang="less">
+@import './index.less';
+</style>

+ 36 - 0
src/packages/mobile/views/presale/detail/index.less

@@ -0,0 +1,36 @@
+.spot-list {
+    .waterfall {
+        display: flex;
+        flex-wrap: wrap;
+        padding: .12rem;
+
+        &-item {
+            width: 50%;
+            padding: .12rem;
+
+            .goods {
+                background-color: #fff;
+                border-radius: .12rem;
+                overflow: hidden;
+
+                &-image {
+                    font-size: 0;
+                }
+
+                &-info {
+                    padding: .2rem;
+
+                    &__price {
+                        .unit {
+                            &::before {
+                                content: '¥';
+                            }
+
+                            color: red;
+                        }
+                    }
+                }
+            }
+        }
+    }
+}

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

@@ -11,7 +11,7 @@
         <div>正在抢购</div>
         <div class="waterfall">
             <div class="waterfall-item" v-for="(item, index) in dataList" :key="index">
-                <div class="goods" @click="$router.push({ name: 'presale-detail' })">
+                <div class="goods" @click="$router.push({ name: 'presale-detail', params: { item: JSON.stringify(item) } })">
                     <div class="goods-image">
                         <img :src="getFileUrl(item.attachmenturl)" />
                     </div>
@@ -37,7 +37,7 @@ import { queryPresaleAuctions } from '@/services/api/presale'
 
 const { dataList } = useRequest(queryPresaleAuctions, {
     params: {
-        presalemode: 2,
+        presalemode: 4,
     },
 })
 </script>

+ 36 - 0
src/packages/mobile/views/presale/list/index.less

@@ -0,0 +1,36 @@
+.presale-list {
+    .waterfall {
+        display: flex;
+        flex-wrap: wrap;
+        padding: .12rem;
+
+        &-item {
+            width: 50%;
+            padding: .12rem;
+
+            .goods {
+                background-color: #fff;
+                border-radius: .12rem;
+                overflow: hidden;
+
+                &-image {
+                    font-size: 0;
+                }
+
+                &-info {
+                    padding: .2rem;
+
+                    &__price {
+                        .unit {
+                            &::before {
+                                content: '¥';
+                            }
+
+                            color: red;
+                        }
+                    }
+                }
+            }
+        }
+    }
+}

+ 52 - 0
src/services/api/presale/index.ts

@@ -1,6 +1,8 @@
+import { useLoginStore, useAccountStore } from '@/stores'
 import http from '@/services/http'
 import { RequestConfig } from '@/services/http/types'
 
+const loginStore = useLoginStore()
 
 /**
  * 查询预售竞拍列表
@@ -10,4 +12,54 @@ export function queryPresaleAuctions(config: RequestConfig<Model.PresaleAuctions
         url: '/Presale/QueryPresaleAuctions',
         params: config.data,
     })
+}
+
+/**
+ * 我的持仓-预售持仓
+ */
+export function queryMineCpTradePreSaleResults(config: RequestConfig<Model.MineCpTradePreSaleResultsReq> = {}) {
+    return http.commonRequest<Model.MineCpTradePreSaleResultsRsp[]>({
+        url: '/Mine/QueryMineCpTradePreSaleResults',
+        params: {
+            userid: loginStore.userId,
+            ...config.data
+        },
+    })
+}
+
+/**
+ * 我的订单-预售认购
+ */
+export function queryMineTradeOrderDetails(config: RequestConfig<Model.MineTradeOrderDetailsReq> = {}) {
+    return http.commonRequest<Model.MineTradeOrderDetailsRsp[]>({
+        url: '/Mine/QueryMineTradeOrderDetails',
+        params: {
+            userid: loginStore.userId,
+            ...config.data
+        },
+    })
+}
+
+/**
+ * 交易委托
+ */
+export function order(config: RequestConfig<Partial<Proto.OrderReq>>) {
+    return http.mqRequest<Proto.OrderRsp>({
+        data: config.data,
+        requestCode: 'OrderReq',
+        responseCode: 'OrderRsp',
+        marketId: config.data?.MarketID
+    })
+}
+
+/**
+ * 撤单
+ */
+export function cancelOrder(config: RequestConfig<Proto.CancelOrderReq>) {
+    return http.mqRequest<Proto.CancelOrderRsp>({
+        data: config.data,
+        requestCode: 'CancelOrderReq',
+        responseCode: 'CancelOrderRsp',
+        marketId: 48201
+    })
 }

+ 1 - 1
src/services/http/index.ts

@@ -66,7 +66,7 @@ export default new (class {
                         }
                     }
                 }
-                return Promise.reject('出现错误,请稍后再试')
+                return Promise.reject('发生错误,请稍后再试')
             }
         )
     }

+ 18 - 10
src/types/model/order.d.ts

@@ -168,7 +168,7 @@ declare namespace Model {
         /// 手续费
         chargevalue: number
         /// 合同地址
-        contractaddr: string; 
+        contractaddr: string;
         /// 品种代码
         deliverygoodscode: string
         /// 品种ID
@@ -469,16 +469,22 @@ declare namespace Model {
         bannerpicurl: string
         /// 开始交易日(yyyymmdd)
         begindate: string
+        cityid: number; // 市
+        cityname: string; // 城市名称
         /// 联系人
         contactname: string
         /// 联系方式
         contactnum: string
+        countryid: number; // 国家
+        countryname: string; // 国家名称
         /// 品种代码
         deliverygoodscode: string
         /// 品种ID
         deliverygoodsid: number
         /// 品种名称
         deliverygoodsname: string
+        districtid: number; // 区
+        districtname: string; // 地区名称
         /// 结束交易日(yyyymmdd)
         enddate: string
         /// 单位名称
@@ -491,6 +497,8 @@ declare namespace Model {
         minivalue: number
         /// 选择项比较串【{选择项ID}+{冒号}+选择项值 } ,逗号分隔,头尾加逗号】-- 所有选择项拼接,用于比较
         optioncompare: string
+        provinceid: number; // 省
+        provincename: string; // 省名称
         /// 数量
         qty: number
         /// 用户id
@@ -797,7 +805,7 @@ declare namespace Model {
         username: string
     }
 
-     /*   查询我的订单/掉期委托 请求*/
+    /*   查询我的订单/掉期委托 请求*/
     interface TradeOrderDetailReq {
         /// 资金账户 - 格式:1,2,3
         accountID?: string
@@ -852,9 +860,9 @@ declare namespace Model {
         /// 商品单位id
         goodunitid: number
         /// 挂牌点选类型 - 1:挂牌 2:摘牌 3:先摘后挂
-        listingselecttype: number       
+        listingselecttype: number
         /// 市场ID
-        marketid: number       
+        marketid: number
         /// 市场名称
         marketname: string
         /// 开仓冻结手续费(先建后平操作,需要记录)
@@ -993,7 +1001,7 @@ declare namespace Model {
 
     /* 查询我的订单/历史成交 请求 */
     interface HisTradeDetailReq {
-         /// 资金账户 - 格式:1,2,3
+        /// 资金账户 - 格式:1,2,3
         accountID?: string
         /// 成交单号
         tradeID?: number
@@ -1120,7 +1128,7 @@ declare namespace Model {
         /// 成交单号(101+Unix秒时间戳(10位)+2位(MarketServiceID)+xxxx)
         tradeid: string
         /// 交易模式
-        trademode: number 
+        trademode: number
         /// 成交价格
         tradeprice: number
         /// 交易属性
@@ -1313,9 +1321,9 @@ declare namespace Model {
         tradeType?: string
         /// 商品ID
         goodsID?: number
-    } 
-    
-     /* 查询我的订单/订单成交 回应 */
+    }
+
+    /* 查询我的订单/订单成交 回应 */
     interface TradeDetailRsp {
         /// 账户ID[报价币种]
         accountid: number
@@ -1429,6 +1437,6 @@ declare namespace Model {
         tradetime: string
         /// 成交类别 - 1:正常委托成交 2:定向做市成交(接单) 3:交割协议平仓成交 4:交割减仓成交 5:到期强平成交 6:风控斩仓成交 7:协议平仓(管理端)成交 8:仓单转持仓成交 9: 交割协议转让成交 10:受托竞价成交(接单) 11:协议转让成交 12:系统强行平仓 13:期权违约平仓
         tradetype: number
-        
+
     }
 }

+ 131 - 0
src/types/model/presale.d.ts

@@ -2,6 +2,7 @@ declare namespace Model {
     /** 查询预售竞拍列表 请求 */
     interface PresaleAuctionsReq {
         presalemode: number; // 预售模式 - 1:一口价 2:大宗式竞拍 3:挂牌预售(HSBY)
+        presalestatus?: number; // 预售状态 - 1:未开始 2:预售中 3:已结束
         page?: number; // 页码
         pagesize?: number; // 每页条数
     }
@@ -43,4 +44,134 @@ declare namespace Model {
         transferdepositratio: number; // 转让定金比例(49)
         userid: number; // 卖方用户ID
     }
+
+    /** 我的持仓-预售持仓 请求 */
+    interface MineCpTradePreSaleResultsReq {
+        userid?: number; // 用户ID
+        page?: number; // 页码
+        pagesize?: number; // 每页条数
+    }
+
+    /** 我的持仓-预售持仓 响应 */
+    interface MineCpTradePreSaleResultsRsp {
+        applyid: number; // 预售申请ID
+        buyaccountid: number; // 买方账户ID
+        buyhandleflag: number; // 买处理标识
+        buyuserid: number; // 买方用户ID
+        createtime: string; // 创建时间
+        depositremain: number; // 未付定金
+        endtime: string; // 预售结束时间
+        goodscode: string; // 期货合约代码(内部)
+        goodsid: number; // 商品ID
+        goodsname: string; // 期货合约名称
+        goodsnamedisplay: string; // 商品名称
+        handleflag: number; // 处理标识 - 0:未处理 1:已处理
+        handlestatus: number; // 处理状态
+        marketid: number; // 市场ID
+        openprice: number; // 建仓价格\预售价
+        paystatus: number; // 支付状态 - 1:待支付 2:已支付
+        relatedgoodsid: number; // 关联交易合约ID
+        relatedmarketid: number; // 关联交易合约市场ID
+        relatedtradeid: number; // 二级市场成交单ID
+        sellaccountid: number; // 卖方账户ID
+        sellhandleflag: number; // 卖处理标识
+        sellname: string; // 客户名称(企业名称)
+        selluserid: number; // 卖方用户ID
+        starttime: string; // 预售开始时间
+        tradeamount: number; // 成交金额\转让定金
+        tradedate: string; // 交易日(yyyyMMdd)
+        tradeid: number; // 成交单号(101+Unix秒时间戳(10位)+2位(MarketServiceID)+xxxx)
+        tradeqty: number; // 成交数量
+        transferdeposit: number; // 转让定金
+        transferdepositratio: number; // 转让定金比例(49)
+    }
+
+    /** 我的订单-预售认购 请求 */
+    interface MineTradeOrderDetailsReq {
+        userid?: number; // 用户ID
+        page?: number; // 页码
+        pagesize?: number; // 每页条数
+        ishis?: boolean; // 是否历史查询
+        begindate?: string; // 开始交易日(yyyymmdd)
+        enddate?: string; // 结束交易日(yyyymmdd)
+    }
+
+    /** 我的订单-预售认购 响应 */
+    interface MineTradeOrderDetailsRsp {
+        accountid: number; // 账户ID[报价币种]
+        amountflag: number; // 资金标识 - 1:余额 2;待付
+        buildtype: number; // 委托单据类型 - 1:建仓 2:平仓 3:先平后建
+        buyorsell: number; // 买卖 - 0:买 1:卖
+        cancelorderid: number; // 撤单单号(撤单时填写)
+        cancelqty: number; // 撤单数量
+        clientordertime: string; // 客户端委托时间
+        clientticket: string; // 客户端流水号
+        clienttype: number; // 客户端类型 - 0:保留为未填终端类型 1:PC管理端 2:PC交易端 3:手机客户端安卓 4:网页客户端 5:微信客户端 6:手机客户端苹果 7:网上开户客户端 8:无效终端编号 9:报价终端(中江)
+        closeexchagechargevalue: number; // 平仓交易所手续费设置值
+        closefeealgorithm: number; // 平仓手续费收取方式 1:比率 2:固定
+        closefreezecharge: number; // 平仓冻结手续费(先建后平操作,需要记录)
+        closememberchargevalue: number; // 平仓会员手续费设置值
+        closeqty: number; // 平仓数量(先建后平操作 需要记录)
+        closetradeqty: number; // 平仓成交数量(先建后平操作,需要记录)
+        closeunfreezecharge: number; // 平仓解冻手续费(先建后平操作,需要记录)
+        delistingtype: number; // 摘牌类型 - 1:价格最优 2:点选成交
+        endtime: string; // 预售结束时间
+        freezecharge: number; // 冻结手续费
+        freezemargin: number; // 冻结保证金(冻结交易金额)
+        freezeqty: number; // 冻结数量
+        gcaccountid: number; // 账户ID[合约币种]
+        goodscode: string; // 期货合约代码(内部)
+        goodsid: number; // 商品ID
+        goodsname: string; // 期货合约名称
+        goodsnamedisplay: string; // 商品名称
+        isconfirmexercise: number; // 是否确认行权- 0:否 1:是
+        ispreexercise: number; // 是否预申报- 0:否 1:是
+        listingselecttype: number; // 挂牌点选类型 - 1:挂牌 2:摘牌 3:先摘后挂
+        marginalgorithm: number; // 保证金收取方式 1:比率 2:固定
+        marginvalue: number; // 即市保证金设置值
+        marketid: number; // 市场ID
+        marketmaxsub: number; // 市价最大偏移范围 [浮动价 - 点差]
+        memberuserid: number; // 所属会员UserID
+        openexchagechargevalue: number; // 建仓交易所手续费设置值
+        openfeealgorithm: number; // 建仓手续费收取方式 1:比率 2:固定
+        openfreezecharge: number; // 开仓冻结手续费(先建后平操作,需要记录)
+        openmemberchargevalue: number; // 建仓会员手续费设置值
+        openqty: number; // 开仓数量(先建后平操作,需要记录)
+        opentradeqty: number; // 开仓成交数量(先建后平操作,需要记录)
+        openunfreezecharge: number; // 开仓解冻手续费(先建后平操作,需要记录)
+        operatetype: number; // 操作类型 - 1:正常下单 2:斩仓 3:转单 4:结算撤单 5:系统卖出(适用于先平后建的卖出) 6:行情源报价 7:(结算)到期强平 8:(结算)协议转让 9:系统对冲单 10:(结算)到期无效 11:交割协议转让 12:交割协议平仓 13:交割成交(所有权) 14:管理端强行平仓 15:管理端协议转让 … 23:融资买入
+        operatorid: number; // 登录账号(LoginID)
+        optiontype: number; // 期权类型 - 1:认购(看涨) 2:认沽(看跌)
+        orderflag: number; // 委托标识 - 1:按量 2:按金额
+        orderid: string; // 委托单号(100+Unix秒时间戳(10位)+2位(MarketServiceID)+xxxx)
+        orderprice: number; // 委托价格
+        orderqty: number; // 委托数量
+        ordersrc: number; // 委托来源 - 1:客户端 2:管理端 3:风控服务 4:交割服务 5:交易服务 6:交易日结 7:商品强平 8:管理端商品退市强平 9:交易接口 10:交割服务商被动(受托竞价) 11:预埋触发
+        orderstatus: number; // 委托状态 - 参考枚举’orderstatus’ - 1:委托请求 2:待冻结 3:委托成功 4:委托失败 5:配对成功 6:已撤 7:部成 8:已成 9:部成部撤 10:成交失败 11:委托拒绝 12:经过摘牌(先摘后挂专用) 13:冻结成功(通道交易专用) 14:通道已撤 15:通道部成部撤 16:成交失败违约(荷兰式竞拍专用) 17:冻结PD成功 18:冻结PD失败 19:冻结能量成功 20:冻结能量失败 21:预约已报价 22:过期未付 23:优惠券处理中 24:仓单生成失败 25:首付扣款失败 26:履约失败 27:撤单解冻贷款失败
+        ordertime: string; // 委托时间
+        preexerciseprice: number; // 预申报价格
+        premium: number; // 权利金
+        preorderid: number; // 关联预埋单号(止盈止损单时填写)
+        presaledepositalgorithm: number; // 预售定金方式(48) - 1:比率 2:固定
+        presaledepositvalue: number; // 预售定金设置值(48)
+        pricemode: number; // 取价方式 - 1:市价 2: 限价 3:浮动价
+        quoteid: number; // 报价单ID
+        relatedid: number; // 关联单号(交割单)
+        retcode: number; // 错误代码
+        sellname: string; // 客户名称(企业名称)
+        sessionid: number; // 会话ID
+        startprice: number; // 起拍价[大宗式竞拍]
+        starttime: string; // 预售开始时间
+        tradedate: string; // 交易日(yyyyMMdd)
+        tradeprice: number; // 成交价[大宗]
+        tradeproperty: number; // 交易属性
+        tradeqty: number; // 成交数量
+        unfreezecharge: number; // 解冻手续费
+        unfreezemargin: number; // 解冻保证金
+        updatetime: string; // 更新时间
+        uuid: string; // 发起端唯一id
+        validtime: string; // 有效期限
+        validtype: number; // 有效类型 - 1当日有效 2本周有效 3指定日期有效 4一直有效 5指定时间有效
+        volumetype: number; // 当时间有效类型为 “立即执行否则取消 IOC” 时,需要此项 - 0:任意量 1:最小量(暂时不支持) 2:全部量
+    }
 }

+ 78 - 0
src/types/proto/presale.d.ts

@@ -0,0 +1,78 @@
+import { IMessageHead } from './proto'
+import Long from 'long'
+
+declare global {
+    namespace Proto {
+        /** 交易委托请求 */
+        interface OrderReq {
+            Header?: IMessageHead;
+            ClientSerialNo: string; // 客户端流水号
+            ClientOrderTime: string; // 客户端委托时间
+            ClientType: number; // 终端类型
+            LoginID: number; // 登陆账号
+            AccountID: number; // 交易账号
+            GoodsID: number; // 商品ID
+            MarketID: number; // 市场ID
+            ValidType: number; // 校验类型
+            OperateType: number; // 操作类型:
+            OrderSrc: number; // 单据来源
+            OperatorID: number; // 操作员账号ID
+            OrderPrice: number; // 委托价格
+            MarketMaxSub: number; // 市价允许最大偏差(做市)
+            OrderQty: number; // 委托数量
+            BuyOrSell: number; // 买卖方向
+            BuildType: number; // 下单类型
+            CurtQuotePrice: number; // 保留,计算冻结金额使用
+            SpPrice: number; // 止盈价格
+            SlPrice: number; // 止损价格
+            PriceMode: number; // 取价方式
+            TimevalidType: number; // 时间有效类型
+            TriggerType: number; // 预埋单触发类型
+            TriggerPrice: number; // 预埋单触发价格
+            ListingSelectType: number; // 挂牌点选类型
+            DelistingType: number; // 摘牌类型
+            RelatedID: number; // 关联单号
+            OptionType: number; // 期权类型(1:认购(看涨)2:认沽(看跌))
+            Premium: number; // 权利金
+            TriggerOperator: number; // 触发条件(1:大于等于2:小于等于)
+            ServiceTime: string; // 服务端时间
+            CouponTypeID: number; // 优惠券类型ID(买方)
+            UsedQty: number; // 使用数量
+            ValidTime: string; // 指定有效日期
+            ReceiveInfoID: number; // 收货地址ID
+            OrderFlag: number; // 委托标识-1:按量
+            OrderAmount: number; // 委托金额OrderFlag=2必填
+        }
+
+        /** 交易委托应答 */
+        interface OrderRsp {
+            Header?: IMessageHead;
+            RetCode: number; // 返回码
+            RetDesc: string; // 描述信息
+            OrderID: number; // 一级生成的订单号
+            OrderTime: string; // 接收委托交易的时间
+        }
+
+        /** 撤单请求 */
+        interface CancelOrderReq {
+            Header?: IMessageHead;
+            ClientSerialNo: string; // 客户端流水号
+            ClientOrderTime: string; // 客户端委托时间
+            ClientType: number; // 终端类型
+            OperateType: number; // 操作类型
+            OldOrderId: number; // 原委托单号
+            AccountID: number; // 交易账号
+            OrderSrc: string; // 单据来源
+            OperatorID: number; // 操作员账号ID
+        }
+
+        /** 撤单应答 */
+        interface CancelOrderRsp {
+            Header?: IMessageHead;
+            RetCode: number; // 返回码
+            RetDesc: string; // 描述信息
+            ExchActionID: number; // 交易所操作号
+            OrderTime: string; // 接收委托交易的时间
+        }
+    }
+}