From 8fc07dd9cd2fc6c9e046f8ab91b75f3eb6daa481 Mon Sep 17 00:00:00 2001 From: zc <2064281269@qq.com> Date: Mon, 3 Nov 2025 23:02:22 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20auto-import=20=E4=BC=98=E5=8C=96+?= =?UTF-8?q?=E5=95=86=E5=93=81=E5=B1=9E=E6=80=A7=E5=80=BC=E6=8E=92=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/login.ts | 2 +- src/auto-import.d.ts | 154 ++++++++---------- .../goods/commodity/detail-dialog/index.vue | 4 +- .../commodity/detail-dialog/init-method.ts | 27 ++- .../commodity/detail-dialog/use-method.ts | 85 +++++++++- src/views/goods/commodity/use-method.ts | 27 ++- src/views/login/index.vue | 19 +-- vite.config.ts | 6 +- 8 files changed, 204 insertions(+), 120 deletions(-) diff --git a/src/api/login.ts b/src/api/login.ts index 450215e..b4ffa3f 100644 --- a/src/api/login.ts +++ b/src/api/login.ts @@ -1,7 +1,7 @@ const login = { apiGetUserRoleInfo: ['/user/getRoleUserInfo'], // 获取用户信息及权限 apiLogout: ['/login/out'], // 退出登录 - login: ['/login'] // 登录 + login: ['/user/login'] // 登录 } export default login diff --git a/src/auto-import.d.ts b/src/auto-import.d.ts index 700add6..fa9d29c 100644 --- a/src/auto-import.d.ts +++ b/src/auto-import.d.ts @@ -6,95 +6,77 @@ // biome-ignore lint: disable export {} declare global { - const EffectScope: (typeof import('vue'))['EffectScope'] - const api: (typeof import('src/api/index'))['api'] - const computed: (typeof import('vue'))['computed'] - const createApp: (typeof import('vue'))['createApp'] - const customRef: (typeof import('vue'))['customRef'] - const defineAsyncComponent: (typeof import('vue'))['defineAsyncComponent'] - const defineComponent: (typeof import('vue'))['defineComponent'] - const effectScope: (typeof import('vue'))['effectScope'] - const getCurrentInstance: (typeof import('vue'))['getCurrentInstance'] - const getCurrentScope: (typeof import('vue'))['getCurrentScope'] - const getCurrentWatcher: (typeof import('vue'))['getCurrentWatcher'] - const h: (typeof import('vue'))['h'] - const handleInit: (typeof import('src/utils/page/index'))['handleInit'] - const handleMessageBox: (typeof import('src/utils/page/index'))['handleMessageBox'] - const inject: (typeof import('vue'))['inject'] - const isProxy: (typeof import('vue'))['isProxy'] - const isReactive: (typeof import('vue'))['isReactive'] - const isReadonly: (typeof import('vue'))['isReadonly'] - const isRef: (typeof import('vue'))['isRef'] - const isShallow: (typeof import('vue'))['isShallow'] - const markRaw: (typeof import('vue'))['markRaw'] - const nextTick: (typeof import('vue'))['nextTick'] - const onActivated: (typeof import('vue'))['onActivated'] - const onBeforeMount: (typeof import('vue'))['onBeforeMount'] - const onBeforeRouteLeave: (typeof import('vue-router'))['onBeforeRouteLeave'] - const onBeforeRouteUpdate: (typeof import('vue-router'))['onBeforeRouteUpdate'] - const onBeforeUnmount: (typeof import('vue'))['onBeforeUnmount'] - const onBeforeUpdate: (typeof import('vue'))['onBeforeUpdate'] - const onDeactivated: (typeof import('vue'))['onDeactivated'] - const onErrorCaptured: (typeof import('vue'))['onErrorCaptured'] - const onMounted: (typeof import('vue'))['onMounted'] - const onRenderTracked: (typeof import('vue'))['onRenderTracked'] - const onRenderTriggered: (typeof import('vue'))['onRenderTriggered'] - const onScopeDispose: (typeof import('vue'))['onScopeDispose'] - const onServerPrefetch: (typeof import('vue'))['onServerPrefetch'] - const onUnmounted: (typeof import('vue'))['onUnmounted'] - const onUpdated: (typeof import('vue'))['onUpdated'] - const onWatcherCleanup: (typeof import('vue'))['onWatcherCleanup'] - const pageConfig: (typeof import('src/utils/page/config'))['pageConfig'] - const provide: (typeof import('vue'))['provide'] - const reactive: (typeof import('vue'))['reactive'] - const readonly: (typeof import('vue'))['readonly'] - const ref: (typeof import('vue'))['ref'] - const resolveComponent: (typeof import('vue'))['resolveComponent'] - const shallowReactive: (typeof import('vue'))['shallowReactive'] - const shallowReadonly: (typeof import('vue'))['shallowReadonly'] - const shallowRef: (typeof import('vue'))['shallowRef'] - const toRaw: (typeof import('vue'))['toRaw'] - const toRef: (typeof import('vue'))['toRef'] - const toRefs: (typeof import('vue'))['toRefs'] - const toValue: (typeof import('vue'))['toValue'] - const triggerRef: (typeof import('vue'))['triggerRef'] - const unref: (typeof import('vue'))['unref'] - const useAttrs: (typeof import('vue'))['useAttrs'] - const useCssModule: (typeof import('vue'))['useCssModule'] - const useCssVars: (typeof import('vue'))['useCssVars'] - const useId: (typeof import('vue'))['useId'] - const useLink: (typeof import('vue-router'))['useLink'] - const useModel: (typeof import('vue'))['useModel'] - const useRoute: (typeof import('vue-router'))['useRoute'] - const useRouter: (typeof import('vue-router'))['useRouter'] - const useSlots: (typeof import('vue'))['useSlots'] - const useTemplateRef: (typeof import('vue'))['useTemplateRef'] - const watch: (typeof import('vue'))['watch'] - const watchEffect: (typeof import('vue'))['watchEffect'] - const watchPostEffect: (typeof import('vue'))['watchPostEffect'] - const watchSyncEffect: (typeof import('vue'))['watchSyncEffect'] + const EffectScope: typeof import('vue')['EffectScope'] + const api: typeof import('@/api/index')['api'] + const computed: typeof import('vue')['computed'] + const createApp: typeof import('vue')['createApp'] + const customRef: typeof import('vue')['customRef'] + const defineAsyncComponent: typeof import('vue')['defineAsyncComponent'] + const defineComponent: typeof import('vue')['defineComponent'] + const effectScope: typeof import('vue')['effectScope'] + const getCurrentInstance: typeof import('vue')['getCurrentInstance'] + const getCurrentScope: typeof import('vue')['getCurrentScope'] + const getCurrentWatcher: typeof import('vue')['getCurrentWatcher'] + const h: typeof import('vue')['h'] + const handleInit: typeof import('@/utils/page/index')['handleInit'] + const handleMessageBox: typeof import('@/utils/page/index')['handleMessageBox'] + const inject: typeof import('vue')['inject'] + const isProxy: typeof import('vue')['isProxy'] + const isReactive: typeof import('vue')['isReactive'] + const isReadonly: typeof import('vue')['isReadonly'] + const isRef: typeof import('vue')['isRef'] + const isShallow: typeof import('vue')['isShallow'] + const markRaw: typeof import('vue')['markRaw'] + const nextTick: typeof import('vue')['nextTick'] + const onActivated: typeof import('vue')['onActivated'] + const onBeforeMount: typeof import('vue')['onBeforeMount'] + const onBeforeRouteLeave: typeof import('vue-router')['onBeforeRouteLeave'] + const onBeforeRouteUpdate: typeof import('vue-router')['onBeforeRouteUpdate'] + const onBeforeUnmount: typeof import('vue')['onBeforeUnmount'] + const onBeforeUpdate: typeof import('vue')['onBeforeUpdate'] + const onDeactivated: typeof import('vue')['onDeactivated'] + const onErrorCaptured: typeof import('vue')['onErrorCaptured'] + const onMounted: typeof import('vue')['onMounted'] + const onRenderTracked: typeof import('vue')['onRenderTracked'] + const onRenderTriggered: typeof import('vue')['onRenderTriggered'] + const onScopeDispose: typeof import('vue')['onScopeDispose'] + const onServerPrefetch: typeof import('vue')['onServerPrefetch'] + const onUnmounted: typeof import('vue')['onUnmounted'] + const onUpdated: typeof import('vue')['onUpdated'] + const onWatcherCleanup: typeof import('vue')['onWatcherCleanup'] + const pageConfig: typeof import('@/utils/page/config')['pageConfig'] + const provide: typeof import('vue')['provide'] + const reactive: typeof import('vue')['reactive'] + const readonly: typeof import('vue')['readonly'] + const ref: typeof import('vue')['ref'] + const resolveComponent: typeof import('vue')['resolveComponent'] + const shallowReactive: typeof import('vue')['shallowReactive'] + const shallowReadonly: typeof import('vue')['shallowReadonly'] + const shallowRef: typeof import('vue')['shallowRef'] + const toRaw: typeof import('vue')['toRaw'] + const toRef: typeof import('vue')['toRef'] + const toRefs: typeof import('vue')['toRefs'] + const toValue: typeof import('vue')['toValue'] + const triggerRef: typeof import('vue')['triggerRef'] + const unref: typeof import('vue')['unref'] + const useAttrs: typeof import('vue')['useAttrs'] + const useCssModule: typeof import('vue')['useCssModule'] + const useCssVars: typeof import('vue')['useCssVars'] + const useId: typeof import('vue')['useId'] + const useLink: typeof import('vue-router')['useLink'] + const useModel: typeof import('vue')['useModel'] + const useRoute: typeof import('vue-router')['useRoute'] + const useRouter: typeof import('vue-router')['useRouter'] + const useSlots: typeof import('vue')['useSlots'] + const useTemplateRef: typeof import('vue')['useTemplateRef'] + const watch: typeof import('vue')['watch'] + const watchEffect: typeof import('vue')['watchEffect'] + const watchPostEffect: typeof import('vue')['watchPostEffect'] + const watchSyncEffect: typeof import('vue')['watchSyncEffect'] } // for type re-export declare global { // @ts-ignore - export type { - Component, - Slot, - Slots, - ComponentPublicInstance, - ComputedRef, - DirectiveBinding, - ExtractDefaultPropTypes, - ExtractPropTypes, - ExtractPublicPropTypes, - InjectionKey, - PropType, - Ref, - ShallowRef, - MaybeRef, - MaybeRefOrGetter, - VNode, - WritableComputedRef - } from 'vue' + export type { Component, Slot, Slots, ComponentPublicInstance, ComputedRef, DirectiveBinding, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, ShallowRef, MaybeRef, MaybeRefOrGetter, VNode, WritableComputedRef } from 'vue' import('vue') } diff --git a/src/views/goods/commodity/detail-dialog/index.vue b/src/views/goods/commodity/detail-dialog/index.vue index 43f5ce9..a0d7cfb 100644 --- a/src/views/goods/commodity/detail-dialog/index.vue +++ b/src/views/goods/commodity/detail-dialog/index.vue @@ -126,7 +126,7 @@ v-model="editPropertyTypeValue" size="small" class="w-20" - @keyup.enter="handleEditPropertyTypeConfirm(item, skuList)" + @keyup.enter="handleEditPropertyTypeConfirm(item, skuList, adminCategoryData)" @blur="editPropertyTypeIndex = NaN" />: @@ -138,7 +138,7 @@ class="w-20" size="small" v-model="inputEditPropertyValue" - @keyup.enter="onEditPropertyValue(child, skuList)" + @keyup.enter="onEditPropertyValue(child, skuList, item.vvPropertyValueList)" @blur="curPropertyValueId = ''" > { }) } -export const handleEditPropertyTypeConfirm = async (item: any, skuList: any) => { +export const handleEditPropertyTypeConfirm = async ( + item: any, + skuList: any, + adminCategoryData: any +) => { const oldCategoryPropertyName = item.categoryPropertyName + if ( + oldCategoryPropertyName !== editPropertyTypeValue.value && + adminCategoryData.find((item: any) => item.categoryPropertyName === editPropertyTypeValue.value) + ) { + editPropertyTypeValue.value = '' + ElMessage.error('属性类型已存在,请重新输入') + return + } item.categoryPropertyName = editPropertyTypeValue.value item.vvPropertyValueList.forEach((item: any) => { item.categoryPropertyName = editPropertyTypeValue.value @@ -56,8 +70,17 @@ export const onClickPropertyValue = (item: any, child: any) => { }) } -export const onEditPropertyValue = (child: any, skuList: any) => { +export const onEditPropertyValue = (child: any, skuList: any, vvPropertyValueList: any) => { const oldCategoryPropertyValue = child.categoryPropertyValue + if ( + oldCategoryPropertyValue !== inputEditPropertyValue.value && + vvPropertyValueList.find( + (item: any) => item.categoryPropertyValue === inputEditPropertyValue.value + ) + ) { + ElMessage.error('属性值已存在,请重新输入') + return + } child.categoryPropertyValue = inputEditPropertyValue.value handleEditSkuListPropertyValue( child.categoryPropertyName, diff --git a/src/views/goods/commodity/detail-dialog/use-method.ts b/src/views/goods/commodity/detail-dialog/use-method.ts index 4262b22..0c9ff1c 100644 --- a/src/views/goods/commodity/detail-dialog/use-method.ts +++ b/src/views/goods/commodity/detail-dialog/use-method.ts @@ -1,3 +1,4 @@ +import { ElMessage } from 'element-plus' import { useDraggable } from 'vue-draggable-plus' // 定义源数据的结构类型 interface Option { @@ -28,7 +29,7 @@ export interface TSkuList { vvSkuPropertyValueList: any[] } -// 当改变后台类目的时候,重新创建sku列表 +/* // 当改变后台类目的时候,重新创建sku列表 export const generateSkuList = (adminCategoryData: CategoryDataMock): TSkuList[] => { if (adminCategoryData.length === 0) { return [] @@ -62,7 +63,7 @@ export const generateSkuList = (adminCategoryData: CategoryDataMock): TSkuList[] combine(0, []) return result -} +} */ // 增加属性、删除属性 export const usePropertyValue = () => { @@ -105,6 +106,15 @@ export const usePropertyValue = () => { } // 新增回车确认 const handleInputConfirm = (lineIndex: number, skuList: TSkuList[] = []) => { + if ( + adminCategoryData[lineIndex].vvPropertyValueList.find( + (item: any) => item.categoryPropertyValue === inputValue.value + ) + ) { + ElMessage.error('属性值已存在,请重新输入') + inputValue.value = '' + return + } if (inputValue.value) { const id = Math.random() const newData = { @@ -117,6 +127,7 @@ export const usePropertyValue = () => { if (skuList?.length && skuList[0].vvSkuPropertyValueList.length < adminCategoryData.length) { skuList.forEach((item: TSkuList) => { item.name += '-' + inputValue.value + item.categoryPropertyNames += '-' + adminCategoryData[lineIndex].categoryPropertyName item.vvSkuPropertyValueList.push({ ...newData }) }) } else { @@ -126,7 +137,7 @@ export const usePropertyValue = () => { inputVisibles.value[lineIndex] = false inputValue.value = '' } - + /* // 新增属性的时候创建数据 const generateAddSkuList = ( lineIndex: number, @@ -169,8 +180,13 @@ export const usePropertyValue = () => { //bug console.warn('----- my data is result111: ', result) return result - } + } */ const onAddPropertyLine = (categoryId: number, val: string) => { + if (adminCategoryData.find((item: any) => item.categoryPropertyName === val)) { + ElMessage.error('属性类型已存在,请重新输入') + inputPropertyLineValue.value = '' + return + } visiblePropertyLine.value = false console.warn('----- my data is inputPropertyLineValue: ', val) adminCategoryData.push({ @@ -275,3 +291,64 @@ export const handleCheckChange = ( data[type + 'CategoryIds'] = [...checkedStatus.halfCheckedKeys, ...checkedStatus.checkedKeys] return checkedData } + +// 当改变后台类目的时候,重新创建sku列表 +export const generateSkuList = (categories: CategoryDataMock): TSkuList[] => { + if (categories.length === 0) { + return [] + } + // 1) 提取每个分类里可用的值(按传入顺序保序) + const arrays = categories.map((cat) => cat.vvPropertyValueList || []) + + // 若任一分类无可用值,则无组合 + if (arrays.some((arr) => arr.length === 0)) return [] + + // 2) 做笛卡尔积,保持输入顺序 + let combos = arrays[0].map((x) => [x]) + for (let i = 1; i < arrays.length; i++) { + const next = [] + for (const combo of combos) { + for (const x of arrays[i]) { + next.push([...combo, x]) + } + } + combos = next + } + + // 3) 生成目标对象:name 由 value 用 '-' 拼接;originArray 记录来源对象 + return combos.map((combo) => { + const serialNo = combo.map((opt) => opt.id.toString()).join('-') + const name = combo.map((opt) => String(opt.categoryPropertyValue)).join('-') + const categoryPropertyNames = combo.map((opt) => String(opt.categoryPropertyValue)).join('-') + const originArray = combo + return { + serialNo, + name, + categoryPropertyNames, + salePrice: '', + stock: 0, + originPrice: 0, + imageUrl: '', + promotionPrice: '', + vvSkuPropertyValueList: originArray + } + }) +} + +// 新增属性值的时候创建数据 +const generateAddSkuList = ( + lineIndex: number, + addData: Option, + adminCategoryData: CategoryDataMock +): TSkuList[] => { + const filterCategoryData: CategoryDataMock = adminCategoryData.map((category, i) => { + if (i === lineIndex) { + return { + ...category, + vvPropertyValueList: category.vvPropertyValueList.filter((item) => item.id === addData.id) + } + } + return category + }) + return generateSkuList(filterCategoryData) +} diff --git a/src/views/goods/commodity/use-method.ts b/src/views/goods/commodity/use-method.ts index b29317f..0c967e2 100644 --- a/src/views/goods/commodity/use-method.ts +++ b/src/views/goods/commodity/use-method.ts @@ -1,17 +1,18 @@ -type TCommodityType = 'online' | 'down' | 'draft' | 'delete' +type TCommodityType = 'all' | 'online' | 'down' | 'draft' | 'delete' export const useCommodityType = (search: any, table: any) => { let beforeValue = 'online' const commodityType = ref('online') const commodityTypeOptions = [ + { label: '所有商品', value: 'all' }, { label: '在线商品', value: 'online' }, { label: '下架商品', value: 'down' }, { label: '草稿', value: 'draft' }, { label: '已删商品', value: 'delete' } ] - const cacheTableData = { online: [], down: [], draft: [], delete: [] } // 缓存表单数据 - const cacheTablePage = { online: {}, down: {}, draft: {}, delete: {} } // 缓存表单页面数据 - const onChangeCommodityType = (type: 'online' | 'down' | 'draft' | 'delete') => { + const cacheTableData = { all: [], online: [], down: [], draft: [], delete: [] } // 缓存表单数据 + const cacheTablePage = { all: {}, online: {}, down: {}, draft: {}, delete: {} } // 缓存表单页面数据 + const onChangeCommodityType = (type: 'all' | 'online' | 'down' | 'draft' | 'delete') => { cacheTableData[beforeValue as typeof type] = toRaw(table.value.$data) cacheTablePage[beforeValue as typeof type] = toRaw(table.value.$pages) beforeValue = type @@ -22,13 +23,21 @@ export const useCommodityType = (search: any, table: any) => { table.value.$data = cacheTableData[type] table.value.$pages = cacheTablePage[type] } else { - table.value.$onGetData(table.value, 1, search) + if (type === 'all') { + search.value.$data = { status: '' } + table.value.$onGetData(table.value, 1, search) + } else { + table.value.$onGetData(table.value, 1, search) + } } } - const handleSetTableConfig = (table: any, type: 'online' | 'down' | 'draft' | 'delete') => { - const btnOnlineName = { online: '下架', down: '上架', draft: '', delete: '' } // 上下架按钮名称 - const btnHomeName = { online: '加入首页', down: '', draft: '', delete: '' } // 上下架按钮名称 - const btnWidth = { online: '230', down: '180', draft: '160', delete: '160' } // 上下架按钮名称 + const handleSetTableConfig = ( + table: any, + type: 'all' | 'online' | 'down' | 'draft' | 'delete' + ) => { + const btnOnlineName = { all: '', online: '下架', down: '上架', draft: '', delete: '' } // 上下架按钮名称 + const btnHomeName = { all: '', online: '加入首页', down: '', draft: '', delete: '' } // 上下架按钮名称 + const btnWidth = { all: '180', online: '230', down: '180', draft: '160', delete: '160' } // 上下架按钮名称 table.value.btn.$attr.names[2] = btnHomeName[type] table.value.btn.$attr.names[3] = btnOnlineName[type] table.value.btn.$attr.width = btnWidth[type] diff --git a/src/views/login/index.vue b/src/views/login/index.vue index 2db979b..8b81e24 100644 --- a/src/views/login/index.vue +++ b/src/views/login/index.vue @@ -19,17 +19,10 @@ const loginRules = reactive({ const handleLogin = () => { loginFormRef.value.validate((valid) => { if (valid) { - api.login.login - .post(loginData) - .then((res) => { - if (res.code === 200) { - router.push({ path: '/home' }) - } - }) - .finally(() => { - user.onLogin({ tokenValue: '123', tokenName: '123' }) - router.push({ path: '/home' }) - }) + api.login.login.post(loginData).then((res) => { + router.push({ path: '/home' }) + user.onLogin({ tokenValue: res.data.token, tokenName: 'mmToken' }) + }) } else { return false } @@ -48,10 +41,10 @@ const handleLogin = () => { @keyup.enter="handleLogin" class="login_form" > - +