From 8c4c26f554cb2a1edad849df9c2d3d7bd1cdc949 Mon Sep 17 00:00:00 2001 From: THK3121 <thk121969318@163.com> Date: Wed, 11 Oct 2023 16:59:50 +0800 Subject: [PATCH] =?UTF-8?q?im=E9=A1=B5=E9=9D=A2=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 +- src/api/talk.ts | 22 ++ src/assets/images/SP.png | Bin 0 -> 5848 bytes src/assets/images/XC.png | Bin 0 -> 5791 bytes src/config/index.ts | 14 +- src/utils/request/indexs.ts | 131 +++++++ src/views/business/index.vue | 686 +++++++++++++++++++++++++++++++++++ 7 files changed, 852 insertions(+), 7 deletions(-) create mode 100644 src/api/talk.ts create mode 100644 src/assets/images/SP.png create mode 100644 src/assets/images/XC.png create mode 100644 src/utils/request/indexs.ts create mode 100644 src/views/business/index.vue diff --git a/README.md b/README.md index 2a2fad7..343abb1 100644 --- a/README.md +++ b/README.md @@ -13,8 +13,8 @@ TypeScript cannot handle type information for `.vue` imports by default, so we r If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: 1. Disable the built-in TypeScript Extension - 1. Run `Extensions: Show Built-in Extensions` from VSCode's command palette - 2. Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` 2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. ## Customize configuration @@ -44,5 +44,3 @@ npm run build ```sh npm run lint ``` - -zmj 分支 diff --git a/src/api/talk.ts b/src/api/talk.ts new file mode 100644 index 0000000..ca397c3 --- /dev/null +++ b/src/api/talk.ts @@ -0,0 +1,22 @@ +import request from "@/utils/request/indexs"; + +/** + * 绑定scoket + */ +export const bindScoket = (data: any) => + request.post({ url: "/common/im/doBindUid", data }); +// 发送消息 +export const sendMsgApi = (data: any) => + request.post({ url: "/common/im/sendTextMsg", data }); +// 发送文件 +export const sendFileApi = (data: any) => + request.post({ url: "/common/im/sendFileMsg", data }); +// 消息列表 +export const getMsgListApi = (data: any) => + request.post({ url: "/common/im/msgList", data }); +// 片区经理id +export const getAreaManagerApi = (data: any) => + request.post({ url: "/common/im/getAreaManager", data }); +// 联系人列表 +export const getContactListApi = (data: any) => + request.post({ url: "/common/im/contactList", data }); diff --git a/src/assets/images/SP.png b/src/assets/images/SP.png new file mode 100644 index 0000000000000000000000000000000000000000..a786f632b32c4ffb5d16eebfcb61a9da623511c0 GIT binary patch literal 5848 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 PQZ-0V+eoVd?G*YSEvZYz literal 0 HcmV?d00001 diff --git a/src/assets/images/XC.png b/src/assets/images/XC.png new file mode 100644 index 0000000000000000000000000000000000000000..e9eba659d1b75a4c32ae586be0a9a25bafd7436e GIT binary patch literal 5791 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 OknzRK`Y&|x_x}sa-!)7C literal 0 HcmV?d00001 diff --git a/src/config/index.ts b/src/config/index.ts index efe50ec..b6d5725 100644 --- a/src/config/index.ts +++ b/src/config/index.ts @@ -2,11 +2,19 @@ const config = { terminal: 1, //终端 title: "后台管理系统", //网站默认标题 version: "1.6.0", //版本号 - baseUrl: `${ - import.meta.env.VITE_APP_BASE_URL - }/`, //请求接口域名 + baseUrl: `${import.meta.env.VITE_APP_BASE_URL}/`, //请求接口域名 urlPrefix: "adminapi", //请求默认前缀 timeout: 20 * 1000, //请求超时时长 }; export default config; +// const config = { +// terminal: 1, //终端 +// title: "后台管理系统", //网站默认标题 +// version: "1.6.0", //版本号 +// baseUrl: `https://worker-task.lihaink.cn`, //请求接口域名 +// urlPrefix: "adminapi", //请求默认前缀 +// timeout: 20 * 1000, //请求超时时长 +// }; + +// export default config; diff --git a/src/utils/request/indexs.ts b/src/utils/request/indexs.ts new file mode 100644 index 0000000..530f736 --- /dev/null +++ b/src/utils/request/indexs.ts @@ -0,0 +1,131 @@ +import { merge } from "lodash"; +import configs from "@/config"; +import { Axios } from "./axios"; +import { + ContentTypeEnum, + RequestCodeEnum, + RequestMethodsEnum, +} from "@/enums/requestEnums"; +import type { AxiosHooks } from "./type"; +import { clearAuthInfo, getToken } from "../auth"; +import feedback from "../feedback"; +import NProgress from "nprogress"; +import { AxiosError, type AxiosRequestConfig } from "axios"; +import router from "@/router"; +import { PageEnum } from "@/enums/pageEnum"; + +// 处理axios的钩子函数 +const axiosHooks: AxiosHooks = { + requestInterceptorsHook(config) { + NProgress.start(); + const { withToken, isParamsToData } = config.requestOptions; + const params = config.params || {}; + const headers = config.headers || {}; + + // 添加token + if (withToken) { + const token = getToken(); + headers.token = token; + } + // POST请求下如果无data,则将params视为data + if ( + isParamsToData && + !Reflect.has(config, "data") && + config.method?.toUpperCase() === RequestMethodsEnum.POST + ) { + config.data = params; + config.params = {}; + } + config.headers = headers; + return config; + }, + requestInterceptorsCatchHook(err) { + NProgress.done(); + return err; + }, + async responseInterceptorsHook(response) { + NProgress.done(); + const { isTransformResponse, isReturnDefaultResponse } = + response.config.requestOptions; + + //返回默认响应,当需要获取响应头及其他数据时可使用 + if (isReturnDefaultResponse) { + return response; + } + // 是否需要对数据进行处理 + if (!isTransformResponse) { + return response.data; + } + const { code, data, show, msg } = response.data; + switch (code) { + case RequestCodeEnum.SUCCESS: + if (show) { + msg && feedback.msgSuccess(msg); + } + return data; + case RequestCodeEnum.FAIL: + if (show) { + msg && feedback.msgError(msg); + } + return Promise.reject(data); + case RequestCodeEnum.LOGIN_FAILURE: + clearAuthInfo(); + router.push(PageEnum.LOGIN); + return Promise.reject(); + case RequestCodeEnum.OPEN_NEW_PAGE: + window.location.href = data.url; + return data; + default: + return data; + } + }, + responseInterceptorsCatchHook(error) { + NProgress.done(); + if (error.code !== AxiosError.ERR_CANCELED) { + error.message && feedback.msgError(error.message); + } + return Promise.reject(error); + }, +}; + +const defaultOptions: AxiosRequestConfig = { + //接口超时时间 + timeout: configs.timeout, + // 基础接口地 + baseURL: configs.baseUrl, + + // baseURL: "http://192.168.1.11:8081/", + + //请求头 + headers: { "Content-Type": ContentTypeEnum.JSON, version: configs.version }, + // 处理 axios的钩子函数 + axiosHooks: axiosHooks, + // 每个接口可以单独配置 + requestOptions: { + // 是否将params视为data参数,仅限post请求 + isParamsToData: true, + //是否返回默认的响应 + isReturnDefaultResponse: false, + // 需要对返回数据进行处理 + isTransformResponse: true, + // 接口拼接地址 + urlPrefix: "", + // 忽略重复请求 + ignoreCancelToken: false, + // 是否携带token + withToken: true, + // 开启请求超时重新发起请求请求机制 + isOpenRetry: true, + // 重新请求次数 + retryCount: 2, + }, +}; + +function createAxios(opt?: Partial<AxiosRequestConfig>) { + return new Axios( + // 深度合并 + merge(defaultOptions, opt || {}) + ); +} +const request = createAxios(); +export default request; diff --git a/src/views/business/index.vue b/src/views/business/index.vue new file mode 100644 index 0000000..9454242 --- /dev/null +++ b/src/views/business/index.vue @@ -0,0 +1,686 @@ +<template> + <div class="box"> + <div class="talk-list"> + <div class="mt-4 serch"> + <el-input v-model="queryUserName" placeholder="搜索联系人" class="input-with-select"> + <template #append> + <el-button :icon="Search" @click="serchUserFn" /> + </template> + </el-input> + </div> + <div style="height: 5vh;"></div> + + <div class="contacts" v-for="(item, index) in userList" :key="index" @click="choseTalkFn(item, index)"> + <div class="l"> + <div style="position: relative;"> + <el-image style="width: 40px; height: 40px" :src="item.avatar" /> + <div class="brage" v-if="item.no_read_num">{{ item.no_read_num }}</div> + </div> + <div class="tit-a"> + <div>{{ item.name }}</div> + <div v-if="item.last_msg_type == 'text'" class="value">{{ item.last_msg_content }}</div> + <div v-if="item.last_msg_type == 'image'" class="value">[图片]</div> + <div v-if="item.last_msg_type == 'video'" class="value">[视频]</div> + </div> + </div> + <div class="r"> + {{ timeFn(item.last_msg_time) }} + </div> + </div> + </div> + <div class="talk-detail" id="content"> + <div class="top"> + {{ talkDetail.name }} + </div> + <div style="height: 4vh"></div> + <div class="center" id="center" @scroll="handleScroll"> + <div class="talk" v-for="(item, index) in talkDetail.talkList" :key="index"> + + <div style="text-align: center;" v-show="index % 5 == 0">{{ timeFn(item.create_time) }}</div> + <!-- 我的消息 --> + <div class="my_task" v-if="item.from_user_id == user_id"> + <div class="content"> + <!-- 文本 --> + <div v-if="item.type == 'text'"> + <a :href="item.content" v-if="isLink(item.content)" target="_blank" + style="color: #576B95;">{{ + item.content }} + </a> + <div v-else> {{ item.content }}</div> + </div> + <!-- 图片 --> + <div v-if="item.type == 'image'"> + <el-image style="width: 100px;height: auto;" :src="item.content" :preview-src-list="srcList" + @click="PreviewImgFn(item)"></el-image> + </div> + <!-- 视频 --> + <div v-if="item.type == 'video'"> + <video controls :src="item.content"></video> + </div> + </div> + <el-image style="width: 40px; height: 40px" :src="userStore.userInfo.avatar" /> + </div> + <!-- 对方消息 --> + <div class="to_task" v-else> + <el-image style="width: 40px; height: 40px;margin-right: 5px;" :src="item.from_user_avatar" /> + <div class="content"> + <!-- 文本 --> + <div v-if="item.type == 'text'"> + <a :href="item.content" target="_blank" v-if="isLink(item.content)" + style="color: #576B95;">{{ + item.content }} + </a> + <div v-else> {{ item.content }}</div> + </div> + <!-- 图片 --> + <div v-if="item.type == 'image'"> + <el-image style="width: 100px;height: auto;" :src="item.content" :preview-src-list="srcList" + @click="PreviewImgFn(item)"></el-image> + </div> + <!-- 视频 --> + <div v-if="item.type == 'video'"> + <video controls :src="item.content"></video> + </div> + </div> + </div> + + </div> + <!-- 本地 --> + <div v-show="item.status" class="my_task" v-for="item, index in local"> + <!-- <div></div> --> + <!-- <div >上传中</div> --> + <div class="content" v-loading="true"> + <div style="width: 120px;margin-right: 10px;"> + <video controls :src="item.localSrc" v-if="item.type == 'video'"></video> + <img controls :src="item.localSrc" v-else /> + </div> + <!-- <el-progress :text-inside="true" :stroke-width="14" :percentage="item.percentage" /> --> + </div> + <el-image style="width: 40px; height: 40px;margin-right: 10px;" :src="url" /> + </div> + + </div> + <div class="bottom"> + <div style="display: flex;"> + <el-upload :action="base_url + '/common/im/sendFileMsg'" :data="{ + from_user_id: user_id, + to_user_id: talkDetail.to_user_id, + scene: 1, + type: 'image', + msg_id: msg_id + + }" multiple :show-file-list="false" :on-success="handleAvatarSuccess" :before-upload="changeFile"> + <img class="img_cls" src="@/assets/images/XC.png" style="width: 50px;height: 50px;" /> + </el-upload> + <el-upload :action="base_url + '/common/im/sendFileMsg'" :data="{ + from_user_id: user_id, + to_user_id: talkDetail.to_user_id, + scene: 1, + type: 'video', + msg_id: msg_id + }" multiple :show-file-list="false" :on-success="handleAvatarSuccess" :before-upload="changeFile1"> + + <img style="width: 50px; height: 50px" src="@/assets/images/SP.png" /> + </el-upload> + </div> + <el-input v-model="textarea" style="border: none;outline: none;" placeholder="请输入..." + @keydown="keyup_submit(event)" /> + <div class="send-btn" @click="sendMsgFn">发送</div> + </div> + <!-- <div style="height: 30vh;"></div> --> + </div> + </div> +</template> + +<script lang="ts" scoped setup> +import { reactive, ref, onBeforeUnmount } from 'vue'; +import { Search } from '@element-plus/icons-vue' +import feedback from '@/utils/feedback' +import { + sendMsgApi, getMsgListApi, bindScoket, sendFileApi, getContactListApi +} from "@/api/talk" +import { ElMessage } from 'element-plus' +import useUserStore from "@/stores/modules/user"; +import { inject } from "vue"; +const base_url: any = inject("base_url").replace('adminapi', ''); +const userStore = useUserStore(); +const user_id = userStore.userInfo.id +let page_no = 1 +let to_id: any = null +// 图片预览 +const srcList: any = reactive( + [] +) +const PreviewImgFn = (item: any) => { + srcList[0] = item.content +} +// 上拉加载 +const handleScroll = (e) => { + let top = e.target.scrollTop + if (top <= 0) { + page_no++ + getMsgListApi({ + from_user_id: user_id, + to_user_id: to_id, + scene: 1, + page_no: page_no, + page_size: 10 + }).then(res2 => { + if (res2.length <= 0) return + talkDetail.talkList = res2.reverse().concat(talkDetail.talkList) + e.target.scrollTop = 100 + }) + } +} +let bind = false +// 获取用户列表 +const userList = reactive([]) +let queryList = reactive([]) +const talkDetail = reactive({ + name: "", + to_user_id: "", + talkList: [], + index: 0, +}) +getContactListApi({ user_id: user_id }).then(res => { + res.forEach((element: any) => { + userList.push(element) + queryList.push(element) + }); + // queryList = userList + console.log(queryList, 6666) + talkDetail.name = userList[0].name + talkDetail.to_user_id = userList[0].id + to_id = userList[0].id + getMsgListApi({ + from_user_id: user_id, + to_user_id: userList[0].id, + scene: 1, + page_no: 1, + page_size: 10 + }).then(res2 => { + talkDetail.talkList = res2.reverse() + // console.log(talkDetail) + }) +}) +const url = 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg' +// 用户搜索 +const queryUserName = ref('') +const serchUserFn = () => { + getContactListApi({ user_id: user_id, keywords: queryUserName.value }).then(res => { + userList.splice(0, userList.length); + res.forEach((element: any) => { + // @ts-ignore + userList.push(element) + // queryList.push(element) + }); + }) +} +// 发送文本消息 +const isLink = (text: string) => { + var pattern = /^(https?:\/\/|www\.|.*\.com).*$/i; + return pattern.test(text); +} +const textarea = ref("") +const sendMsgFn = () => { + if (!textarea.value) return + sendMsgApi({ + from_user_id: user_id, + to_user_id: talkDetail.to_user_id, + type: "text", + content: textarea.value, + scene: 1, + msg_id: msg_id.value + }).then(res => { + talkDetail.talkList.push(res) + userList[talkDetail.index].last_msg_content = textarea.value + userList[talkDetail.index].last_msg_time = res.create_time + userList[talkDetail.index].last_msg_type = 'text' + // userList[talkDetail.index].last_msg_content = textarea.value + scrollFn() + textarea.value = "" + generateRandId() + + + }) +} +const keyup_submit = (evt: any) => { + var evt = window.event || evt; + if (evt.keyCode == 13) { + sendMsgFn() + } +} +// 发送媒体消息 +let msg_id: any = ref('') +const generateRandId = () => { + var d = new Date().getTime(); + var uuid = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) { + var r = (d + Math.random() * 16) % 16 | 0; + d = Math.floor(d / 16); + return (c == "x" ? r : r & 0x3 | 0x8).toString(16); + }); + // return uuid; + msg_id.value = uuid +} +generateRandId() +const local = reactive([]) +let localData = () => { + return { + status: false, + localType: null, + localSrc: null, + type: "", + percentage: 0, + msg_id: msg_id.value + } +} +const changeFile = (res) => { + console.log(res.type) + + if (!res.type.includes('image')) { + ElMessage.error('请选择正确的图片格式!!') + return false + } + local.push(localData()) + let type = 'image' + var localIndex = local.findIndex(function (element) { + return element.msg_id === msg_id.value; + }); + // userList[talkDetail.index].last_msg_type = type + let file = res + local[localIndex].type = type + const blob = file; + var reader = new FileReader(); + reader.readAsDataURL(blob); + //监听文件读取结束后事件 + reader.onloadend = function (e) { + local[localIndex].status = true + local[localIndex].localSrc = e.target?.result + scrollFn() + generateRandId() + }; +} +const changeFile1 = (res) => { + if (!res.type.includes('video')) { + ElMessage.error('请选择正确的视频格式!!') + return false + } + local.push(localData()) + let type = 'video' + var localIndex = local.findIndex(function (element) { + return element.msg_id === msg_id.value; + }); + // userList[talkDetail.index].last_msg_type = type + let file = res + local[localIndex].type = type + const blob = file; + var reader = new FileReader(); + reader.readAsDataURL(blob); + //监听文件读取结束后事件 + reader.onloadend = function (e) { + local[localIndex].status = true + local[localIndex].localSrc = e.target?.result + scrollFn() + generateRandId() + }; +} +const handleAvatarSuccess: any = ( + res: any +) => { + if (res.show == 0) { + talkDetail.talkList.push(res.data) + } + else { + feedback.msgError(res.msg) + } + var localIndex = local.findIndex(function (element) { + return element.msg_id === res.data.msg_id; + }); + local[localIndex].status = false + userList[talkDetail.index].last_msg_type = res.data.type + console.log(res.data) + +} +// 选择聊天 +const choseTalkFn = (item: any, index: number) => { + userList[index].no_read_num = 0 + talkDetail.name = item.name + talkDetail.to_user_id = item.id + talkDetail.index = index + to_id = item.id + getMsgListApi({ + from_user_id: user_id, + to_user_id: item.id, + scene: 1, + page_no: 1, + page_size: 10 + }).then(res2 => { + talkDetail.talkList = res2.reverse() + scrollFn() + + }) +} +// 滚动底部 +let scrollTop: any = null +onMounted(() => { + scrollTop = document.getElementById('center') + +}) +const scrollFn = () => { + setTimeout(() => { + scrollTop.scrollTop = 9999999 + }, 100) +} +// 时间处理 +const timeFn = (time) => { + const currentDate = new Date(); // 当前日期对象 + const targetDate = new Date(time * 1000); + if (isSameDay(currentDate, targetDate)) { + const hours = targetDate.getHours(); // 小时 + const minutes = targetDate.getMinutes(); // 分钟 + return hours + ':' + (minutes < 10 ? '0' + minutes : minutes); + + } else if (isYesterday(currentDate, targetDate)) { + return '昨天'; + } + const month = targetDate.getMonth() + 1; // 月份(注意月份从0开始,需要加1) + const day = targetDate.getDate(); // 日期 + return month + '月' + day + '日'; + + +} +const isSameDay = (date1, date2) => { + return ( + date1.getFullYear() === date2.getFullYear() && + date1.getMonth() === date2.getMonth() && + date1.getDate() === date2.getDate() + ); +} +const isYesterday = (currentDate, targetDate) => { + const yesterday = new Date(currentDate.getFullYear(), currentDate.getMonth(), currentDate.getDate() - 1); + return isSameDay(yesterday, targetDate); +} +// scoket +const socket = new WebSocket('wss://worker-task.lihaink.cn/wss'); +const onSocketOpen = (event: any) => { + console.log('WebSocket连接已打开'); +} +const onSocketMessage = (event: any) => { + let data = JSON.parse(event.data) + if (!bind) { + let client_id = (JSON.parse(event.data).client_id) + bindScoket({ + client_id: client_id, + user_id: user_id, + scene: 1, + }).then(res => { + bind = true + console.log('绑定成功') + }) + } + else if (data.id) { + var index = userList.findIndex(function (element) { + return element.id == data.from_user_id; + }); + // talkDetail.talkList.push(data) + if (data.from_user_id == talkDetail.to_user_id) { + console.log(data, "收到scoket消息") + talkDetail.talkList.push(data) + userList[index].last_msg_content = data.content + userList[index].last_msg_time = data.create_time + userList[index].last_msg_type = data.type + + scrollFn() + } else { + userList[index].no_read_num++ + userList[index].last_msg_content = data.content + userList[index].last_msg_time = data.create_time + userList[index].last_msg_type = data.type + + // userList.forEach + } + } + console.log(data) +} +const onSocketClose = (event: any) => { + console.log('WebSocket连接已关闭'); +} +const onSocketError = (event: any) => { + console.error('WebSocket连接发生错误'); +} +socket.addEventListener('open', onSocketOpen); +socket.addEventListener('message', onSocketMessage); +socket.addEventListener('close', onSocketClose); +socket.addEventListener('error', onSocketError); +onBeforeUnmount(() => { + socket.close() +}) + +</script> + +<style lang="scss" scoped> +:deep(.el-input__wrapper) { + box-shadow: none !important; + // border-bottom: 1px solid black; + border-radius: 0; +} + +.box { + display: flex; + + .serch { + background-color: #F6F6F6; + position: fixed; + top: 9vh; + width: 17vw; + z-index: 99; + padding-left: 10px; + padding-top: 10px; + + } + + .talk-list { + width: 20vw; + overflow: hidden; + height: 85vh; + position: relative; + // background-color: #fff; + cursor: pointer; + + .contacts { + // margin-bottom: 10px; + // background-color: red; + padding: 10px; + display: flex; + justify-content: space-between; + + .l { + display: flex; + + .tit-a { + margin-left: 10px; + display: flex; + flex-direction: column; + justify-content: space-around; + + .value { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + width: 8vw; + + } + + } + } + } + + } + + .contacts:active { + background-color: #fff; + } + + .contacts:hover { + background-color: #fff; + + } + + .talk-list::-webkit-scrollbar { + width: 2px; + /* 滚动条宽度 */ + } + + .talk-list::-webkit-scrollbar-thumb { + background-color: #888; + /* 滚动条颜色 */ + border-radius: 1px; + /* 滚动条圆角 */ + } + + .img_cls { + + margin-right: 10PX; + margin-bottom: 10PX; + cursor: pointer; + } + + .talk-list:hover { + // background-color: #888; + overflow: scroll; + + } + + .talk-detail { + width: 80vw; + height: 85vh; + + .top { + position: fixed; + height: 4vh; + width: 70vw; + box-sizing: border-box; + padding: 10px; + background-color: #fff; + z-index: 9; + border-bottom: 1px solid #EAE8E7; + } + + .center { + height: 65vh; + + overflow-y: scroll; + background-color: #fff; + + } + + .bottom { + position: fixed; + background-color: white; + height: 20vh; + border-top: 1px solid #EAE8E7; + width: 70vw; + box-sizing: border-box; + // padding-top: 10px; + padding: 10px; + } + + // overflow: scroll; + + } + + + + .center::-webkit-scrollbar { + width: 2px; + /* 滚动条宽度 */ + } + + .center::-webkit-scrollbar-thumb { + background-color: #888; + /* 滚动条颜色 */ + border-radius: 5px; + /* 滚动条圆角 */ + } + + .talk { + // height: 4vh; + // background-color: #fff; + padding: 10px; + margin-bottom: 10px; + + } + + .send-btn { + width: 50px; + height: 30px; + background-color: green; + color: white; + line-height: 30px; + text-align: center; + border-radius: 5px; + float: right; + margin-top: 5px; + cursor: pointer; + + } + + .send-btn:active { + background-color: yellowgreen; + } + + .my_task { + display: flex; + justify-content: flex-end; + + .content { + background-color: #95EC69; + border-radius: 5px; + // height: 30px; + padding: 5px; + // height: 40px; + // min-height: 40px; + margin-right: 5px; + line-height: 30px; + max-width: 20vw; + // overflow: hidden; + word-break: break-all; + overflow-wrap: break-word; + + } + } + + .to_task { + display: flex; + // justify-content: flex-end; + + .content { + background-color: #95EC69; + border-radius: 5px; + // height: 30px; + padding: 5px 10px; + // height: 40px; + // min-height: 40px; + margin-right: 5px; + line-height: 30px; + max-width: 20vw; + word-break: break-all; + overflow-wrap: break-word; + } + } + + .brage { + background-color: red; + color: white; + width: 16px; + height: 16px; + border-radius: 16px; + text-align: center; + line-height: 16px; + position: absolute; + font-size: 12px; + top: -8px; + right: -5px; + } +} +</style> \ No newline at end of file