feat: 商品详情编辑
This commit is contained in:
parent
8fc07dd9cd
commit
7099bea338
@ -19,9 +19,10 @@ const useUserStore = defineStore('user', {
|
|||||||
this.$reset()
|
this.$reset()
|
||||||
},
|
},
|
||||||
// 登录
|
// 登录
|
||||||
onLogin(data: { tokenValue: string; tokenName: string }) {
|
onLogin(data: { tokenValue: string; tokenName: string; userNickName: string }) {
|
||||||
this.tokenValue = data.tokenValue
|
this.tokenValue = data.tokenValue
|
||||||
this.tokenName = data.tokenName
|
this.tokenName = data.tokenName
|
||||||
|
this.userNickName = data.userNickName
|
||||||
},
|
},
|
||||||
// 获取用户信息(昵称、头像、角色集合、权限集合)
|
// 获取用户信息(昵称、头像、角色集合、权限集合)
|
||||||
getUserRoleInfo() {
|
getUserRoleInfo() {
|
||||||
|
|||||||
@ -5,6 +5,8 @@ interface PreviewItem {
|
|||||||
type: 'image' | 'video'
|
type: 'image' | 'video'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const curPropertyTypeImage = ref(null)
|
||||||
|
|
||||||
// 选择资源库图片
|
// 选择资源库图片
|
||||||
export const useImportFile = (fileList: Ref<PreviewItem[]>) => {
|
export const useImportFile = (fileList: Ref<PreviewItem[]>) => {
|
||||||
const showFileExplorer = ref(false)
|
const showFileExplorer = ref(false)
|
||||||
@ -18,10 +20,15 @@ export const useImportFile = (fileList: Ref<PreviewItem[]>) => {
|
|||||||
|
|
||||||
// 处理文件选择
|
// 处理文件选择
|
||||||
const handleChooseResourceFileCallback = (files: PreviewItem[] = []) => {
|
const handleChooseResourceFileCallback = (files: PreviewItem[] = []) => {
|
||||||
handleChooseFiles(curFileType.value, files, fileList.value)
|
if (curPropertyTypeImage.value) {
|
||||||
|
curPropertyTypeImage.value.imageUrl = files[0].resourceUrl
|
||||||
|
} else {
|
||||||
|
handleChooseFiles(curFileType.value, files, fileList.value)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const onClickChooseResourceBtn = (type: 'mainImageUrl' | 'videoUrl' | 'subImageUrl') => {
|
const onClickChooseResourceBtn = (type: 'mainImageUrl' | 'videoUrl' | 'subImageUrl') => {
|
||||||
|
curPropertyTypeImage.value = null
|
||||||
curFileType.value = type
|
curFileType.value = type
|
||||||
showFileExplorer.value = true
|
showFileExplorer.value = true
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,7 +21,11 @@ export const handleGetDialogData = (
|
|||||||
result.adminCategoryId = defaultCheckedNodes.value.admin.slice(-1)[0]
|
result.adminCategoryId = defaultCheckedNodes.value.admin.slice(-1)[0]
|
||||||
defaultCheckedNodes.value.app = [data.appCategoryId1, data.appCategoryId2]
|
defaultCheckedNodes.value.app = [data.appCategoryId1, data.appCategoryId2]
|
||||||
result.isTest = data.isTest
|
result.isTest = data.isTest
|
||||||
|
result.isNew = data.isNew
|
||||||
|
result.isFlash = data.isFlash
|
||||||
result.title = data.title
|
result.title = data.title
|
||||||
|
result.frontPage = data.frontPage
|
||||||
|
result.status = data.status
|
||||||
result.feature1 = data.feature1
|
result.feature1 = data.feature1
|
||||||
result.feature2 = data.feature2
|
result.feature2 = data.feature2
|
||||||
result.htmlContent = data.vvProductDetailList.find((item: any) => item.type === 2)?.detail || ''
|
result.htmlContent = data.vvProductDetailList.find((item: any) => item.type === 2)?.detail || ''
|
||||||
@ -86,7 +90,7 @@ export const handleGetNewAdminCategoryData = (data: any) => {
|
|||||||
|
|
||||||
// 编辑的时候对sku进行重组
|
// 编辑的时候对sku进行重组
|
||||||
export const handleGetNewSkuList = (data: any) => {
|
export const handleGetNewSkuList = (data: any) => {
|
||||||
return data.map((item: any) => {
|
const arr = data.map((item: any) => {
|
||||||
let categoryPropertyNames = ''
|
let categoryPropertyNames = ''
|
||||||
let name = ''
|
let name = ''
|
||||||
item.vvSkuPropertyValueList.forEach((child: any, index: number) => {
|
item.vvSkuPropertyValueList.forEach((child: any, index: number) => {
|
||||||
@ -101,4 +105,45 @@ export const handleGetNewSkuList = (data: any) => {
|
|||||||
categoryPropertyNames
|
categoryPropertyNames
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
return sortByPrefix(arr)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按照 name 字段的前缀进行排序,将前几位相同的项排序到一起
|
||||||
|
* @param arr 要排序的数组
|
||||||
|
* @returns 排序后的新数组
|
||||||
|
*/
|
||||||
|
export const sortByPrefix = <T extends { name?: string }>(arr: T[]): T[] => {
|
||||||
|
if (!Array.isArray(arr) || arr.length === 0) {
|
||||||
|
return arr
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算前缀:如果 name 包含 "-",取最后一个 "-" 之前的部分作为前缀
|
||||||
|
const getPrefix = (name: string): string => {
|
||||||
|
if (!name) return ''
|
||||||
|
|
||||||
|
// 找到最后一个 "-" 的位置,取之前的部分作为前缀
|
||||||
|
const lastDashIndex = name.lastIndexOf('-')
|
||||||
|
if (lastDashIndex > 0) {
|
||||||
|
return name.substring(0, lastDashIndex + 1) // 包含 "-" 分隔符
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果没有 "-",返回整个字符串
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建副本并排序
|
||||||
|
return [...arr].sort((a, b) => {
|
||||||
|
const prefixA = getPrefix(a.name || '')
|
||||||
|
const prefixB = getPrefix(b.name || '')
|
||||||
|
|
||||||
|
// 先按前缀排序
|
||||||
|
const prefixCompare = prefixA.localeCompare(prefixB, 'zh-CN')
|
||||||
|
if (prefixCompare !== 0) {
|
||||||
|
return prefixCompare
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果前缀相同,再按完整的 name 排序
|
||||||
|
return (a.name || '').localeCompare(b.name || '', 'zh-CN')
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -77,9 +77,6 @@
|
|||||||
>
|
>
|
||||||
</el-tree-select>
|
</el-tree-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="测试商品">
|
|
||||||
<el-switch v-model="$dialog.data.isTest" active-value="1" inactive-value="0" />
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="特色">
|
<el-form-item label="特色">
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<el-input
|
<el-input
|
||||||
@ -94,6 +91,22 @@
|
|||||||
></el-input>
|
></el-input>
|
||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<br />
|
||||||
|
<el-form-item label="测试商品">
|
||||||
|
<el-switch v-model="$dialog.data.isTest" :active-value="1" :inactive-value="0" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="新品">
|
||||||
|
<el-switch v-model="$dialog.data.isNew" :active-value="1" :inactive-value="0" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="限时秒杀">
|
||||||
|
<el-switch v-model="$dialog.data.isFlash" :active-value="1" :inactive-value="0" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="上线">
|
||||||
|
<el-switch v-model="$dialog.data.status" active-value="online" inactive-value="down" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="加入首页">
|
||||||
|
<el-switch v-model="$dialog.data.frontPage" :active-value="1" :inactive-value="0" />
|
||||||
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-popover
|
<el-popover
|
||||||
:visible="visiblePropertyLine"
|
:visible="visiblePropertyLine"
|
||||||
@ -146,10 +159,47 @@
|
|||||||
closable
|
closable
|
||||||
effect="plain"
|
effect="plain"
|
||||||
:type="colors[index % 4]"
|
:type="colors[index % 4]"
|
||||||
class="mr-1"
|
class="mr-1 property-type-tag"
|
||||||
|
size="large"
|
||||||
@click="onClickPropertyValue(item, child)"
|
@click="onClickPropertyValue(item, child)"
|
||||||
@close="onDeletePropertyValue(index, child.id)"
|
@close="onDeletePropertyValue(index, child.id)"
|
||||||
>{{ child.categoryPropertyValue }}</el-tag
|
>
|
||||||
|
<el-popover title="" placement="top-start" :width="280">
|
||||||
|
<template #reference>
|
||||||
|
<el-icon
|
||||||
|
color="#999"
|
||||||
|
class="mr-1"
|
||||||
|
v-if="!child.imageUrl"
|
||||||
|
@click.stop="onChangePropertyTypeImage(child)"
|
||||||
|
><Picture
|
||||||
|
/></el-icon>
|
||||||
|
<img
|
||||||
|
v-else
|
||||||
|
:src="child.imageUrl"
|
||||||
|
alt=""
|
||||||
|
class="w-6 h-6 mr-1"
|
||||||
|
@click.stop="onChangePropertyTypeImage(child)"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<div>
|
||||||
|
<file-upload-btn
|
||||||
|
class="inline-block"
|
||||||
|
size="small"
|
||||||
|
accept="image/*"
|
||||||
|
@change="(val) => (child.imageUrl = val[0].resourceUrl)"
|
||||||
|
/>
|
||||||
|
<el-button
|
||||||
|
type="success"
|
||||||
|
size="small"
|
||||||
|
class="ml-2"
|
||||||
|
@click="(showFileExplorer = true) && (curPropertyTypeImage = child)"
|
||||||
|
>资源库导入</el-button
|
||||||
|
>
|
||||||
|
<el-button type="danger" size="small" class="ml-2" @click="child.imageUrl = ''"
|
||||||
|
>清空</el-button
|
||||||
|
>
|
||||||
|
</div> </el-popover
|
||||||
|
><span>{{ child.categoryPropertyValue }}</span></el-tag
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<el-input
|
<el-input
|
||||||
@ -233,7 +283,8 @@ import {
|
|||||||
defaultAdminCategoryTreeProps,
|
defaultAdminCategoryTreeProps,
|
||||||
defaultCheckedNodes,
|
defaultCheckedNodes,
|
||||||
fileList,
|
fileList,
|
||||||
TSkuList
|
TSkuList,
|
||||||
|
onChangePropertyTypeImage
|
||||||
} from './use-method'
|
} from './use-method'
|
||||||
import {
|
import {
|
||||||
handleGetDialogData,
|
handleGetDialogData,
|
||||||
@ -258,10 +309,11 @@ import categoryConfig from './category-config.vue'
|
|||||||
import wanEditor from './editor.vue'
|
import wanEditor from './editor.vue'
|
||||||
import fileUploadBtn from '@/components/FileUploadBtn/index.vue'
|
import fileUploadBtn from '@/components/FileUploadBtn/index.vue'
|
||||||
import resourceReview from '@/components/ResourceReview/index.vue'
|
import resourceReview from '@/components/ResourceReview/index.vue'
|
||||||
import { useImportFile, handleChooseFiles } from './choose-file-method'
|
import { curPropertyTypeImage, useImportFile, handleChooseFiles } from './choose-file-method'
|
||||||
import FileExplorerDialog from '@/components/FileExplorerDialog/index.vue'
|
import FileExplorerDialog from '@/components/FileExplorerDialog/index.vue'
|
||||||
import { Atrans$DialogRes } from '@/utils/page/config'
|
import { Atrans$DialogRes } from '@/utils/page/config'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
|
import { Picture } from '@element-plus/icons-vue'
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const $dialog = ref<Atrans$DialogRes>({} as Atrans$DialogRes)
|
const $dialog = ref<Atrans$DialogRes>({} as Atrans$DialogRes)
|
||||||
@ -275,7 +327,11 @@ const init = async () => {
|
|||||||
appCategoryId: '',
|
appCategoryId: '',
|
||||||
adminCategoryId: '',
|
adminCategoryId: '',
|
||||||
isTest: 0,
|
isTest: 0,
|
||||||
title: ''
|
isNew: 0,
|
||||||
|
isFlash: 0,
|
||||||
|
title: '',
|
||||||
|
frontPage: 0,
|
||||||
|
status: 'down'
|
||||||
}
|
}
|
||||||
adminCategoryData.value = []
|
adminCategoryData.value = []
|
||||||
skuList.value = []
|
skuList.value = []
|
||||||
@ -378,5 +434,11 @@ init()
|
|||||||
}
|
}
|
||||||
color: #666;
|
color: #666;
|
||||||
}
|
}
|
||||||
|
.property-type-tag {
|
||||||
|
:deep(.el-tag__content) {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -319,7 +319,7 @@ export const generateSkuList = (categories: CategoryDataMock): TSkuList[] => {
|
|||||||
return combos.map((combo) => {
|
return combos.map((combo) => {
|
||||||
const serialNo = combo.map((opt) => opt.id.toString()).join('-')
|
const serialNo = combo.map((opt) => opt.id.toString()).join('-')
|
||||||
const name = combo.map((opt) => String(opt.categoryPropertyValue)).join('-')
|
const name = combo.map((opt) => String(opt.categoryPropertyValue)).join('-')
|
||||||
const categoryPropertyNames = combo.map((opt) => String(opt.categoryPropertyValue)).join('-')
|
const categoryPropertyNames = combo.map((opt) => String(opt.categoryPropertyName)).join('-')
|
||||||
const originArray = combo
|
const originArray = combo
|
||||||
return {
|
return {
|
||||||
serialNo,
|
serialNo,
|
||||||
@ -352,3 +352,7 @@ const generateAddSkuList = (
|
|||||||
})
|
})
|
||||||
return generateSkuList(filterCategoryData)
|
return generateSkuList(filterCategoryData)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const onChangePropertyTypeImage = (child: any) => {
|
||||||
|
console.log(1111, child)
|
||||||
|
}
|
||||||
|
|||||||
@ -21,7 +21,11 @@ const handleLogin = () => {
|
|||||||
if (valid) {
|
if (valid) {
|
||||||
api.login.login.post(loginData).then((res) => {
|
api.login.login.post(loginData).then((res) => {
|
||||||
router.push({ path: '/home' })
|
router.push({ path: '/home' })
|
||||||
user.onLogin({ tokenValue: res.data.token, tokenName: 'mmToken' })
|
user.onLogin({
|
||||||
|
tokenValue: res.data.token,
|
||||||
|
tokenName: 'mmToken',
|
||||||
|
userNickName: res.data.username
|
||||||
|
})
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user