优化pc 出售界面
This commit is contained in:
@@ -490,7 +490,7 @@ async function handleSubmit() {
|
|||||||
loading.value = true;
|
loading.value = true;
|
||||||
try {
|
try {
|
||||||
const title = `${form.server_region} ${form.rank_level} ${form.haf_coin_amount}M哈夫币`;
|
const title = `${form.server_region} ${form.rank_level} ${form.haf_coin_amount}M哈夫币`;
|
||||||
const dailyPrice = calculatedFinalPrice.value;
|
const listingPrice = calculatedFinalPrice.value;
|
||||||
|
|
||||||
const listing = await createListing({
|
const listing = await createListing({
|
||||||
title,
|
title,
|
||||||
@@ -501,7 +501,7 @@ async function handleSubmit() {
|
|||||||
haf_coin_amount: coinMAmount.value * 1000000,
|
haf_coin_amount: coinMAmount.value * 1000000,
|
||||||
asset_summary: buildAssetSummary(),
|
asset_summary: buildAssetSummary(),
|
||||||
screenshot_urls: screenshotUrls.value,
|
screenshot_urls: screenshotUrls.value,
|
||||||
price: dailyPrice,
|
price: listingPrice,
|
||||||
deposit_amount: Number(form.deposit_amount),
|
deposit_amount: Number(form.deposit_amount),
|
||||||
});
|
});
|
||||||
localStorage.removeItem(draftKey);
|
localStorage.removeItem(draftKey);
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
import { computed, onBeforeUnmount, onMounted, reactive, ref, watch } from 'vue'
|
import { computed, onBeforeUnmount, onMounted, reactive, ref, watch } from 'vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
import { Delete, Picture, RefreshRight, UploadFilled } from '@element-plus/icons-vue'
|
import { Delete, DocumentChecked, Picture, RefreshRight, UploadFilled } from '@element-plus/icons-vue'
|
||||||
|
|
||||||
import { fetchFileBlobByURL, uploadFile } from '@/api/files'
|
import { fetchFileBlobByURL, uploadFile } from '@/api/files'
|
||||||
import {
|
import {
|
||||||
@@ -49,10 +49,12 @@ interface PublishDraft {
|
|||||||
|
|
||||||
const draftKey = 'hfb.pc.publish.draft'
|
const draftKey = 'hfb.pc.publish.draft'
|
||||||
const dailyLossOptions = [10, 20, 30, 40, 50]
|
const dailyLossOptions = [10, 20, 30, 40, 50]
|
||||||
|
const commonOnlineTimes = ['00:00', '08:00', '10:00', '12:00', '14:00', '18:00', '20:00', '22:00', '23:59']
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const uploading = ref(false)
|
const uploading = ref(false)
|
||||||
const suppressDraftSave = ref(false)
|
const suppressDraftSave = ref(false)
|
||||||
|
const draftReady = ref(false)
|
||||||
const publishOptions = ref<ListingPublishOptions>(emptyListingPublishOptions)
|
const publishOptions = ref<ListingPublishOptions>(emptyListingPublishOptions)
|
||||||
const salePriceConfig = ref<PublishSalePriceConfig>(emptyListingSalePriceConfig)
|
const salePriceConfig = ref<PublishSalePriceConfig>(emptyListingSalePriceConfig)
|
||||||
const fileInput = ref<HTMLInputElement | null>(null)
|
const fileInput = ref<HTMLInputElement | null>(null)
|
||||||
@@ -141,10 +143,18 @@ const acceleratedSaleRatioPlaceholder = computed(() => {
|
|||||||
if (calculatedDefaultSaleRatio.value <= 0) return '填写资料后自动生成可设置范围'
|
if (calculatedDefaultSaleRatio.value <= 0) return '填写资料后自动生成可设置范围'
|
||||||
return `默认 ${formatNumber(calculatedDefaultSaleRatio.value)},最高 ${formatNumber(maxAcceleratedSaleRatio.value)}`
|
return `默认 ${formatNumber(calculatedDefaultSaleRatio.value)},最高 ${formatNumber(maxAcceleratedSaleRatio.value)}`
|
||||||
})
|
})
|
||||||
const selectedSkinCount = computed(() => selectedSkins.value.length)
|
|
||||||
const uploadedScreenshotCount = computed(() => screenshotUrls.value.length)
|
const uploadedScreenshotCount = computed(() => screenshotUrls.value.length)
|
||||||
const requiredScreenshotCount = computed(() => screenshotSlots.value.filter((item) => isScreenshotRequired(item)).length)
|
const requiredScreenshotCount = computed(() => screenshotSlots.value.filter((item) => isScreenshotRequired(item)).length)
|
||||||
const recommendedDepositAmount = computed(() => calculateRecommendedDeposit())
|
const recommendedDepositAmount = computed(() => calculateRecommendedDeposit())
|
||||||
|
const depositBreakdownItems = computed(() => buildDepositBreakdownItems())
|
||||||
|
const platformRuleLabel = computed(() => {
|
||||||
|
const labels: Record<string, string> = {
|
||||||
|
fixed_markup: '固定加价',
|
||||||
|
ratio_subtract: '比例修正',
|
||||||
|
none: '无加价',
|
||||||
|
}
|
||||||
|
return labels[calculatedPlatformPricing.value.ruleType] || calculatedPlatformPricing.value.ruleType
|
||||||
|
})
|
||||||
const publishTitle = computed(() => {
|
const publishTitle = computed(() => {
|
||||||
const parts = [form.server_region, form.rank_level, coinMAmount.value ? `${coinMAmount.value}M哈夫币` : ''].filter(Boolean)
|
const parts = [form.server_region, form.rank_level, coinMAmount.value ? `${coinMAmount.value}M哈夫币` : ''].filter(Boolean)
|
||||||
return parts.length ? parts.join(' ') : '待完善账号信息'
|
return parts.length ? parts.join(' ') : '待完善账号信息'
|
||||||
@@ -152,10 +162,14 @@ const publishTitle = computed(() => {
|
|||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
restoreDraft()
|
restoreDraft()
|
||||||
|
draftReady.value = true
|
||||||
|
window.addEventListener('beforeunload', handleBeforeUnload)
|
||||||
loadPublishOptions()
|
loadPublishOptions()
|
||||||
})
|
})
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
|
saveDraft({ force: true })
|
||||||
|
window.removeEventListener('beforeunload', handleBeforeUnload)
|
||||||
revokeAllScreenshotPreviews()
|
revokeAllScreenshotPreviews()
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -206,11 +220,21 @@ function buildDraft(): PublishDraft {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveDraft() {
|
function saveDraft(options: { force?: boolean } = {}) {
|
||||||
if (suppressDraftSave.value) return
|
if (suppressDraftSave.value) return
|
||||||
|
if (!options.force && !draftReady.value) return
|
||||||
localStorage.setItem(draftKey, JSON.stringify(buildDraft()))
|
localStorage.setItem(draftKey, JSON.stringify(buildDraft()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleSaveDraft() {
|
||||||
|
saveDraft({ force: true })
|
||||||
|
ElMessage.success('草稿已保存')
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleBeforeUnload() {
|
||||||
|
saveDraft({ force: true })
|
||||||
|
}
|
||||||
|
|
||||||
function restoreDraft() {
|
function restoreDraft() {
|
||||||
const raw = localStorage.getItem(draftKey)
|
const raw = localStorage.getItem(draftKey)
|
||||||
if (!raw) return
|
if (!raw) return
|
||||||
@@ -388,6 +412,28 @@ function calculateRecommendedDeposit() {
|
|||||||
return roundMoney(baseAmount + skinAmount)
|
return roundMoney(baseAmount + skinAmount)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function buildDepositBreakdownItems() {
|
||||||
|
const items = [
|
||||||
|
{
|
||||||
|
label: '基础押金',
|
||||||
|
amount: Number(depositRecommendConfig.value.base_amount || 0),
|
||||||
|
count: 1,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
for (const rule of depositRecommendConfig.value.skin_group_rules) {
|
||||||
|
const group = skinGroups.value.find((item) => item.key === rule.group_key)
|
||||||
|
if (!group) continue
|
||||||
|
const count = group.options.filter((skin) => selectedSkins.value.includes(skin)).length
|
||||||
|
if (count <= 0) continue
|
||||||
|
items.push({
|
||||||
|
label: rule.label,
|
||||||
|
amount: Number(rule.amount_per_item || 0) * count,
|
||||||
|
count,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return items
|
||||||
|
}
|
||||||
|
|
||||||
function useRecommendedDeposit() {
|
function useRecommendedDeposit() {
|
||||||
if (recommendedDepositAmount.value > 0) {
|
if (recommendedDepositAmount.value > 0) {
|
||||||
form.deposit_amount = recommendedDepositAmount.value
|
form.deposit_amount = recommendedDepositAmount.value
|
||||||
@@ -457,6 +503,7 @@ async function handleSubmit() {
|
|||||||
deposit_amount: Number(form.deposit_amount),
|
deposit_amount: Number(form.deposit_amount),
|
||||||
})
|
})
|
||||||
localStorage.removeItem(draftKey)
|
localStorage.removeItem(draftKey)
|
||||||
|
suppressDraftSave.value = true
|
||||||
ElMessage.success(
|
ElMessage.success(
|
||||||
listing.status === 'published' && listing.review_status === 'approved'
|
listing.status === 'published' && listing.review_status === 'approved'
|
||||||
? '发布成功,已上架'
|
? '发布成功,已上架'
|
||||||
@@ -753,7 +800,7 @@ function readError(error: unknown, fallback: string) {
|
|||||||
<span>{{ publishTitle }}</span>
|
<span>{{ publishTitle }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="field-row">
|
<div class="field-row panel-field-row">
|
||||||
<label>区服<span>*</span></label>
|
<label>区服<span>*</span></label>
|
||||||
<div class="chip-group">
|
<div class="chip-group">
|
||||||
<button
|
<button
|
||||||
@@ -769,7 +816,7 @@ function readError(error: unknown, fallback: string) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="faceOptions.length" class="field-row">
|
<div v-if="faceOptions.length" class="field-row panel-field-row">
|
||||||
<label>是否本人人脸</label>
|
<label>是否本人人脸</label>
|
||||||
<div class="chip-group">
|
<div class="chip-group">
|
||||||
<button
|
<button
|
||||||
@@ -785,7 +832,7 @@ function readError(error: unknown, fallback: string) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="compact-grid">
|
<div class="compact-grid panel-input-grid">
|
||||||
<label class="input-block">
|
<label class="input-block">
|
||||||
<span>哈夫币/M<b>*</b></span>
|
<span>哈夫币/M<b>*</b></span>
|
||||||
<el-input-number v-model="form.haf_coin_amount" :min="0" :controls="false" placeholder="100M 写 100" />
|
<el-input-number v-model="form.haf_coin_amount" :min="0" :controls="false" placeholder="100M 写 100" />
|
||||||
@@ -806,7 +853,7 @@ function readError(error: unknown, fallback: string) {
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="field-row">
|
<div class="field-row panel-field-row">
|
||||||
<label>段位<span>*</span></label>
|
<label>段位<span>*</span></label>
|
||||||
<div class="chip-group">
|
<div class="chip-group">
|
||||||
<button
|
<button
|
||||||
@@ -822,7 +869,7 @@ function readError(error: unknown, fallback: string) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="field-row">
|
<div class="field-row panel-field-row">
|
||||||
<label>赛季保险<span>*</span></label>
|
<label>赛季保险<span>*</span></label>
|
||||||
<div class="chip-group">
|
<div class="chip-group">
|
||||||
<button
|
<button
|
||||||
@@ -875,9 +922,16 @@ function readError(error: unknown, fallback: string) {
|
|||||||
<section v-if="quantityItems.length" class="form-section">
|
<section v-if="quantityItems.length" class="form-section">
|
||||||
<div class="section-heading">
|
<div class="section-heading">
|
||||||
<h2>额外消耗品</h2>
|
<h2>额外消耗品</h2>
|
||||||
<span>收费项会计入每日价格</span>
|
<span>收费项会计入发布价格</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="quantity-grid">
|
<div class="quantity-table">
|
||||||
|
<div class="quantity-header">
|
||||||
|
<span>物资</span>
|
||||||
|
<span>单价</span>
|
||||||
|
<span>数量</span>
|
||||||
|
<span>计费</span>
|
||||||
|
<span>状态</span>
|
||||||
|
</div>
|
||||||
<div
|
<div
|
||||||
v-for="item in quantityItems"
|
v-for="item in quantityItems"
|
||||||
:key="item.key"
|
:key="item.key"
|
||||||
@@ -886,8 +940,9 @@ function readError(error: unknown, fallback: string) {
|
|||||||
>
|
>
|
||||||
<div class="quantity-meta">
|
<div class="quantity-meta">
|
||||||
<strong :title="item.placeholder || item.label">{{ item.label }}</strong>
|
<strong :title="item.placeholder || item.label">{{ item.label }}</strong>
|
||||||
<small>{{ isQuantityItemDisabled(item) ? '3*3 已包含,不能填写' : item.price }}</small>
|
<small v-if="item.placeholder">{{ item.placeholder }}</small>
|
||||||
</div>
|
</div>
|
||||||
|
<span class="quantity-price">{{ item.price }}</span>
|
||||||
<el-input-number
|
<el-input-number
|
||||||
v-model="quantityValues[item.key]"
|
v-model="quantityValues[item.key]"
|
||||||
:min="0"
|
:min="0"
|
||||||
@@ -912,6 +967,9 @@ function readError(error: unknown, fallback: string) {
|
|||||||
收费
|
收费
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
<span class="quantity-status">
|
||||||
|
{{ isQuantityItemDisabled(item) ? '3*3 已包含' : '可填写' }}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -919,14 +977,16 @@ function readError(error: unknown, fallback: string) {
|
|||||||
<section class="form-section">
|
<section class="form-section">
|
||||||
<div class="section-heading">
|
<div class="section-heading">
|
||||||
<h2>皮肤与交接</h2>
|
<h2>皮肤与交接</h2>
|
||||||
<span>已选 {{ selectedSkinCount }} 项皮肤</span>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="skinGroups.length" class="skin-groups">
|
<div v-if="skinGroups.length" class="skin-groups">
|
||||||
<div v-for="group in skinGroups" :key="group.key" class="skin-group">
|
<div
|
||||||
|
v-for="group in skinGroups"
|
||||||
|
:key="group.key"
|
||||||
|
class="skin-group"
|
||||||
|
>
|
||||||
<div class="skin-title">
|
<div class="skin-title">
|
||||||
<strong>{{ group.title }}</strong>
|
<strong>{{ group.title }}</strong>
|
||||||
<span>{{ group.options.filter((skin) => selectedSkins.includes(skin)).length }} 项</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="chip-group">
|
<div class="chip-group">
|
||||||
<button
|
<button
|
||||||
@@ -943,7 +1003,7 @@ function readError(error: unknown, fallback: string) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="field-row">
|
<div class="field-row login-method-row">
|
||||||
<label>上号方式</label>
|
<label>上号方式</label>
|
||||||
<div class="chip-group">
|
<div class="chip-group">
|
||||||
<button
|
<button
|
||||||
@@ -960,15 +1020,55 @@ function readError(error: unknown, fallback: string) {
|
|||||||
<p class="field-hint">优先推荐账密登录,出售速度通常更快;请结合账号安全情况自行选择。</p>
|
<p class="field-hint">优先推荐账密登录,出售速度通常更快;请结合账号安全情况自行选择。</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="compact-grid two">
|
<div class="time-preset-panel">
|
||||||
<label class="input-block">
|
<div class="time-preset-row">
|
||||||
<span>在线开始</span>
|
<strong>在线开始</strong>
|
||||||
<el-time-picker v-model="form.online_start" value-format="HH:mm" format="HH:mm" placeholder="开始时间" />
|
<div class="time-preset-content">
|
||||||
</label>
|
<el-time-picker
|
||||||
<label class="input-block">
|
v-model="form.online_start"
|
||||||
<span>在线结束</span>
|
value-format="HH:mm"
|
||||||
<el-time-picker v-model="form.online_end" value-format="HH:mm" format="HH:mm" placeholder="结束时间" />
|
format="HH:mm"
|
||||||
</label>
|
placeholder="开始时间"
|
||||||
|
class="time-input"
|
||||||
|
/>
|
||||||
|
<div class="chip-group">
|
||||||
|
<button
|
||||||
|
v-for="time in commonOnlineTimes"
|
||||||
|
:key="`start-${time}`"
|
||||||
|
type="button"
|
||||||
|
class="chip"
|
||||||
|
:class="{ active: form.online_start === time }"
|
||||||
|
@click="form.online_start = time"
|
||||||
|
>
|
||||||
|
{{ time }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="time-preset-row">
|
||||||
|
<strong>在线结束</strong>
|
||||||
|
<div class="time-preset-content">
|
||||||
|
<el-time-picker
|
||||||
|
v-model="form.online_end"
|
||||||
|
value-format="HH:mm"
|
||||||
|
format="HH:mm"
|
||||||
|
placeholder="结束时间"
|
||||||
|
class="time-input"
|
||||||
|
/>
|
||||||
|
<div class="chip-group">
|
||||||
|
<button
|
||||||
|
v-for="time in commonOnlineTimes"
|
||||||
|
:key="`end-${time}`"
|
||||||
|
type="button"
|
||||||
|
class="chip"
|
||||||
|
:class="{ active: form.online_end === time }"
|
||||||
|
@click="form.online_end = time"
|
||||||
|
>
|
||||||
|
{{ time }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p class="field-hint">请填写能稳定联系上您的时间,便于扫码、冻结人脸和订单交接。</p>
|
<p class="field-hint">请填写能稳定联系上您的时间,便于扫码、冻结人脸和订单交接。</p>
|
||||||
|
|
||||||
@@ -988,7 +1088,7 @@ function readError(error: unknown, fallback: string) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="regionOptions.length" class="region-panel">
|
<div v-if="regionOptions.length" class="region-panel login-region-panel">
|
||||||
<div class="region-title">
|
<div class="region-title">
|
||||||
<strong>常用登录地区</strong>
|
<strong>常用登录地区</strong>
|
||||||
<span>已选 {{ form.common_regions.length }}</span>
|
<span>已选 {{ form.common_regions.length }}</span>
|
||||||
@@ -1049,15 +1149,22 @@ function readError(error: unknown, fallback: string) {
|
|||||||
<div class="compact-grid two">
|
<div class="compact-grid two">
|
||||||
<label class="input-block">
|
<label class="input-block">
|
||||||
<span>押金<b>*</b></span>
|
<span>押金<b>*</b></span>
|
||||||
<el-input-number
|
<div class="deposit-control">
|
||||||
v-model="form.deposit_amount"
|
<el-input-number
|
||||||
:min="0"
|
v-model="form.deposit_amount"
|
||||||
:controls="false"
|
:min="0"
|
||||||
:placeholder="priceConfig.deposit_placeholder"
|
:controls="false"
|
||||||
/>
|
:placeholder="priceConfig.deposit_placeholder"
|
||||||
<button class="recommend-button" type="button" @click="useRecommendedDeposit">
|
/>
|
||||||
推荐押金 ¥{{ recommendedDepositAmount }}
|
<button class="recommend-button" type="button" @click="useRecommendedDeposit">
|
||||||
</button>
|
使用推荐 ¥{{ recommendedDepositAmount }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="deposit-breakdown">
|
||||||
|
<span v-for="item in depositBreakdownItems" :key="`${item.label}-${item.count}`">
|
||||||
|
{{ item.label }}<template v-if="item.count > 1"> x{{ item.count }}</template> ¥{{ item.amount }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</label>
|
</label>
|
||||||
<label class="input-block">
|
<label class="input-block">
|
||||||
<span>每日损耗<b>*</b></span>
|
<span>每日损耗<b>*</b></span>
|
||||||
@@ -1131,7 +1238,7 @@ function readError(error: unknown, fallback: string) {
|
|||||||
<strong>¥{{ calculatedConsumablePrice }}</strong>
|
<strong>¥{{ calculatedConsumablePrice }}</strong>
|
||||||
</div>
|
</div>
|
||||||
<div class="price-cell accent">
|
<div class="price-cell accent">
|
||||||
<span>买家每日价</span>
|
<span>发布价格</span>
|
||||||
<strong>{{ calculatedFinalPrice ? `¥${calculatedFinalPrice}` : '--' }}</strong>
|
<strong>{{ calculatedFinalPrice ? `¥${calculatedFinalPrice}` : '--' }}</strong>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -1151,7 +1258,7 @@ function readError(error: unknown, fallback: string) {
|
|||||||
<aside class="summary-column">
|
<aside class="summary-column">
|
||||||
<div class="summary-panel">
|
<div class="summary-panel">
|
||||||
<div class="summary-main">
|
<div class="summary-main">
|
||||||
<span>预计买家每日价</span>
|
<span>预计发布价格</span>
|
||||||
<strong>{{ calculatedFinalPrice ? `¥${calculatedFinalPrice}` : '--' }}</strong>
|
<strong>{{ calculatedFinalPrice ? `¥${calculatedFinalPrice}` : '--' }}</strong>
|
||||||
</div>
|
</div>
|
||||||
<div class="summary-list">
|
<div class="summary-list">
|
||||||
@@ -1173,11 +1280,12 @@ function readError(error: unknown, fallback: string) {
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<span>加价规则</span>
|
<span>加价规则</span>
|
||||||
<strong>{{ calculatedPlatformPricing.ruleType }}</strong>
|
<strong>{{ platformRuleLabel }}</strong>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="summary-actions">
|
<div class="summary-actions">
|
||||||
<el-button :icon="UploadFilled" type="primary" :loading="loading" @click="handleSubmit">保存发布</el-button>
|
<el-button :icon="UploadFilled" type="primary" :loading="loading" @click="handleSubmit">保存发布</el-button>
|
||||||
|
<el-button :icon="DocumentChecked" :disabled="loading" @click="handleSaveDraft">保存草稿</el-button>
|
||||||
<el-button :icon="RefreshRight" :disabled="loading" @click="handleResetDraft">重置草稿</el-button>
|
<el-button :icon="RefreshRight" :disabled="loading" @click="handleResetDraft">重置草稿</el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -1194,16 +1302,17 @@ function readError(error: unknown, fallback: string) {
|
|||||||
|
|
||||||
.publish-layout {
|
.publish-layout {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: minmax(0, 1fr) 320px;
|
grid-template-columns: minmax(760px, 920px) 300px;
|
||||||
gap: 20px;
|
align-items: start;
|
||||||
max-width: 1480px;
|
gap: 18px;
|
||||||
|
max-width: 1238px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-column {
|
.form-column {
|
||||||
display: grid;
|
display: grid;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
gap: 16px;
|
gap: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-section,
|
.form-section,
|
||||||
@@ -1215,15 +1324,16 @@ function readError(error: unknown, fallback: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.form-section {
|
.form-section {
|
||||||
padding: 18px;
|
padding: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.section-heading {
|
.section-heading {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-start;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
margin-bottom: 16px;
|
min-height: 28px;
|
||||||
|
margin-bottom: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.section-heading h2 {
|
.section-heading h2 {
|
||||||
@@ -1241,10 +1351,21 @@ function readError(error: unknown, fallback: string) {
|
|||||||
|
|
||||||
.field-row {
|
.field-row {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 118px minmax(0, 1fr);
|
grid-template-columns: 112px minmax(0, 1fr);
|
||||||
gap: 12px;
|
gap: 14px;
|
||||||
align-items: start;
|
align-items: center;
|
||||||
margin-top: 14px;
|
margin-top: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-field-row,
|
||||||
|
.panel-input-grid {
|
||||||
|
padding: 12px;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: #f7f9fc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-input-grid {
|
||||||
|
align-items: end;
|
||||||
}
|
}
|
||||||
|
|
||||||
.field-row > label,
|
.field-row > label,
|
||||||
@@ -1252,7 +1373,7 @@ function readError(error: unknown, fallback: string) {
|
|||||||
color: #303743;
|
color: #303743;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
line-height: 32px;
|
line-height: 22px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.field-row label span,
|
.field-row label span,
|
||||||
@@ -1265,7 +1386,7 @@ function readError(error: unknown, fallback: string) {
|
|||||||
.chip-group {
|
.chip-group {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
gap: 8px;
|
gap: 7px;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1288,10 +1409,10 @@ function readError(error: unknown, fallback: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.chip {
|
.chip {
|
||||||
min-height: 32px;
|
min-height: 30px;
|
||||||
padding: 0 13px;
|
padding: 0 12px;
|
||||||
border-radius: 16px;
|
border-radius: 15px;
|
||||||
font-size: 13px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chip.active,
|
.chip.active,
|
||||||
@@ -1305,8 +1426,8 @@ function readError(error: unknown, fallback: string) {
|
|||||||
.compact-grid {
|
.compact-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||||
gap: 14px;
|
gap: 16px;
|
||||||
margin-top: 14px;
|
margin-top: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.compact-grid.two {
|
.compact-grid.two {
|
||||||
@@ -1316,7 +1437,7 @@ function readError(error: unknown, fallback: string) {
|
|||||||
.input-block {
|
.input-block {
|
||||||
display: grid;
|
display: grid;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
gap: 7px;
|
gap: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.input-block :deep(.el-input-number),
|
.input-block :deep(.el-input-number),
|
||||||
@@ -1339,10 +1460,10 @@ function readError(error: unknown, fallback: string) {
|
|||||||
|
|
||||||
.level-row {
|
.level-row {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 74px minmax(0, 1fr);
|
grid-template-columns: 72px minmax(0, 1fr);
|
||||||
gap: 10px;
|
gap: 12px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 12px;
|
padding: 10px 12px;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
background: #f7f9fc;
|
background: #f7f9fc;
|
||||||
}
|
}
|
||||||
@@ -1354,13 +1475,13 @@ function readError(error: unknown, fallback: string) {
|
|||||||
.level-options {
|
.level-options {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(7, minmax(0, 1fr));
|
grid-template-columns: repeat(7, minmax(0, 1fr));
|
||||||
gap: 8px;
|
gap: 9px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.level-btn {
|
.level-btn {
|
||||||
height: 32px;
|
height: 30px;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
border-radius: 16px;
|
border-radius: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.field-hint {
|
.field-hint {
|
||||||
@@ -1371,18 +1492,39 @@ function readError(error: unknown, fallback: string) {
|
|||||||
line-height: 1.55;
|
line-height: 1.55;
|
||||||
}
|
}
|
||||||
|
|
||||||
.quantity-grid {
|
.login-method-row {
|
||||||
|
padding: 12px;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: #f7f9fc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-method-row .field-hint {
|
||||||
|
margin-top: -2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.quantity-table {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.quantity-header,
|
||||||
|
.quantity-item {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: minmax(160px, 1fr) 90px 112px 112px 92px;
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.quantity-header {
|
||||||
|
min-height: 30px;
|
||||||
|
padding: 0 12px;
|
||||||
|
color: #7b8492;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 800;
|
||||||
}
|
}
|
||||||
|
|
||||||
.quantity-item {
|
.quantity-item {
|
||||||
display: grid;
|
min-height: 58px;
|
||||||
grid-template-columns: minmax(0, 1fr) 112px 112px;
|
|
||||||
gap: 10px;
|
|
||||||
align-items: center;
|
|
||||||
min-height: 76px;
|
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
background: #f7f9fc;
|
background: #f7f9fc;
|
||||||
@@ -1391,7 +1533,7 @@ function readError(error: unknown, fallback: string) {
|
|||||||
.quantity-meta {
|
.quantity-meta {
|
||||||
display: grid;
|
display: grid;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
gap: 5px;
|
gap: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.quantity-meta strong {
|
.quantity-meta strong {
|
||||||
@@ -1402,14 +1544,20 @@ function readError(error: unknown, fallback: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.quantity-meta small,
|
.quantity-meta small,
|
||||||
|
.quantity-price,
|
||||||
|
.quantity-status,
|
||||||
.upload-copy small,
|
.upload-copy small,
|
||||||
.skin-title span,
|
|
||||||
.region-title span {
|
.region-title span {
|
||||||
color: #7f8895;
|
color: #7f8895;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.quantity-price,
|
||||||
|
.quantity-status {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
.quantity-item.disabled {
|
.quantity-item.disabled {
|
||||||
opacity: 0.62;
|
opacity: 0.62;
|
||||||
}
|
}
|
||||||
@@ -1427,10 +1575,10 @@ function readError(error: unknown, fallback: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.mode-toggle button {
|
.mode-toggle button {
|
||||||
height: 32px;
|
height: 30px;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
font-size: 13px;
|
font-size: 12px;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1445,11 +1593,11 @@ function readError(error: unknown, fallback: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.recommend-button {
|
.recommend-button {
|
||||||
justify-self: start;
|
flex: 0 0 auto;
|
||||||
height: 28px;
|
height: 32px;
|
||||||
padding: 0 10px;
|
padding: 0 12px;
|
||||||
border: 1px solid #ffba86;
|
border: 1px solid #ffba86;
|
||||||
border-radius: 14px;
|
border-radius: 8px;
|
||||||
background: #fff7f0;
|
background: #fff7f0;
|
||||||
color: #e65f00;
|
color: #e65f00;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
@@ -1457,9 +1605,32 @@ function readError(error: unknown, fallback: string) {
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.deposit-control {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: minmax(0, 1fr) auto;
|
||||||
|
gap: 8px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.deposit-breakdown {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.deposit-breakdown span {
|
||||||
|
min-height: 24px;
|
||||||
|
padding: 4px 8px;
|
||||||
|
border-radius: 12px;
|
||||||
|
background: #fff7f0;
|
||||||
|
color: #e65f00;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 800;
|
||||||
|
}
|
||||||
|
|
||||||
.skin-groups {
|
.skin-groups {
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 12px;
|
gap: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.skin-group,
|
.skin-group,
|
||||||
@@ -1475,11 +1646,63 @@ function readError(error: unknown, fallback: string) {
|
|||||||
.skin-title,
|
.skin-title,
|
||||||
.region-title {
|
.region-title {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.skin-group {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skin-title {
|
||||||
|
min-height: 34px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.time-preset-panel {
|
||||||
|
display: grid;
|
||||||
|
gap: 10px;
|
||||||
|
margin-top: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.time-preset-row {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 88px minmax(0, 1fr);
|
||||||
|
gap: 12px;
|
||||||
|
align-items: start;
|
||||||
|
padding: 12px;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: #f7f9fc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.time-preset-row strong {
|
||||||
|
color: #303743;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 800;
|
||||||
|
line-height: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.time-preset-content {
|
||||||
|
display: grid;
|
||||||
|
gap: 8px;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.time-input {
|
||||||
|
width: 118px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.time-input :deep(.el-input__wrapper) {
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 0 0 1px #dfe5ee inset;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-region-panel {
|
||||||
|
margin-top: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
.region-grid {
|
.region-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(8, minmax(0, 1fr));
|
grid-template-columns: repeat(8, minmax(0, 1fr));
|
||||||
@@ -1684,11 +1907,13 @@ function readError(error: unknown, fallback: string) {
|
|||||||
|
|
||||||
.summary-column {
|
.summary-column {
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
|
position: sticky;
|
||||||
|
top: 76px;
|
||||||
|
align-self: start;
|
||||||
|
height: fit-content;
|
||||||
}
|
}
|
||||||
|
|
||||||
.summary-panel {
|
.summary-panel {
|
||||||
position: sticky;
|
|
||||||
top: 152px;
|
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1730,6 +1955,7 @@ function readError(error: unknown, fallback: string) {
|
|||||||
color: #20242a;
|
color: #20242a;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
|
overflow-wrap: anywhere;
|
||||||
}
|
}
|
||||||
|
|
||||||
.summary-actions {
|
.summary-actions {
|
||||||
@@ -1745,6 +1971,7 @@ function readError(error: unknown, fallback: string) {
|
|||||||
@media (max-width: 1180px) {
|
@media (max-width: 1180px) {
|
||||||
.publish-layout {
|
.publish-layout {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
|
max-width: 920px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.summary-column {
|
.summary-column {
|
||||||
@@ -1756,12 +1983,15 @@ function readError(error: unknown, fallback: string) {
|
|||||||
.field-row,
|
.field-row,
|
||||||
.compact-grid,
|
.compact-grid,
|
||||||
.compact-grid.two,
|
.compact-grid.two,
|
||||||
.quantity-grid,
|
|
||||||
.upload-grid,
|
.upload-grid,
|
||||||
.price-grid {
|
.price-grid {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.quantity-header {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
.field-hint {
|
.field-hint {
|
||||||
grid-column: auto;
|
grid-column: auto;
|
||||||
}
|
}
|
||||||
@@ -1771,6 +2001,16 @@ function readError(error: unknown, fallback: string) {
|
|||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.deposit-control,
|
||||||
|
.ratio-mode-grid,
|
||||||
|
.time-preset-row {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.time-input {
|
||||||
|
width: 140px;
|
||||||
|
}
|
||||||
|
|
||||||
.upload-add,
|
.upload-add,
|
||||||
.upload-preview {
|
.upload-preview {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|||||||
Reference in New Issue
Block a user