diff --git a/package.json b/package.json index e2fe75f9..50b7f9ac 100644 --- a/package.json +++ b/package.json @@ -9,11 +9,11 @@ "dev": "vite --mode env.local", "dev-server": "vite --mode dev", "ts:check": "vue-tsc --noEmit", - "build:local": "node ./node_modules/vite/bin/vite.js build", - "build:dev": "node ./node_modules/vite/bin/vite.js build --mode dev", - "build:test": "node ./node_modules/vite/bin/vite.js build --mode test", - "build:stage": "node ./node_modules/vite/bin/vite.js build --mode stage", - "build:prod": "node ./node_modules/vite/bin/vite.js build --mode prod", + "build:local": "node --max_old_space_size=4096 ./node_modules/vite/bin/vite.js build", + "build:dev": "node --max_old_space_size=4096 ./node_modules/vite/bin/vite.js build --mode dev", + "build:test": "node --max_old_space_size=4096 ./node_modules/vite/bin/vite.js build --mode test", + "build:stage": "node --max_old_space_size=4096 ./node_modules/vite/bin/vite.js build --mode stage", + "build:prod": "node --max_old_space_size=4096 ./node_modules/vite/bin/vite.js build --mode prod", "serve:dev": "vite preview --mode dev", "serve:prod": "vite preview --mode prod", "preview": "pnpm build:local && vite preview", diff --git a/src/api/mall/promotion/kefu/conversation/index.ts b/src/api/mall/promotion/kefu/conversation/index.ts index 1b8d5389..eb6eb9c9 100644 --- a/src/api/mall/promotion/kefu/conversation/index.ts +++ b/src/api/mall/promotion/kefu/conversation/index.ts @@ -21,6 +21,10 @@ export const KeFuConversationApi = { getConversationList: async () => { return await request.get({ url: '/promotion/kefu-conversation/list' }) }, + // 获得客服会话 + getConversation: async (id: number) => { + return await request.get({ url: `/promotion/kefu-conversation/get?id=` + id }) + }, // 客服会话置顶 updateConversationPinned: async (data: any) => { return await request.put({ @@ -30,6 +34,6 @@ export const KeFuConversationApi = { }, // 删除客服会话 deleteConversation: async (id: number) => { - return await request.delete({ url: `/promotion/kefu-conversation/delete?id=${id}`}) + return await request.delete({ url: `/promotion/kefu-conversation/delete?id=${id}` }) } } diff --git a/src/api/mall/promotion/kefu/message/index.ts b/src/api/mall/promotion/kefu/message/index.ts index a12167fa..4c3bed88 100644 --- a/src/api/mall/promotion/kefu/message/index.ts +++ b/src/api/mall/promotion/kefu/message/index.ts @@ -29,8 +29,8 @@ export const KeFuMessageApi = { url: '/promotion/kefu-message/update-read-status?conversationId=' + conversationId }) }, - // 获得消息分页数据 - getKeFuMessagePage: async (params: any) => { - return await request.get({ url: '/promotion/kefu-message/page', params }) + // 获得消息列表(流式加载) + getKeFuMessageList: async (params: any) => { + return await request.get({ url: '/promotion/kefu-message/list', params }) } } diff --git a/src/store/modules/mall/kefu.ts b/src/store/modules/mall/kefu.ts new file mode 100644 index 00000000..2aecee0d --- /dev/null +++ b/src/store/modules/mall/kefu.ts @@ -0,0 +1,81 @@ +import { store } from '@/store' +import { defineStore } from 'pinia' +import { KeFuConversationApi, KeFuConversationRespVO } from '@/api/mall/promotion/kefu/conversation' +import { KeFuMessageRespVO } from '@/api/mall/promotion/kefu/message' +import { isEmpty } from '@/utils/is' + +interface MallKefuInfoVO { + conversationList: KeFuConversationRespVO[] // 会话列表 + conversationMessageList: Map // 会话消息 +} + +export const useMallKefuStore = defineStore('mall-kefu', { + state: (): MallKefuInfoVO => ({ + conversationList: [], + conversationMessageList: new Map() // key 会话,value 会话消息列表 + }), + getters: { + getConversationList(): KeFuConversationRespVO[] { + return this.conversationList + }, + getConversationMessageList(): (conversationId: number) => KeFuMessageRespVO[] | undefined { + return (conversationId: number) => this.conversationMessageList.get(conversationId) + } + }, + actions: { + // ======================= 会话消息相关 ======================= + /** 缓存历史消息 */ + saveMessageList(conversationId: number, messageList: KeFuMessageRespVO[]) { + this.conversationMessageList.set(conversationId, messageList) + }, + + // ======================= 会话相关 ======================= + /** 加载会话缓存列表 */ + async setConversationList() { + this.conversationList = await KeFuConversationApi.getConversationList() + this.conversationSort() + }, + /** 更新会话缓存已读 */ + async updateConversationStatus(conversationId: number) { + if (isEmpty(this.conversationList)) { + return + } + const conversation = this.conversationList.find((item) => item.id === conversationId) + conversation && (conversation.adminUnreadMessageCount = 0) + }, + /** 更新会话缓存 */ + async updateConversation(conversationId: number) { + if (isEmpty(this.conversationList)) { + return + } + + const conversation = await KeFuConversationApi.getConversation(conversationId) + this.deleteConversation(conversationId) + conversation && this.conversationList.push(conversation) + this.conversationSort() + }, + /** 删除会话缓存 */ + deleteConversation(conversationId: number) { + const index = this.conversationList.findIndex((item) => item.id === conversationId) + // 存在则删除 + if (index > -1) { + this.conversationList.splice(index, 1) + } + }, + conversationSort() { + // 按置顶属性和最后消息时间排序 + this.conversationList.sort((a, b) => { + // 按照置顶排序,置顶的会在前面 + if (a.adminPinned !== b.adminPinned) { + return a.adminPinned ? -1 : 1 + } + // 按照最后消息时间排序,最近的会在前面 + return (b.lastMessageTime as unknown as number) - (a.lastMessageTime as unknown as number) + }) + } + } +}) + +export const useMallKefuStoreWithOut = () => { + return useMallKefuStore(store) +} diff --git a/src/views/mall/product/spu/form/SkuForm.vue b/src/views/mall/product/spu/form/SkuForm.vue index eb8a7f4b..18cd0296 100644 --- a/src/views/mall/product/spu/form/SkuForm.vue +++ b/src/views/mall/product/spu/form/SkuForm.vue @@ -8,7 +8,7 @@ :rules="rules" label-width="120px" > - + 单独设置 - + 单规格 多规格 diff --git a/src/views/mall/promotion/components/SpuSelect.vue b/src/views/mall/promotion/components/SpuSelect.vue index fd7dffe0..648a8635 100644 --- a/src/views/mall/promotion/components/SpuSelect.vue +++ b/src/views/mall/promotion/components/SpuSelect.vue @@ -115,7 +115,7 @@ import { getPropertyList, PropertyAndValues, SkuList } from '@/views/mall/produc import { ElTable } from 'element-plus' import { dateFormatter } from '@/utils/formatTime' import { createImageViewer } from '@/components/ImageViewer' -import { formatToFraction } from '@/utils' +import { floatToFixed2, formatToFraction } from '@/utils' import { defaultProps, handleTree } from '@/utils/tree' import * as ProductCategoryApi from '@/api/mall/product/category' @@ -228,6 +228,13 @@ const expandChange = async (row: ProductSpuApi.Spu, expandedRows?: ProductSpuApi } // 获取 SPU 详情 const res = (await ProductSpuApi.getSpu(row.id as number)) as ProductSpuApi.Spu + res.skus?.forEach((item) => { + item.price = floatToFixed2(item.price) + item.marketPrice = floatToFixed2(item.marketPrice) + item.costPrice = floatToFixed2(item.costPrice) + item.firstBrokeragePrice = floatToFixed2(item.firstBrokeragePrice) + item.secondBrokeragePrice = floatToFixed2(item.secondBrokeragePrice) + }) propertyList.value = getPropertyList(res) spuData.value = res isExpand.value = true diff --git a/src/views/mall/promotion/kefu/components/KeFuConversationList.vue b/src/views/mall/promotion/kefu/components/KeFuConversationList.vue index 6e011231..075edc33 100644 --- a/src/views/mall/promotion/kefu/components/KeFuConversationList.vue +++ b/src/views/mall/promotion/kefu/components/KeFuConversationList.vue @@ -1,10 +1,13 @@ diff --git a/src/views/mall/promotion/kefu/components/history/MemberBrowsingHistory.vue b/src/views/mall/promotion/kefu/components/history/MemberBrowsingHistory.vue deleted file mode 100644 index 52c1095b..00000000 --- a/src/views/mall/promotion/kefu/components/history/MemberBrowsingHistory.vue +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - diff --git a/src/views/mall/promotion/kefu/components/index.ts b/src/views/mall/promotion/kefu/components/index.ts index 585d0da7..0f60a6e4 100644 --- a/src/views/mall/promotion/kefu/components/index.ts +++ b/src/views/mall/promotion/kefu/components/index.ts @@ -1,5 +1,5 @@ import KeFuConversationList from './KeFuConversationList.vue' import KeFuMessageList from './KeFuMessageList.vue' -import MemberBrowsingHistory from './history/MemberBrowsingHistory.vue' +import MemberInfo from './member/MemberInfo.vue' -export { KeFuConversationList, KeFuMessageList, MemberBrowsingHistory } +export { KeFuConversationList, KeFuMessageList, MemberInfo } diff --git a/src/views/mall/promotion/kefu/components/member/MemberInfo.vue b/src/views/mall/promotion/kefu/components/member/MemberInfo.vue new file mode 100644 index 00000000..849992b3 --- /dev/null +++ b/src/views/mall/promotion/kefu/components/member/MemberInfo.vue @@ -0,0 +1,252 @@ + + + + + + diff --git a/src/views/mall/promotion/kefu/components/history/OrderBrowsingHistory.vue b/src/views/mall/promotion/kefu/components/member/OrderBrowsingHistory.vue similarity index 100% rename from src/views/mall/promotion/kefu/components/history/OrderBrowsingHistory.vue rename to src/views/mall/promotion/kefu/components/member/OrderBrowsingHistory.vue diff --git a/src/views/mall/promotion/kefu/components/history/ProductBrowsingHistory.vue b/src/views/mall/promotion/kefu/components/member/ProductBrowsingHistory.vue similarity index 95% rename from src/views/mall/promotion/kefu/components/history/ProductBrowsingHistory.vue rename to src/views/mall/promotion/kefu/components/member/ProductBrowsingHistory.vue index 8bc4aeaf..a9b38561 100644 --- a/src/views/mall/promotion/kefu/components/history/ProductBrowsingHistory.vue +++ b/src/views/mall/promotion/kefu/components/member/ProductBrowsingHistory.vue @@ -1,15 +1,14 @@ diff --git a/src/views/mall/promotion/kefu/components/message/OrderItem.vue b/src/views/mall/promotion/kefu/components/message/OrderItem.vue index c50d7c5d..9385f10b 100644 --- a/src/views/mall/promotion/kefu/components/message/OrderItem.vue +++ b/src/views/mall/promotion/kefu/components/message/OrderItem.vue @@ -14,11 +14,11 @@
@@ -112,14 +112,14 @@ function formatOrderStatus(order: any) { border-radius: 10px; padding: 10px; border: 1px var(--el-border-color) solid; - background-color: var(--app-content-bg-color); + background-color: #fff; // 透明色,暗黑模式下也能体现 .order-card-header { height: 28px; + font-weight: bold; .order-no { - font-size: 12px; - font-weight: 500; + font-size: 13px; span { &:hover { @@ -128,27 +128,29 @@ function formatOrderStatus(order: any) { } } } + + .order-state { + font-size: 13px; + } } .pay-box { padding-top: 10px; + font-weight: bold; .discounts-title { font-size: 16px; line-height: normal; - color: #999999; } .discounts-money { font-size: 16px; line-height: normal; - color: #999; font-family: OPPOSANS; } .pay-color { font-size: 13px; - color: var(--left-menu-text-color); } } } diff --git a/src/views/mall/promotion/kefu/components/message/ProductItem.vue b/src/views/mall/promotion/kefu/components/message/ProductItem.vue index 4e59365b..bc6cd979 100644 --- a/src/views/mall/promotion/kefu/components/message/ProductItem.vue +++ b/src/views/mall/promotion/kefu/components/message/ProductItem.vue @@ -1,51 +1,27 @@ - -