Files
aida_front/src/views/SellerDashboard/MyListings/EditDetail/index.vue

854 lines
19 KiB
Vue
Raw Normal View History

2026-04-09 14:23:52 +08:00
<template>
2026-04-15 10:54:21 +08:00
<div class="edit-detail-wrapper flex-1">
2026-04-09 14:23:52 +08:00
<seller-header
2026-04-15 10:54:21 +08:00
class="edit-detail-header"
2026-04-09 14:23:52 +08:00
title="Edit Listing Details"
:breadcrumbs="[
{ title: 'My Listings', name: 'myListingsIndex' },
{ title: 'Select Collection', name: 'myListingsSelect' },
{ title: 'Select Sketch', name: 'myListingsSelectItem' },
{ title: 'Edit Listing Details', name: 'EditDetail' }
]"
>
<template #right>
<div class="operate-menu flex">
2026-04-16 17:31:31 +08:00
<div class="menu-btn flex align-center save" @click="handleClickMenu('draft')">
2026-04-15 10:54:21 +08:00
<span>{{ $t("SellerListEdit.saveDraft") }}</span>
2026-04-16 14:03:05 +08:00
<SvgIcon name="CSave" size="16" />
2026-04-09 14:23:52 +08:00
</div>
2026-04-16 17:31:31 +08:00
<div
class="menu-btn flex align-center publish"
@click="handleClickMenu('publish')"
>
2026-04-15 10:54:21 +08:00
<span>{{ $t("SellerListEdit.publish") }}</span>
2026-04-16 14:03:05 +08:00
<SvgIcon name="CPublish" size="16" />
2026-04-09 14:23:52 +08:00
</div>
</div>
</template>
</seller-header>
2026-04-16 14:03:05 +08:00
<div class="edit-detail-content flex">
2026-04-09 14:23:52 +08:00
<div class="left">
<div class="main-image-container flex">
2026-04-15 10:54:21 +08:00
<div
v-for="type in topImageList"
:key="type"
:class="`main-image-item flex flex-col align-center ${type}`"
>
<div class="title" :class="{ required: type !== 'mainProductImage' }">
2026-04-16 14:03:05 +08:00
{{ topImageTitleMap[type] }}
2026-04-15 10:54:21 +08:00
</div>
<div class="sketch-item flex flex-center" :class="type">
2026-04-17 17:59:51 +08:00
<div
v-if="previewImageMap[type]"
class="crop-tool flex flex-center"
2026-04-21 13:47:23 +08:00
@click="handleClickCrop(previewImageMap[type], type)"
2026-04-17 17:59:51 +08:00
>
2026-04-15 10:54:21 +08:00
<SvgIcon name="CCrop" color="#fff" size="12" />
</div>
<img
2026-04-16 14:03:05 +08:00
v-if="previewImageMap[type]"
:src="previewImageMap[type]"
2026-04-15 10:54:21 +08:00
class="sketch-img"
2026-04-16 14:03:05 +08:00
:class="{ cover: type === 'cover' }"
2026-04-15 10:54:21 +08:00
alt=""
/>
2026-04-16 14:03:05 +08:00
<div v-else class="trigger flex flex-col align-center">
2026-04-15 10:54:21 +08:00
<template v-if="type === 'cover'">
<SvgIcon
class="trigger-icon"
name="CCrop"
color="#585858"
size="24"
/>
<div class="trigger-tips">
{{ $t("SellerListEdit.cropDesc") }}
</div>
</template>
<template v-else>
2026-04-16 14:03:05 +08:00
<div class="trigger-img placeholder"></div>
2026-04-15 10:54:21 +08:00
<div class="trigger-tips">
{{ $t("SellerListEdit.productImageDesc") }}
</div>
</template>
</div>
</div>
</div>
</div>
<div class="product-image-list-container">
<div class="title flex align-center space-between">
<div class="title-left">
<span class="main-title">{{
$t("SellerListEdit.productImageMainTitle")
}}</span>
<span class="sub-title">{{
$t("SellerListEdit.productImageSubTitle")
}}</span>
</div>
<div class="title-right">
{{ selectedProdImgs }}/{{ prodImgList.length }} selected
</div>
</div>
<div class="product-image-list flex">
<div
v-for="(item, index) in prodImgList"
2026-04-16 14:03:05 +08:00
:key="index"
2026-04-15 10:54:21 +08:00
class="product-image-item flex flex-center"
:class="{ selected: item.selected }"
@click="handleSelectProdImg(index)"
>
<img
2026-04-16 14:03:05 +08:00
v-if="item.selected"
2026-04-15 10:54:21 +08:00
src="@/assets/images/seller/checked.png"
class="checked"
2026-04-16 14:03:05 +08:00
alt=""
2026-04-15 10:54:21 +08:00
/>
2026-04-16 14:03:05 +08:00
<img class="img-src" :src="item.url" alt="" />
2026-04-15 10:54:21 +08:00
<div
v-if="item.selected && index === firstSelectedIndex"
class="main-pic"
>
main
</div>
</div>
</div>
</div>
<div class="apparel-container">
<div class="title">
<span class="main-title">{{
$t("SellerListEdit.apparelSketchTitle")
}}</span>
<span class="sub-title">
{{ $t("SellerListEdit.apparelSketchSubTitle") }}</span
>
</div>
<div class="sketch-list-container flex">
<div
2026-04-17 17:59:51 +08:00
v-for="(item, index) in selectList[currentIndex].sketchList"
2026-04-15 10:54:21 +08:00
:key="index"
class="sketch-element flex flex-center"
>
2026-04-16 14:03:05 +08:00
<img class="img-src" :src="item.url" alt="" />
2026-04-21 13:47:23 +08:00
<div
class="crop-tool flex flex-center"
@click="handleClickCrop(item.url, 'apparel')"
>
2026-04-15 10:54:21 +08:00
<SvgIcon name="CCrop" color="#fff" size="12" />
</div>
</div>
</div>
</div>
</div>
<div class="right">
<div class="form-container flex flex-col">
<div class="form-item">
2026-04-16 17:31:31 +08:00
<div class="form-item-label required">
{{ $t("SellerListEdit.productName") }}
</div>
2026-04-15 10:54:21 +08:00
<div class="form-item-value product-name">
<a-input
2026-04-16 14:03:05 +08:00
v-model:value="currentListing.productName"
2026-04-15 10:54:21 +08:00
show-count
placeholder="Enter product name"
:bordered="false"
:maxlength="60"
/>
</div>
</div>
<div class="form-item">
2026-04-16 17:31:31 +08:00
<div class="form-item-label required">{{ $t("SellerListEdit.price") }}</div>
2026-04-15 10:54:21 +08:00
<div class="form-item-value price flex align-center">
<span>HK$</span>
<a-input
2026-04-16 14:03:05 +08:00
v-model:value="currentListing.price"
2026-04-15 10:54:21 +08:00
placeholder="0.00"
:bordered="false"
/>
</div>
</div>
2026-04-16 14:03:05 +08:00
<div class="form-item">
2026-04-16 17:31:31 +08:00
<div class="form-item-label required">
{{ $t("SellerListEdit.productDescription") }}
</div>
2026-04-16 14:03:05 +08:00
<div class="form-item-value desc">
<a-textarea
v-model:value="currentListing.desc"
show-count
:rows="4"
placeholder="Enter product description"
:bordered="false"
:maxlength="500"
/>
</div>
</div>
<div class="form-item">
2026-04-16 17:31:31 +08:00
<div class="form-item-label required">
{{ $t("SellerListEdit.designFor") }}
</div>
2026-04-16 14:03:05 +08:00
<div class="form-item-value no-border">
<Radio :options="genderOptions" v-model="currentListing.gender" />
</div>
</div>
<div class="form-item">
<div class="form-item-label with-tip">
2026-04-16 17:31:31 +08:00
<span class="required">{{ $t("SellerListEdit.productCategory") }}</span>
<span class="help-text">{{ $t("SellerListEdit.categoryTips") }}</span>
2026-04-16 14:03:05 +08:00
</div>
<div class="form-item-value no-border">
<Radio :options="categoryOptions" v-model="currentListing.category" />
</div>
</div>
<div class="license-note flex align-center">
<img src="@/assets/images/seller/tips.png" class="info-icon" />
<div class="note-copy">
2026-04-16 17:31:31 +08:00
{{ $t("SellerListEdit.policy") }}
<a href="javascript:void(0)">{{ $t("SellerListEdit.learnMore") }}</a>
2026-04-16 14:03:05 +08:00
</div>
</div>
</div>
<div class="page-control flex align-center">
<a-pagination
v-model:current="currentPage"
:total="selectList.length"
:page-size="1"
showQuickJumper
showLessItems
responsive
:showSizeChanger="false"
/>
2026-04-09 14:23:52 +08:00
</div>
</div>
</div>
</div>
2026-04-17 17:59:51 +08:00
<ImageClipDialog
ref="imageClipDialogRef"
fixedBox
isProduct
:info="false"
:autoCropWidth="90"
2026-04-21 13:47:23 +08:00
v-bind="$attrs"
:type="cropType"
2026-04-17 17:59:51 +08:00
/>
2026-04-09 14:23:52 +08:00
</template>
<script setup lang="ts">
2026-04-16 17:31:31 +08:00
import { computed, ref, watch, defineOptions } from "vue"
import { useRouter } from "vue-router"
2026-04-09 14:23:52 +08:00
import SellerHeader from "../../seller-header.vue"
2026-04-15 10:54:21 +08:00
import testImg from "@/assets/images/test.png"
2026-04-16 14:03:05 +08:00
import Radio from "./components/Radio.vue"
2026-04-17 17:59:51 +08:00
import ImageClipDialog from "../../BrandProfile/image-clip-dialog.vue"
2026-04-16 14:03:05 +08:00
import { Https } from "@/tool/https"
import { useStore } from "vuex"
2026-04-09 14:23:52 +08:00
2026-04-16 17:31:31 +08:00
const ROUTER = useRouter()
2026-04-17 17:59:51 +08:00
const imageClipDialogRef = ref<InstanceType<typeof ImageClipDialog> | null>(null)
2026-04-16 17:31:31 +08:00
defineOptions({
name: "EditDetail"
})
2026-04-16 14:03:05 +08:00
const STORE = useStore()
type CategoryOption = {
label: string
value: string
}
type ListingItem = {
sketch: string
mainProductImage: string
cover: string
productImage: string[]
apparelSketch: string[]
productName: string
price: string
desc: string
gender: string
category: string
prodImageList: Array<{
url: string
selected: boolean
}>
}
const topImageList = ["sketch", "mainProductImage", "cover"] as const
const topImageTitleMap: Record<(typeof topImageList)[number], string> = {
sketch: "Sketch",
mainProductImage: "Main Product Image",
cover: "Cover"
}
2026-04-16 17:31:31 +08:00
const genderOptions = STORE.state.UserHabit?.sex.value || []
2026-04-16 14:03:05 +08:00
const fallbackCategoryOptions: Record<string, CategoryOption[]> = {
MALE: STORE.state.UserHabit?.MalePosition || [],
FEMALE: STORE.state.UserHabit?.FemalePosition || []
}
const currentPage = ref(1)
const currentIndex = computed(() => currentPage.value - 1)
const selectList = ref<ListingItem[]>([
2026-04-09 14:23:52 +08:00
{
2026-04-15 10:54:21 +08:00
sketch: testImg,
2026-04-09 14:23:52 +08:00
mainProductImage: "",
cover: "",
productImage: [],
apparelSketch: [],
productName: "",
2026-04-16 14:03:05 +08:00
price: "12",
2026-04-15 10:54:21 +08:00
desc: "",
2026-04-16 14:03:05 +08:00
gender: "FEMALE",
category: "",
prodImageList: [
{ url: testImg, selected: false },
{ url: testImg, selected: false },
{ url: testImg, selected: false },
{ url: testImg, selected: false },
{ url: testImg, selected: false },
{ url: testImg, selected: false },
{ url: testImg, selected: false }
2026-04-17 17:59:51 +08:00
],
sketchList: [{ url: testImg }]
2026-04-15 10:54:21 +08:00
},
{
2026-04-16 14:03:05 +08:00
sketch: testImg,
mainProductImage: "",
cover: "",
productImage: [],
apparelSketch: [],
productName: "",
price: "12",
desc: "",
gender: "",
category: "",
prodImageList: [
{ url: testImg, selected: false },
{ url: testImg, selected: false },
{ url: testImg, selected: false },
{ url: testImg, selected: false },
{ url: testImg, selected: false },
{ url: testImg, selected: false },
{ url: testImg, selected: false }
2026-04-17 17:59:51 +08:00
],
sketchList: [{ url: testImg }, { url: testImg }]
2026-04-15 10:54:21 +08:00
},
{
2026-04-16 14:03:05 +08:00
sketch: testImg,
mainProductImage: "",
cover: "",
productImage: [],
apparelSketch: [],
productName: "",
price: "12",
desc: "",
gender: "",
category: "",
prodImageList: [
{ url: testImg, selected: false },
{ url: testImg, selected: false },
{ url: testImg, selected: false },
{ url: testImg, selected: false },
{ url: testImg, selected: false },
{ url: testImg, selected: false },
{ url: testImg, selected: false }
2026-04-17 17:59:51 +08:00
],
sketchList: [{ url: testImg }, { url: testImg }, { url: testImg }]
2026-04-09 14:23:52 +08:00
}
])
2026-04-15 10:54:21 +08:00
2026-04-16 14:03:05 +08:00
const prodImgList = computed(() => currentListing.value.prodImageList || [])
const categoryOptions = computed(() => {
const gender = selectList.value[currentIndex.value].gender
return fallbackCategoryOptions[gender] || []
})
const currentListing = computed(() => selectList.value[currentIndex.value])
const previewImageMap = computed(() => ({
sketch: currentListing.value.sketch,
mainProductImage: currentListing.value.mainProductImage,
cover:
currentListing.value.cover ||
currentListing.value.mainProductImage ||
currentListing.value.sketch
}))
const firstSelectedIndex = ref(null) //显示main标签的图片索引
2026-04-15 10:54:21 +08:00
const selectedProdImgs = computed(() => {
return prodImgList.value.filter((item) => item.selected).length
})
const handleSelectProdImg = (index: number) => {
2026-04-16 14:03:05 +08:00
const target = prodImgList.value[index]
2026-04-15 10:54:21 +08:00
2026-04-16 14:03:05 +08:00
const willSelect = !target.selected
target.selected = willSelect
if (willSelect && !currentListing.value.mainProductImage) {
currentListing.value.mainProductImage = target.url
firstSelectedIndex.value = index
2026-04-15 10:54:21 +08:00
}
2026-04-16 14:03:05 +08:00
if (!willSelect && currentListing.value.mainProductImage === target.url) {
firstSelectedIndex.value = null
currentListing.value.mainProductImage = ""
}
}
2026-04-16 17:31:31 +08:00
2026-04-21 13:47:23 +08:00
const cropType = ref("")
const handleClickCrop = (data, type) => {
console.log(data, type)
const titleList = {
sketch: "Crop Sketch",
mainProductImage: "Crop Main Product Image",
cover: "Crop Cover"
}
cropType.value = type
2026-04-17 17:59:51 +08:00
imageClipDialogRef.value.open(
data,
(file) => {
selectList.value[currentIndex.value].sketch = URL.createObjectURL(file)
},
2026-04-21 13:47:23 +08:00
{ ratio: [9, 16], isPreview: true, title: titleList[type], isProduct: true }
2026-04-17 17:59:51 +08:00
)
}
2026-04-16 17:31:31 +08:00
const handleClickMenu = (status: "draft" | "publish") => {
if (status === "draft") {
// save draft logic
console.log("Saving draft...", currentListing.value)
ROUTER.push({ name: "Status", params: { status: "draft" } })
} else if (status === "publish") {
// publish logic
console.log("Publishing...", currentListing.value)
ROUTER.push({ name: "Status", params: { status: "publish" } })
}
}
2026-04-09 14:23:52 +08:00
</script>
<style lang="less" scoped>
.c-svg {
width: initial;
2026-04-15 10:54:21 +08:00
height: initial;
2026-04-09 14:23:52 +08:00
}
.edit-detail-wrapper {
2026-04-16 14:03:05 +08:00
display: flex;
flex-direction: column;
height: 100%;
min-height: 0;
margin-top: -1rem;
overflow: hidden;
2026-04-15 10:54:21 +08:00
&::-webkit-scrollbar {
display: none;
}
2026-04-09 14:23:52 +08:00
.menu-btn {
height: 6rem;
border: 0.15rem solid #000000;
border-radius: 4rem;
text-align: center;
line-height: 6rem;
padding: 0 2rem;
font-size: 1.6rem;
column-gap: 0.8rem;
cursor: pointer;
2026-04-16 14:03:05 +08:00
transition: all 0.25s ease;
2026-04-16 17:31:31 +08:00
&:hover {
2026-04-16 14:03:05 +08:00
background: #000;
color: #fff;
}
2026-04-16 17:31:31 +08:00
// &.publish:hover {
// background: #fff;
// color: #000;
// }
2026-04-09 14:23:52 +08:00
}
2026-04-15 10:54:21 +08:00
.edit-detail-header {
margin-bottom: 2rem;
}
2026-04-16 14:03:05 +08:00
2026-04-09 14:23:52 +08:00
.operate-menu {
column-gap: 2rem;
2026-04-16 17:31:31 +08:00
// .publish {
// background-color: #000000;
// color: #ffffff;
// }
2026-04-09 14:23:52 +08:00
}
2026-04-15 10:54:21 +08:00
}
2026-04-16 14:03:05 +08:00
2026-04-15 10:54:21 +08:00
.edit-detail-content {
2026-04-16 14:03:05 +08:00
flex: 1;
min-height: 0;
overflow-y: auto;
justify-content: space-between;
&::-webkit-scrollbar {
width: 0;
height: 0;
}
2026-04-15 10:54:21 +08:00
.required {
&::after {
content: "*";
color: #df2b2c;
margin-left: 0.4rem;
}
}
2026-04-16 14:03:05 +08:00
2026-04-15 10:54:21 +08:00
.left {
2026-04-16 14:03:05 +08:00
// flex: 1;
// min-width: 0;
2026-04-15 10:54:21 +08:00
.main-image-container {
2026-04-16 14:03:05 +08:00
// max-width: 80.2rem;
2026-04-15 10:54:21 +08:00
.main-image-item {
2026-04-16 14:03:05 +08:00
flex-shrink: 0;
2026-04-15 10:54:21 +08:00
.title {
font-size: 1.4rem;
margin-bottom: 0.8rem;
text-align: center;
}
2026-04-16 14:03:05 +08:00
2026-04-15 10:54:21 +08:00
.sketch-item {
width: 11.6rem;
height: 20.4rem;
border: 0.15rem solid #d1d1d1;
border-radius: 1rem;
position: relative;
background-color: #f6f6f6;
2026-04-16 14:03:05 +08:00
overflow: hidden;
2026-04-15 10:54:21 +08:00
&.cover {
2026-04-16 14:03:05 +08:00
width: 16.2rem;
background-image: url("data:image/svg+xml,%3csvg width='100%25' height='100%25' xmlns='http://www.w3.org/2000/svg'%3e%3crect width='100%25' height='100%25' rx='11' ry='11' fill='none' stroke='%23D1D1D1' stroke-width='1.5' stroke-dasharray='8%2c 5' stroke-linecap='square'/%3e%3c/svg%3e");
2026-04-15 10:54:21 +08:00
border: none;
}
2026-04-16 14:03:05 +08:00
2026-04-15 10:54:21 +08:00
.crop-tool {
position: absolute;
2026-04-16 14:03:05 +08:00
top: 0.8rem;
right: 0.8rem;
2026-04-15 10:54:21 +08:00
width: 2rem;
height: 2rem;
border-radius: 50%;
background-color: #000000;
2026-04-16 14:03:05 +08:00
z-index: 1;
cursor: pointer;
2026-04-15 10:54:21 +08:00
}
2026-04-16 14:03:05 +08:00
2026-04-15 10:54:21 +08:00
.sketch-img {
height: 100%;
}
2026-04-16 14:03:05 +08:00
2026-04-15 10:54:21 +08:00
.trigger {
row-gap: 1.2rem;
cursor: pointer;
height: 100%;
2026-04-16 14:03:05 +08:00
padding: 6rem 2rem 0;
.placeholder {
2026-04-15 10:54:21 +08:00
width: 2.4rem;
height: 2.4rem;
2026-04-16 14:03:05 +08:00
border-radius: 0.6rem;
background: linear-gradient(135deg, #efefef 0%, #cdcdcd 100%);
2026-04-15 10:54:21 +08:00
}
2026-04-16 14:03:05 +08:00
2026-04-15 10:54:21 +08:00
.trigger-tips {
font-size: 1.2rem;
text-align: center;
color: #585858;
2026-04-16 14:03:05 +08:00
line-height: 1.3;
2026-04-15 10:54:21 +08:00
}
}
}
}
}
2026-04-16 14:03:05 +08:00
2026-04-15 10:54:21 +08:00
.product-image-list-container {
margin-top: 3rem;
2026-04-16 14:03:05 +08:00
2026-04-15 10:54:21 +08:00
.title {
font-size: 1.4rem;
margin-bottom: 1.2rem;
2026-04-16 14:03:05 +08:00
.main-title {
font-weight: 400;
font-style: bold;
}
2026-04-15 10:54:21 +08:00
.sub-title {
font-size: 1.2rem;
color: #999;
}
2026-04-16 14:03:05 +08:00
2026-04-15 10:54:21 +08:00
.title-right {
color: #585858;
font-size: 1.4rem;
}
}
2026-04-16 14:03:05 +08:00
2026-04-15 10:54:21 +08:00
.product-image-list {
overflow-x: auto;
overflow-y: hidden;
column-gap: 0.8rem;
max-width: 80.2rem;
padding-bottom: 1.2rem;
&::-webkit-scrollbar {
height: 0.8rem;
}
2026-04-16 14:03:05 +08:00
2026-04-15 10:54:21 +08:00
&::-webkit-scrollbar-track {
background: #d9d9d9;
border-radius: 0.8rem;
}
2026-04-16 14:03:05 +08:00
2026-04-15 10:54:21 +08:00
&::-webkit-scrollbar-thumb {
background: #000000;
border-radius: 0.8rem;
}
2026-04-09 14:23:52 +08:00
2026-04-15 10:54:21 +08:00
.product-image-item {
width: 11.6rem;
height: 20.6rem;
border-radius: 1rem;
border: 0.15rem solid #c7c7c7;
position: relative;
cursor: pointer;
2026-04-16 14:03:05 +08:00
overflow: hidden;
flex-shrink: 0;
2026-04-15 10:54:21 +08:00
&::after {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
content: "";
background-color: #fcfcfc;
opacity: 0.7;
border-radius: 1rem;
}
2026-04-16 14:03:05 +08:00
2026-04-15 10:54:21 +08:00
&.selected {
2026-04-16 14:03:05 +08:00
border-color: #000;
2026-04-15 10:54:21 +08:00
&::after {
display: none;
}
}
2026-04-16 14:03:05 +08:00
2026-04-15 10:54:21 +08:00
.checked {
width: 2rem;
height: 2rem;
position: absolute;
top: 0.8rem;
right: 0.8rem;
2026-04-16 14:03:05 +08:00
z-index: 1;
2026-04-15 10:54:21 +08:00
}
2026-04-16 14:03:05 +08:00
2026-04-15 10:54:21 +08:00
.img-src {
height: 100%;
}
2026-04-16 14:03:05 +08:00
2026-04-15 10:54:21 +08:00
.main-pic {
position: absolute;
height: 2.4rem;
line-height: 2.4rem;
left: 0.8rem;
right: 0.8rem;
bottom: 0.8rem;
z-index: 1;
2026-04-16 14:03:05 +08:00
background: rgba(0, 0, 0, 0.8);
2026-04-15 10:54:21 +08:00
color: #fff;
font-size: 1.4rem;
border-radius: 1.2rem;
text-align: center;
}
}
}
}
2026-04-16 14:03:05 +08:00
2026-04-15 10:54:21 +08:00
.apparel-container {
margin-top: 3rem;
2026-04-16 14:03:05 +08:00
2026-04-15 10:54:21 +08:00
.title {
font-size: 1.4rem;
margin-bottom: 0.8rem;
2026-04-16 14:03:05 +08:00
2026-04-15 10:54:21 +08:00
.main-title {
2026-04-16 14:03:05 +08:00
font-weight: 400;
font-style: bold;
2026-04-15 10:54:21 +08:00
&::after {
content: "*";
color: #df2b2c;
}
}
2026-04-16 14:03:05 +08:00
2026-04-15 10:54:21 +08:00
.sub-title {
font-size: 1.2rem;
color: #999;
}
}
2026-04-16 14:03:05 +08:00
2026-04-15 10:54:21 +08:00
.sketch-list-container {
column-gap: 1rem;
2026-04-16 14:03:05 +08:00
flex-wrap: wrap;
2026-04-15 10:54:21 +08:00
.sketch-element {
width: 10rem;
2026-04-16 14:03:05 +08:00
height: 14.6rem;
2026-04-15 10:54:21 +08:00
border: 0.15rem solid #c7c7c7;
border-radius: 1.2rem;
position: relative;
2026-04-16 14:03:05 +08:00
overflow: hidden;
2026-04-15 10:54:21 +08:00
.img-src {
2026-04-16 14:03:05 +08:00
height: 100%;
2026-04-15 10:54:21 +08:00
}
2026-04-16 14:03:05 +08:00
2026-04-15 10:54:21 +08:00
.crop-tool {
position: absolute;
top: 0.4rem;
right: 0.4rem;
width: 2rem;
height: 2rem;
border-radius: 50%;
background-color: #000000;
}
}
}
}
}
2026-04-16 14:03:05 +08:00
2026-04-15 10:54:21 +08:00
.right {
width: 55.2rem;
2026-04-16 14:03:05 +08:00
flex-shrink: 0;
2026-04-15 10:54:21 +08:00
.form-container {
row-gap: 3rem;
2026-04-16 14:03:05 +08:00
2026-04-15 10:54:21 +08:00
.form-item {
.form-item-label {
font-size: 1.4rem;
font-weight: 400;
font-style: bold;
margin-bottom: 0.6rem;
2026-04-16 14:03:05 +08:00
line-height: 1.5;
&.with-tip {
display: flex;
align-items: center;
column-gap: 0.8rem;
}
.help-text {
font-size: 1rem;
color: #999;
}
2026-04-15 10:54:21 +08:00
}
2026-04-16 14:03:05 +08:00
2026-04-15 10:54:21 +08:00
.form-item-value {
border: 0.16rem solid #d1d1d1;
border-radius: 1.2rem;
position: relative;
padding: 1.6rem;
box-sizing: border-box;
font-size: 1.2rem;
color: #000;
2026-04-16 14:03:05 +08:00
&.no-border {
border: none;
padding: 0;
}
2026-04-15 10:54:21 +08:00
&.price {
column-gap: 0.6rem;
}
2026-04-16 14:03:05 +08:00
:deep(.ant-input),
:deep(.ant-input-affix-wrapper),
:deep(.ant-input-textarea textarea) {
2026-04-15 10:54:21 +08:00
border: none;
padding: 0;
font-size: 1.2rem;
2026-04-16 14:03:05 +08:00
color: #000;
box-shadow: none;
2026-04-15 10:54:21 +08:00
}
2026-04-16 14:03:05 +08:00
:deep(.ant-input) {
line-height: 1.5;
2026-04-15 10:54:21 +08:00
}
2026-04-16 14:03:05 +08:00
2026-04-15 10:54:21 +08:00
:deep(.ant-input-show-count-suffix) {
color: #df2c2c;
font-size: 1rem;
}
2026-04-16 14:03:05 +08:00
:deep(textarea.ant-input) {
resize: none;
min-height: 5.4rem;
padding-bottom: 1.8rem;
line-height: 1.5;
}
:deep(.ant-input-textarea-show-count) {
position: relative;
&::after {
float: none;
position: absolute;
color: #df2c2c;
bottom: 0;
right: 1.6rem;
}
}
2026-04-15 10:54:21 +08:00
}
}
}
2026-04-16 14:03:05 +08:00
.license-note {
padding: 1.6rem;
column-gap: 1.6rem;
background: #f7f7f7;
border-radius: 0.8rem;
.info-icon {
width: 2.4rem;
height: 2.4rem;
flex-shrink: 0;
}
.note-copy {
font-size: 1.2rem;
line-height: 1.5;
color: #000;
font-weight: 400;
font-style: medium;
a {
color: #0080ed;
text-decoration: underline;
margin-left: 0.4rem;
}
}
}
.page-control {
justify-content: flex-end;
margin-top: 4rem;
}
2026-04-09 14:23:52 +08:00
}
}
</style>