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.
|
||||
- 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
|
||||
|
||||
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>
|
||||
<div class="apparel-container">
|
||||
<div class="title">
|
||||
@@ -23,16 +11,30 @@ const emit = defineEmits<{
|
||||
class="sketch-element flex flex-center"
|
||||
>
|
||||
<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" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</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>
|
||||
.apparel-container {
|
||||
.apparel-container {
|
||||
margin-top: 3rem;
|
||||
|
||||
.title {
|
||||
@@ -82,5 +84,5 @@ const emit = defineEmits<{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</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>
|
||||
<div class="form-container flex flex-col">
|
||||
<div class="form-item">
|
||||
@@ -102,16 +79,39 @@ const emit = defineEmits<{
|
||||
</div>
|
||||
</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>
|
||||
.required {
|
||||
.required {
|
||||
&::after {
|
||||
content: "*";
|
||||
color: #df2b2c;
|
||||
margin-left: 0.4rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.form-container {
|
||||
.form-container {
|
||||
row-gap: 3rem;
|
||||
|
||||
.form-item {
|
||||
@@ -191,9 +191,9 @@ const emit = defineEmits<{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.license-note {
|
||||
.license-note {
|
||||
padding: 1.6rem;
|
||||
column-gap: 1.6rem;
|
||||
background: #f7f7f7;
|
||||
@@ -218,5 +218,5 @@ const emit = defineEmits<{
|
||||
margin-left: 0.4rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</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>
|
||||
<div class="product-image-list-container">
|
||||
<div class="title flex align-center space-between">
|
||||
@@ -45,9 +29,24 @@ const selectedCount = computed(() => props.imageList.filter((item) => item.selec
|
||||
</div>
|
||||
</div>
|
||||
</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>
|
||||
.product-image-list-container {
|
||||
.product-image-list-container {
|
||||
margin-top: 3rem;
|
||||
|
||||
.title {
|
||||
@@ -150,5 +149,5 @@ const selectedCount = computed(() => props.imageList.filter((item) => item.selec
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</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>
|
||||
<div class="main-image-container flex">
|
||||
<div
|
||||
@@ -64,22 +45,40 @@ const topImageTitleMap: Record<TopImageType, string> = {
|
||||
</div>
|
||||
</div>
|
||||
</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>
|
||||
.c-svg {
|
||||
.c-svg {
|
||||
width: initial;
|
||||
height: initial;
|
||||
}
|
||||
}
|
||||
|
||||
.required {
|
||||
.required {
|
||||
&::after {
|
||||
content: "*";
|
||||
color: #df2b2c;
|
||||
margin-left: 0.4rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.main-image-container {
|
||||
.main-image-container {
|
||||
column-gap: 3.5rem;
|
||||
|
||||
.main-image-item {
|
||||
@@ -153,5 +152,5 @@ const topImageTitleMap: Record<TopImageType, string> = {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -267,7 +267,7 @@
|
||||
const handleClickCrop = (data: any, type: string, paramThree: any = []) => {
|
||||
// 处理来自TopImageSection的调用: (data, type, list)
|
||||
// 处理来自ApparelSketchList的调用: (data, type, index)
|
||||
const index = typeof paramThree === 'number' ? paramThree : undefined
|
||||
const index = typeof paramThree === "number" ? paramThree : undefined
|
||||
const list = Array.isArray(paramThree) ? paramThree : []
|
||||
|
||||
// console.log(data, type)
|
||||
@@ -376,9 +376,9 @@
|
||||
})
|
||||
if (item.mainProductImage) {
|
||||
params.images.push({
|
||||
category: 'main_product',
|
||||
category: "main_product",
|
||||
imageUrl: item.mainProductImage,
|
||||
isSeleted:1
|
||||
isSeleted: 1
|
||||
})
|
||||
}
|
||||
item.prodImageList.forEach((item) => {
|
||||
@@ -404,7 +404,7 @@
|
||||
message.error("请先完成封面制作")
|
||||
return
|
||||
}
|
||||
if (status === "publish" && !validatePublishRequired()) return
|
||||
if (!validatePublishRequired()) return
|
||||
|
||||
await handleSaveForm(status)
|
||||
if (status === "draft") {
|
||||
|
||||
Reference in New Issue
Block a user