feat: edit detail

This commit is contained in:
2026-04-15 10:54:21 +08:00
parent a525d4f54a
commit 66a5f632fb
5 changed files with 483 additions and 11 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 479 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 621 B

View File

@@ -1735,5 +1735,18 @@ export default {
step4Info: '发布后,你的设计将立即在市场上线。',
showAgain: '不再提示',
GetStarted: '开始体验',
},
SellerListEdit:{
saveDraft: "保存草稿",
publish: "发布",
sketch: "线稿图",
mainProductImage: "产品主图",
cover: "封面",
productImageDesc:'从产品图中选取',
cropDesc:'从主产品图或线稿图中裁剪',
productImageMainTitle:'产品图 ',
productImageSubTitle:' (来自设计集)',
apparelSketchTitle:'服装线稿图 ',
apparelSketchSubTitle:' (来自设计集)',
}
}

View File

@@ -1786,5 +1786,18 @@ export default {
step4Info: 'Publish and your design goes live on the marketplace.',
showAgain: 'Dont show me again',
GetStarted: 'Get Started',
},
SellerListEdit:{
saveDraft:'Save Draft',
publish:'Publish',
sketch:'Sketch',
mainProductImage:'Main Product Image',
cover:'Cover',
productImageDesc:'Choose from product image',
cropDesc:'Crop from main product image or sketch',
productImageMainTitle:'Product Image ',
productImageSubTitle:'(from design collection)',
apparelSketchTitle:'Apparel Sketch ',
apparelSketchSubTitle:'(from design collection)',
}
}

View File

@@ -1,6 +1,7 @@
<template>
<div class="edit-detail-wrapper">
<div class="edit-detail-wrapper flex-1">
<seller-header
class="edit-detail-header"
title="Edit Listing Details"
:breadcrumbs="[
{ title: 'My Listings', name: 'myListingsIndex' },
@@ -12,11 +13,11 @@
<template #right>
<div class="operate-menu flex">
<div class="menu-btn flex align-center save">
<span>Save Draft</span>
<span>{{ $t("SellerListEdit.saveDraft") }}</span>
<SvgIcon name="CSave" color="#000000" size="16" />
</div>
<div class="menu-btn flex align-center publish">
<span>Publish</span>
<span>{{ $t("SellerListEdit.publish") }}</span>
<SvgIcon name="CPublish" color="#ffffff" size="16" />
</div>
</div>
@@ -25,7 +26,141 @@
<div class="edit-detail-content flex space-between">
<div class="left">
<div class="main-image-container flex">
<div class="sketch"></div>
<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' }">
{{ $t(`SellerListEdit.${type}`) }}
</div>
<div class="sketch-item flex flex-center" :class="type">
<div
v-show="selectList[currentIndex][type]"
class="crop-tool flex flex-center"
>
<SvgIcon name="CCrop" color="#fff" size="12" />
</div>
<img
v-show="selectList[currentIndex][type]"
:src="selectList[currentIndex][type]"
class="sketch-img"
alt=""
/>
<div
class="trigger flex flex-col align-center"
v-show="!selectList[currentIndex][type]"
>
<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>
<img
src="@/assets/images/seller/image-placeholder.png"
class="trigger-img"
/>
<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"
class="product-image-item flex flex-center"
:class="{ selected: item.selected }"
:key="index"
@click="handleSelectProdImg(index)"
>
<img
v-show="item.selected"
src="@/assets/images/seller/checked.png"
class="checked"
/>
<img class="img-src" :src="item.url" />
<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
v-for="(item, index) in sketchList"
:key="index"
class="sketch-element flex flex-center"
>
<img class="img-src" :src="item.url" />
<div class="crop-tool flex flex-center">
<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">
<div class="form-item-label required">Product Name</div>
<div class="form-item-value product-name">
<a-input
v-model:value="selectList[currentIndex].productName"
show-count
:rows="2"
placeholder="Enter product name"
:bordered="false"
:maxlength="60"
/>
</div>
</div>
<div class="form-item">
<div class="form-item-label required">Price</div>
<div class="form-item-value price flex align-center">
<span>HK$</span>
<a-input
v-model:value="selectList[currentIndex].desc"
placeholder="0.00"
:bordered="false"
/>
</div>
</div>
</div>
</div>
</div>
@@ -33,32 +168,99 @@
</template>
<script setup lang="ts">
import { ref } from "vue"
import { ref, computed } from "vue"
import SellerHeader from "../../seller-header.vue"
import testImg from "@/assets/images/test.png"
import { ElInput } from "element-plus"
const topImageList = ["sketch", "mainProductImage", "cover"]
const currentIndex = ref(0)
const selectList = ref([
{
sketch: "",
sketch: testImg,
mainProductImage: "",
cover: "",
productImage: [],
apparelSketch: [],
productName: "",
price: "",
desc: '',
gender: '',
category:''
desc: "",
gender: "",
category: ""
}
])
const prodImgList = ref([
{
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
},
{
url: testImg,
selected: false
}
])
const selectedProdImgs = computed(() => {
return prodImgList.value.filter((item) => item.selected).length
})
const firstSelectedIndex = ref(-1)
const handleSelectProdImg = (index: number) => {
const item = prodImgList.value[index]
item.selected = !item.selected
if (item.selected) {
if (firstSelectedIndex.value === -1) {
firstSelectedIndex.value = index
selectList.value[currentIndex.value].mainProductImage = item.url
}
} else if (firstSelectedIndex.value === index) {
selectList.value[currentIndex.value].mainProductImage = null
firstSelectedIndex.value = -1
}
}
const sketchList = ref([{ url: testImg }, { url: testImg }, { url: testImg }])
</script>
<style lang="less" scoped>
.c-svg {
width: initial;
height: initial;
}
.edit-detail-wrapper {
overflow-y: auto;
// set the scollbar hidden
&::-webkit-scrollbar {
display: none;
}
.menu-btn {
height: 6rem;
border: 0.15rem solid #000000;
@@ -72,6 +274,9 @@ const selectList = ref([
cursor: pointer;
}
.edit-detail-header {
margin-bottom: 2rem;
}
.operate-menu {
column-gap: 2rem;
@@ -80,9 +285,250 @@ const selectList = ref([
color: #ffffff;
}
}
}
.edit-detail-content {
padding-right: 6.4rem;
.required {
&::after {
content: "*";
color: #df2b2c;
margin-left: 0.4rem;
}
}
.left {
.main-image-container {
column-gap: 3.6rem;
.main-image-item {
.title {
font-weight: 400;
font-style: bold;
font-size: 1.4rem;
margin-bottom: 0.8rem;
text-align: center;
}
.sketch-item {
width: 11.6rem;
height: 20.4rem;
border: 0.15rem solid #d1d1d1;
border-radius: 1rem;
position: relative;
background-color: #f6f6f6;
&.cover {
width: 16.17rem;
// border-style: dashed;
border: none;
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' fill='none' stroke='%23D1D1D1' stroke-width='1.5' stroke-dasharray='13%2c 5' stroke-dashoffset='0' stroke-linecap='square'/%3e%3c/svg%3e");
}
.crop-tool {
position: absolute;
top: 0.4rem;
right: 0.4rem;
width: 2rem;
height: 2rem;
border-radius: 50%;
cursor: pointer;
background-color: #000000;
}
.sketch-img {
// width: 100%;
height: 100%;
}
.trigger {
row-gap: 1.2rem;
cursor: pointer;
height: 100%;
padding-top: 6.8rem;
.trigger-img {
width: 2.4rem;
height: 2.4rem;
}
.trigger-tips {
font-size: 1.2rem;
width: 9rem;
text-align: center;
color: #585858;
}
}
}
}
}
.product-image-list-container {
margin-top: 3rem;
.title {
font-weight: 400;
font-style: bold;
font-size: 1.4rem;
margin-bottom: 1.2rem;
.sub-title {
font-size: 1.2rem;
color: #999;
}
.title-right {
color: #585858;
font-size: 1.4rem;
font-weight: 400;
}
}
.product-image-list {
overflow-x: auto;
overflow-y: hidden;
column-gap: 0.8rem;
max-width: 80.2rem;
padding-bottom: 1.2rem;
.edit-detail-content {
padding-right: 6.4rem;
//滚动条高度0.8rem,背景色#D9D9D9,滚动条圆角0.4rem,小方块为黑色
&::-webkit-scrollbar {
height: 0.8rem;
}
&::-webkit-scrollbar-track {
background: #d9d9d9;
border-radius: 0.8rem;
height: 0.8rem;
}
&::-webkit-scrollbar-thumb {
background: #000000;
border-radius: 0.8rem;
height: 0.8rem;
}
.product-image-item {
width: 11.6rem;
height: 20.6rem;
border-radius: 1rem;
border: 0.15rem solid #c7c7c7;
position: relative;
cursor: pointer;
&::after {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
content: "";
background-color: #fcfcfc;
opacity: 0.7;
border-radius: 1rem;
}
&.selected {
// border-color: #000000;
&::after {
display: none;
}
}
.checked {
width: 2rem;
height: 2rem;
position: absolute;
top: 0.8rem;
right: 0.8rem;
}
.img-src {
height: 100%;
}
.main-pic {
position: absolute;
height: 2.4rem;
line-height: 2.4rem;
left: 0.8rem;
right: 0.8rem;
bottom: 0.8rem;
z-index: 1;
background: #000000cc;
font-weight: 400;
color: #fff;
font-size: 1.4rem;
border-radius: 1.2rem;
text-align: center;
}
}
}
}
.apparel-container {
margin-top: 3rem;
.title {
font-weight: 400;
font-style: bold;
font-size: 1.4rem;
margin-bottom: 0.8rem;
.main-title {
&::after {
content: "*";
color: #df2b2c;
}
}
.sub-title {
font-size: 1.2rem;
color: #999;
}
}
.sketch-list-container {
column-gap: 1rem;
.sketch-element {
width: 10rem;
border: 0.15rem solid #c7c7c7;
border-radius: 1.2rem;
position: relative;
.img-src {
width: 100%;
}
.crop-tool {
position: absolute;
top: 0.4rem;
right: 0.4rem;
width: 2rem;
height: 2rem;
border-radius: 50%;
cursor: pointer;
background-color: #000000;
}
}
}
}
}
.right {
width: 55.2rem;
.form-container {
row-gap: 3rem;
.form-item {
.form-item-label {
font-size: 1.4rem;
font-weight: 400;
font-style: bold;
margin-bottom: 0.6rem;
}
.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;
font-weight: 400;
color: #000;
&.price {
column-gap: 0.6rem;
}
:deep(.ant-input) {
border: none;
padding: 0;
font-size: 1.2rem;
font-weight: 400;
}
:deep(.ant-input-affix-wrapper) {
padding: 0;
font-weight: 400;
input {
font-size: 1.2rem;
}
}
:deep(.ant-input-show-count-suffix) {
color: #df2c2c;
font-size: 1rem;
}
}
}
}
}
}
</style>