feat: 在线客服(移动端)聊天静态界面
parent
e025ee6f64
commit
b6997d4158
Binary file not shown.
|
After Width: | Height: | Size: 9.7 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 10 KiB |
@ -0,0 +1,22 @@
|
|||||||
|
import { defineStore } from 'pinia';
|
||||||
|
|
||||||
|
export default defineStore('chat', {
|
||||||
|
state: () => ({
|
||||||
|
messages: [
|
||||||
|
{
|
||||||
|
role: 'system',
|
||||||
|
content: '查询中,请稍后!',
|
||||||
|
cmd: 'common',
|
||||||
|
timestamp: new Date().getTime(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
actions: {
|
||||||
|
addMessage(message: Array<[]>) {
|
||||||
|
this.messages.push({
|
||||||
|
...message,
|
||||||
|
timestamp: new Date().getTime(),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
@ -0,0 +1,133 @@
|
|||||||
|
<template>
|
||||||
|
<div class="chat-input">
|
||||||
|
<!-- 输入框 -->
|
||||||
|
<div class="input-box">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
class="input"
|
||||||
|
:value="input"
|
||||||
|
readonly
|
||||||
|
placeholder=""
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 数字键盘 -->
|
||||||
|
<div class="keyboard-grid">
|
||||||
|
<div
|
||||||
|
v-for="(key, index) in keyboardKeys"
|
||||||
|
:key="index"
|
||||||
|
class="keyboard-key"
|
||||||
|
:class="{ 'keyboard-key-delete': key === 'delete', 'keyboard-key-confirm': key === 'confirm' }"
|
||||||
|
@click="handleInput(key)"
|
||||||
|
>
|
||||||
|
<span v-if="key === 'delete'">
|
||||||
|
<span>删除</span>
|
||||||
|
</span>
|
||||||
|
<span v-else-if="key === 'confirm'">发送</span>
|
||||||
|
<span v-else>{{ key }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import useChatStore from '@/store/modules/chat';
|
||||||
|
|
||||||
|
const $store = useChatStore();
|
||||||
|
|
||||||
|
const addMessage = (message) => {
|
||||||
|
$store.addMessage({
|
||||||
|
role: 'user',
|
||||||
|
cmd: 'common',
|
||||||
|
senderName: '匿名',
|
||||||
|
content: message,
|
||||||
|
});
|
||||||
|
input.value = '';
|
||||||
|
};
|
||||||
|
|
||||||
|
const input = ref('');
|
||||||
|
const keyboardKeys = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '*', '0', '#', 'delete', 'confirm'];
|
||||||
|
|
||||||
|
const handleInput = (char) => {
|
||||||
|
if (char === 'delete') {
|
||||||
|
input.value = input.value.slice(0, -1);
|
||||||
|
} else if (char === 'confirm') {
|
||||||
|
addMessage(input.value);
|
||||||
|
} else {
|
||||||
|
input.value += char;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.chat-input {
|
||||||
|
position: relative;
|
||||||
|
height: 320px;
|
||||||
|
background: #fff;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
z-index: 9;
|
||||||
|
}
|
||||||
|
.input-box {
|
||||||
|
box-sizing: border-box;
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 70px;
|
||||||
|
padding: 15px;
|
||||||
|
}
|
||||||
|
.input {
|
||||||
|
box-sizing: border-box;
|
||||||
|
border-radius: 8px;
|
||||||
|
overflow: hidden;
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
border: 2px solid transparent;
|
||||||
|
background:
|
||||||
|
linear-gradient(white, white) padding-box,
|
||||||
|
linear-gradient(45deg, #f6855c, #e29cf9, #5cacfe) border-box;
|
||||||
|
padding-left: 5px;
|
||||||
|
}
|
||||||
|
.keyboard-grid {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 250px;
|
||||||
|
background: #d1d5db;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(4, 1fr);
|
||||||
|
grid-template-rows: repeat(4, 1fr);
|
||||||
|
grid-gap: 10px 6px;
|
||||||
|
padding: 10px 6px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.keyboard-grid .keyboard-key {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 25px;
|
||||||
|
border-radius: 5px;
|
||||||
|
box-shadow: 0 1px 0 0 #898a8d;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
.keyboard-key-delete,
|
||||||
|
.keyboard-key-confirm {
|
||||||
|
grid-column: 4;
|
||||||
|
font-size: 18px !important;
|
||||||
|
}
|
||||||
|
.keyboard-key-delete {
|
||||||
|
grid-row: 1 / span 2;
|
||||||
|
}
|
||||||
|
.keyboard-key-confirm {
|
||||||
|
grid-row: 3 / span 2;
|
||||||
|
}
|
||||||
|
.keyboard-key-delete > span {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-self: center;
|
||||||
|
}
|
||||||
|
.keyboard-key-delete > span > span {
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, onMounted, onUnmounted } from 'vue';
|
||||||
|
import ChatInput from './components/ChatInput.vue';
|
||||||
|
import ChatMessages from './components/ChatMessages.vue';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="chat-container">
|
||||||
|
<!-- 聊天内容区域 -->
|
||||||
|
<ChatMessages />
|
||||||
|
|
||||||
|
<!-- 底部输入区域 -->
|
||||||
|
<ChatInput />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.chat-container {
|
||||||
|
width: 100vw;
|
||||||
|
height: calc(100vh - 48px - 33px);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
background-color: #f7f8fa;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Loading…
Reference in New Issue