Merge branch 'dev_vite' of ssh://18.167.251.121:10002/aidlab/aida_front into dev_vite
This commit is contained in:
@@ -20,6 +20,11 @@ This directory owns the seller listing edit/create detail page.
|
|||||||
- Child components should receive props and emit events only. Do not import listing APIs or mutate parent state directly from children.
|
- Child components should receive props and emit events only. Do not import listing APIs or mutate parent state directly from children.
|
||||||
- If a new visual section is added to this page, prefer a new child component under `components/` plus shared types in `types.ts`.
|
- If a new visual section is added to this page, prefer a new child component under `components/` plus shared types in `types.ts`.
|
||||||
|
|
||||||
|
## Vue SFC Order
|
||||||
|
|
||||||
|
- Vue single-file components must keep sections in this order: `<template>` first, then `<script setup lang="ts">`, then `<style>`.
|
||||||
|
- When creating or refactoring `.vue` files in this page, preserve that order even if external Vue guidance suggests another layout.
|
||||||
|
|
||||||
## Image Category Mapping
|
## Image Category Mapping
|
||||||
|
|
||||||
Detail API images are mapped by `category`:
|
Detail API images are mapped by `category`:
|
||||||
|
|||||||
@@ -1,15 +1,3 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import type { ListingItem } from "../types"
|
|
||||||
|
|
||||||
defineProps<{
|
|
||||||
sketchList: ListingItem["sketchList"]
|
|
||||||
}>()
|
|
||||||
|
|
||||||
const emit = defineEmits<{
|
|
||||||
(e: "crop", data: string | null, type: "apparel", index?: number): void
|
|
||||||
}>()
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="apparel-container">
|
<div class="apparel-container">
|
||||||
<div class="title">
|
<div class="title">
|
||||||
@@ -23,64 +11,78 @@ const emit = defineEmits<{
|
|||||||
class="sketch-element flex flex-center"
|
class="sketch-element flex flex-center"
|
||||||
>
|
>
|
||||||
<img class="img-src" :src="item.url || ''" alt="" />
|
<img class="img-src" :src="item.url || ''" alt="" />
|
||||||
<div class="crop-tool flex flex-center" @click="emit('crop', item.url, 'apparel', index)">
|
<div
|
||||||
|
class="crop-tool flex flex-center"
|
||||||
|
@click="emit('crop', item.url, 'apparel', index)"
|
||||||
|
>
|
||||||
<SvgIcon name="CCrop" color="#fff" size="12" />
|
<SvgIcon name="CCrop" color="#fff" size="12" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { ListingItem } from "../types"
|
||||||
|
|
||||||
|
defineProps<{
|
||||||
|
sketchList: ListingItem["sketchList"]
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: "crop", data: string | null, type: "apparel", index?: number): void
|
||||||
|
}>()
|
||||||
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.apparel-container {
|
.apparel-container {
|
||||||
margin-top: 3rem;
|
margin-top: 3rem;
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
font-size: 1.4rem;
|
font-size: 1.4rem;
|
||||||
margin-bottom: 0.8rem;
|
margin-bottom: 0.8rem;
|
||||||
|
|
||||||
.main-title {
|
.main-title {
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-style: bold;
|
font-style: bold;
|
||||||
|
|
||||||
&::after {
|
&::after {
|
||||||
content: "*";
|
content: "*";
|
||||||
color: #df2b2c;
|
color: #df2b2c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub-title {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
color: #999;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.sub-title {
|
.sketch-list-container {
|
||||||
font-size: 1.2rem;
|
column-gap: 1rem;
|
||||||
color: #999;
|
flex-wrap: wrap;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.sketch-list-container {
|
.sketch-element {
|
||||||
column-gap: 1rem;
|
width: 10rem;
|
||||||
flex-wrap: wrap;
|
height: 14.6rem;
|
||||||
|
border: 0.15rem solid #c7c7c7;
|
||||||
|
border-radius: 1.2rem;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
.sketch-element {
|
.img-src {
|
||||||
width: 10rem;
|
width: 100%;
|
||||||
height: 14.6rem;
|
}
|
||||||
border: 0.15rem solid #c7c7c7;
|
|
||||||
border-radius: 1.2rem;
|
|
||||||
position: relative;
|
|
||||||
overflow: hidden;
|
|
||||||
|
|
||||||
.img-src {
|
.crop-tool {
|
||||||
width: 100%;
|
position: absolute;
|
||||||
}
|
top: 0.4rem;
|
||||||
|
right: 0.4rem;
|
||||||
.crop-tool {
|
width: 2rem;
|
||||||
position: absolute;
|
height: 2rem;
|
||||||
top: 0.4rem;
|
border-radius: 50%;
|
||||||
right: 0.4rem;
|
background-color: #000000;
|
||||||
width: 2rem;
|
}
|
||||||
height: 2rem;
|
|
||||||
border-radius: 50%;
|
|
||||||
background-color: #000000;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,26 +1,3 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import Radio from "./Radio.vue"
|
|
||||||
import type { RadioOption } from "../types"
|
|
||||||
|
|
||||||
defineProps<{
|
|
||||||
productName: string
|
|
||||||
price: string
|
|
||||||
desc: string
|
|
||||||
gender: string
|
|
||||||
category: string[] | null
|
|
||||||
genderOptions: RadioOption[]
|
|
||||||
categoryOptions: RadioOption[]
|
|
||||||
}>()
|
|
||||||
|
|
||||||
const emit = defineEmits<{
|
|
||||||
(e: "update:productName", value: string): void
|
|
||||||
(e: "update:price", value: string): void
|
|
||||||
(e: "update:desc", value: string): void
|
|
||||||
(e: "update:gender", value: string): void
|
|
||||||
(e: "update:category", value: string[] | null): void
|
|
||||||
}>()
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="form-container flex flex-col">
|
<div class="form-container flex flex-col">
|
||||||
<div class="form-item">
|
<div class="form-item">
|
||||||
@@ -102,121 +79,144 @@ const emit = defineEmits<{
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import Radio from "./Radio.vue"
|
||||||
|
import type { RadioOption } from "../types"
|
||||||
|
|
||||||
|
defineProps<{
|
||||||
|
productName: string
|
||||||
|
price: string
|
||||||
|
desc: string
|
||||||
|
gender: string
|
||||||
|
category: string[] | null
|
||||||
|
genderOptions: RadioOption[]
|
||||||
|
categoryOptions: RadioOption[]
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: "update:productName", value: string): void
|
||||||
|
(e: "update:price", value: string): void
|
||||||
|
(e: "update:desc", value: string): void
|
||||||
|
(e: "update:gender", value: string): void
|
||||||
|
(e: "update:category", value: string[] | null): void
|
||||||
|
}>()
|
||||||
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.required {
|
.required {
|
||||||
&::after {
|
&::after {
|
||||||
content: "*";
|
content: "*";
|
||||||
color: #df2b2c;
|
color: #df2b2c;
|
||||||
margin-left: 0.4rem;
|
margin-left: 0.4rem;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-container {
|
|
||||||
row-gap: 3rem;
|
|
||||||
|
|
||||||
.form-item {
|
|
||||||
.form-item-label {
|
|
||||||
font-size: 1.4rem;
|
|
||||||
font-weight: 400;
|
|
||||||
font-style: bold;
|
|
||||||
margin-bottom: 0.6rem;
|
|
||||||
line-height: 1.5;
|
|
||||||
|
|
||||||
&.with-tip {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
column-gap: 0.8rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.help-text {
|
|
||||||
font-size: 1rem;
|
|
||||||
color: #999;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.form-item-value {
|
.form-container {
|
||||||
border: 0.16rem solid #d1d1d1;
|
row-gap: 3rem;
|
||||||
border-radius: 1.2rem;
|
|
||||||
position: relative;
|
|
||||||
padding: 1.6rem;
|
|
||||||
box-sizing: border-box;
|
|
||||||
font-size: 1.2rem;
|
|
||||||
color: #000;
|
|
||||||
|
|
||||||
&.no-border {
|
.form-item {
|
||||||
border: none;
|
.form-item-label {
|
||||||
padding: 0;
|
font-size: 1.4rem;
|
||||||
|
font-weight: 400;
|
||||||
|
font-style: bold;
|
||||||
|
margin-bottom: 0.6rem;
|
||||||
|
line-height: 1.5;
|
||||||
|
|
||||||
|
&.with-tip {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
column-gap: 0.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.help-text {
|
||||||
|
font-size: 1rem;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.price {
|
.form-item-value {
|
||||||
column-gap: 0.6rem;
|
border: 0.16rem solid #d1d1d1;
|
||||||
}
|
border-radius: 1.2rem;
|
||||||
|
position: relative;
|
||||||
:deep(.ant-input),
|
padding: 1.6rem;
|
||||||
:deep(.ant-input-affix-wrapper),
|
box-sizing: border-box;
|
||||||
:deep(.ant-input-textarea textarea) {
|
|
||||||
border: none;
|
|
||||||
padding: 0;
|
|
||||||
font-size: 1.2rem;
|
font-size: 1.2rem;
|
||||||
color: #000;
|
color: #000;
|
||||||
box-shadow: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.ant-input) {
|
&.no-border {
|
||||||
line-height: 1.5;
|
border: none;
|
||||||
}
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
:deep(.ant-input-show-count-suffix) {
|
&.price {
|
||||||
color: #df2c2c;
|
column-gap: 0.6rem;
|
||||||
font-size: 1rem;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
:deep(textarea.ant-input) {
|
:deep(.ant-input),
|
||||||
resize: none;
|
:deep(.ant-input-affix-wrapper),
|
||||||
min-height: 5.4rem;
|
:deep(.ant-input-textarea textarea) {
|
||||||
padding-bottom: 1.8rem;
|
border: none;
|
||||||
line-height: 1.5;
|
padding: 0;
|
||||||
}
|
font-size: 1.2rem;
|
||||||
|
color: #000;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
:deep(.ant-input-textarea-show-count) {
|
:deep(.ant-input) {
|
||||||
position: relative;
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
&::after {
|
:deep(.ant-input-show-count-suffix) {
|
||||||
float: none;
|
|
||||||
position: absolute;
|
|
||||||
color: #df2c2c;
|
color: #df2c2c;
|
||||||
bottom: 0;
|
font-size: 1rem;
|
||||||
right: 1.6rem;
|
}
|
||||||
|
|
||||||
|
: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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.license-note {
|
.license-note {
|
||||||
padding: 1.6rem;
|
padding: 1.6rem;
|
||||||
column-gap: 1.6rem;
|
column-gap: 1.6rem;
|
||||||
background: #f7f7f7;
|
background: #f7f7f7;
|
||||||
border-radius: 0.8rem;
|
border-radius: 0.8rem;
|
||||||
|
|
||||||
.info-icon {
|
.info-icon {
|
||||||
width: 2.4rem;
|
width: 2.4rem;
|
||||||
height: 2.4rem;
|
height: 2.4rem;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.note-copy {
|
.note-copy {
|
||||||
font-size: 1.2rem;
|
font-size: 1.2rem;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
color: #000;
|
color: #000;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-style: medium;
|
font-style: medium;
|
||||||
|
|
||||||
a {
|
a {
|
||||||
color: #0080ed;
|
color: #0080ed;
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
margin-left: 0.4rem;
|
margin-left: 0.4rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,19 +1,3 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import { computed } from "vue"
|
|
||||||
import type { ListingItem } from "../types"
|
|
||||||
|
|
||||||
const props = defineProps<{
|
|
||||||
imageList: ListingItem["prodImageList"]
|
|
||||||
firstSelectedIndex: number | null
|
|
||||||
}>()
|
|
||||||
|
|
||||||
const emit = defineEmits<{
|
|
||||||
(e: "select", index: number): void
|
|
||||||
}>()
|
|
||||||
|
|
||||||
const selectedCount = computed(() => props.imageList.filter((item) => item.selected).length)
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="product-image-list-container">
|
<div class="product-image-list-container">
|
||||||
<div class="title flex align-center space-between">
|
<div class="title flex align-center space-between">
|
||||||
@@ -45,110 +29,125 @@ const selectedCount = computed(() => props.imageList.filter((item) => item.selec
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed } from "vue"
|
||||||
|
import type { ListingItem } from "../types"
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
imageList: ListingItem["prodImageList"]
|
||||||
|
firstSelectedIndex: number | null
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: "select", index: number): void
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const selectedCount = computed(() => props.imageList.filter((item) => item.selected).length)
|
||||||
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.product-image-list-container {
|
.product-image-list-container {
|
||||||
margin-top: 3rem;
|
margin-top: 3rem;
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
font-size: 1.4rem;
|
|
||||||
margin-bottom: 1.2rem;
|
|
||||||
|
|
||||||
.main-title {
|
|
||||||
font-weight: 400;
|
|
||||||
font-style: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sub-title {
|
|
||||||
font-size: 1.2rem;
|
|
||||||
color: #999;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title-right {
|
|
||||||
color: #585858;
|
|
||||||
font-size: 1.4rem;
|
font-size: 1.4rem;
|
||||||
}
|
margin-bottom: 1.2rem;
|
||||||
}
|
|
||||||
|
|
||||||
.product-image-list {
|
.main-title {
|
||||||
overflow-x: auto;
|
font-weight: 400;
|
||||||
overflow-y: hidden;
|
font-style: bold;
|
||||||
column-gap: 0.8rem;
|
|
||||||
max-width: 80.2rem;
|
|
||||||
padding-bottom: 1.2rem;
|
|
||||||
|
|
||||||
&::-webkit-scrollbar {
|
|
||||||
height: 0.8rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
&::-webkit-scrollbar-track {
|
|
||||||
background: #d9d9d9;
|
|
||||||
border-radius: 0.8rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
&::-webkit-scrollbar-thumb {
|
|
||||||
background: #000000;
|
|
||||||
border-radius: 0.8rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.product-image-item {
|
|
||||||
width: 11.6rem;
|
|
||||||
height: 20.6rem;
|
|
||||||
border-radius: 1rem;
|
|
||||||
border: 0.15rem solid #c7c7c7;
|
|
||||||
position: relative;
|
|
||||||
cursor: pointer;
|
|
||||||
overflow: hidden;
|
|
||||||
flex-shrink: 0;
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
content: "";
|
|
||||||
background-color: #fcfcfc;
|
|
||||||
opacity: 0.7;
|
|
||||||
border-radius: 1rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&.selected {
|
.sub-title {
|
||||||
border-color: #000;
|
font-size: 1.2rem;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-right {
|
||||||
|
color: #585858;
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::-webkit-scrollbar-track {
|
||||||
|
background: #d9d9d9;
|
||||||
|
border-radius: 0.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::-webkit-scrollbar-thumb {
|
||||||
|
background: #000000;
|
||||||
|
border-radius: 0.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-image-item {
|
||||||
|
width: 11.6rem;
|
||||||
|
height: 20.6rem;
|
||||||
|
border-radius: 1rem;
|
||||||
|
border: 0.15rem solid #c7c7c7;
|
||||||
|
position: relative;
|
||||||
|
cursor: pointer;
|
||||||
|
overflow: hidden;
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
&::after {
|
&::after {
|
||||||
display: none;
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
content: "";
|
||||||
|
background-color: #fcfcfc;
|
||||||
|
opacity: 0.7;
|
||||||
|
border-radius: 1rem;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.checked {
|
&.selected {
|
||||||
width: 2rem;
|
border-color: #000;
|
||||||
height: 2rem;
|
|
||||||
position: absolute;
|
|
||||||
top: 0.8rem;
|
|
||||||
right: 0.8rem;
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.img-src {
|
&::after {
|
||||||
height: 100%;
|
display: none;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.main-pic {
|
.checked {
|
||||||
position: absolute;
|
width: 2rem;
|
||||||
height: 2.4rem;
|
height: 2rem;
|
||||||
line-height: 2.4rem;
|
position: absolute;
|
||||||
left: 0.8rem;
|
top: 0.8rem;
|
||||||
right: 0.8rem;
|
right: 0.8rem;
|
||||||
bottom: 0.8rem;
|
z-index: 1;
|
||||||
z-index: 1;
|
}
|
||||||
background: rgba(0, 0, 0, 0.8);
|
|
||||||
color: #fff;
|
.img-src {
|
||||||
font-size: 1.4rem;
|
height: 100%;
|
||||||
border-radius: 1.2rem;
|
}
|
||||||
text-align: center;
|
|
||||||
|
.main-pic {
|
||||||
|
position: absolute;
|
||||||
|
height: 2.4rem;
|
||||||
|
line-height: 2.4rem;
|
||||||
|
left: 0.8rem;
|
||||||
|
right: 0.8rem;
|
||||||
|
bottom: 0.8rem;
|
||||||
|
z-index: 1;
|
||||||
|
background: rgba(0, 0, 0, 0.8);
|
||||||
|
color: #fff;
|
||||||
|
font-size: 1.4rem;
|
||||||
|
border-radius: 1.2rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,22 +1,3 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import type { TopImageType } from "../types"
|
|
||||||
|
|
||||||
defineProps<{
|
|
||||||
images: Record<TopImageType, string | null>
|
|
||||||
}>()
|
|
||||||
|
|
||||||
const emit = defineEmits<{
|
|
||||||
(e: "crop", data: string | null, type: TopImageType): void
|
|
||||||
}>()
|
|
||||||
|
|
||||||
const topImageList: TopImageType[] = ["sketch", "mainProductImage", "cover"]
|
|
||||||
const topImageTitleMap: Record<TopImageType, string> = {
|
|
||||||
sketch: "SellerListEdit.sketch",
|
|
||||||
mainProductImage: "SellerListEdit.mainProductImage",
|
|
||||||
cover: "SellerListEdit.cover"
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="main-image-container flex">
|
<div class="main-image-container flex">
|
||||||
<div
|
<div
|
||||||
@@ -64,94 +45,112 @@ const topImageTitleMap: Record<TopImageType, string> = {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { TopImageType } from "../types"
|
||||||
|
|
||||||
|
defineProps<{
|
||||||
|
images: Record<TopImageType, string | null>
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: "crop", data: string | null, type: TopImageType): void
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const topImageList: TopImageType[] = ["sketch", "mainProductImage", "cover"]
|
||||||
|
const topImageTitleMap: Record<TopImageType, string> = {
|
||||||
|
sketch: "SellerListEdit.sketch",
|
||||||
|
mainProductImage: "SellerListEdit.mainProductImage",
|
||||||
|
cover: "SellerListEdit.cover"
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.c-svg {
|
.c-svg {
|
||||||
width: initial;
|
width: initial;
|
||||||
height: initial;
|
height: initial;
|
||||||
}
|
|
||||||
|
|
||||||
.required {
|
|
||||||
&::after {
|
|
||||||
content: "*";
|
|
||||||
color: #df2b2c;
|
|
||||||
margin-left: 0.4rem;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.main-image-container {
|
.required {
|
||||||
column-gap: 3.5rem;
|
&::after {
|
||||||
|
content: "*";
|
||||||
.main-image-item {
|
color: #df2b2c;
|
||||||
flex-shrink: 0;
|
margin-left: 0.4rem;
|
||||||
|
|
||||||
.title {
|
|
||||||
font-size: 1.4rem;
|
|
||||||
margin-bottom: 0.8rem;
|
|
||||||
text-align: center;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.sketch-item {
|
.main-image-container {
|
||||||
width: 11.6rem;
|
column-gap: 3.5rem;
|
||||||
height: 20.4rem;
|
|
||||||
border: 0.15rem solid #d1d1d1;
|
|
||||||
border-radius: 1rem;
|
|
||||||
position: relative;
|
|
||||||
background-color: #f6f6f6;
|
|
||||||
overflow: hidden;
|
|
||||||
|
|
||||||
&.cover {
|
.main-image-item {
|
||||||
width: 16.2rem;
|
flex-shrink: 0;
|
||||||
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");
|
|
||||||
border: none;
|
.title {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
margin-bottom: 0.8rem;
|
||||||
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.crop-tool {
|
.sketch-item {
|
||||||
position: absolute;
|
width: 11.6rem;
|
||||||
top: 0.8rem;
|
height: 20.4rem;
|
||||||
right: 0.8rem;
|
border: 0.15rem solid #d1d1d1;
|
||||||
width: 2rem;
|
border-radius: 1rem;
|
||||||
height: 2rem;
|
position: relative;
|
||||||
border-radius: 50%;
|
background-color: #f6f6f6;
|
||||||
background-color: #000000;
|
overflow: hidden;
|
||||||
z-index: 1;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sketch-img {
|
&.cover {
|
||||||
height: 100%;
|
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");
|
||||||
&.sketch {
|
border: none;
|
||||||
height: initial;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.trigger {
|
|
||||||
cursor: pointer;
|
|
||||||
height: 100%;
|
|
||||||
padding: 6rem 2rem 0;
|
|
||||||
|
|
||||||
&,
|
|
||||||
.cover-trigger {
|
|
||||||
row-gap: 1.2rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.placeholder {
|
.crop-tool {
|
||||||
width: 2.4rem;
|
position: absolute;
|
||||||
height: 2.4rem;
|
top: 0.8rem;
|
||||||
border-radius: 0.6rem;
|
right: 0.8rem;
|
||||||
background: linear-gradient(135deg, #efefef 0%, #cdcdcd 100%);
|
width: 2rem;
|
||||||
|
height: 2rem;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: #000000;
|
||||||
|
z-index: 1;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.trigger-tips {
|
.sketch-img {
|
||||||
font-size: 1.2rem;
|
height: 100%;
|
||||||
text-align: center;
|
|
||||||
color: #585858;
|
&.sketch {
|
||||||
line-height: 1.3;
|
height: initial;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.trigger {
|
||||||
|
cursor: pointer;
|
||||||
|
height: 100%;
|
||||||
|
padding: 6rem 2rem 0;
|
||||||
|
|
||||||
|
&,
|
||||||
|
.cover-trigger {
|
||||||
|
row-gap: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.placeholder {
|
||||||
|
width: 2.4rem;
|
||||||
|
height: 2.4rem;
|
||||||
|
border-radius: 0.6rem;
|
||||||
|
background: linear-gradient(135deg, #efefef 0%, #cdcdcd 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.trigger-tips {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
text-align: center;
|
||||||
|
color: #585858;
|
||||||
|
line-height: 1.3;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -267,7 +267,7 @@
|
|||||||
const handleClickCrop = (data: any, type: string, paramThree: any = []) => {
|
const handleClickCrop = (data: any, type: string, paramThree: any = []) => {
|
||||||
// 处理来自TopImageSection的调用: (data, type, list)
|
// 处理来自TopImageSection的调用: (data, type, list)
|
||||||
// 处理来自ApparelSketchList的调用: (data, type, index)
|
// 处理来自ApparelSketchList的调用: (data, type, index)
|
||||||
const index = typeof paramThree === 'number' ? paramThree : undefined
|
const index = typeof paramThree === "number" ? paramThree : undefined
|
||||||
const list = Array.isArray(paramThree) ? paramThree : []
|
const list = Array.isArray(paramThree) ? paramThree : []
|
||||||
|
|
||||||
// console.log(data, type)
|
// console.log(data, type)
|
||||||
@@ -376,9 +376,9 @@
|
|||||||
})
|
})
|
||||||
if (item.mainProductImage) {
|
if (item.mainProductImage) {
|
||||||
params.images.push({
|
params.images.push({
|
||||||
category: 'main_product',
|
category: "main_product",
|
||||||
imageUrl: item.mainProductImage,
|
imageUrl: item.mainProductImage,
|
||||||
isSeleted:1
|
isSeleted: 1
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
item.prodImageList.forEach((item) => {
|
item.prodImageList.forEach((item) => {
|
||||||
@@ -404,7 +404,7 @@
|
|||||||
message.error("请先完成封面制作")
|
message.error("请先完成封面制作")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (status === "publish" && !validatePublishRequired()) return
|
if (!validatePublishRequired()) return
|
||||||
|
|
||||||
await handleSaveForm(status)
|
await handleSaveForm(status)
|
||||||
if (status === "draft") {
|
if (status === "draft") {
|
||||||
|
|||||||
Reference in New Issue
Block a user