优化发布确认与订单资金拆分
This commit is contained in:
@@ -42,6 +42,12 @@ const paymentRecords = ref<AdminPayment[]>([])
|
|||||||
const actionType = ref<'close' | 'abnormal' | 'reset' | ''>('')
|
const actionType = ref<'close' | 'abnormal' | 'reset' | ''>('')
|
||||||
const reason = ref('')
|
const reason = ref('')
|
||||||
const refundStatus = ref<RefundStatus | null>(null)
|
const refundStatus = ref<RefundStatus | null>(null)
|
||||||
|
|
||||||
|
type FundSplitRow = {
|
||||||
|
label: string
|
||||||
|
amountCent: number | null | undefined
|
||||||
|
}
|
||||||
|
|
||||||
const listingCode = computed(() =>
|
const listingCode = computed(() =>
|
||||||
order.value ? formatListingNo(order.value.listing_no, order.value.listing_id) : '-'
|
order.value ? formatListingNo(order.value.listing_no, order.value.listing_id) : '-'
|
||||||
)
|
)
|
||||||
@@ -109,10 +115,14 @@ const assetSummary = computed(() => {
|
|||||||
if (typeof summary !== 'object' || summary === null) return null
|
if (typeof summary !== 'object' || summary === null) return null
|
||||||
return summary as Record<string, unknown>
|
return summary as Record<string, unknown>
|
||||||
})
|
})
|
||||||
const snapshotRatio = computed(() => {
|
const snapshotPriceBreakdown = computed(() => {
|
||||||
const breakdown = assetSummary.value?.price_breakdown
|
const breakdown = assetSummary.value?.price_breakdown
|
||||||
if (typeof breakdown !== 'object' || breakdown === null) return null
|
if (typeof breakdown !== 'object' || breakdown === null) return null
|
||||||
const row = breakdown as Record<string, unknown>
|
return breakdown as Record<string, unknown>
|
||||||
|
})
|
||||||
|
const snapshotRatio = computed(() => {
|
||||||
|
const row = snapshotPriceBreakdown.value
|
||||||
|
if (!row) return null
|
||||||
const sellerRatio = Number(row.seller_ratio || 0)
|
const sellerRatio = Number(row.seller_ratio || 0)
|
||||||
const buyerRatio = Number(row.buyer_ratio || 0)
|
const buyerRatio = Number(row.buyer_ratio || 0)
|
||||||
const publishRatio = Number(assetSummary.value?.publish_ratio || 0)
|
const publishRatio = Number(assetSummary.value?.publish_ratio || 0)
|
||||||
@@ -121,6 +131,36 @@ const snapshotRatio = computed(() => {
|
|||||||
sellRatio: buyerRatio > 0 ? buyerRatio : 0,
|
sellRatio: buyerRatio > 0 ? buyerRatio : 0,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
const ownerCoinBasePriceCent = computed(() => readPriceBreakdownCent('seller_coin_base_price'))
|
||||||
|
const ownerLossPriceCent = computed(() => {
|
||||||
|
const consumableCent = readPriceBreakdownCent('consumable_price')
|
||||||
|
if (consumableCent !== null) return consumableCent
|
||||||
|
if (ownerCoinBasePriceCent.value === null || !order.value?.owner_rent_amount_cent) return null
|
||||||
|
return Math.max(Number(order.value.owner_rent_amount_cent) - ownerCoinBasePriceCent.value, 0)
|
||||||
|
})
|
||||||
|
const hasOwnerRentBreakdown = computed(() => ownerCoinBasePriceCent.value !== null)
|
||||||
|
const fundSplitRows = computed(() => {
|
||||||
|
if (!order.value) return []
|
||||||
|
const rows: FundSplitRow[] = [
|
||||||
|
{ label: '租客租金', amountCent: order.value.rent_amount_cent },
|
||||||
|
]
|
||||||
|
if (hasOwnerRentBreakdown.value) {
|
||||||
|
rows.push(
|
||||||
|
{ label: '号主纯币价格', amountCent: ownerCoinBasePriceCent.value },
|
||||||
|
{ label: '号主损耗', amountCent: ownerLossPriceCent.value ?? 0 },
|
||||||
|
{ label: '号主租金合计', amountCent: order.value.owner_rent_amount_cent }
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
rows.push({ label: '号主租金', amountCent: order.value.owner_rent_amount_cent })
|
||||||
|
}
|
||||||
|
rows.push(
|
||||||
|
{ label: '平台费用', amountCent: order.value.platform_fee_cent },
|
||||||
|
{ label: '实付押金', amountCent: order.value.deposit_amount_cent },
|
||||||
|
{ label: '原始押金', amountCent: order.value.deposit_original_amount_cent },
|
||||||
|
{ label: '免押额度', amountCent: order.value.deposit_waived_amount_cent }
|
||||||
|
)
|
||||||
|
return rows
|
||||||
|
})
|
||||||
const snapshotSeasonTags = computed(() => {
|
const snapshotSeasonTags = computed(() => {
|
||||||
const tags = currentSnapshot.value?.season_tags
|
const tags = currentSnapshot.value?.season_tags
|
||||||
return Array.isArray(tags) ? tags.map(item => String(item)).filter(Boolean) : []
|
return Array.isArray(tags) ? tags.map(item => String(item)).filter(Boolean) : []
|
||||||
@@ -298,6 +338,14 @@ function moneyCent(value: number | undefined | null) {
|
|||||||
return formatCentWithSymbol(Number(value || 0))
|
return formatCentWithSymbol(Number(value || 0))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function readPriceBreakdownCent(key: string) {
|
||||||
|
const raw = snapshotPriceBreakdown.value?.[key]
|
||||||
|
if (raw === undefined || raw === null || raw === '') return null
|
||||||
|
const value = Number(raw)
|
||||||
|
if (!Number.isFinite(value)) return null
|
||||||
|
return Math.round(value * 100)
|
||||||
|
}
|
||||||
|
|
||||||
function firstQueryValue(value: unknown) {
|
function firstQueryValue(value: unknown) {
|
||||||
if (Array.isArray(value)) return typeof value[0] === 'string' ? value[0] : ''
|
if (Array.isArray(value)) return typeof value[0] === 'string' ? value[0] : ''
|
||||||
return typeof value === 'string' ? value : ''
|
return typeof value === 'string' ? value : ''
|
||||||
@@ -564,29 +612,9 @@ function paymentPaidAt(record: AdminPayment) {
|
|||||||
<span class="panel-subtitle">{{ priceRoleLabel(order.price_role) }}</span>
|
<span class="panel-subtitle">{{ priceRoleLabel(order.price_role) }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="money-list">
|
<div class="money-list">
|
||||||
<div class="money-row">
|
<div v-for="row in fundSplitRows" :key="row.label" class="money-row">
|
||||||
<span>租客租金</span>
|
<span>{{ row.label }}</span>
|
||||||
<strong>{{ moneyCent(order.rent_amount_cent) }}</strong>
|
<strong>{{ moneyCent(row.amountCent) }}</strong>
|
||||||
</div>
|
|
||||||
<div class="money-row">
|
|
||||||
<span>号主租金</span>
|
|
||||||
<strong>{{ moneyCent(order.owner_rent_amount_cent) }}</strong>
|
|
||||||
</div>
|
|
||||||
<div class="money-row">
|
|
||||||
<span>平台费用</span>
|
|
||||||
<strong>{{ moneyCent(order.platform_fee_cent) }}</strong>
|
|
||||||
</div>
|
|
||||||
<div class="money-row">
|
|
||||||
<span>实付押金</span>
|
|
||||||
<strong>{{ moneyCent(order.deposit_amount_cent) }}</strong>
|
|
||||||
</div>
|
|
||||||
<div class="money-row">
|
|
||||||
<span>原始押金</span>
|
|
||||||
<strong>{{ moneyCent(order.deposit_original_amount_cent) }}</strong>
|
|
||||||
</div>
|
|
||||||
<div class="money-row">
|
|
||||||
<span>免押额度</span>
|
|
||||||
<strong>{{ moneyCent(order.deposit_waived_amount_cent) }}</strong>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="money-row total">
|
<div class="money-row total">
|
||||||
<span>订单实付合计</span>
|
<span>订单实付合计</span>
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ export function usePublishForm(options: UsePublishFormOptions) {
|
|||||||
const publishAgreements = ref<ListingPublishAgreements>(emptyListingPublishAgreements)
|
const publishAgreements = ref<ListingPublishAgreements>(emptyListingPublishAgreements)
|
||||||
const virtualAssetSaleAgreementChecked = ref(false)
|
const virtualAssetSaleAgreementChecked = ref(false)
|
||||||
const sellerAgreementChecked = ref(false)
|
const sellerAgreementChecked = ref(false)
|
||||||
|
const passwordAndDeviceConfirmed = ref(false)
|
||||||
const fileInput = ref<HTMLInputElement | null>(null)
|
const fileInput = ref<HTMLInputElement | null>(null)
|
||||||
const activeUploadKey = ref<ScreenshotKey>('coin')
|
const activeUploadKey = ref<ScreenshotKey>('coin')
|
||||||
const form = reactive<PublishForm>(defaultPublishForm())
|
const form = reactive<PublishForm>(defaultPublishForm())
|
||||||
@@ -81,6 +82,7 @@ export function usePublishForm(options: UsePublishFormOptions) {
|
|||||||
const pageTitle = computed(() => (isEditMode.value ? '编辑账号' : '发布账号'))
|
const pageTitle = computed(() => (isEditMode.value ? '编辑账号' : '发布账号'))
|
||||||
const submitButtonText = computed(() => (isEditMode.value ? '提交修改' : '立即发布'))
|
const submitButtonText = computed(() => (isEditMode.value ? '提交修改' : '立即发布'))
|
||||||
const submitLoadingText = computed(() => (isEditMode.value ? '提交中...' : '发布中...'))
|
const submitLoadingText = computed(() => (isEditMode.value ? '提交中...' : '发布中...'))
|
||||||
|
const showBanRecordRiskHint = false
|
||||||
|
|
||||||
const pricing = usePricingCalculator({
|
const pricing = usePricingCalculator({
|
||||||
form,
|
form,
|
||||||
@@ -96,7 +98,10 @@ export function usePublishForm(options: UsePublishFormOptions) {
|
|||||||
)
|
)
|
||||||
const requiredScreenshotCount = ref(0)
|
const requiredScreenshotCount = ref(0)
|
||||||
const canPublishAfterAgreements = computed(
|
const canPublishAfterAgreements = computed(
|
||||||
() => virtualAssetSaleAgreementChecked.value && sellerAgreementChecked.value
|
() =>
|
||||||
|
virtualAssetSaleAgreementChecked.value &&
|
||||||
|
sellerAgreementChecked.value &&
|
||||||
|
passwordAndDeviceConfirmed.value
|
||||||
)
|
)
|
||||||
const disabledOnlineStartOptions = computed(() =>
|
const disabledOnlineStartOptions = computed(() =>
|
||||||
commonOnlineTimes.filter(time => !canUseOnlineStart(time))
|
commonOnlineTimes.filter(time => !canUseOnlineStart(time))
|
||||||
@@ -316,6 +321,7 @@ export function usePublishForm(options: UsePublishFormOptions) {
|
|||||||
selectedSkins.value = Object.values(skinGroups).flatMap(value => stringArray(value))
|
selectedSkins.value = Object.values(skinGroups).flatMap(value => stringArray(value))
|
||||||
virtualAssetSaleAgreementChecked.value = true
|
virtualAssetSaleAgreementChecked.value = true
|
||||||
sellerAgreementChecked.value = true
|
sellerAgreementChecked.value = true
|
||||||
|
passwordAndDeviceConfirmed.value = true
|
||||||
hydrateScreenshotPreviews()
|
hydrateScreenshotPreviews()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -328,6 +334,7 @@ export function usePublishForm(options: UsePublishFormOptions) {
|
|||||||
selectedSkins.value = []
|
selectedSkins.value = []
|
||||||
virtualAssetSaleAgreementChecked.value = false
|
virtualAssetSaleAgreementChecked.value = false
|
||||||
sellerAgreementChecked.value = false
|
sellerAgreementChecked.value = false
|
||||||
|
passwordAndDeviceConfirmed.value = false
|
||||||
activeUploadKey.value = 'coin'
|
activeUploadKey.value = 'coin'
|
||||||
|
|
||||||
// Also re-initialize quantityValues to 0
|
// Also re-initialize quantityValues to 0
|
||||||
@@ -767,7 +774,10 @@ export function usePublishForm(options: UsePublishFormOptions) {
|
|||||||
if (!pricing.calculatedFinalPrice.value) return '请完善币数、保险、体力和负重后再发布'
|
if (!pricing.calculatedFinalPrice.value) return '请完善币数、保险、体力和负重后再发布'
|
||||||
if (!Number.isFinite(pricing.calculatedFinalPrice.value))
|
if (!Number.isFinite(pricing.calculatedFinalPrice.value))
|
||||||
return '发布价格计算异常,请检查填写内容'
|
return '发布价格计算异常,请检查填写内容'
|
||||||
if (!canPublishAfterAgreements.value) return '请先阅读并勾选两份发布协议'
|
if (!virtualAssetSaleAgreementChecked.value || !sellerAgreementChecked.value) {
|
||||||
|
return '请先阅读并勾选两份发布协议'
|
||||||
|
}
|
||||||
|
if (!passwordAndDeviceConfirmed.value) return '请确认已知晓打完需改密并清除登录设备'
|
||||||
for (const item of pricing.screenshotSlots.value) {
|
for (const item of pricing.screenshotSlots.value) {
|
||||||
if (isScreenshotRequired(item) && getScreenshotCount(item.key) === 0)
|
if (isScreenshotRequired(item) && getScreenshotCount(item.key) === 0)
|
||||||
return `请上传${item.label}`
|
return `请上传${item.label}`
|
||||||
@@ -931,7 +941,9 @@ export function usePublishForm(options: UsePublishFormOptions) {
|
|||||||
publishAgreements,
|
publishAgreements,
|
||||||
virtualAssetSaleAgreementChecked,
|
virtualAssetSaleAgreementChecked,
|
||||||
sellerAgreementChecked,
|
sellerAgreementChecked,
|
||||||
|
passwordAndDeviceConfirmed,
|
||||||
canPublishAfterAgreements,
|
canPublishAfterAgreements,
|
||||||
|
showBanRecordRiskHint,
|
||||||
fileInput,
|
fileInput,
|
||||||
activeUploadKey,
|
activeUploadKey,
|
||||||
form,
|
form,
|
||||||
|
|||||||
@@ -23,7 +23,9 @@ const {
|
|||||||
publishAgreements,
|
publishAgreements,
|
||||||
virtualAssetSaleAgreementChecked,
|
virtualAssetSaleAgreementChecked,
|
||||||
sellerAgreementChecked,
|
sellerAgreementChecked,
|
||||||
|
passwordAndDeviceConfirmed,
|
||||||
canPublishAfterAgreements,
|
canPublishAfterAgreements,
|
||||||
|
showBanRecordRiskHint,
|
||||||
fileInput,
|
fileInput,
|
||||||
activeUploadKey,
|
activeUploadKey,
|
||||||
form,
|
form,
|
||||||
@@ -474,6 +476,9 @@ const screenshotGuides: Record<string, string> = {
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</van-field>
|
</van-field>
|
||||||
|
<p v-if="showBanRecordRiskHint && banRecordOptions.length" class="field-hint">
|
||||||
|
刚出租结算完的账号需冷号七天才可再次出租,IP频繁变动会导致封号。
|
||||||
|
</p>
|
||||||
|
|
||||||
<div class="region-panel">
|
<div class="region-panel">
|
||||||
<div class="region-title">
|
<div class="region-title">
|
||||||
@@ -744,6 +749,9 @@ const screenshotGuides: Record<string, string> = {
|
|||||||
</button>
|
</button>
|
||||||
</span>
|
</span>
|
||||||
</van-checkbox>
|
</van-checkbox>
|
||||||
|
<van-checkbox v-model="passwordAndDeviceConfirmed" icon-size="18px">
|
||||||
|
<span class="agreement-check-label">我已知晓打完需改密并清除登录设备</span>
|
||||||
|
</van-checkbox>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="publish-actions">
|
<div class="publish-actions">
|
||||||
|
|||||||
@@ -26,7 +26,9 @@ const {
|
|||||||
publishAgreements,
|
publishAgreements,
|
||||||
virtualAssetSaleAgreementChecked,
|
virtualAssetSaleAgreementChecked,
|
||||||
sellerAgreementChecked,
|
sellerAgreementChecked,
|
||||||
|
passwordAndDeviceConfirmed,
|
||||||
canPublishAfterAgreements,
|
canPublishAfterAgreements,
|
||||||
|
showBanRecordRiskHint,
|
||||||
fileInput,
|
fileInput,
|
||||||
activeUploadKey,
|
activeUploadKey,
|
||||||
form,
|
form,
|
||||||
@@ -414,6 +416,9 @@ function selectDailyLoss(value: string | number) {
|
|||||||
@select="form.ban_record = String($event)"
|
@select="form.ban_record = String($event)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<p v-if="showBanRecordRiskHint && banRecordOptions.length" class="field-hint">
|
||||||
|
刚出租结算完的账号需冷号七天才可再次出租,IP频繁变动会导致封号。
|
||||||
|
</p>
|
||||||
|
|
||||||
<div v-if="regionOptions.length" class="region-panel login-region-panel">
|
<div v-if="regionOptions.length" class="region-panel login-region-panel">
|
||||||
<div class="region-title">
|
<div class="region-title">
|
||||||
@@ -702,6 +707,9 @@ function selectDailyLoss(value: string | number) {
|
|||||||
</button>
|
</button>
|
||||||
</span>
|
</span>
|
||||||
</el-checkbox>
|
</el-checkbox>
|
||||||
|
<el-checkbox v-model="passwordAndDeviceConfirmed">
|
||||||
|
<span class="agreement-check-label">我已知晓打完需改密并清除登录设备</span>
|
||||||
|
</el-checkbox>
|
||||||
</div>
|
</div>
|
||||||
<div class="summary-actions">
|
<div class="summary-actions">
|
||||||
<el-button
|
<el-button
|
||||||
|
|||||||
Reference in New Issue
Block a user