Procházet zdrojové kódy

Merge branch 'master' of http://47.101.159.18:3000/Muchinfo/MTP20_WEB_GLOBAL

zhou.xiaoning před 2 roky
rodič
revize
cb29c87d07

+ 104 - 2
src/packages/mobile/views/ballot/detail/Index.vue

@@ -1,10 +1,112 @@
 <template>
-    <app-view>
+    <app-view class="g-detail">
         <template #header>
             <app-navbar title="商品详情" />
         </template>
+        <Banner :data-list="detailBanners" height="4rem" />
+        <div class="g-detail__info">
+            <div class="pricebar">
+                <div class="pricebar-left">
+                    <span class="tag">发行价</span>
+                    <span class="unit">¥</span>
+                    <span class="price">{{ detail.refprice?.toFixed(2) }}</span>
+                </div>
+                <div class="pricebar-right">
+                    <span>总量:{{ detail.presaleqty }}</span>
+                </div>
+            </div>
+            <div class="tag">
+                <Tag type="danger" round>摇号中签</Tag>
+            </div>
+            <div class="titlebar">
+                <span>{{ detail.sellname }}</span>
+                <span>{{ detail.goodsname }}</span>
+            </div>
+            <div class="timebar">
+
+            </div>
+        </div>
+        <div class="g-detail__cell">
+            <ul>
+                <li>
+                    <span>预售定金</span>
+                    <span>{{ earnest }}</span>
+                </li>
+                <li>
+                    <span>转让比例</span>
+                    <span>{{ parsePercent(detail.transferdepositratio) }}</span>
+                </li>
+            </ul>
+        </div>
+        <div class="g-detail__cell">
+            <ul>
+                <li>
+                    <span>开始时间</span>
+                    <span>{{ detail.starttime }}</span>
+                </li>
+                <li>
+                    <span>结束时间</span>
+                    <span>{{ detail.endtime }}</span>
+                </li>
+            </ul>
+        </div>
+        <div class="g-detail__desc">
+            <template v-for="(url, index) in detailImages" :key="index">
+                <img :src="url" alt="" />
+            </template>
+        </div>
+        <template #footer>
+            <div class="g-detail__footer">
+                <Button type="primary" block round @click="openComponent('delisting')">我要认购</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 { Button, Tag } from 'vant'
+import { getFileUrl, parsePercent } from '@/filters'
+import { useComponent } from '@/hooks/component'
+import { useNavigation } from '@/hooks/navigation'
+import Banner from '@mobile/components/base/banner/index.vue'
+
+const componentMap = new Map<string, unknown>([
+    ['delisting', defineAsyncComponent(() => import('./components/delisting/index.vue'))], // 摘牌
+])
+
+const { getParamString } = useNavigation()
+const { componentRef, componentId, openComponent, closeComponent } = useComponent()
+const qs = getParamString('item')
+const detail: Model.PresaleAuctionsRsp = JSON.parse(qs.toString() || '{}')
+
+// 商品banner
+const detailBanners = computed(() => {
+    const bannerpicurl = detail.bannerpicurl ?? ''
+    return bannerpicurl?.split(',').map((path) => path)
+})
+
+// 预售定金
+const earnest = computed(() => {
+    switch (detail.presaledepositalgorithm) {
+        case 1:
+            return (detail.presaledepositvalue * 100).toFixed(2)
+        case 2:
+            return detail.presaledepositvalue.toFixed(2)
+        default:
+            return '0.0'
+    }
+})
+
+// 商品图片列表
+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/ballot/detail/components/delisting/index.less

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

+ 119 - 0
src/packages/mobile/views/ballot/detail/components/delisting/index.vue

@@ -0,0 +1,119 @@
+<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.refprice }}</span>
+                </template>
+            </Field>
+            <Field name="OrderQty" :rules="formRules.OrderQty" label="认购数量">
+                <template #input>
+                    <Stepper v-model="formData.OrderQty" theme="round" :max="detail.presaleqty" button-size="22"
+                        :auto-fixed="false" integer />
+                </template>
+            </Field>
+            <Field label="预售定金">
+                <template #input>
+                    <span>{{ deposit }}</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, onMounted, computed } 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/trade'
+import AppPopup from '@mobile/components/base/popup/index.vue'
+import { BuyOrSell } from '@/constants/order'
+import { EPriceMode, EValidType } from '@/constants/client'
+//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()
+const accountStore = useAccountStore()
+const formRef = shallowRef<FormInstance>()
+const refresh = shallowRef(false) // 是否刷新父组件数据
+const showModal = shallowRef(true)
+
+// 表单验证规则
+const formRules: { [key in keyof Proto.OrderReq]?: FieldRule[] } = {
+    OrderQty: [{
+        message: '请输入数量',
+        validator: () => {
+            return !!formData.OrderQty
+        }
+    }],
+}
+
+// 预售定金
+const deposit = computed(() => {
+    const { refprice, presaledepositalgorithm, presaledepositvalue } = props.detail
+    const qty = formData.OrderQty ?? 0
+
+    switch (presaledepositalgorithm) {
+        case 1:
+            return (presaledepositvalue * refprice * qty).toFixed(2)
+        case 2:
+            return (presaledepositvalue * qty).toFixed(2)
+        default:
+            return '0.0'
+    }
+})
+
+// 关闭弹窗
+const closed = (isRefresh = false) => {
+    refresh.value = isRefresh
+    showModal.value = false
+}
+
+// 提交摘牌
+const onSubmit = () => {
+    const { applyid, goodsid, marketid } = props.detail
+    formData.GoodsID = goodsid
+    formData.MarketID = marketid
+    formData.BuyOrSell = BuyOrSell.Buy
+    formData.RelatedID = applyid
+    formData.ValidType = EValidType.VALIDTYPE_YZ
+    formData.PriceMode = EPriceMode.PRICEMODE_LIMIT
+
+    fullloading((hideLoading) => {
+        formSubmit().then(() => {
+            hideLoading()
+            dialog('提交成功').then(() => closed(true))
+        }).catch((err) => {
+            hideLoading(err, 'fail')
+        })
+    })
+}
+
+onMounted(() => {
+    formData.OrderPrice = props.detail.startprice
+})
+
+// 暴露组件属性给父组件调用
+defineExpose({
+    closed,
+})
+</script>
+
+<style lang="less">
+@import './index.less';
+</style>

+ 84 - 0
src/packages/mobile/views/ballot/detail/index.less

@@ -0,0 +1,84 @@
+.g-detail {
+    &__info {
+        background-color: #fff;
+        border-bottom-left-radius: .2rem;
+        border-bottom-right-radius: .2rem;
+        padding: .32rem;
+
+        .pricebar {
+            display: flex;
+            justify-content: space-between;
+            align-items: center;
+
+            &-left {
+                color: red;
+
+                .tag {
+                    font-size: .24rem;
+                }
+
+                .price {
+                    font-size: .44rem;
+                }
+            }
+
+            &-right {
+                font-size: .24rem;
+                color: #999;
+            }
+        }
+
+        .tag {
+            margin-top: .24rem;
+        }
+
+        .titlebar {
+            font-size: .32rem;
+            font-weight: bold;
+            margin-top: .2rem;
+
+            span {
+                margin-right: .1rem;
+            }
+        }
+
+        .timebar {
+            display: flex;
+            justify-content: space-around;
+        }
+    }
+
+    &__cell {
+        background-color: #fff;
+        border-radius: .2rem;
+        margin-top: .24rem;
+        padding: .2rem .32rem;
+
+        ul {
+            li {
+                display: flex;
+                padding: .12rem;
+
+                span {
+                    &:first-child {
+                        width: 1.6rem;
+                        color: #999;
+                    }
+
+                    &:last-child {
+                        flex: 1;
+                    }
+                }
+            }
+        }
+    }
+
+    &__desc {
+        margin-top: .24rem;
+    }
+
+    &__footer {
+        background-color: #fff;
+        padding: .12rem .24rem;
+    }
+}

+ 3 - 5
src/packages/mobile/views/ballot/list/Index.vue

@@ -6,8 +6,7 @@
         <Banner :data-list="bannerList" />
         <Waterfall class="g-goods-list" :data-list="startList">
             <template #default="{ item }">
-                <div class="goods"
-                    @click="$router.push({ name: 'presale-detail', params: { item: JSON.stringify(item) } })">
+                <div class="goods" @click="$router.push({ name: 'ballot-detail', params: { item: JSON.stringify(item) } })">
                     <div class="goods-image">
                         <img :src="getFileUrl(item.attachmenturl)" />
                     </div>
@@ -15,7 +14,7 @@
                         <div class="goods-info__title">{{ item.goodsname }}</div>
                         <div class="goods-info__price">
                             <Tag type="danger">卖价</Tag>
-                            <span class="unit">{{ item.startprice }}</span>
+                            <span class="unit">{{ item.refprice }}</span>
                         </div>
                     </div>
                 </div>
@@ -24,8 +23,7 @@
         <Divider>发售历史</Divider>
         <Waterfall class="g-goods-list" :data-list="endList">
             <template #default="{ item }">
-                <div class="goods"
-                    @click="$router.push({ name: 'presale-detail', params: { item: JSON.stringify(item) } })">
+                <div class="goods" @click="$router.push({ name: 'ballot-detail', params: { item: JSON.stringify(item) } })">
                     <div class="goods-image">
                         <img :src="getFileUrl(item.attachmenturl)" />
                     </div>

+ 1 - 1
src/stores/modules/futures.ts

@@ -313,7 +313,7 @@ export const useFuturesStore = defineStore(() => {
                 state.quoteDayList.push(quoteItem)
             }
         })
-    }, 200)
+    }, 100)
 
     // 接收行情推送通知
     const quotePushNotify = eventBus.$on('QuotePushNotify', (res) => {