Merge branch 'dev_vite' of ssh://18.167.251.121:10002/aidlab/aida_front into dev_vite

This commit is contained in:
X1627315083@163.com
2026-04-29 14:50:00 +08:00
6 changed files with 374 additions and 369 deletions

View File

@@ -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`:

View File

@@ -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,13 +11,27 @@ 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 {

View File

@@ -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,6 +79,29 @@ 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 {

View File

@@ -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,6 +29,21 @@ 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 {

View File

@@ -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,6 +45,24 @@ 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 {

View File

@@ -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,7 +376,7 @@
}) })
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
}) })
@@ -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") {