diff --git a/package.json b/package.json index f2d17bb..b90aa30 100644 --- a/package.json +++ b/package.json @@ -12,25 +12,26 @@ "format": "prettier --write src/" }, "dependencies": { - "vue": "^3.4.21", - "vue-router": "^4.3.0", - "element-plus": "^2.7.3", "@element-plus/icons-vue": "^2.3.1", "@vueup/vue-quill": "1.2.0", "axios": "^1.6.8", + "element-plus": "^2.7.3", + "qs": "^6.12.1", "unplugin-auto-import": "^0.17.5", "unplugin-vue-setup-extend-plus": "^1.0.1", "vite-plugin-compression": "^0.5.1", + "vue": "^3.4.21", + "vue-router": "^4.3.0", "vuex": "^4.1.0" }, "devDependencies": { "@rushstack/eslint-patch": "^1.8.0", "@vitejs/plugin-vue": "^5.0.4", "@vue/eslint-config-prettier": "^9.0.0", + "babel-polyfill": "^6.26.0", "eslint": "^8.57.0", "eslint-plugin-vue": "^9.23.0", "prettier": "^3.2.5", - "vite": "^5.2.8", - "babel-polyfill": "^6.26.0" + "vite": "^5.2.8" } } diff --git a/public/emojis/冷酷.png b/public/emojis/冷酷.png new file mode 100644 index 0000000..dd265f3 Binary files /dev/null and b/public/emojis/冷酷.png differ diff --git a/public/emojis/发呆.png b/public/emojis/发呆.png new file mode 100644 index 0000000..35476f6 Binary files /dev/null and b/public/emojis/发呆.png differ diff --git a/public/emojis/呕吐.png b/public/emojis/呕吐.png new file mode 100644 index 0000000..4dd060a Binary files /dev/null and b/public/emojis/呕吐.png differ diff --git a/public/emojis/呲牙.png b/public/emojis/呲牙.png new file mode 100644 index 0000000..7e55c01 Binary files /dev/null and b/public/emojis/呲牙.png differ diff --git a/public/emojis/坏笑.png b/public/emojis/坏笑.png new file mode 100644 index 0000000..fd6f0db Binary files /dev/null and b/public/emojis/坏笑.png differ diff --git a/public/emojis/大惊.png b/public/emojis/大惊.png new file mode 100644 index 0000000..7b8899c Binary files /dev/null and b/public/emojis/大惊.png differ diff --git a/public/emojis/大笑.png b/public/emojis/大笑.png new file mode 100644 index 0000000..5b2f79c Binary files /dev/null and b/public/emojis/大笑.png differ diff --git a/public/emojis/大闹.png b/public/emojis/大闹.png new file mode 100644 index 0000000..2baeff7 Binary files /dev/null and b/public/emojis/大闹.png differ diff --git a/public/emojis/天使.png b/public/emojis/天使.png new file mode 100644 index 0000000..09a6fbe Binary files /dev/null and b/public/emojis/天使.png differ diff --git a/public/emojis/奋斗.png b/public/emojis/奋斗.png new file mode 100644 index 0000000..5c49a1a Binary files /dev/null and b/public/emojis/奋斗.png differ diff --git a/public/emojis/尴尬.png b/public/emojis/尴尬.png new file mode 100644 index 0000000..f76698b Binary files /dev/null and b/public/emojis/尴尬.png differ diff --git a/public/emojis/开心.png b/public/emojis/开心.png new file mode 100644 index 0000000..95653d6 Binary files /dev/null and b/public/emojis/开心.png differ diff --git a/public/emojis/心碎.png b/public/emojis/心碎.png new file mode 100644 index 0000000..5ef1306 Binary files /dev/null and b/public/emojis/心碎.png differ diff --git a/public/emojis/恶魔.png b/public/emojis/恶魔.png new file mode 100644 index 0000000..df2b8dc Binary files /dev/null and b/public/emojis/恶魔.png differ diff --git a/public/emojis/惊恐.png b/public/emojis/惊恐.png new file mode 100644 index 0000000..417042b Binary files /dev/null and b/public/emojis/惊恐.png differ diff --git a/public/emojis/惊悚.png b/public/emojis/惊悚.png new file mode 100644 index 0000000..62e9088 Binary files /dev/null and b/public/emojis/惊悚.png differ diff --git a/public/emojis/惊讶.png b/public/emojis/惊讶.png new file mode 100644 index 0000000..477d026 Binary files /dev/null and b/public/emojis/惊讶.png differ diff --git a/public/emojis/感冒.png b/public/emojis/感冒.png new file mode 100644 index 0000000..0941517 Binary files /dev/null and b/public/emojis/感冒.png differ diff --git a/public/emojis/愤怒.png b/public/emojis/愤怒.png new file mode 100644 index 0000000..d4a6ad2 Binary files /dev/null and b/public/emojis/愤怒.png differ diff --git a/public/emojis/懵逼.png b/public/emojis/懵逼.png new file mode 100644 index 0000000..d2dbc28 Binary files /dev/null and b/public/emojis/懵逼.png differ diff --git a/public/emojis/无聊.png b/public/emojis/无聊.png new file mode 100644 index 0000000..8337bd2 Binary files /dev/null and b/public/emojis/无聊.png differ diff --git a/public/emojis/汗颜.png b/public/emojis/汗颜.png new file mode 100644 index 0000000..2199477 Binary files /dev/null and b/public/emojis/汗颜.png differ diff --git a/public/emojis/流汗.png b/public/emojis/流汗.png new file mode 100644 index 0000000..94dbc8b Binary files /dev/null and b/public/emojis/流汗.png differ diff --git a/public/emojis/流泪.png b/public/emojis/流泪.png new file mode 100644 index 0000000..f1a1268 Binary files /dev/null and b/public/emojis/流泪.png differ diff --git a/public/emojis/点赞.png b/public/emojis/点赞.png new file mode 100644 index 0000000..1c0beb8 Binary files /dev/null and b/public/emojis/点赞.png differ diff --git a/public/emojis/爱你.png b/public/emojis/爱你.png new file mode 100644 index 0000000..4c4a330 Binary files /dev/null and b/public/emojis/爱你.png differ diff --git a/public/emojis/爱心.png b/public/emojis/爱心.png new file mode 100644 index 0000000..17d91df Binary files /dev/null and b/public/emojis/爱心.png differ diff --git a/public/emojis/犯困.png b/public/emojis/犯困.png new file mode 100644 index 0000000..4a227ca Binary files /dev/null and b/public/emojis/犯困.png differ diff --git a/public/emojis/生气.png b/public/emojis/生气.png new file mode 100644 index 0000000..70974bb Binary files /dev/null and b/public/emojis/生气.png differ diff --git a/public/emojis/白眼.png b/public/emojis/白眼.png new file mode 100644 index 0000000..b25d56d Binary files /dev/null and b/public/emojis/白眼.png differ diff --git a/public/emojis/睡着.png b/public/emojis/睡着.png new file mode 100644 index 0000000..c52f233 Binary files /dev/null and b/public/emojis/睡着.png differ diff --git a/public/emojis/瞌睡.png b/public/emojis/瞌睡.png new file mode 100644 index 0000000..8aaa578 Binary files /dev/null and b/public/emojis/瞌睡.png differ diff --git a/public/emojis/笑哭.png b/public/emojis/笑哭.png new file mode 100644 index 0000000..db9bf6a Binary files /dev/null and b/public/emojis/笑哭.png differ diff --git a/public/emojis/笑脸.png b/public/emojis/笑脸.png new file mode 100644 index 0000000..043b9a4 Binary files /dev/null and b/public/emojis/笑脸.png differ diff --git a/public/emojis/讨厌.png b/public/emojis/讨厌.png new file mode 100644 index 0000000..d4a5fdc Binary files /dev/null and b/public/emojis/讨厌.png differ diff --git a/public/emojis/调皮.png b/public/emojis/调皮.png new file mode 100644 index 0000000..81d8543 Binary files /dev/null and b/public/emojis/调皮.png differ diff --git a/public/emojis/酷.png b/public/emojis/酷.png new file mode 100644 index 0000000..ae29af1 Binary files /dev/null and b/public/emojis/酷.png differ diff --git a/public/emojis/闭嘴.png b/public/emojis/闭嘴.png new file mode 100644 index 0000000..69c7b06 Binary files /dev/null and b/public/emojis/闭嘴.png differ diff --git a/public/emojis/难过.png b/public/emojis/难过.png new file mode 100644 index 0000000..8a86041 Binary files /dev/null and b/public/emojis/难过.png differ diff --git a/public/emojis/飞吻.png b/public/emojis/飞吻.png new file mode 100644 index 0000000..9bc914c Binary files /dev/null and b/public/emojis/飞吻.png differ diff --git a/public/emojis/饿死.png b/public/emojis/饿死.png new file mode 100644 index 0000000..434d7b1 Binary files /dev/null and b/public/emojis/饿死.png differ diff --git a/public/emojis/骂人.png b/public/emojis/骂人.png new file mode 100644 index 0000000..17da101 Binary files /dev/null and b/public/emojis/骂人.png differ diff --git a/src/App.vue b/src/App.vue index da3b098..925db06 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,5 +1,5 @@ @@ -15,8 +15,18 @@ body { margin: 0; padding: 0; } -.home-app { +.app { width: 100%; height: 100%; } + +body, +input, +select, +button, +textarea { + font-size: 12px; + font-family: arial, "微软雅黑", sans-serif; + color: #000; +} diff --git a/src/api/CustomerClient/index.js b/src/api/CustomerClient/index.js new file mode 100644 index 0000000..2cdd0ca --- /dev/null +++ b/src/api/CustomerClient/index.js @@ -0,0 +1,59 @@ +import request from '@/utils/request' + +/** + * 客户端 API + */ + +const CustomerClientApi = { + auth: '/api/customer/auth', + opinion: '/api/opinion/rate', + chatRecord: '/api/chat/before', + hot: '/api/hot/question', + uploadImage: '/api/upload/image', + uploadImgb64: '/api/upload/imgb64', + goodsDetail: '/api/goods/info', + recommendList: '/api/recommend/list', + orderList: '/api/order/list', + logistics: '/api/order/logistics', + poll: '/poll/poll.io' +} + +export function findClientWarnRecord(parameter) { + return request({ + url: CustomerClientApi.orderList, + method: 'get', + params: parameter + }) +} + +export function clientAuth(parameter) { + return request({ + url: CustomerClientApi.auth, + method: 'post', + params: parameter + }) +} + +export function findChatRecord(parameter) { + return request({ + url: CustomerClientApi.chatRecord, + method: 'post', + params: parameter + }) +} + +export function loadHots(parameter) { + return request({ + url: CustomerClientApi.hot, + method: 'post', + params: parameter + }) +} + +export function sendMessage(parameter) { + return request({ + url: CustomerClientApi.poll, + method: 'get', + params: parameter + }) +} diff --git a/src/assets/base.css b/src/assets/css/base.css similarity index 100% rename from src/assets/base.css rename to src/assets/css/base.css diff --git a/src/assets/css/left.css b/src/assets/css/left.css new file mode 100644 index 0000000..20102e1 --- /dev/null +++ b/src/assets/css/left.css @@ -0,0 +1,207 @@ + +.message { + display: flex; + padding: 0 15px 0 15px; + line-height: 36px; + background: #fafafa; + border-bottom: 1px solid #e4e4e4; +} + +.chat-service-status-tip { + width: 36px; + height: 36px; + background: url('@/assets/img/msg-tip.png') center no-repeat; + background-size: 22px 22px; +} + +.chat { + height: calc(70% - 39px); + margin: 1px 0; + padding: 15px; + background-color: #ffffff; + overflow-y: auto; +} + +.service-chat, +.user-chat, +.robot-chat { + margin-bottom: 20px; +} + +.clearfix:after { + display: block; + clear: both; + height: 0; + visibility: hidden; + font-size: 0; + line-height: 0; + content: ""; +} + +.clearfix { + zoom: 1; +} + +.service-chat .portrait { + float: left; + background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACIAAAAiCAYAAAA6RwvCAAADWUlEQVRYR9WYf0hTURTHv/e5NnWac0qaTSVyZlJQEZVBBv2gsCIoUtR+qGWWJVnU6CfRDx0YlP2wHyCaSaUSgUn9oRFlYYYURqS1XGitmrSZq9ya6XvxHqym1t7bcM3OXw/eOed+7jn3nMu5BHbSppBE9Xsx6QyDJAAT7P8N47eWAaoYmpTG6qyvbX6J7eNVhDifAfYO44K8rgignvi2dx+ryIF4AsIuEhwMaVFIlBTFaHjx3aggoomStEaI88k/TsngPRGCfPIyQtzmxoMpNI5aFoQRqu1Ovf8bxEseDL8FCfCeNgvSuQsAioLl8QNYmptgedII64tmp4PndEQCkjMQlK2CueEevtXW4Pvzp9yi3lOmQ6yMgTxrJwzHD6H7arFTME6BKC5Vo/+zEZ37c0Cbe/64EOU/GiGHC0H5++N95mrBMIJB/JeuQkBiGnTrlwtyriirwfdnTTCcOCJIXxCIJGYyxp4oQXvCTEFObUqRtxrRXVoE0/VyXjtBIIEZOaAtPTBdK+F1aK8QkJQO6fwl+JDF3qGORRBI2NlyGE+rYdW08Pkb8F+inITwqjt4M0cJ2mJ2aMsLIt+UC1naVuh3ZXKV4oz4xs1DeEUt9KrNMFWWug4SWnCR6xF9ug6Io2PRq2mBofCYIJbg3ANgWzZ7vVOBcnjJ5Pi4Pe2vtg4jEl5ZB+PJozA31sN3djyCdhzEu6RFgkBYW/Oj+zAWHgNbcbJ1mx3auhek4R6Mp/I8D/L19g10l533PIjpSjG+3KyE3+IVCMzYNnypYfP8ITtF8BnpKipAT30dpPGLIN+qch0kJO8M+j918laKz4w49Go13D1kE7ZqbJUmUkQCNA29Ksu1qhmliESI+hz69O/xpboC5od3hziSb9mNoJw9oKR+0K1dxkXAJrKUjRCNCUVflwHdly+43kfsdxeQmgkiluBHh3ZAl2TLun3hVG73suQNeLcmQVDqBivxdlZ7A1FoGESh40B5+/ze9bosWDWtkETHclcA2zdcEadA/rbA6JWpEEeM5z1LjgCHBcSVCPwpNSNjnHgVKc5jGHDzp6eEAdSEfQHoo5hfU7knYGiaRI+cIdwWAU+8CAx5lrDBsC8DhGLSCZDoxnlYSwgqvfpJaZTOyhYKJz8BNAh0ufLDVpEAAAAASUVORK5CYII=); +} + +.robot-chat .portrait { + float: left; + background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACIAAAAiCAYAAAA6RwvCAAACwklEQVRYR+2YXUiTURjH/5u1pa5tlbSZmUJE0U1XgVcSRER4USPNEvoQIsQo8iaK2tWSMIglgUhJBcHI7IOILsIu+rjIGETRRYmUc/NrNm0u1+baWjwvntjevV/bxLeLPbCL7ZzzPL/znOf8z9nRAMCXDbr7ALYDqKbvS2geAO4t3tgBzQJEwxIGFwrVRyBeAJUqg/gIJJkrxPL1VSipqUUyHkf45XMkgjO5ukJeINaObpgONnPB/edPIujqUQdk0yc/tEYzF/zXwGv4GnepA7Kuy4WVdfu54NNOBwLXLqkDQlE3j8znnQ3yI1kjVIz0kbLK3n4OhDIiZTHPV8Qnx0S7iIIY9x1CeeednFPNH/gnPAf/hVMIPXYJ+hQFoZmSRd6+WhSYNW12ySWUBclnJ6TOQK6WCiD89RbMSNmZixBbU7aLfo+OCNbOsrXlSISCSEYjae20NGQzN5z43n4uY2wGiKmxGdYr3YJqSecKK+Kx4/WY63+a5tBUfxjWqz2IfRvC+IkGzA99/tfOQOiHidNHEXpyL21sBkiqWvJlm2VKTEkJkmCF2lNBfj57iPHWJmkQw846VNx6JJgR+pGCaUsNCHTYEX7zIs2Zfus2VNzsQyIwhdFje5H4MS2YkcmzLZjtvS0NQq00K8vlLsSnJvI6yPjbl+qKFHj2wV35GmE9WC0UdKSQEbE7K+kBiZfqh17pjt2wtF+XvY9kczRL3eJkL88anR7a4mJoVpSgyLwKhj02lLXZMVilz2BgyhtwOrhMRj66kYxGFbHKgpAXo62Jyw4JGTSvU13Bhk3xtVY6mqr46q9sUnL9FhDZXNkVGcFkq240QQWFcR8pAUWR6eiteZ38tpqEXn/TnasoowUmVeDdpGueqOsw9QOkQ9u7q+oEiOQYRWeI/hsnv/nWYLQFt5IalR4nvABGKCHmr+VxYyrrQxH5wAAAABJRU5ErkJggg==); +} + +.user-chat .portrait { + background-position: 0 0; + float: right; + background: url(@/assets/img/user.png) no-repeat; +} + +.portrait { + width: 34px; + height: 34px; + margin-top: 0px; + overflow: hidden; +} + +.portrait img { + width: 100%; + height: 100%; +} + +.container { + position: relative; + max-width: 533px; + min-width: 170px; + min-height: 44px; + padding: 8px 10px; + box-shadow: 0 0 4px rgba(0, 0, 0, .2); + border-radius: 3px; +} + +.container .arrow { + position: absolute; + top: 12px; + width: 7px; + height: 10px; +} + +.service-chat .container { + float: left; + margin-left: 15px; + background-color: #CAEFFD; +} + +.robot-chat .container { + float: left; + margin-left: 15px; + background-color: #CAEFFD; +} + +.user-chat .container { + float: right; + margin-right: 15px; + background-color: #f3f3f3; +} + +.chat-head { + line-height: 16px; +} + +.service-chat .chat-head { + color: #005982; +} + +.user-chat .chat-head { + color: #707070; +} + +.chat-head span { + float: right; + padding-left: 10px; +} + +.chat-head b.left-space { + padding-left: 4px; +} + +.ell { + overflow: hidden; + text-overflow: ellipsis; + -o-text-overflow: ellipsis; + white-space: nowrap; +} + +.config { + position: relative; + height: 34px; + padding: 5px 15px; + line-height: 34px; + background-color: #fafafa; + border-top: 1px solid #e4e4e4; + border-bottom: 1px solid #e4e4e4; +} + +.toolbox { + display: flex; + flex-direction: row; + height: 100%; +} + +.face { + width: 22px; + background: url('@/assets/img/face.png') center no-repeat; +} + +.emoji-img { + width: 25px; + height: 25px; + margin: 10px; +} + +.input { + height: calc(30% - 77px); + margin: 1px 0; + background-color: #ffffff; +} + +.editor { + padding: 0 15px; + height: 100%; + width: 100%; + resize: none; + overflow-y: auto; + color: #000; + font-size: 14px; + line-height: 20px; + outline: none; + background-color: #fff; + word-break: break-all; + white-space: normal; +} +.editor:empty:before { + content: attr(placeholder); + color: #cfcfcf; + display: block; +} + +.editor::-webkit-scrollbar { + width: 0px; +} +.editor::-webkit-scrollbar-thumb { + width: 0px; +} +.editor::-webkit-scrollbar-track { + background: transparent; +} + +.send { + height: 41px; + padding: 0 10px; + background-color: #fafafa; + border-top: 1px solid #e8e8e8; + display: flex; + flex-direction: row-reverse; + align-items: center; +} \ No newline at end of file diff --git a/src/assets/css/main.css b/src/assets/css/main.css new file mode 100644 index 0000000..ce7fbe1 --- /dev/null +++ b/src/assets/css/main.css @@ -0,0 +1,20 @@ +@import 'base.css'; + +#app { + font-weight: normal; + height: 100vh; +} + +a, +.green { + text-decoration: none; + color: hsl(210, 100%, 63%); + transition: 0.4s; + padding: 3px; +} + +@media (hover: hover) { + a:hover { + background-color: hsla(160, 100%, 37%, 0.2); + } +} diff --git a/src/assets/img/about.png b/src/assets/img/about.png new file mode 100644 index 0000000..ace2c20 Binary files /dev/null and b/src/assets/img/about.png differ diff --git a/src/assets/img/face.png b/src/assets/img/face.png new file mode 100644 index 0000000..fb5480f Binary files /dev/null and b/src/assets/img/face.png differ diff --git a/src/assets/img/icon.png b/src/assets/img/icon.png new file mode 100644 index 0000000..6200dac Binary files /dev/null and b/src/assets/img/icon.png differ diff --git a/src/assets/logo.png b/src/assets/img/logo.png similarity index 100% rename from src/assets/logo.png rename to src/assets/img/logo.png diff --git a/src/assets/img/msg-tip.png b/src/assets/img/msg-tip.png new file mode 100644 index 0000000..6c0dd41 Binary files /dev/null and b/src/assets/img/msg-tip.png differ diff --git a/src/assets/img/user.png b/src/assets/img/user.png new file mode 100644 index 0000000..f6b416d Binary files /dev/null and b/src/assets/img/user.png differ diff --git a/src/assets/js/emoji.js b/src/assets/js/emoji.js new file mode 100644 index 0000000..0533c95 --- /dev/null +++ b/src/assets/js/emoji.js @@ -0,0 +1,247 @@ +const dataMap = new Map() +const data = initData(dataMap) + +const emoji = { + getEmojis() { + return data + }, + resolve(strs) { + // 转换表情 + if (!strs) { + return '' + } + let temp = strs[0] + let result = '' + for (let i = 1; i < strs.length; i++) { + if (temp === '[' && strs[i] === ':') { + i++ + const find = findEmoji(i, strs) + result += find.stay + i = find.i + temp = find.temp + } else { + result += temp + temp = strs[i] + } + } + result += temp + return result + }, + adapter(str) { + return '[:' + str + ':]' + } +} + +function findEmoji(i, strs) { + let temp = '' + let stay = '[:' + let key = '' + while (i < strs.length - 1) { + if (strs[i] === ':' && strs[i + 1] === ']') { + const m = dataMap.get(key) + if (m) { + stay = + '' + } else { + stay += key + ':]' + } + i++ + break + } else if (strs[i] === '[') { + stay += key + temp = strs[i] + break + } else { + key += strs[i] + i++ + } + } + return { stay: stay, temp: temp, i: i } +} + +function initData(dataMap) { + const data = [ + { + name: '笑脸', + src: 'emojis/笑脸.png' + }, + { + name: '开心', + src: 'emojis/开心.png' + }, + { + name: '大笑', + src: 'emojis/大笑.png' + }, + { + name: '爱心', + src: 'emojis/爱心.png' + }, + { + name: '飞吻', + src: 'emojis/飞吻.png' + }, + { + name: '调皮', + src: 'emojis/调皮.png' + }, + { + name: '讨厌', + src: 'emojis/讨厌.png' + }, + { + name: '笑哭', + src: 'emojis/笑哭.png' + }, + { + name: '流泪', + src: 'emojis/流泪.png' + }, + { + name: '坏笑', + src: 'emojis/坏笑.png' + }, + { + name: '流汗', + src: 'emojis/流汗.png' + }, + { + name: '汗颜', + src: 'emojis/汗颜.png' + }, + { + name: '尴尬', + src: 'emojis/尴尬.png' + }, + { + name: '流泪', + src: 'emojis/流泪.png' + }, + { + name: '冷酷', + src: 'emojis/冷酷.png' + }, + { + name: '惊恐', + src: 'emojis/惊恐.png' + }, + { + name: '惊悚', + src: 'emojis/惊悚.png' + }, + { + name: '惊讶', + src: 'emojis/惊讶.png' + }, + { + name: '大惊', + src: 'emojis/大惊.png' + }, + { + name: '大闹', + src: 'emojis/大闹.png' + }, + { + name: '发呆', + src: 'emojis/发呆.png' + }, + { + name: '犯困', + src: 'emojis/犯困.png' + }, + { + name: '心碎', + src: 'emojis/心碎.png' + }, + { + name: '酷', + src: 'emojis/酷.png' + }, + { + name: '生气', + src: 'emojis/生气.png' + }, + { + name: '闭嘴', + src: 'emojis/闭嘴.png' + }, + { + name: '睡着', + src: 'emojis/睡着.png' + }, + { + name: '奋斗', + src: 'emojis/奋斗.png' + }, + { + name: '愤怒', + src: 'emojis/愤怒.png' + }, + { + name: '瞌睡', + src: 'emojis/瞌睡.png' + }, + { + name: '难过', + src: 'emojis/难过.png' + }, + { + name: '天使', + src: 'emojis/天使.png' + }, + { + name: '无聊', + src: 'emojis/无聊.png' + }, + { + name: '骂人', + src: 'emojis/骂人.png' + }, + { + name: '点赞', + src: 'emojis/点赞.png' + }, + { + name: '懵逼', + src: 'emojis/懵逼.png' + }, + { + name: '白眼', + src: 'emojis/白眼.png' + }, + { + name: '恶魔', + src: 'emojis/恶魔.png' + }, + { + name: '感冒', + src: 'emojis/感冒.png' + }, + { + name: '爱你', + src: 'emojis/爱你.png' + }, + { + name: '呕吐', + src: 'emojis/呕吐.png' + }, + { + name: '呲牙', + src: 'emojis/呲牙.png' + } + ] + + for (const i in data) { + dataMap.set(data[i].name, data[i]) + } + + return data +} + +export default emoji diff --git a/src/assets/main.css b/src/assets/main.css deleted file mode 100644 index 36fb845..0000000 --- a/src/assets/main.css +++ /dev/null @@ -1,35 +0,0 @@ -@import './base.css'; - -#app { - max-width: 1280px; - margin: 0 auto; - padding: 2rem; - font-weight: normal; -} - -a, -.green { - text-decoration: none; - color: hsla(160, 100%, 37%, 1); - transition: 0.4s; - padding: 3px; -} - -@media (hover: hover) { - a:hover { - background-color: hsla(160, 100%, 37%, 0.2); - } -} - -@media (min-width: 1024px) { - body { - display: flex; - place-items: center; - } - - #app { - display: grid; - grid-template-columns: 1fr 1fr; - padding: 0 2rem; - } -} diff --git a/src/main.js b/src/main.js index 910ca04..7e6ec1a 100644 --- a/src/main.js +++ b/src/main.js @@ -1,11 +1,12 @@ -import './assets/main.css' +import './assets/css/main.css' import { createApp } from 'vue' import App from './App.vue' import router from './router' +import store from './store' import ElementPlus from 'element-plus' import 'element-plus/dist/index.css' -import 'element-plus/theme-chalk/display.css'; +import 'element-plus/theme-chalk/display.css' import * as ElementPlusIconsVue from '@element-plus/icons-vue' const app = createApp(App) @@ -14,6 +15,7 @@ app.use(router) for (const [key, component] of Object.entries(ElementPlusIconsVue)) { app.component(key, component) } +app.use(store) app.use(ElementPlus) app.mount('#app') diff --git a/src/router/index.js b/src/router/index.js index 2fb680b..1b6934a 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -7,8 +7,8 @@ const router = createRouter({ path: '/', name: 'Home', meta: { title: '主页', icon: '', activeIndex: 'home' }, - component: () => import('@/views/Home.vue'), - }, + component: () => import('@/views/HomeView.vue') + } ] }) diff --git a/src/store/editor.js b/src/store/editor.js new file mode 100644 index 0000000..ef45077 --- /dev/null +++ b/src/store/editor.js @@ -0,0 +1,56 @@ +const editor = { + state: { + range: null, + el: null + }, + mutations: { + SET_EDITOR(state, el) { + state.el = el + }, + INSERT(state, content) { + // state.el.focus() + const selection = window.getSelection() + if (state.range) { + selection.removeAllRanges() + selection.addRange(state.range) + } + const range = selection.getRangeAt(0) + const el = document.createElement('div') + const frag = document.createDocumentFragment() + el.innerHTML = content + const node = frag.appendChild(el.firstChild) + range.insertNode(frag) + const newRange = document.createRange() + newRange.setStartAfter(node) + selection.removeAllRanges() + selection.addRange(newRange) + }, + REPLACE(state, content) { + state.el.innerHTML = content + var range = document.createRange() + range.selectNodeContents(state.el) + range.collapse(false) + var sel = window.getSelection() + sel.removeAllRanges() + sel.addRange(range) + }, + FOCUS(state) { + if (state.el.innerHTML) { + var range = document.createRange() + range.selectNodeContents(state.el) + range.collapse(false) + var sel = window.getSelection() + sel.removeAllRanges() + sel.addRange(range) + } else { + state.el.focus() + } + }, + UPDATE_RANGE(state, range) { + state.range = range + } + }, + actions: {} +} + +export default editor diff --git a/src/store/store.js b/src/store/index.js similarity index 70% rename from src/store/store.js rename to src/store/index.js index 6029b86..b24a019 100644 --- a/src/store/store.js +++ b/src/store/index.js @@ -1,6 +1,10 @@ import { createStore } from 'vuex' +import editor from '@/store/editor.js' -const store = createStore({ +const index = createStore({ + modules: { + editor + }, state() { return { currentRoute: null @@ -18,4 +22,4 @@ const store = createStore({ } }) -export default store +export default index diff --git a/src/utils/axios.js b/src/utils/axios.js new file mode 100644 index 0000000..3b91f6b --- /dev/null +++ b/src/utils/axios.js @@ -0,0 +1,35 @@ +const VueAxios = { + vm: {}, + // eslint-disable-next-line no-unused-vars + install (Vue, instance) { + if (this.installed) { + return + } + this.installed = true + + if (!instance) { + // eslint-disable-next-line no-console + console.error('You have to install axios') + return + } + + Vue.axios = instance + + Object.defineProperties(Vue.prototype, { + axios: { + get: function get () { + return instance + } + }, + $http: { + get: function get () { + return instance + } + } + }) + } +} + +export { + VueAxios +} diff --git a/src/utils/request.js b/src/utils/request.js index 813015f..ad8a4b3 100644 --- a/src/utils/request.js +++ b/src/utils/request.js @@ -1,107 +1,75 @@ import axios from 'axios' -import { ElNotification, ElMessage } from 'element-plus' -import errorCode from '@/utils/errorCode' -import cache from '@/plugins/cache' +import { VueAxios } from './axios' +import qs from 'qs' +import { ElMessage } from 'element-plus' -axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8' -// 创建axios实例 -const service = axios.create({ - // axios中请求配置有baseURL选项,表示请求URL公共部分 - baseURL: import.meta.env.VITE_APP_BASE_API, - // 超时 - timeout: 10000 +// 创建 axios 实例 +const request = axios.create({ + // API 请求的默认前缀` + // baseURL: '/api', + timeout: 600000, // 请求超时时间 + maxBodyLength: 5 * 1024 * 1024, + withCredentials: false, + paramsSerializer: { + serialize: params => { + if (params && params.sorter) { + params.sorter = JSON.stringify(params.sorter) + } + return qs.stringify(params, { indices: false }) + } + }, }) -// request拦截器 -service.interceptors.request.use( - (config) => { - // 是否需要防止数据重复提交 - const isRepeatSubmit = (config.headers || {}).repeatSubmit === false - // get请求映射params参数 - if (config.method === 'get' && config.params) { - let url = config.url + '?' + tansParams(config.params) - url = url.slice(0, -1) - config.params = {} - config.url = url +// 异常拦截处理器 +const errorHandler = (error) => { + if (error.response) { + const data = error.response.data + console.error('response => ', data) + // const token = Vue.ls.get(ACCESS_TOKEN) + if (error.response.status === 403) { + ElMessage.error(data.message) } - if (!isRepeatSubmit && (config.method === 'post' || config.method === 'put')) { - const requestObj = { - url: config.url, - data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data, - time: new Date().getTime() - } - const requestSize = Object.keys(JSON.stringify(requestObj)).length // 请求数据大小 - const limitSize = 5 * 1024 * 1024 // 限制存放数据5M - if (requestSize >= limitSize) { - console.warn(`[${config.url}]: ` + '请求数据大小超出允许的5M限制,无法进行防重复提交验证。') - return config - } - const sessionObj = cache.session.getJSON('sessionObj') - if (sessionObj === undefined || sessionObj === null || sessionObj === '') { - cache.session.setJSON('sessionObj', requestObj) - } else { - const s_url = sessionObj.url // 请求地址 - const s_data = sessionObj.data // 请求数据 - const s_time = sessionObj.time // 请求时间 - const interval = 1000 // 间隔时间(ms),小于此时间视为重复提交 - if ( - s_data === requestObj.data && - requestObj.time - s_time < interval && - s_url === requestObj.url - ) { - const message = '数据正在处理,请勿重复提交' - console.warn(`[${s_url}]: ` + message) - return Promise.reject(new Error(message)) - } else { - cache.session.setJSON('sessionObj', requestObj) - } - } + if (error.response.status === 401 && !(data.result && data.result.isLogin)) { + ElMessage.error('Authorization verification failed') + /*if (token) { + store.dispatch('Logout').then(() => { + setTimeout(() => { + window.location.reload() + }, 1500) + }) + }*/ + } + if (error.response.status === 404) { + ElMessage.error(data.path) } - return config - }, - (error) => { - console.log(error) - Promise.reject(error) } -) + return Promise.reject(error) +} -// 响应拦截器 -service.interceptors.response.use( - (res) => { - // 未设置状态码则默认成功状态 - const code = res.data.code || 200 - // 获取错误信息 - const msg = errorCode[code] || res.data.msg || errorCode['default'] - // 二进制数据则直接返回 - if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') { - return res.data - } - if (code === 500) { - ElMessage({ message: msg, type: 'error' }) - return Promise.reject(new Error(msg)) - } else if (code === 601) { - ElMessage({ message: msg, type: 'warning' }) - return Promise.reject(new Error(msg)) - } else if (code !== 200) { - ElNotification.error({ title: msg }) - return Promise.reject('error') - } else { - return Promise.resolve(res.data) - } - }, - (error) => { - console.log('err' + error) - let { message } = error - if (message == 'Network Error') { - message = '后端接口连接异常' - } else if (message.includes('timeout')) { - message = '系统接口请求超时' - } else if (message.includes('Request failed with status code')) { - message = '系统接口' + message.substr(message.length - 3) + '异常' - } - ElMessage({ message: message, type: 'error', duration: 5 * 1000 }) - return Promise.reject(error) +// request interceptor +request.interceptors.request.use(config => { + /*const token = Vue.ls.get(ACCESS_TOKEN) + if (token) { + config.headers.Authorization = token + }*/ + return config +}, errorHandler) + +// response interceptor +request.interceptors.response.use((response) => { + return response.data +}, errorHandler) + +const installer = { + vm: {}, + install (Vue) { + Vue.use(VueAxios, request) } -) +} -export default service +export default request + +export { + installer as VueAxios, + request as axios +} diff --git a/src/views/HeaderView.vue b/src/views/HeaderView.vue new file mode 100644 index 0000000..8fae1ed --- /dev/null +++ b/src/views/HeaderView.vue @@ -0,0 +1,36 @@ + + + + + diff --git a/src/views/Home.vue b/src/views/Home.vue deleted file mode 100644 index ea40df9..0000000 --- a/src/views/Home.vue +++ /dev/null @@ -1,11 +0,0 @@ - - - - - \ No newline at end of file diff --git a/src/views/HomeView.vue b/src/views/HomeView.vue new file mode 100644 index 0000000..fa40462 --- /dev/null +++ b/src/views/HomeView.vue @@ -0,0 +1,59 @@ + + + + + diff --git a/src/views/LeftView.vue b/src/views/LeftView.vue new file mode 100644 index 0000000..7ba19c6 --- /dev/null +++ b/src/views/LeftView.vue @@ -0,0 +1,500 @@ + + + + + diff --git a/src/views/RightView.vue b/src/views/RightView.vue new file mode 100644 index 0000000..a8fe833 --- /dev/null +++ b/src/views/RightView.vue @@ -0,0 +1,176 @@ + + + + + diff --git a/vite.config.js b/vite.config.js index 02fbf5e..4ac53f2 100644 --- a/vite.config.js +++ b/vite.config.js @@ -1,6 +1,6 @@ import { defineConfig, loadEnv } from 'vite' import createVitePlugins from './vite/plugins' -import path from 'path' +import { resolve } from 'path' // https://vitejs.dev/config/ export default defineConfig(({ mode, command }) => { @@ -12,16 +12,15 @@ export default defineConfig(({ mode, command }) => { resolve: { alias: { // 设置路径 - '~': path.resolve(__dirname, './'), + '~': resolve(__dirname, './'), // 设置别名 - '@': path.resolve(__dirname, './src') + '@': resolve(__dirname, 'src') }, extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue'] }, server: { port: 3500, host: true, - open: true, proxy: { '/api': { // target: 'http://117.62.238.129:10050', @@ -36,7 +35,8 @@ export default defineConfig(({ mode, command }) => { // target: 'http://10.70.132.177:11002', pathRewrite: { '^/poll': '' }, ws: false, - changeOrigin: true + changeOrigin: true, + rewrite: (path) => path.replace(/^\/poll/, '') } } },