提交 9829b6de 作者: Hao

添加拼团抢购

父级 f2f9a1e6
...@@ -4,5 +4,5 @@ ...@@ -4,5 +4,5 @@
// Generated by unplugin-auto-import // Generated by unplugin-auto-import
export {} export {}
declare global { declare global {
const ElMessage: typeof import('element-plus/es')['ElMessage']
} }
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
"cos-wx-sdk-v5": "^1.6.0", "cos-wx-sdk-v5": "^1.6.0",
"element-plus": "^2.6.1", "element-plus": "^2.6.1",
"emoji.json": "^15.1.0", "emoji.json": "^15.1.0",
"html-webpack-plugin": "^5.6.0",
"mockjs": "^1.1.0", "mockjs": "^1.1.0",
"moment": "^2.30.1", "moment": "^2.30.1",
"pinia": "^2.1.7", "pinia": "^2.1.7",
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0"> <meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico"> <link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title> <title>客服端</title>
</head> </head>
<body> <body>
<noscript> <noscript>
......
// axios.js // axios.js
import axios from "axios"; import axios from "axios";
const instance = axios.create({ const instance = axios.create({
baseURL: "/api", // 设置基础 URL // baseURL: "http://192.168.31.228:8080", // 设置基础 URL
baseURL:'',
timeout: 1000, // 设置请求超时时间 timeout: 1000, // 设置请求超时时间
}); });
...@@ -10,7 +11,7 @@ instance.interceptors.request.use( ...@@ -10,7 +11,7 @@ instance.interceptors.request.use(
// 在发送请求之前做些什么,例如添加 token // 在发送请求之前做些什么,例如添加 token
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
if (token) { if (token) {
config.headers.Authorization = `Bearer ${token}`; config.headers['X-Access-Token'] = `Bearer ${token}`;
} }
return config; return config;
}, },
...@@ -29,5 +30,4 @@ instance.interceptors.response.use( ...@@ -29,5 +30,4 @@ instance.interceptors.response.use(
return Promise.reject(error); return Promise.reject(error);
} }
); );
export default instance; export default instance;
...@@ -2,10 +2,11 @@ import http from "../index"; ...@@ -2,10 +2,11 @@ import http from "../index";
//登录 //登录
const Login = (query: any) => { const Login = (query: any) => {
return http({ return http({
url: `/login`, url: `/kf/auth/login`,
method: "get", method: "post",
data: query, data: query,
}); });
}; };
//新增询价单 //新增询价单
const InquiryAdd = (query: any) => { const InquiryAdd = (query: any) => {
...@@ -56,6 +57,14 @@ const upload = (query: any) => { ...@@ -56,6 +57,14 @@ const upload = (query: any) => {
data: query, data: query,
}); });
}; };
//删除
const deleteUserList = (query: any) => {
return http({
url: `/deleteUserList`,
method: "delete",
params:query
});
};
export { export {
Login, Login,
InquiryAdd, InquiryAdd,
...@@ -64,4 +73,5 @@ export { ...@@ -64,4 +73,5 @@ export {
checkMesssages, checkMesssages,
upload, upload,
getUploadConfigInfo, getUploadConfigInfo,
deleteUserList
}; };
...@@ -31,24 +31,18 @@ ...@@ -31,24 +31,18 @@
快捷回复 快捷回复
</div> </div>
</div> </div>
<!-- <el-autocomplete <div
class="autocomplete" class="el-autocomplete textarea"
v-model="state" id="el-autocomplete"
:fetch-suggestions="querySearchAsync" ref="elAutocomplete"
placeholder="请输入问题"
type="textarg"
@select="handleSelect"
ref="automaticPromptRef"
/> -->
<el-input
v-model="state"
ref="automaticPromptRef"
class="el-autocomplete"
placeholder="输入信息" placeholder="输入信息"
type="textarea" contenteditable="true"
resize="none" style="outline: none; height: 150px;"
@change="handleSelect" @paste.prevent="handlePaste"
/> @focus="removeDefaultContent"
@input="handleSelect"
@blur="addDefaultContent"
></div>
</div> </div>
<emotion <emotion
...@@ -73,30 +67,27 @@ import { ElLoading } from 'element-plus' ...@@ -73,30 +67,27 @@ import { ElLoading } from 'element-plus'
import { ref, watch, defineEmits, defineExpose } from 'vue' import { ref, watch, defineEmits, defineExpose } from 'vue'
import { upLoadFilesHander } from '../minxins/UploadMixin' import { upLoadFilesHander } from '../minxins/UploadMixin'
import axios from 'axios' import axios from 'axios'
const state = ref('') const inputVal = ref('')
const elAutocomplete = ref(null)
const file = ref(null) const file = ref(null)
interface LinkItem { const imgShowWidth = ref<number>(50)
value: string const imgShowHeight = ref<number>(50)
link: string
}
// uploadMixin()
const showEmotion = ref<boolean>(false) const showEmotion = ref<boolean>(false)
const automaticPromptRef = ref(null)
const links = ref<LinkItem[]>([])
const handleEmotion = (i) => { const handleEmotion = (i) => {
state.value += i elAutocomplete.value.innerHTML += i
inputVal.value = elAutocomplete.value.innerHTML
showEmotion.value = false showEmotion.value = false
automaticPromptRef.value.focus() elAutocomplete.value.focus()
} }
const upfile = () => { const upfile = () => {
file.value.click() file.value.click()
} }
//上传的数据
const fileChange = () => { const fileChange = () => {
var e = window.event || event var e = window.event || event
var oFile = e.target.files[0] var oFile = e.target.files[0]
upLoadFilesHander(oFile).then((ress) => { upLoadFilesHander(oFile).then((ress) => {
const { success, result } = ress const { success, result } = ress
console.log(result)
}) })
const loading = ElLoading.service({ const loading = ElLoading.service({
lock: true, lock: true,
...@@ -105,53 +96,145 @@ const fileChange = () => { ...@@ -105,53 +96,145 @@ const fileChange = () => {
}) })
loading.close() loading.close()
} }
const showWord = () => {
console.log(3)
}
// const loadFromBackend = async (value: string) => {
// try {
// //输入时候请求后端根据输入值得到提示。 后端返回集合,集合里面对象属性为value和link都是string类型
// const response = await axios.get(
// `http://localhost:8080/getAutoMsg/${value}`,
// )
// links.value = response.data
// } catch (error) {
// console.error(error)
// }
// }
const querySearchAsync = (queryString: string, cb: (arg: any) => void) => {
const results = queryString
? links.value.filter(createFilter(queryString))
: links.value
cb(results)
}
const createFilter = (queryString: string) => {
return (link: LinkItem) => {
return link.value.toLowerCase().indexOf(queryString.toLowerCase()) === 0
}
}
const handleSelect = (value: string) => { const handleSelect = (value: string) => {
console.log(value) inputVal.value = value.target.innerHTML
} }
const emit = defineEmits(['updateState']) const emit = defineEmits(['updateState'])
watch(state, async (newValue) => { watch(inputVal, async (newValue) => {
if (!newValue) elAutocomplete.value.innerHTML = ''
emit('updateState', newValue) emit('updateState', newValue)
}) })
// 去文本粘贴
const handlePaste = async (event) => {
event.preventDefault()
const pasteResult = handlePastePlainText(event.clipboardData)
if (pasteResult) return
await handlePasteImageFile(event.clipboardData)
}
// 去格式粘贴 文本
const handlePastePlainText = (clipboardData) => {
const text = clipboardData.getData('text/plain')
if (text) {
const textNode = document.createTextNode(text)
cursorInsert(textNode)
return true
}
return false
}
//改变光标位置
const cursorInsert = (node) => {
// 获取光标范围
const selObj = window.getSelection()
const range = selObj.getRangeAt(0)
// 光标处插入节点
range.insertNode(node)
// 取消insert node 后的选中状态,将光标恢复到 insert node 后面
range.collapse(false)
inputVal.value = elAutocomplete.value.innerHTML
}
//粘贴图片
const handlePasteImageFile = async (clipboardData) => {
const img = getPasteImageFile(clipboardData.files)
if (!img) {
return
}
const uploadRes = await fileToBase64(img)
if (!uploadRes) {
return
}
const oImage = await getImageObject(
uploadRes,
imgShowWidth.value,
imgShowHeight.value,
)
cursorInsert(oImage)
inputVal.value = elAutocomplete.value.innerHTML
}
// 获取一个 image object
const getImageObject = (uploadRes, showWidth, showHeight) => {
const oImage = new Image(showWidth, showHeight)
const datasetFields = ['width', 'height']
const datasetSizes = {
width: '200',
height: '200',
}
datasetFields.forEach((field) => {
oImage.setAttribute(`data-${field}`, datasetSizes[field])
})
oImage.src = uploadRes
return oImage
}
const getPasteImageFile = (clipboardDataFiles) => {
if (!clipboardDataFiles.length) {
return null
}
// 剪切版中选择的(用户第一个点的在尾)第一张图片
const clipboardDataFileList = Array.from(clipboardDataFiles || [])
let firstSelectedImage = null
clipboardDataFileList.forEach((file) => {
if (!file.type.match(/image\//i)) {
return
}
firstSelectedImage = file
})
return firstSelectedImage
}
//将文件流转base64
const fileToBase64 = function (file) {
return new Promise((resolve, reject) => {
const reader = new FileReader()
reader.onload = (event) => {
resolve(event.target.result)
}
reader.onerror = (error) => {
reject(error)
}
reader.readAsDataURL(file)
})
}
const removeDefaultContent = function (event) {
elAutocomplete.value.classList.remove('textarea')
cursorIn()
}
const addDefaultContent = function (event) {
if (!event.target.innerHTML && event.target.innerText.length == 0) {
elAutocomplete.value.classList.add('textarea')
}
}
const cursorIn = function () {
var divElement = document.querySelector('div[contenteditable="true"]')
var range = document.createRange()
range.selectNodeContents(divElement)
range.collapse(false)
var selection = window.getSelection()
selection.removeAllRanges()
selection.addRange(range)
}
defineExpose({ defineExpose({
setState(res: any) { setState(res: any) {
state.value = res inputVal.value = res
}, },
getState() { getState() {
return state.value return inputVal.value
}, },
}) })
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.textarea {
&:after {
content: attr(placeholder);
display: inline-block;
color: #999;
font-size: 13px;
vertical-align: middle;
line-height: 16px;
}
}
.icon { .icon {
width: 24px; width: 24px;
height: 24px; height: 24px;
...@@ -165,17 +248,13 @@ defineExpose({ ...@@ -165,17 +248,13 @@ defineExpose({
} }
.el-autocomplete { .el-autocomplete {
width: 100%; width: 100%;
height: 100%; max-width: 100%;
.el-input { max-height: 150px;
width: 100%; overflow: auto;
} }
:deep(.el-textarea__inner) { .el-autocomplete img {
width: 100%; max-width: 100%; /* 设置图片最大宽度为容器宽度 */
align-items: start; max-height: 100%; /* 设置图片最大高度为容器高度 */
box-shadow: none;
padding: 0px;
background: transparent;
}
} }
.chat-bar-right { .chat-bar-right {
font-family: 'PingFang SC'; font-family: 'PingFang SC';
......
...@@ -4,21 +4,13 @@ import router from "./router"; ...@@ -4,21 +4,13 @@ import router from "./router";
import store from "./store/index"; import store from "./store/index";
import "./assets/css/reset.css"; import "./assets/css/reset.css";
import * as ElementPlusIconsVue from "@element-plus/icons-vue"; import * as ElementPlusIconsVue from "@element-plus/icons-vue";
import { initWebSocket } from "../src/utils/websocket";
import { useUserStore } from "./store/modules/user"; import { useUserStore } from "./store/modules/user";
import 'element-plus/dist/index.css' import "@/permission"; // permission control
import "element-plus/dist/index.css";
import "../src/mocks/mock"; import "../src/mocks/mock";
const app = createApp(App); const app = createApp(App);
app.use(store).use(router).mount("#app"); app.use(store).use(router).mount("#app");
for (const [key, component] of Object.entries(ElementPlusIconsVue)) { for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component); app.component(key, component);
} }
const connectMsg = () => {
const useUser = useUserStore();
const toIp = `ws://192.168.31.228:8888?username=admin&password=123`;
console.log(useUser.isConnected, "store");
useUser.connect();
initWebSocket(toIp);
};
connectMsg();
const Mock = require('mockjs') const Mock = require('mockjs')
Mock.mock("/api/login", "get", () => { Mock.mock("/kf/auth/login", "post", () => {
return { return {
code: "200", code: "200",
success: true, success: true,
message: '', message: '',
result: { result: {
userName: "admin", username: "admin",
token: 'admin' token: 'admin'
}, },
}; };
...@@ -17,7 +17,7 @@ Mock.mock("/api/inquiryAdd", "get", () => { ...@@ -17,7 +17,7 @@ Mock.mock("/api/inquiryAdd", "get", () => {
success: true, success: true,
message: '操作成功!', message: '操作成功!',
result: { result: {
userName: "admin", username: "admin",
token: 'admin' token: 'admin'
}, },
}; };
...@@ -49,12 +49,12 @@ Mock.mock("/api/getUserList", 'get', () => { ...@@ -49,12 +49,12 @@ Mock.mock("/api/getUserList", 'get', () => {
message: '', message: '',
result: [{ result: [{
userId: '11fb824c0deb4e8b947275e1e7c4f7a2', userId: '11fb824c0deb4e8b947275e1e7c4f7a2',
userName: '1710323861524', username: '1710323861524',
userImg: 'https://cdn.lirimall.com//lirigo/filetempImage/新鲜水果_1661668973048.png', userImg: 'https://cdn.lirimall.com//lirigo/filetempImage/新鲜水果_1661668973048.png',
messages: [] messages: []
}, { }, {
userId: '4f99b6dc32d84a288d88e7d9635521a3', userId: '4f99b6dc32d84a288d88e7d9635521a3',
userName: '1710317951930', username: '1710317951930',
userImg: 'https://cdn.lirimall.com//lirigo/filetempImage/新鲜水果_1661668973048.png', userImg: 'https://cdn.lirimall.com//lirigo/filetempImage/新鲜水果_1661668973048.png',
messages: [] messages: []
}] }]
...@@ -110,4 +110,14 @@ Mock.mock("/api/upload", 'get', () => { ...@@ -110,4 +110,14 @@ Mock.mock("/api/upload", 'get', () => {
}, },
}, },
} }
})
Mock.mock("/deleteUserList",'delete',(req)=>{
console.log(req)
const id = Mock.mock.env.url.match(/\/(\d+)/)[1];
return {
code: '200',
success: true,
message: '删除成功!',
result: null,
}
}) })
\ No newline at end of file
//路由守卫.ts
import router from "../src/router";
import { useUserStore } from "./store/modules/user";
router.beforeEach((to: any, from: any, next: any) => {
const store = useUserStore();
const whiteList = ["/login", "/register"];
if (store.userInfo.token) {
next();
} else {
if (whiteList.includes(to.path)) {
//白名单登录
next();
} else {
next("/login");
}
}
});
import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router"; import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router";
import HomeView from "../views/HomeView.vue"; import HomeView from "../views/HomeView.vue";
const routes: Array<RouteRecordRaw> = [ const routes: Array<RouteRecordRaw> = [
{ {
path: "/", path: "/",
......
...@@ -2,5 +2,6 @@ import { createPinia } from "pinia"; ...@@ -2,5 +2,6 @@ import { createPinia } from "pinia";
// 创建 Pinia 实例 // 创建 Pinia 实例
import piniaPluginPersistedstate from "pinia-plugin-persistedstate"; import piniaPluginPersistedstate from "pinia-plugin-persistedstate";
const pinia = createPinia(); const pinia = createPinia();
console.log(piniaPluginPersistedstate,'打印')
pinia.use(piniaPluginPersistedstate); pinia.use(piniaPluginPersistedstate);
export default pinia; export default pinia;
...@@ -8,7 +8,9 @@ export const useUserStore = defineStore("user", { ...@@ -8,7 +8,9 @@ export const useUserStore = defineStore("user", {
customerInfo: {}, customerInfo: {},
count: 0, count: 0,
userInfo: { userInfo: {
userName: "admin", username: "admin",
password:"",
token:""
}, },
userList: [], userList: [],
}; };
...@@ -24,42 +26,39 @@ export const useUserStore = defineStore("user", { ...@@ -24,42 +26,39 @@ export const useUserStore = defineStore("user", {
this.userInfo = res; this.userInfo = res;
}, },
setUserList(res: any) { setUserList(res: any) {
console.log(res,'数据呢')
this.userList = res; this.userList = res;
}, },
setUserListMessages(res: any) { setUserListMessages(res: any) {
console.log(res)
const userList: any = this.userList || []; const userList: any = this.userList || [];
// res.from = res.from.replace('游客','')
const obj = { const obj = {
...res,
isSent: false, isSent: false,
msgType: res.msgType,
content: res.content,
cmd: res.cmd,
to: res.to,
id: res.id,
form: res.from,
userImg: userImg:
"https://cdn.lirimall.com//lirigo/filetempImage/新鲜水果_1661668973048.png", "https://cdn.lirimall.com//lirigo/filetempImage/新鲜水果_1661668973048.png",
time: moment(res.createTime).format("YYYY-DD-MM HH:mm:ss"), time: moment(res.createTime).format("YYYY-DD-MM HH:mm:ss"),
}; };
const info = { const info = {
userId: res.id, userId: res.id,
userName: res.from, username: res.from,
messages: [obj], messages: [obj],
userImg: obj.userImg, userImg: obj.userImg,
}; };
if ( if (
userList.length > 0 && userList.length > 0 &&
userList.some((item: any) => item.userName == res.from) userList.some((item: any) => item.username == res.from)
) { ) {
userList.forEach((item: any) => { userList.forEach((item: any) => {
if (item.userName == res.from) item.messages.push(obj); if (item.username == res.from) item.messages.push(obj);
}); });
} else { } else {
userList.push(info); userList.push(info);
} }
this.userList = userList; this.userList = userList;
}, },
setUserNameMessage(res: any) { setusernameMessage(res: any) {
const friends = res.friends; const friends = res.friends;
for (const key in friends) { for (const key in friends) {
const chatDatas = friends[key]; const chatDatas = friends[key];
...@@ -71,7 +70,7 @@ export const useUserStore = defineStore("user", { ...@@ -71,7 +70,7 @@ export const useUserStore = defineStore("user", {
for (const index in chatDatas) { for (const index in chatDatas) {
const userId = chatDatas[index].from; const userId = chatDatas[index].from;
this.userList.forEach((item: any) => { this.userList.forEach((item: any) => {
if (item && item?.userName == userId) { if (item && item?.username == userId) {
item.messages = chatDatas; item.messages = chatDatas;
} }
}); });
......
export interface LoginFace { export interface LoginFace {
userName: string; username: string;
passWord: string; password: string;
} }
export class LoginData<LoginFace> { export class LoginData<LoginFace> {
userName = "admin"; username = "10086";
passWord = "123456"; password = "123456";
} }
...@@ -64,14 +64,14 @@ function websocketOpen() { ...@@ -64,14 +64,14 @@ function websocketOpen() {
} }
// 数据接收 // 数据接收
function websocketonmessage(e: MessageEvent<any>) { function websocketonmessage(e: MessageEvent<any>) {
console.log('接受数据',e.data)
const res = JSON.parse(e.data); // 解析JSON格式的数据 const res = JSON.parse(e.data); // 解析JSON格式的数据
console.log(res, "发送一次");
// 下面的判断则是后台返回的接收到的数据 如何处理自己决定 // 下面的判断则是后台返回的接收到的数据 如何处理自己决定
if (res.command == 11) { if (res.command == 11) {
//将数据放在store中 //将数据放在store中
useUserStore().setUserListMessages(res.data); useUserStore().setUserListMessages(res.data);
} else if (res.command == 20) { } else if (res.command == 20) {
useUserStore().setUserNameMessage(res.data); useUserStore().setusernameMessage(res.data);
} }
} }
......
...@@ -25,9 +25,9 @@ ...@@ -25,9 +25,9 @@
<div class="user-info-right"> <div class="user-info-right">
<div class="user-box-right-nbs"> <div class="user-box-right-nbs">
<div class="user-name-box"> <div class="user-name-box">
<span class="user-name">{{ item?.userName }}</span> <span class="user-name">{{ item?.username }}</span>
<div class="user-time"> <div class="user-time">
05-19 16:38 {{ item?.time }}
</div> </div>
</div> </div>
<div class="user-reply-box"> <div class="user-reply-box">
...@@ -35,8 +35,8 @@ ...@@ -35,8 +35,8 @@
{{ {{
item?.messages[ item?.messages[
item?.messages.length - 1 item?.messages.length - 1
]?.content.includes('http') ]?.content.includes('img')
? '[图]' ? '[图]'
: item.messages[item.messages.length - 1]?.content : item.messages[item.messages.length - 1]?.content
}} }}
</span> </span>
...@@ -48,9 +48,9 @@ ...@@ -48,9 +48,9 @@
</div> </div>
</div> </div>
</el-aside> </el-aside>
<el-container class="el-container-center" v-if="customerInfo.userName"> <el-container class="el-container-center" v-if="customerInfo.username">
<el-header class="el-header-center"> <el-header class="el-header-center">
<p class="name">{{ customerInfo.userName }}</p> <p class="name">{{ customerInfo.username }}</p>
<p class="url">US|https://www.ibeautytop.com</p> <p class="url">US|https://www.ibeautytop.com</p>
</el-header> </el-header>
<el-main <el-main
...@@ -71,12 +71,10 @@ ...@@ -71,12 +71,10 @@
<div class="time">{{ message.time }}</div> <div class="time">{{ message.time }}</div>
<div v-if="message.isSent" class="message-container"> <div v-if="message.isSent" class="message-container">
<div class="bubble"> <div class="bubble">
<div <div v-if="message?.msgType == 0" class="message">
v-if="message?.msgType == 0" <div class="content" v-html="message?.content"></div>
class="message" <div class="contentFy" v-html="message?.contentFy"></div>
v-html="message?.content" </div>
@click.prevent="handleMessageClick($event)"
></div>
<div v-else class="img-wraper"> <div v-else class="img-wraper">
<el-image <el-image
:src="message?.content" :src="message?.content"
...@@ -97,12 +95,10 @@ ...@@ -97,12 +95,10 @@
<img :src="message?.userImg" class="avatar-image" /> <img :src="message?.userImg" class="avatar-image" />
</div> </div>
<div class="bubble"> <div class="bubble">
<div <div v-if="message?.msgType == 0" class="message">
v-if="message?.msgType == 0" <div class="content" v-html="message?.content"></div>
class="message" <div class="contentFy" v-html="message?.contentFy"></div>
v-html="message?.content" </div>
@click.prevent="handleMessageClick($event)"
></div>
<div v-else class="img-wraper"> <div v-else class="img-wraper">
<el-image <el-image
:src="message?.content" :src="message?.content"
...@@ -254,13 +250,21 @@ import AutomaticPrompt from '../components/AutomaticPrompt.vue' ...@@ -254,13 +250,21 @@ import AutomaticPrompt from '../components/AutomaticPrompt.vue'
import ImageViewer from '@luohc92/vue3-image-viewer' import ImageViewer from '@luohc92/vue3-image-viewer'
import { sendWebSocket } from '../utils/websocket' import { sendWebSocket } from '../utils/websocket'
import type { FormInstance } from 'element-plus' import type { FormInstance } from 'element-plus'
import { initWebSocket } from '../utils/websocket'
import '@luohc92/vue3-image-viewer/dist/style.css' import '@luohc92/vue3-image-viewer/dist/style.css'
import { getUserList, InquiryAdd, checkMesssages } from '../axios/model/user' import { getUserList, InquiryAdd, checkMesssages } from '../axios/model/user'
const ruleForm = ref({ const ruleForm = ref({
count: 1, count: 1,
}) })
const connectMsg = () => {
const useUser = useUserStore()
const toIp = `ws://192.168.31.228:8081?type=kf&code=${useUser.userInfo?.username}`
console.log(toIp)
useUser.connect()
initWebSocket(toIp)
}
connectMsg()
const ruleFormRef = ref<FormInstance>() const ruleFormRef = ref<FormInstance>()
const customerInfo = ref({}) const customerInfo = ref({})
const messages = ref([]) const messages = ref([])
...@@ -321,16 +325,17 @@ let msg = '' ...@@ -321,16 +325,17 @@ let msg = ''
//进入页面直接发送请求从后端获取热点数据 //进入页面直接发送请求从后端获取热点数据
onMounted(async () => { onMounted(async () => {
count.value = store.count count.value = store.count
if (store.userList.length > 0) { // if (store.userList.length > 0) {
userList.value = store.userList // userList.value = store.userList
} else { // } else {
getList() // getList()
} // }
userList.value = store.userList
setMessage() setMessage()
}) })
//设置message //设置message
const setMessage = () => { const setMessage = () => {
if (store.customerInfo.userName) { if (store.customerInfo.username) {
customerInfo.value = store.customerInfo customerInfo.value = store.customerInfo
messages.value = customerInfo.value.messages || [] messages.value = customerInfo.value.messages || []
} }
...@@ -348,7 +353,7 @@ const getList = async () => { ...@@ -348,7 +353,7 @@ const getList = async () => {
}) })
userList.value = list userList.value = list
store.setUserList(list) store.setUserList(list)
if (customerInfo.value.userName) handleMenuClick(customerInfo.value) if (customerInfo.value.username) handleMenuClick(customerInfo.value)
} }
} catch (error) { } catch (error) {
console.log(error) console.log(error)
...@@ -366,10 +371,10 @@ const handleChange = (val: any) => { ...@@ -366,10 +371,10 @@ const handleChange = (val: any) => {
watch( watch(
userList, userList,
(newVal, oldVal) => { (newVal, oldVal) => {
if (newVal && newVal.length > 0 && customerInfo.value.userName) { if (newVal && newVal.length > 0 && customerInfo.value.username) {
const obj = const obj =
newVal.find((item: any) => { newVal.find((item: any) => {
return item.userName == customerInfo.value.userName return item.username == customerInfo.value.username
}) || {} }) || {}
messages.value = obj.messages || [] messages.value = obj.messages || []
} }
...@@ -400,28 +405,37 @@ const handleMenuClick = (item: object) => { ...@@ -400,28 +405,37 @@ const handleMenuClick = (item: object) => {
const data = { const data = {
cmd: '19', cmd: '19',
type: '1', type: '1',
fromUserId: item?.userName, fromUserId: item?.username,
group_id: '', group_id: '',
userId: store.userInfo.userName, userId: store.userInfo.username,
} }
sendWebSocket(data) sendWebSocket(data)
getCheckMesssages(data) getCheckMesssages(data)
} }
//发送按钮 //发送按钮
const handleButtonClick = () => { const handleButtonClick = () => {
if (!msg) {
return ElMessage({
message: '请输入内容',
type: 'error',
})
}
let data = { let data = {
content: msg, content: msg,
contentFy: msg,
isSent: true, isSent: true,
cmd: '11', cmd: '11',
msgType: 0, msgType: 0,
fromLang: 'cn',
toLang: 'en',
chatType: '2', chatType: '2',
group_id: '', group_id: '',
time: getShortDate(), time: getShortDate(),
to: customerInfo.value.userName, to: customerInfo.value.username,
form: store.userInfo.userName, form: store.userInfo.username,
} }
messages.value?.push(data) messages.value?.push(data)
console.log('打印客户发送的内容', data)
sendWebSocket(data) sendWebSocket(data)
automaticPromptRef.value.setState('') automaticPromptRef.value.setState('')
} }
...@@ -460,7 +474,7 @@ const handleMessageClick = (event: any) => { ...@@ -460,7 +474,7 @@ const handleMessageClick = (event: any) => {
const getCheckMesssages = async (res: any) => { const getCheckMesssages = async (res: any) => {
try { try {
const { success, result, message }: any = await checkMesssages({ const { success, result, message }: any = await checkMesssages({
userName: res.userName, username: res.username,
}) })
} catch (error) { } catch (error) {
console.log(error) console.log(error)
...@@ -498,7 +512,7 @@ const getMessageClass = (isSent: boolean) => { ...@@ -498,7 +512,7 @@ const getMessageClass = (isSent: boolean) => {
} }
//左边按钮操作 //左边按钮操作
const getMenuItem = (item: any) => { const getMenuItem = (item: any) => {
return item.userName == customerInfo.value?.userName ? 'is-active' : '' return item.username == customerInfo.value?.username ? 'is-active' : ''
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
...@@ -523,7 +537,7 @@ const getMenuItem = (item: any) => { ...@@ -523,7 +537,7 @@ const getMenuItem = (item: any) => {
} }
} }
.el-container-center { .el-container-center {
background: #e6e8ed; background: #F8F8FA;
} }
.el-header-center { .el-header-center {
height: 76px; height: 76px;
...@@ -831,7 +845,7 @@ const getMenuItem = (item: any) => { ...@@ -831,7 +845,7 @@ const getMenuItem = (item: any) => {
.bubble { .bubble {
background-color: #e8e8e8; background-color: #e8e8e8;
color: #000; color: #000;
padding: 10px; padding: 10px 14px;
border-radius: 5px; border-radius: 5px;
max-width: 320px; max-width: 320px;
background: #f5f5f5; background: #f5f5f5;
...@@ -849,14 +863,38 @@ const getMenuItem = (item: any) => { ...@@ -849,14 +863,38 @@ const getMenuItem = (item: any) => {
.message { .message {
text-align: left; text-align: left;
margin: 0; margin: 0;
.content {
font-family: 'Inter';
font-size: 16px;
font-style: normal;
font-weight: 400;
color: #0c203d;
}
.contentFy {
font-family: "PingFang SC";
font-size: 14px;
font-style: normal;
font-weight: 400;
color: #798494;
line-height: 20px;
}
} }
.message-container-right { .message-container-right {
justify-content: flex-end; justify-content: flex-end;
.bubble{
background: #E6E8EB;
border-radius: 8px 0 8px 8px;
}
} }
.message-container-left { .message-container-left {
justify-content: flex-start; justify-content: flex-start;
.bubble{
background: #FFFFFF;
border-radius: 0px 8px 8px 8px;
margin-left: 8px;
}
} }
.avatar-number-input :deep(.el-input) { .avatar-number-input :deep(.el-input) {
width: 102px !important; width: 102px !important;
......
...@@ -9,17 +9,17 @@ ...@@ -9,17 +9,17 @@
class="form-box" class="form-box"
> >
<h2>客服登录</h2> <h2>客服登录</h2>
<el-form-item label="账号" prop="userName" size="large"> <el-form-item label="账号" prop="username" size="large">
<el-input <el-input
v-model="ruleForm.userName" v-model="ruleForm.username"
type="userName" type="username"
placeholder="请输入账号" placeholder="请输入账号"
autocomplete="off" autocomplete="off"
/> />
</el-form-item> </el-form-item>
<el-form-item label="密码" prop="passWord" size="large"> <el-form-item label="密码" prop="password" size="large">
<el-input <el-input
v-model="ruleForm.passWord" v-model="ruleForm.password"
type="password" type="password"
autocomplete="off" autocomplete="off"
placeholder="请输入密码" placeholder="请输入密码"
...@@ -46,7 +46,9 @@ import { LoginData } from '../type/Login' ...@@ -46,7 +46,9 @@ import { LoginData } from '../type/Login'
import { reactive, ref } from 'vue' import { reactive, ref } from 'vue'
import { useUserStore } from '../store/modules/user' import { useUserStore } from '../store/modules/user'
import type { FormInstance } from 'element-plus' import type { FormInstance } from 'element-plus'
import { ElMessage } from 'element-plus'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import axios from 'axios'
import { Login } from '../axios/model/user' import { Login } from '../axios/model/user'
export default { export default {
setup() { setup() {
...@@ -55,14 +57,14 @@ export default { ...@@ -55,14 +57,14 @@ export default {
const store = useUserStore() const store = useUserStore()
const router = useRouter() const router = useRouter()
const rules = reactive({ const rules = reactive({
userName: [ username: [
{ {
required: true, required: true,
message: '请输入账号', message: '请输入账号',
trigger: 'blur', trigger: 'blur',
}, },
], ],
passWord: [ password: [
{ {
required: true, required: true,
message: '请输入密码', message: '请输入密码',
...@@ -72,22 +74,51 @@ export default { ...@@ -72,22 +74,51 @@ export default {
}) })
//重置 //重置
const resetForm = (formEl: FormInstance | undefined) => { const resetForm = (formEl: FormInstance | undefined) => {
ruleForm.userName = '' ruleForm.username = ''
ruleForm.passWord = '' ruleForm.password = ''
if (!formEl) return if (!formEl) return
formEl.resetFields() formEl.resetFields()
} }
//登录
//登录
const deleteList1 = () => {
let data = {
id: '111',
}
// deleteUserList(data).then((res: any) => {
// console.log(res)
// ElMessage({
// message: '请输入内容',
// type: 'error',
// })
// console.log(res)
// })
// axios
// .delete('/api/getUserList/' + data.id)
// .then((response) => {
// console.log(response.data)
// })
// .catch((error) => {
// console.error(error)
// })
}
const submitForm = (formEl: FormInstance | undefined) => { const submitForm = (formEl: FormInstance | undefined) => {
let query = {}
if (!formEl) return if (!formEl) return
formEl.validate((valid: boolean) => { formEl.validate((valid: boolean) => {
if (valid) { if (valid) {
Login(query).then(({ success, message,result }: any) => { let data = {
username: ruleForm.username,
password: ruleForm.password,
}
Login(data).then(({ success, message, result }: any) => {
if (success) { if (success) {
router.push('/') router.push('/')
store.setUserInfo(result)
store.setUserInfo({
...result.userInfo,
token: result.token,
})
} }
}) })
} else { } else {
...@@ -95,7 +126,7 @@ export default { ...@@ -95,7 +126,7 @@ export default {
} }
}) })
} }
deleteList1()
return { ruleForm, ruleFormRef, rules, resetForm, submitForm } return { ruleForm, ruleFormRef, rules, resetForm, submitForm }
}, },
} }
......
const { defineConfig } = require('@vue/cli-service') const { defineConfig } = require('@vue/cli-service')
const AutoImport = require('unplugin-auto-import/webpack') const AutoImport = require('unplugin-auto-import/webpack')
const Components = require('unplugin-vue-components/webpack') const Components = require('unplugin-vue-components/webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { ElementPlusResolver } = require('unplugin-vue-components/resolvers') const { ElementPlusResolver } = require('unplugin-vue-components/resolvers')
module.exports = defineConfig({ module.exports = defineConfig({
transpileDependencies: true, transpileDependencies: true,
...@@ -14,4 +15,9 @@ module.exports = defineConfig({ ...@@ -14,4 +15,9 @@ module.exports = defineConfig({
}), }),
], ],
}, },
// chainWebpack: config => {
// config.plugin('html').use(HtmlWebpackPlugin, [{
// title:'客服端',
// }])
// }
}) })
\ No newline at end of file
...@@ -4036,6 +4036,17 @@ html-webpack-plugin@^5.1.0: ...@@ -4036,6 +4036,17 @@ html-webpack-plugin@^5.1.0:
pretty-error "^4.0.0" pretty-error "^4.0.0"
tapable "^2.0.0" tapable "^2.0.0"
html-webpack-plugin@^5.6.0:
version "5.6.0"
resolved "https://registry.npmmirror.com/html-webpack-plugin/-/html-webpack-plugin-5.6.0.tgz#50a8fa6709245608cb00e811eacecb8e0d7b7ea0"
integrity sha512-iwaY4wzbe48AfKLZ/Cc8k0L+FKG6oSNRaZ8x5A/T/IVDGyXcbHncM9TdDa93wn0FsSm82FhTKW7f3vS61thXAw==
dependencies:
"@types/html-minifier-terser" "^6.0.0"
html-minifier-terser "^6.0.2"
lodash "^4.17.21"
pretty-error "^4.0.0"
tapable "^2.0.0"
htmlparser2@^6.1.0: htmlparser2@^6.1.0:
version "6.1.0" version "6.1.0"
resolved "https://registry.npmmirror.com/htmlparser2/-/htmlparser2-6.1.0.tgz" resolved "https://registry.npmmirror.com/htmlparser2/-/htmlparser2-6.1.0.tgz"
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论