Quellcode durchsuchen

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

li.shaoyi vor 2 Jahren
Ursprung
Commit
cc491fa3b8

+ 17 - 0
src/constants/order.ts

@@ -461,4 +461,21 @@ export function getDeliveryPayModeName(value: number) {
 export function getConfirmStatusName(value: number) {
     const enums = getConfirmStatusList()
     return getEnumTypeName(enums, value)
+}
+
+/**
+ * 获取预售状态列表
+ * @returns 
+ */
+export function getWRPresaleStatusList() {
+    return getEnumTypeList('WRPresaleStatus')
+}
+
+/**
+ * 获取预售状态类型名称
+ * @returns 
+ */
+export function getWRPresaleStatusName(value: number) {
+    const enums = getWRPresaleStatusList()
+    return getEnumTypeName(enums, value)
 }

+ 78 - 0
src/packages/pc/views/footer/presell/transferposition/delivery/index.vue

@@ -0,0 +1,78 @@
+<!-- 预售转让-转让持仓-交收申请 -->
+<template>
+     <app-drawer title="交收申请" v-model:show="show" :loading="loading" :refresh="refresh" :width="900">
+        <app-table :data="dataList" v-model:columns="tableColumns" :loading="loading" :row-key="rowKey"
+            :expand-row-keys="expandKeys" @row-click="rowClick">
+            <!-- 商品代码/名称 -->
+            <template #wrstandardname="{ row }">
+                {{ row.wrstandardcode }}/{{ row.wrstandardname }}
+            </template>
+            <!-- 展开行 -->
+            <template #expand="{ row }">
+                <div class="buttonbar">
+                    <el-button type="danger" size="small" @click="showComponent('trader', row)">点选</el-button>
+                </div>
+            </template>
+            <template #footer>
+                <component ref="componentRef" v-bind="{ selectedRow, detail }" :is="componentMap.get(componentId)"
+                    @closed="closeComponent" v-if="componentId" />
+            </template>
+        </app-table>
+        <template #footer>
+            <el-button type="info" @click="onCancel(false)">取消</el-button>
+        </template>
+    </app-drawer>
+</template>
+
+<script lang="ts" setup>
+import { ref, defineAsyncComponent, PropType } from 'vue'
+import { useRequest } from '@/hooks/request'
+import { queryWrDeliveryAvalidHoldLB } from '@/services/api/transfer'
+import { useComponent } from '@/hooks/component'
+import { useComposeTable } from '@pc/components/base/table'
+import AppDrawer from '@pc/components/base/drawer/index.vue'
+import AppTable from '@pc/components/base/table/index.vue'
+
+const componentMap = new Map<string, unknown>([
+    ['trader', defineAsyncComponent(() => import('./trader/index.vue'))], // 追加定金
+])
+const show = ref(true)
+const refresh = ref(false)
+
+const props = defineProps({
+    detail: {
+        type: Object as PropType<Model.MineTradePositionExsRsp>,
+        required: true,
+    }
+})
+
+const { loading, dataList, run } = useRequest(queryWrDeliveryAvalidHoldLB, {
+    params: {
+        pagesize: 20,
+        goodsid: props.detail.goodsid,
+    },
+})
+
+const { componentRef, componentId, openComponent, closeComponent } = useComponent(() => {
+    run()
+})
+
+const { rowKey, expandKeys, selectedRow, rowClick } = useComposeTable<Model.WrDeliveryAvalidHoldLBRsp>({ rowKey: 'ladingbillid' })
+
+const tableColumns = ref<Model.TableColumn[]>([
+    { prop: 'wrstandardname', label: '商品代码/名称' },
+    { prop: 'username', label: '仓单持有人' },
+    { prop: 'warehousename', label: '仓库' },
+    { prop: 'pricemove', label: '升贴水' },
+    { prop: 'avalidqty', label: '可用数量' },
+])
+
+const showComponent = (componentName: string) => {
+    openComponent(componentName)
+}
+
+const onCancel = (isRefresh = false) => {
+    show.value = false
+    refresh.value = isRefresh
+}
+</script>

+ 129 - 0
src/packages/pc/views/footer/presell/transferposition/delivery/trader/index.vue

@@ -0,0 +1,129 @@
+<!-- 预售转让-转让持仓-交收申请-点选 -->
+<template>
+    <app-drawer title="点选" v-model:show="show" :loading="loading" :refresh="refresh" :width="800">
+        <el-form ref="formRef" class="el-form--horizontal" label-width="120px" label-position="left" :model="formData"
+            :rules="formRules">
+            <el-form-item label="商品代码/名称">
+                <span>{{ selectedRow.wrstandardcode }}/{{ selectedRow.wrstandardname }}</span>
+            </el-form-item>
+            <el-form-item label="仓库">
+                <span>{{ selectedRow.warehousename }}</span>
+            </el-form-item>
+            <el-form-item label="升贴水">
+                <span>{{ discount.toFixed(2) }}</span>
+            </el-form-item>
+            <el-form-item label="数量">
+                <span>{{ selectedRow.avalidqty }}</span>
+            </el-form-item>
+            <el-form-item label="总货款">
+                <span>{{ payment.toFixed(2) }}</span>
+            </el-form-item>
+            <el-form-item label="已付定金">
+                <span>{{ deposit.toFixed(2) }}</span>
+            </el-form-item>
+            <el-form-item label="剩余货款">
+                <span>{{ available.toFixed(2) }}</span>
+            </el-form-item>
+            <el-form-item prop="DeliveryQty" label="点选数量">
+                <el-input-number placeholder="请输入点选数量" v-model="formData.DeliveryQty" :max="selectedRow.buycurpositionqty" :min="0" />
+            </el-form-item>
+        </el-form>
+        <template #footer>
+            <el-button type="info" @click="onCancel(false)">取消</el-button>
+            <el-button type="primary" @click="onSubmit">提交</el-button>
+        </template>
+    </app-drawer>
+</template>
+
+<script lang="ts" setup>
+import { ref, PropType, computed, reactive } from 'vue'
+import { ElMessage, FormInstance, FormRules } from 'element-plus'
+import { deliveryOrder } from '@/services/api/trade'
+import { v4 } from 'uuid'
+import { ClientType } from '@/constants/client'
+import { useAccountStore } from '@/stores'
+import moment from 'moment'
+import AppDrawer from '@pc/components/base/drawer/index.vue'
+
+const props = defineProps({
+    selectedRow: {
+        type: Object as PropType<Model.WrDeliveryAvalidHoldLBRsp>,
+        required: true
+    },
+    detail: {
+        type: Object as PropType<Model.MineTradePositionExsRsp>,
+        required: true
+    },
+})
+
+// 可用数量
+const accountStore = useAccountStore()
+
+const show = ref(true)
+const refresh = ref(false)
+const formRef = ref<FormInstance>()
+const formData = reactive<Partial<Proto.DeliveryOrderReq>>({
+    ClientType: ClientType.Web,
+    AccountID: accountStore.currentAccountId,
+    XGoodsID: props.selectedRow.goodsid,
+    DeliveryGoodsID: props.selectedRow.deliverygoodsid,
+})
+
+// 升贴水
+const discount = computed(() => {
+    return props.selectedRow.pricemove * (formData.DeliveryQty ?? 0)
+})
+
+// 总货款
+const payment = computed(() => {
+    return props.detail.presaleprice * (formData.DeliveryQty ?? 0)
+})
+
+// 剩余货款
+const available = computed(() => {
+    return payment.value - deposit.value + discount.value
+})
+
+// 已付定金
+const deposit = computed(() => {
+    return payment.value * props.detail.transferdepositratio
+})
+
+const formRules: FormRules = {
+    DeliveryQty: [{
+        message: '请输入数量',
+        validator: () => {
+            return !!formData.DeliveryQty
+        }
+    }],
+}
+
+const onCancel = (isRefresh = false) => {
+    show.value = false
+    refresh.value = isRefresh
+}
+
+const onSubmit = () => {
+    formRef.value?.validate((valid) => {
+        if (valid) {
+            formData.ClientSerialNo = v4()
+            formData.ClientOrderTime = moment(new Date()).format('YYYY-MM-DD HH:mm:ss')
+            formData.XQty = formData.DeliveryQty
+            formData.DeliveryOrderDetail = {
+                AccountID: props.selectedRow.accountid, // 对手方账号
+                Qty: formData.DeliveryQty, // 点选数量
+                LadingBillID: props.selectedRow.ladingbillid,// 提单ID
+                SubNum: props.selectedRow.subnum, // 提单子单号
+                WRFactorTypeID: props.selectedRow.wrfactortypeid, // 仓单要素类型ID
+            }
+            /// 提交
+            deliveryOrder({ data: formData  }).then(() => {
+                ElMessage.success('挂牌提交成功')
+                onCancel(true)
+            }).catch((err) => {
+                ElMessage.error('挂牌提交失败:' + err)
+            })
+        }
+    })
+}
+</script>

+ 6 - 5
src/packages/pc/views/footer/presell/transferposition/index.vue

@@ -26,19 +26,19 @@
         <template #expand="{ row }">
             <div class="buttonbar">
                 <el-button type="danger" v-if="row.paystatus === PayStatus.UnPay" size="small" @click="showComponent('append', row)">追加定金</el-button>
-                <el-button type="success" v-if="row.paystatus === 2" size="small" @click="showComponent('listing', row)">转让</el-button>
+                <el-button type="danger" v-if="row.paystatus === 2" size="small" @click="showComponent('listing', row)">转让</el-button>
                 <el-button type="primary" v-if="row.paystatus === 2" size="small" @click="showComponent('delivery', row)">交收</el-button>
             </div>
         </template>
         <template #footer>
-            <component ref="componentRef" v-bind="{ selectedRow }" :is="componentMap.get(componentId)"
+            <component ref="componentRef" v-bind="{ detail }" :is="componentMap.get(componentId)"
                 @closed="closeComponent" v-if="componentId" />
         </template>
     </app-table>
 </template>
 
 <script lang="ts" setup>
-import { ref, defineAsyncComponent } from 'vue'
+import { ref, defineAsyncComponent, shallowRef } from 'vue'
 import { parsePercent } from '@/filters'
 import { useRequest } from '@/hooks/request'
 import { queryMineTradePositionExs } from '@/services/api/transfer'
@@ -53,13 +53,14 @@ const componentMap = new Map<string, unknown>([
     ['listing', defineAsyncComponent(() => import('./listing/index.vue'))], // 转让
 ])
 
+const detail = shallowRef<Model.MineTradePositionExsRsp>()
 const { loading, dataList, run } = useRequest(queryMineTradePositionExs, {})
 
 const { componentRef, componentId, openComponent, closeComponent } = useComponent(() => {
     run()
 })
 
-const { rowKey, expandKeys, selectedRow, rowClick } = useComposeTable<Model.MineTradePositionExsRsp>({ rowKey: 'goodsid' })
+const { rowKey, expandKeys, rowClick } = useComposeTable<Model.MineTradePositionExsRsp>({ rowKey: 'goodsid' })
 
 const tableColumns = ref<Model.TableColumn[]>([
     { prop: 'goodsname', label: '商品代码/名称' },
@@ -78,7 +79,7 @@ const tableColumns = ref<Model.TableColumn[]>([
 ])
 
 const showComponent = (componentName: string, row?: Model.MineTradePositionExsRsp) => {
-    selectedRow.value = row
+    detail.value = row
     openComponent(componentName)
 }
 </script>

+ 106 - 0
src/packages/pc/views/footer/presell/transferposition/listing/index.vue

@@ -0,0 +1,106 @@
+<!-- 预售转让-转让持仓-转让 -->
+<template>
+    <app-drawer title="转让" v-model:show="show" :loading="loading" :refresh="refresh" :width="500">
+        <el-form ref="formRef" class="el-form--vertical" label-width="120px" label-position="left" :model="formData"
+            :rules="formRules">
+            <el-form-item label="商品代码/名称">
+                <span>{{ detail.goodscode }}/{{ detail.goodsname }}</span>
+            </el-form-item>
+            <el-form-item label="预售价">
+                <span>{{ detail.presaleprice }}</span>
+            </el-form-item>
+            <el-form-item label="可用量">
+                <span>{{ enableqty }}</span>
+            </el-form-item>
+            <el-form-item label="涨停">
+                <span>{{ handleNumberValue(quote?.limitup) }}</span>
+            </el-form-item>
+            <el-form-item label="涨停">
+                <span>{{ handleNumberValue(quote?.limitdown) }}</span>
+            </el-form-item>
+
+            <el-form-item prop="OrderQty" label="转让数量">
+                <el-input-number placeholder="转让数量" v-model="formData.OrderQty" :max="enableqty" :min="0" />
+            </el-form-item>
+            <el-form-item prop="OrderPrice" label="转让价">
+                <el-input-number placeholder="请输入转让价格" :max="quote?.limitup" :min="quote?.limitdown" :step="Math.pow(10, -detail.decimalplace)" :precision="detail.decimalplace" v-model="formData.OrderPrice" />
+            </el-form-item>
+        </el-form>
+        <template #footer>
+            <el-button type="info" @click="onCancel(false)">取消</el-button>
+            <el-button type="primary" @click="onSubmit">提交</el-button>
+        </template>
+    </app-drawer>
+</template>
+
+<script lang="ts" setup>
+import { ref, PropType, computed } from 'vue'
+import { ElMessage, FormInstance, FormRules } from 'element-plus'
+import { handleNumberValue } from '@/filters'
+import { useOrder } from '@/business/trade'
+import { useFuturesStore } from '@/stores'
+import { BuyOrSell } from '@/constants/order'
+import { EPriceMode, EValidType, EListingSelectType, EBuildType } from '@/constants/client'
+import AppDrawer from '@pc/components/base/drawer/index.vue'
+
+const props = defineProps({
+    detail: {
+        type: Object as PropType<Model.MineTradePositionExsRsp>,
+        required: true
+    },
+    code: String
+})
+
+const { getGoodsQuote } = useFuturesStore()
+// 可用数量
+const enableqty = computed(() => props.detail.buycurpositionqty - props.detail.buyfrozenqty)
+/// 对应的行情信息
+const quote = getGoodsQuote(props.detail.goodscode)
+
+const { formData, formSubmit, loading } = useOrder()
+const show = ref(true)
+const refresh = ref(false)
+const formRef = ref<FormInstance>()
+
+const formRules: FormRules = {
+    OrderPrice: [{
+        message: '请输入价格',
+        validator: () => {
+            return !!formData.OrderPrice
+        }
+    }],
+    OrderQty: [{
+        message: '请输入数量',
+        validator: () => {
+            return !!formData.OrderQty
+        }
+    }],
+}
+
+const onCancel = (isRefresh = false) => {
+    show.value = false
+    refresh.value = isRefresh
+}
+
+const onSubmit = () => {
+    formRef.value?.validate((valid) => {
+        if (valid) {
+            const { goodsid } = props.detail
+            formData.GoodsID = goodsid
+            formData.MarketID = 49201
+            formData.BuyOrSell = BuyOrSell.Sell
+            formData.TimevalidType = EValidType.VALIDTYPE_YZ
+            formData.PriceMode = EPriceMode.PRICEMODE_LIMIT
+            formData.ListingSelectType = EListingSelectType.LISTINGSELECTTYPE_LISTING
+            formData.BuildType = EBuildType.BUILDTYPE_CLOSE
+
+            formSubmit().then(() => {
+                ElMessage.success('挂牌提交成功')
+                onCancel(true)
+            }).catch((err) => {
+                ElMessage.error('挂牌提交失败:' + err)
+            })
+        }
+    })
+}
+</script>

+ 104 - 0
src/packages/pc/views/market/trade/presell/ballot/detail/delisting/index.vue

@@ -0,0 +1,104 @@
+<!-- 交易市场-预售转让-预售中签-详情-我要认购 -->
+<template>
+    <app-drawer title="我要认购" v-model:show="show" :width="800" :loading="loading" :refresh="refresh">
+        <el-form ref="formRef" class="el-form--horizontal" label-width="100px" :model="formData" :rules="formRules">
+            <el-form-item label="发行价">
+                <span>{{ selectedRow.refprice }}</span>
+            </el-form-item>
+            <el-form-item label="最大申购量">
+                <span>{{ selectedRow.buymaxqty }}</span>
+            </el-form-item>
+            <el-form-item label="预售定金">
+                <span>{{ deposit }}</span>
+            </el-form-item>
+            <el-form-item label="可用资金">
+                <span>{{ accountStore.currentAccount.avaiableMoney?.toFixed(2) }}</span>
+            </el-form-item>
+            <el-form-item prop="OrderQty" label="认购数量">
+                <el-input-number placeholder="请输入" :min="0" :max="selectedRow.presaleqty" :precision="0" v-model="formData.OrderQty" />
+            </el-form-item>
+        </el-form>
+        <template #footer>
+            <el-button type="info" @click="onCancel(false)">取消</el-button>
+            <el-button type="primary" @click="onSubmit">提交</el-button>
+        </template>
+    </app-drawer>
+</template>
+
+<script lang="ts" setup>
+import { shallowRef, computed, PropType } from 'vue'
+import { ElMessage, FormInstance, FormRules } from 'element-plus'
+import { BuyOrSell } from '@/constants/order'
+import { useOrder } from '@/business/trade'
+import { useAccountStore } from '@/stores'
+import AppDrawer from '@pc/components/base/drawer/index.vue'
+import { EPriceMode, EValidType } from '@/constants/client'
+
+const props = defineProps({
+    selectedRow: {
+        type: Object as PropType<Model.PresaleAuctionsRsp>,
+        required: true,
+    }
+})
+
+const { formData, formSubmit, loading } = useOrder()
+const accountStore = useAccountStore()
+const show = shallowRef(true)
+const refresh = shallowRef(false)
+const formRef = shallowRef<FormInstance>()
+
+// 预售定金
+const deposit = computed(() => {
+    const { refprice, presaledepositalgorithm, presaledepositvalue } = props.selectedRow
+    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 formRules: FormRules = {
+    OrderQty: [{
+        required: true,
+        validator: (rule, value, callback) => {
+            const buymaxqty = props.selectedRow.buymaxqty
+            if (value <= buymaxqty) {
+                callback()
+            } else {
+                callback(new Error('委托数量不能大于' + `${buymaxqty}`))
+            }
+        }
+    }],
+}
+
+const onCancel = (isRefresh = false) => {
+    show.value = false
+    refresh.value = isRefresh
+}
+
+const onSubmit = () => {
+    formRef.value?.validate((valid) => {
+        if (valid) {
+            const { applyid, goodsid, marketid } = props.selectedRow
+            formData.GoodsID = goodsid
+            formData.MarketID = marketid
+            formData.BuyOrSell = BuyOrSell.Buy
+            formData.RelatedID = applyid
+            formData.PriceMode = EPriceMode.PRICEMODE_LIMIT
+            formData.TimevalidType = EValidType.VALIDTYPE_YZ
+            /// 代码提交
+            formSubmit().then(() => {
+                ElMessage.success('提交成功')
+                onCancel(true)
+            }).catch((err) => {
+                ElMessage.error('提交失败:' + err)
+            })
+        }
+    })
+}
+</script>

+ 115 - 0
src/packages/pc/views/market/trade/presell/ballot/detail/index.vue

@@ -0,0 +1,115 @@
+<!-- 交易市场-预售转让-预售中签-详情 -->
+<template>
+    <app-drawer title="商品详情" v-model:show="show" :width="800" :refresh="refresh">
+        <div class="g-detail__desc">
+            <template v-for="(url, index) in detailBanners" :key="index">
+                <img :src="url" alt="" />
+            </template>
+        </div>
+        <div class="g-detail__buy">
+            <div class="topic">
+                <div class="topic-left">
+                    <span class="price-text">发行价</span>
+                    <span class="price-unit">¥</span>
+                    <span class="price-integer">{{ selectedRow.refprice?.toFixed(2) }}</span>
+                </div>
+                <div class="topic-right">
+                    <span>开始:{{ selectedRow.starttime }}</span>
+                    <span>结束:{{ selectedRow.endtime }}</span>
+                </div>
+            </div>
+            <div class="title">
+                <el-tag type="danger" round>摇号中签</el-tag>
+                <span>{{ selectedRow.sellname }}</span>
+                <span>{{ selectedRow.goodscode }}/{{ selectedRow.goodsname }}</span>
+            </div>
+            <div class="qty">
+                <span>总量:{{ selectedRow.presaleqty }}</span>
+            </div>
+            <div class="info">
+                <ul>
+                    <li>
+                        <span>预售定金</span>
+                        <span>{{ earnest }}</span>
+                    </li>
+                    <li>
+                        <span>转让定金</span>
+                        <span>{{ parsePercent(selectedRow.transferdepositratio) }}</span>
+                    </li>
+                </ul>
+            </div>
+        </div>
+        <div class="g-detail__desc">
+            <template v-for="(url, index) in detailImages" :key="index">
+                <img :src="url" alt="" />
+            </template>
+        </div>
+        <template #footer v-if="selectedRow.presalestatus === 2">
+            <div class="price">
+                <span class="price-text">发行价:</span>
+                <span class="price-unit">¥</span>
+                <span class="price-integer">{{ selectedRow.refprice?.toFixed(2) }}</span>
+            </div>
+            <el-button type="info" @click="onCancel(false)">取消</el-button>
+            <el-button type="primary" @click="onSubmit">我要认购</el-button>
+            <component ref="componentRef" v-bind="{ selectedRow }" :is="componentMap.get(componentId)"
+                @closed="closeComponent" v-if="componentId" />
+        </template>
+    </app-drawer>
+</template>
+
+<script lang="ts" setup>
+import { shallowRef, computed, PropType, defineAsyncComponent } from 'vue'
+import { getFileUrl, parsePercent } from '@/filters'
+import { useComponent } from '@/hooks/component'
+import AppDrawer from '@pc/components/base/drawer/index.vue'
+
+const componentMap = new Map<string, unknown>([
+    ['delisting', defineAsyncComponent(() => import('./delisting/index.vue'))], // 摘牌
+])
+
+const { componentRef, componentId, openComponent, closeComponent } = useComponent(false)
+
+const props = defineProps({
+    selectedRow: {
+        type: Object as PropType<Model.PresaleAuctionsRsp>,
+        required: true,
+    }
+})
+
+// 商品banner
+const detailBanners = computed(() => {
+    const bannerpicurl = props.selectedRow.bannerpicurl ?? ''
+    return bannerpicurl?.split(',').map((path) => getFileUrl(path))
+})
+
+// 预售定金
+const earnest = computed(() => {
+    switch (props.selectedRow.presaledepositalgorithm) {
+        case 1:
+            return parsePercent(props.selectedRow.presaledepositvalue)
+        case 2:
+            return props.selectedRow.presaledepositvalue.toFixed(2)
+        default:
+            return '0.0'
+    }
+})
+
+// 商品图片列表
+const detailImages = computed(() => {
+    const pictureurls = props.selectedRow.pictureurls ?? ''
+    return pictureurls.split(',').map((path) => getFileUrl(path))
+})
+
+const show = shallowRef(true)
+const refresh = shallowRef(false)
+
+const onCancel = (isRefresh = false) => {
+    show.value = false
+    refresh.value = isRefresh
+}
+
+const onSubmit = () => {
+    openComponent('delisting')
+}
+</script>

+ 55 - 0
src/packages/pc/views/market/trade/presell/ballot/index.vue

@@ -0,0 +1,55 @@
+<!-- 交易市场-预售转让-预售中签 -->
+<template>
+    <app-table :data="dataList" v-model:columns="tableColumns" :loading="loading" @row-click="onRowClick" showIndex>
+        <!-- <template #headerLeft>
+            <app-filter :options="filterOptons" />
+        </template> -->
+        <template #goodsname='{ row }'>
+            {{ row.goodscode }}/{{ row.goodsname }}
+        </template>
+        <template #presalestatus='{ value }'>
+            {{ getWRPresaleStatusName(value) }}
+        </template>
+        <template #footer>
+            <component ref="componentRef" v-bind="{ selectedRow }" :is="componentMap.get(componentId)"
+                @closed="closeComponent" v-if="componentId" />
+        </template>
+    </app-table>
+</template>
+
+<script lang="ts" setup>
+import { shallowRef, defineAsyncComponent } from 'vue'
+import { useComponent } from '@/hooks/component'
+import { useRequest } from '@/hooks/request'
+import { getWRPresaleStatusName } from '@/constants/order'
+import { queryPresaleAuctions } from '@/services/api/presale'
+import AppTable from '@pc/components/base/table/index.vue'
+
+const componentMap = new Map<string, unknown>([
+    ['detail', defineAsyncComponent(() => import('./detail/index.vue'))], // 详情
+])
+
+const { componentRef, componentId, openComponent, closeComponent } = useComponent(() => run(), false)
+const selectedRow = shallowRef<Model.PresaleAuctionsRsp>()
+
+const { dataList, run, loading } = useRequest(queryPresaleAuctions, {
+    params: {
+        presalemode: 5,
+        // presalestatusstr: '1'
+    }
+})
+
+const tableColumns = shallowRef<Model.TableColumn[]>([
+    { prop: 'attachmenturl', label: '图片' },
+    { prop: 'goodsname', label: '商品代码/名称' },
+    { prop: 'refprice', label: '价格' },
+    { prop: 'starttime', label: '开始时间' },
+    { prop: 'endtime', label: '结束时间' },
+    { prop: 'presalestatus', label: '预售状态' },
+])
+
+const onRowClick = (row: Model.PresaleAuctionsRsp) => {
+    selectedRow.value = row
+    openComponent('detail')
+}
+</script>

+ 135 - 0
src/packages/pc/views/market/trade/presell/transfer/index.vue

@@ -0,0 +1,135 @@
+<!-- 交易市场-订单交易 -->
+<template>
+    <app-table :data="tableList" v-model:columns="tableColumns" :loading="loading" @row-click="onRowClick" showIndex>
+        <!-- 规格 -->
+        <template #goodscode="{ row }">
+            {{ row.goodscode }}/{{ row.goodsname }}
+        </template>
+        <!-- 规格 -->
+        <template #spec="{ row }">
+            {{ handleNumberValue(row.agreeunit, getGoodsUnitName(row.goodunitid)) }}
+        </template>
+        <!-- 卖价 -->
+        <template #ask="{ row }">
+            <span :class="row.askColor">{{ row.ask }}</span>
+        </template>
+        <!-- 买价 -->
+        <template #bid="{ row }">
+            <span :class="row.bidColor">{{ row.bid }}</span>
+        </template>
+        <!-- 当前价 -->
+        <template #last="{ row }">
+            <span :class="row.lastColor">{{ row.last }}</span>
+        </template>
+        <!-- 涨跌 -->
+        <template #rise="{ row }">
+            <span :class="row.lastColor">{{ row.rise }}</span>
+        </template>
+        <!-- 涨跌幅 -->
+        <template #change="{ row }">
+            <span :class="row.lastColor">{{ row.change }}</span>
+        </template>
+        <!-- 开盘 -->
+        <template #opened="{ row }">
+            <span :class="row.openedColor">{{ row.opened }}</span>
+        </template>
+        <!-- 最低 -->
+        <template #lowest="{ row }">
+            <span :class="row.lowestColor">{{ row.lowest }}</span>
+        </template>
+        <!-- 最高 -->
+        <template #highest="{ row }">
+            <span :class="row.highestColor">{{ row.highest }}</span>
+        </template>
+    </app-table>
+    <component ref="componentRef" v-bind="{ goodsId }" :is="componentMap.get(componentId)" @closed="closeComponent"
+        v-if="componentId" />
+</template>
+
+<script lang="ts" setup>
+import { shallowRef, computed, onMounted, onUnmounted, defineAsyncComponent } from 'vue'
+import { parsePercent, handleNumberValue } from '@/filters'
+import { useComponent } from '@/hooks/component'
+import { getGoodsUnitName } from '@/constants/unit'
+import { useFuturesStore, useGoodsStore } from '@/stores'
+import quoteSocket from '@/services/websocket/quote'
+import AppTable from '@pc/components/base/table/index.vue'
+
+const componentMap = new Map<string, unknown>([
+    
+])
+
+const futuresStore = useFuturesStore()
+const goodsStore = useGoodsStore()
+const subscribe = quoteSocket.createSubscribe()
+
+const { loading, goodsId, quoteGoodsList } = goodsStore.$toRefs()
+const { componentRef, componentId, openComponent, closeComponent } = useComponent(() => goodsStore.getQuoteGoodsList({
+    marketids: '49201'
+}), false)
+
+const tableList = computed(() => {
+    return quoteGoodsList.value.map((item) => {
+        const quote = futuresStore.getGoodsQuote(item.goodscode)
+        const { bid, bidColor, bidvolume, ask, askColor, askvolume, goodunitid, agreeunit, limitdown, limitup, lastColor, openedColor, lowestColor, highestColor, last, presettle, rise, change, amplitude, highest, lowest, opened, decimalplace } = quote.value ?? {}
+        return {
+            ...item,
+            lastColor,
+            openedColor,
+            lowestColor,
+            highestColor,
+            askColor,
+            bidColor,
+            bid: handleNumberValue(bid?.toFixed(decimalplace)),
+            bidvolume: handleNumberValue(bidvolume),
+            ask: handleNumberValue(ask?.toFixed(decimalplace)),
+            askvolume: handleNumberValue(askvolume),
+            last: handleNumberValue(last?.toFixed(decimalplace)),
+            rise: rise?.toFixed(item.decimalplace),
+            change: parsePercent(change),
+            opened: handleNumberValue(opened?.toFixed(decimalplace)),
+            presettle: handleNumberValue(presettle?.toFixed(decimalplace)),
+            lowest: handleNumberValue(lowest?.toFixed(decimalplace)),
+            highest: handleNumberValue(highest?.toFixed(decimalplace)),
+            amplitude: parsePercent(amplitude),
+            limitdown: handleNumberValue(limitdown?.toFixed(decimalplace)),
+            limitup: handleNumberValue(limitup?.toFixed(decimalplace)),
+            agreeunit,
+            goodunitid
+        }
+    })
+})
+
+const tableColumns = shallowRef<Model.TableColumn[]>([
+    { prop: 'goodscode', label: '代码' },
+    { prop: 'goodsname', label: '名称' },
+    { prop: 'spec', label: '规格' },
+    { prop: 'bid', label: '买价' },
+    { prop: 'bidvolume', label: '买量' },
+    { prop: 'ask', label: '卖价' },
+    { prop: 'askvolume', label: '卖量' },
+    { prop: 'last', label: '当前价' },
+    { prop: 'rise', label: '涨跌' },
+    { prop: 'change', label: '涨跌幅' },
+    { prop: 'opened', label: '开盘' },
+    { prop: 'presettle', label: '昨结' },
+    { prop: 'highest', label: '最高' },
+    { prop: 'lowest', label: '最低' },
+    { prop: 'amplitude', label: '振幅' },
+    { prop: 'limitup', label: '涨停价', className: 'g-price-up' },
+    { prop: 'limitdown', label: '跌停价', className: 'g-price-down' },
+])
+
+const onRowClick = (row: Model.OrderQuoteRsp) => {
+    goodsId.value = row.goodsid
+    openComponent('detail')
+}
+
+onMounted(() => {
+    goodsStore.getQuoteGoodsList({ marketids: '49201' }).then(() => {
+        const goodsCodes = goodsStore.quoteGoodsList.map((e) => e.goodscode)
+        subscribe.start(...goodsCodes)
+    })
+})
+onUnmounted(() => subscribe.stop())
+</script>

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

@@ -12,7 +12,7 @@ export interface EnumType {
     disabled?: boolean;
 }
 
-const enumKeys = ['confirmStatus', 'deliveryPayMode', 'deliveryStatus', 'clientType', 'stepStatus', 'scoreConfigType', 'GZBSCPayStatus', 'performanceStatus', 'handlestatus', 'performanceType', 'accountBusinessCode', 'certificatetype', 'signstatus', 'thjOrderStatus', 'THJDeliveryMode', 'goodsunit', 'WROutInApplyStatus2', 'THJTransferStatus', 'WRTradeOrderStatus', 'THJMarket', 'THJProfitRoleType', 'appointmentModelOut', 'orderstatus', 'Pricemode2', 'buildtype', 'listingselecttype', 'certypeperson', 'runstatus'] as const
+const enumKeys = ['confirmStatus', 'deliveryPayMode', 'deliveryStatus', 'WRPresaleStatus', 'clientType', 'stepStatus', 'scoreConfigType', 'GZBSCPayStatus', 'performanceStatus', 'handlestatus', 'performanceType', 'accountBusinessCode', 'certificatetype', 'signstatus', 'thjOrderStatus', 'THJDeliveryMode', 'goodsunit', 'WROutInApplyStatus2', 'THJTransferStatus', 'WRTradeOrderStatus', 'THJMarket', 'THJProfitRoleType', 'appointmentModelOut', 'orderstatus', 'Pricemode2', 'buildtype', 'listingselecttype', 'certypeperson', 'runstatus'] as const
 
 const enumMap = new Map<typeof enumKeys[number], ShallowRef<Model.EnumRsp[]>>()