diff --git a/.env.local b/.env.local index 005d2f0d..71530cc6 100644 --- a/.env.local +++ b/.env.local @@ -29,5 +29,8 @@ VITE_BASE_PATH=/ # 商城H5会员端域名 VITE_MALL_H5_DOMAIN='http://localhost:3000' +# 客户端静态资源地址 空=默认使用服务端指定的CDN资源地址前缀 | local=本地 | http(s)://xxx.xxx=自定义静态资源地址前缀 +VITE_STATIC_URL = https://file.sheepjs.com + # 验证码的开关 VITE_APP_CAPTCHA_ENABLE=false diff --git a/src/api/mall/promotion/kefu/conversation/index.ts b/src/api/mall/promotion/kefu/conversation/index.ts new file mode 100644 index 00000000..17432b35 --- /dev/null +++ b/src/api/mall/promotion/kefu/conversation/index.ts @@ -0,0 +1,71 @@ +import request from '@/config/axios' + +export interface KeFuConversationRespVO { + /** + * 编号 + */ + id: number + /** + * 会话所属用户 + */ + userId: number + /** + * 会话所属用户头像 + */ + userAvatar: string + /** + * 会话所属用户昵称 + */ + nickname: string + /** + * 最后聊天时间 + */ + lastMessageTime: Date + /** + * 最后聊天内容 + */ + lastMessageContent: string + /** + * 最后发送的消息类型 + */ + lastMessageContentType: number + /** + * 管理端置顶 + */ + adminPinned: boolean + /** + * 用户是否可见 + */ + userDeleted: boolean + /** + * 管理员是否可见 + */ + adminDeleted: boolean + /** + * 管理员未读消息数 + */ + adminUnreadMessageCount: number + /** + * 创建时间 + */ + createTime?: string +} + +// 客服会话 API +export const KeFuConversationApi = { + // 获得客服会话列表 + getConversationList: async () => { + return await request.get({ url: '/promotion/kefu-conversation/list' }) + }, + // 客服会话置顶 + updateConversationPinned: async (data: any) => { + return await request.put({ + url: '/promotion/kefu-conversation/update-conversation-pinned', + data + }) + }, + // 删除客服会话 + deleteConversation: async (id: number) => { + return await request.get({ url: '/promotion/kefu-conversation/delete?id' + id }) + } +} diff --git a/src/views/infra/webSocket/index.vue b/src/views/infra/webSocket/index.vue index 0f0e351f..300f6d92 100644 --- a/src/views/infra/webSocket/index.vue +++ b/src/views/infra/webSocket/index.vue @@ -29,8 +29,8 @@ :autosize="{ minRows: 2, maxRows: 4 }" :disabled="!getIsOpen" clearable - type="textarea" placeholder="请输入你要发送的消息" + type="textarea" /> @@ -71,7 +71,7 @@ + + diff --git a/src/views/mall/promotion/kefu/components/KefuChatBox.vue b/src/views/mall/promotion/kefu/components/KefuChatBox.vue new file mode 100644 index 00000000..394c8424 --- /dev/null +++ b/src/views/mall/promotion/kefu/components/KefuChatBox.vue @@ -0,0 +1,77 @@ + + + + + diff --git a/src/views/mall/promotion/kefu/components/constants.ts b/src/views/mall/promotion/kefu/components/constants.ts new file mode 100644 index 00000000..015b46a7 --- /dev/null +++ b/src/views/mall/promotion/kefu/components/constants.ts @@ -0,0 +1,14 @@ +export const KeFuMessageContentTypeEnum = { + TEXT: 1, // 文本消息 + IMAGE: 2, // 图片消息 + VOICE: 3, // 语音消息 + VIDEO: 4, // 视频消息 + SYSTEM: 5, // 系统消息 + // ========== 商城特殊消息 ========== + PRODUCT: 10, // 商品消息 + ORDER: 11 // 订单消息" +} +export const UserTypeEnum = { + MEMBER: 1, // 会员 面向 c 端,普通用户 + ADMIN: 2 // 管理员 面向 b 端,管理后台 +} diff --git a/src/views/mall/promotion/kefu/components/emoji.ts b/src/views/mall/promotion/kefu/components/emoji.ts new file mode 100644 index 00000000..6ccd0cff --- /dev/null +++ b/src/views/mall/promotion/kefu/components/emoji.ts @@ -0,0 +1,91 @@ +export const emojiList = [ + { name: '[笑掉牙]', file: 'xiaodiaoya.png' }, + { name: '[可爱]', file: 'keai.png' }, + { name: '[冷酷]', file: 'lengku.png' }, + { name: '[闭嘴]', file: 'bizui.png' }, + { name: '[生气]', file: 'shengqi.png' }, + { name: '[惊恐]', file: 'jingkong.png' }, + { name: '[瞌睡]', file: 'keshui.png' }, + { name: '[大笑]', file: 'daxiao.png' }, + { name: '[爱心]', file: 'aixin.png' }, + { name: '[坏笑]', file: 'huaixiao.png' }, + { name: '[飞吻]', file: 'feiwen.png' }, + { name: '[疑问]', file: 'yiwen.png' }, + { name: '[开心]', file: 'kaixin.png' }, + { name: '[发呆]', file: 'fadai.png' }, + { name: '[流泪]', file: 'liulei.png' }, + { name: '[汗颜]', file: 'hanyan.png' }, + { name: '[惊悚]', file: 'jingshu.png' }, + { name: '[困~]', file: 'kun.png' }, + { name: '[心碎]', file: 'xinsui.png' }, + { name: '[天使]', file: 'tianshi.png' }, + { name: '[晕]', file: 'yun.png' }, + { name: '[啊]', file: 'a.png' }, + { name: '[愤怒]', file: 'fennu.png' }, + { name: '[睡着]', file: 'shuizhuo.png' }, + { name: '[面无表情]', file: 'mianwubiaoqing.png' }, + { name: '[难过]', file: 'nanguo.png' }, + { name: '[犯困]', file: 'fankun.png' }, + { name: '[好吃]', file: 'haochi.png' }, + { name: '[呕吐]', file: 'outu.png' }, + { name: '[龇牙]', file: 'ziya.png' }, + { name: '[懵比]', file: 'mengbi.png' }, + { name: '[白眼]', file: 'baiyan.png' }, + { name: '[饿死]', file: 'esi.png' }, + { name: '[凶]', file: 'xiong.png' }, + { name: '[感冒]', file: 'ganmao.png' }, + { name: '[流汗]', file: 'liuhan.png' }, + { name: '[笑哭]', file: 'xiaoku.png' }, + { name: '[流口水]', file: 'liukoushui.png' }, + { name: '[尴尬]', file: 'ganga.png' }, + { name: '[惊讶]', file: 'jingya.png' }, + { name: '[大惊]', file: 'dajing.png' }, + { name: '[不好意思]', file: 'buhaoyisi.png' }, + { name: '[大闹]', file: 'danao.png' }, + { name: '[不可思议]', file: 'bukesiyi.png' }, + { name: '[爱你]', file: 'aini.png' }, + { name: '[红心]', file: 'hongxin.png' }, + { name: '[点赞]', file: 'dianzan.png' }, + { name: '[恶魔]', file: 'emo.png' } +] + +export const emojiPage = {} +emojiList.forEach((item, index) => { + if (!emojiPage[Math.floor(index / 30) + 1]) { + emojiPage[Math.floor(index / 30) + 1] = [] + } + emojiPage[Math.floor(index / 30) + 1].push(item) +}) + +// 后端上传地址 +const staticUrl = import.meta.env.VITE_STATIC_URL + +// 处理表情 +export function replaceEmoji(data: string) { + let newData = data + if (typeof newData !== 'object') { + const reg = /\[(.+?)\]/g // [] 中括号 + const zhEmojiName = newData.match(reg) + if (zhEmojiName) { + zhEmojiName.forEach((item) => { + const emojiFile = selEmojiFile(item) + newData = newData.replace( + item, + `` + ) + }) + } + } + return newData +} + +function selEmojiFile(name: string) { + for (const index in emojiList) { + if (emojiList[index].name === name) { + return emojiList[index].file + } + } + return false +} diff --git a/src/views/mall/promotion/kefu/components/index.ts b/src/views/mall/promotion/kefu/components/index.ts new file mode 100644 index 00000000..afd2fd76 --- /dev/null +++ b/src/views/mall/promotion/kefu/components/index.ts @@ -0,0 +1,5 @@ +import KeFuConversationBox from './KeFuConversationBox.vue' +import KeFuChatBox from './KefuChatBox.vue' +import * as Constants from './constants' + +export { KeFuConversationBox, KeFuChatBox, Constants } diff --git a/src/views/mall/promotion/kefu/index.vue b/src/views/mall/promotion/kefu/index.vue new file mode 100644 index 00000000..52c6f2ba --- /dev/null +++ b/src/views/mall/promotion/kefu/index.vue @@ -0,0 +1,55 @@ + + + + + diff --git a/types/env.d.ts b/types/env.d.ts index 057b5268..63d9c3ee 100644 --- a/types/env.d.ts +++ b/types/env.d.ts @@ -19,6 +19,7 @@ interface ImportMetaEnv { readonly VITE_UPLOAD_URL: string readonly VITE_API_URL: string readonly VITE_BASE_PATH: string + readonly VITE_STATIC_URL: string readonly VITE_DROP_DEBUGGER: string readonly VITE_DROP_CONSOLE: string readonly VITE_SOURCEMAP: string