使用 Element UI 实现会话界面

This commit is contained in:
RockYang 2023-03-20 07:19:12 +08:00
parent e2c3f50c8a
commit aa3a38348f
4 changed files with 103 additions and 94 deletions

27
web/package-lock.json generated
View File

@ -8,6 +8,7 @@
"name": "yycloud-webssh",
"version": "0.1.0",
"dependencies": {
"@element-plus/icons-vue": "^2.1.0",
"axios": "^0.27.2",
"core-js": "^3.8.3",
"element-plus": "^2.1.11",
@ -1689,9 +1690,9 @@
}
},
"node_modules/@element-plus/icons-vue": {
"version": "1.1.4",
"resolved": "https://registry.npmmirror.com/@element-plus/icons-vue/-/icons-vue-1.1.4.tgz",
"integrity": "sha512-Iz/nHqdp1sFPmdzRwHkEQQA3lKvoObk8azgABZ81QUOpW9s/lUyQVUSh0tNtEPZXQlKwlSh7SPgoVxzrE0uuVQ==",
"version": "2.1.0",
"resolved": "https://registry.npmmirror.com/@element-plus/icons-vue/-/icons-vue-2.1.0.tgz",
"integrity": "sha512-PSBn3elNoanENc1vnCfh+3WA9fimRC7n+fWkf3rE5jvv+aBohNHABC/KAR5KWPecxWxDTVT1ERpRbOMRcOV/vA==",
"peerDependencies": {
"vue": "^3.2.0"
}
@ -4997,6 +4998,14 @@
"vue": "^3.2.0"
}
},
"node_modules/element-plus/node_modules/@element-plus/icons-vue": {
"version": "1.1.4",
"resolved": "https://registry.npmmirror.com/@element-plus/icons-vue/-/icons-vue-1.1.4.tgz",
"integrity": "sha512-Iz/nHqdp1sFPmdzRwHkEQQA3lKvoObk8azgABZ81QUOpW9s/lUyQVUSh0tNtEPZXQlKwlSh7SPgoVxzrE0uuVQ==",
"peerDependencies": {
"vue": "^3.2.0"
}
},
"node_modules/element-plus/node_modules/@popperjs/core": {
"name": "@sxzz/popperjs-es",
"version": "2.11.7",
@ -12206,9 +12215,9 @@
"integrity": "sha512-ej5oVy6lykXsvieQtqZxCOaLT+xD4+QNarq78cIYISHmZXshCvROLudpQN3lfL8G0NL7plMSSK+zlyvCaIJ4Iw=="
},
"@element-plus/icons-vue": {
"version": "1.1.4",
"resolved": "https://registry.npmmirror.com/@element-plus/icons-vue/-/icons-vue-1.1.4.tgz",
"integrity": "sha512-Iz/nHqdp1sFPmdzRwHkEQQA3lKvoObk8azgABZ81QUOpW9s/lUyQVUSh0tNtEPZXQlKwlSh7SPgoVxzrE0uuVQ==",
"version": "2.1.0",
"resolved": "https://registry.npmmirror.com/@element-plus/icons-vue/-/icons-vue-2.1.0.tgz",
"integrity": "sha512-PSBn3elNoanENc1vnCfh+3WA9fimRC7n+fWkf3rE5jvv+aBohNHABC/KAR5KWPecxWxDTVT1ERpRbOMRcOV/vA==",
"requires": {}
},
"@eslint/eslintrc": {
@ -14932,6 +14941,12 @@
"normalize-wheel-es": "^1.1.2"
},
"dependencies": {
"@element-plus/icons-vue": {
"version": "1.1.4",
"resolved": "https://registry.npmmirror.com/@element-plus/icons-vue/-/icons-vue-1.1.4.tgz",
"integrity": "sha512-Iz/nHqdp1sFPmdzRwHkEQQA3lKvoObk8azgABZ81QUOpW9s/lUyQVUSh0tNtEPZXQlKwlSh7SPgoVxzrE0uuVQ==",
"requires": {}
},
"@popperjs/core": {
"version": "npm:@sxzz/popperjs-es@2.11.7",
"resolved": "https://registry.npmmirror.com/@sxzz/popperjs-es/-/popperjs-es-2.11.7.tgz",

View File

@ -8,6 +8,7 @@
"lint": "vue-cli-service lint"
},
"dependencies": {
"@element-plus/icons-vue": "^2.1.0",
"axios": "^0.27.2",
"core-js": "^3.8.3",
"element-plus": "^2.1.11",

View File

@ -0,0 +1,42 @@
<template>
<div>
<el-dialog
v-show="show"
title="聊天配置"
width="30%"
:before-close="beforeClose"
>
<span>正在努力开发中...</span>
<template #footer>
<span class="dialog-footer">
<el-button @click="show = false">取消</el-button>
<el-button type="primary" @click="show = false">
保存
</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script>
import {defineComponent} from "vue"
export default defineComponent({
name: 'ConfigDialog',
data() {
return {
show: true
}
},
methods: {
beforeClose: function () {
}
}
})
</script>
<style lang="stylus">
</style>

View File

@ -15,26 +15,33 @@
</div><!-- end chat box -->
<div class="input-box" :style="{width: inputBoxWidth+'px'}" id="input-box">
<div class="input-box">
<div class="input-container">
<textarea class="input-text" id="input-text" rows="1" :style="{minHeight:'24px', height: textHeight+'px'}"
v-on:keydown="inputKeyDown"
v-model="inputValue"
placeholder="Input any thing here..."
v-on:focus="focus"></textarea>
<el-input
v-model="inputValue"
:autosize="{ minRows: 1, maxRows: 10 }"
v-on:keydown="inputKeyDown"
v-on:focus="focus"
type="textarea"
placeholder="Input any thing here..."
/>
</div>
<div class="btn-container">
<button type="button"
class="btn btn-success"
:disabled="sending"
v-on:click="sendMessage">发送
</button>
<el-row>
<el-button type="success" class="send" :disabled="sending" v-on:click="sendMessage">发送</el-button>
<el-button type="danger" class="config" circle @click="showDialog = true">
<el-icon>
<Tools/>
</el-icon>
</el-button>
</el-row>
</div>
</div><!-- end input box -->
</div><!-- end container -->
<config-dialog v-model="showDialog"></config-dialog>
</div>
</template>
@ -44,21 +51,19 @@ import ChatPrompt from "@/components/ChatPrompt.vue";
import ChatReply from "@/components/ChatReply.vue";
import {randString} from "@/utils/libs";
import {ElMessage} from 'element-plus'
import {Tools} from '@element-plus/icons-vue'
import ConfigDialog from '@/components/ConfigDialog.vue'
export default defineComponent({
name: "XChat",
components: {ChatPrompt, ChatReply},
components: {ChatPrompt, ChatReply, Tools, ConfigDialog},
data() {
return {
title: "ChatGPT 控制台",
chatData: [],
inputBoxHeight: 63,
inputBoxWidth: 0,
inputValue: '',
textHeight: 24,
textWidth: 0,
chatBoxHeight: 0,
isMobile: false,
showDialog: false,
socket: null,
sending: false
@ -69,24 +74,9 @@ export default defineComponent({
mounted: function () {
nextTick(() => {
this.inputBoxHeight = document.getElementById("input-box").offsetHeight;
this.textWidth = document.getElementById("input-text").offsetWidth;
this.chatBoxHeight = window.innerHeight - this.inputBoxHeight - 40;
this.chatBoxHeight = window.innerHeight - 61;
})
//访
const userAgentInfo = navigator.userAgent.toLowerCase();
const Agents = ["android", "iphone", "windows phone", "ipad", "ipod"];
for (let v = 0; v < Agents.length; v++) {
if (userAgentInfo.toLowerCase().indexOf(Agents[v]) >= 0) {
this.isMobile = true;
}
}
this.inputBoxWidth = window.innerWidth;
window.addEventListener('resize', this.windowResize);
// WebSocket
const socket = new WebSocket(process.env.VUE_APP_WS_HOST + '/api/chat');
socket.addEventListener('open', () => {
@ -135,23 +125,15 @@ export default defineComponent({
},
beforeUnmount() {
window.removeEventListener("resize", this.windowResize);
},
methods: {
inputKeyDown: function (e) {
if (e.keyCode === 13) {
if (!this.isMobile) { // PC
if (this.sending) {
e.preventDefault();
return this.sendMessage();
} else {
return this.inputResize(true);
this.sendMessage();
}
}
this.inputResize(false);
},
//
@ -172,55 +154,16 @@ export default defineComponent({
this.sending = true;
this.socket.send(this.inputValue);
this.inputValue = '';
this.inputResize(false);
return true;
},
/**
* 根据输入内容的多少动态调整输入框的大小
* @param flag 是否输入回车键如果输入了回车键则需要增加一行
*/
inputResize: function (flag) {
let line = 1;
if (flag) {
line++;
}
let textWidth = 0;
for (let i in this.inputValue) {
if (this.inputValue[i] === '\n') {
line++;
textWidth = 0; //
continue;
}
if (this.inputValue.charCodeAt(Number(i)) < 128) {
textWidth += 8; //
} else {
textWidth += 16; //
}
if (textWidth >= this.textWidth) { //
textWidth = textWidth - this.textWidth;
line++;
}
}
this.inputBoxHeight = 63 + (line - 1) * 24;
this.textHeight = line * 24;
},
windowResize: function () {
this.inputResize(false);
this.chatBoxHeight = window.innerHeight - this.inputBoxHeight - 40;
this.inputBoxWidth = window.innerWidth;
},
//
focus: function () {
setTimeout(function () {
document.getElementById('container').scrollTo(0, document.getElementById('container').scrollHeight)
}, 200)
}
},
},
})
@ -267,12 +210,13 @@ export default defineComponent({
.input-box {
padding 10px;
width 100%;
position: absolute;
bottom: 0
display: flex;
justify-content: center;
align-items: flex-start;
justify-content: start;
align-items: center;
.input-container {
overflow hidden
@ -306,8 +250,15 @@ export default defineComponent({
.btn-container {
margin-left 10px;
button {
width 70px;
.el-row {
flex-wrap nowrap
width 106px;
align-items center
}
.send {
width 60px;
height 40px;
}
}
}