新增OnlyOffice文档编辑器和Fluent图标库依赖,优化文件消息组件的下载功能,调整文本消息背景色,改进会话菜单逻辑,优化会话列表排序,修复部分样式问题。
This commit is contained in:
parent
91107e2f85
commit
0fe1119789
@ -18,6 +18,8 @@
|
||||
"@highlightjs/vue-plugin": "^2.1.0",
|
||||
"@iconify-json/ion": "^1.2.3",
|
||||
"@kangc/v-md-editor": "^2.3.18",
|
||||
"@onlyoffice/document-editor-vue": "^1.5.0",
|
||||
"@vicons/fluent": "^0.13.0",
|
||||
"@vicons/ionicons5": "^0.13.0",
|
||||
"@vueup/vue-quill": "^1.2.0",
|
||||
"@vueuse/core": "^10.7.0",
|
||||
|
@ -20,6 +20,12 @@ importers:
|
||||
'@kangc/v-md-editor':
|
||||
specifier: ^2.3.18
|
||||
version: 2.3.18(@vue/compiler-sfc@3.5.13)(vue@3.5.13(typescript@5.2.2))
|
||||
'@onlyoffice/document-editor-vue':
|
||||
specifier: ^1.5.0
|
||||
version: 1.5.0(vue@3.5.13(typescript@5.2.2))
|
||||
'@vicons/fluent':
|
||||
specifier: ^0.13.0
|
||||
version: 0.13.0
|
||||
'@vicons/ionicons5':
|
||||
specifier: ^0.13.0
|
||||
version: 0.13.0
|
||||
@ -594,6 +600,11 @@ packages:
|
||||
resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
|
||||
engines: {node: '>= 8'}
|
||||
|
||||
'@onlyoffice/document-editor-vue@1.5.0':
|
||||
resolution: {integrity: sha512-HZEebUhBloP4LomspI5BddgoQdhtPq91h57yA9K/Lk70MMc1vgOTQ4Wq+N5TZYXNxdDTv+TSsEVFLnBCl1Y71A==}
|
||||
peerDependencies:
|
||||
vue: ^3.0.0
|
||||
|
||||
'@parcel/watcher-android-arm64@2.5.1':
|
||||
resolution: {integrity: sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
@ -988,6 +999,9 @@ packages:
|
||||
peerDependencies:
|
||||
vue: ^3.0.0
|
||||
|
||||
'@vicons/fluent@0.13.0':
|
||||
resolution: {integrity: sha512-bYGZsOE3qzvm3Cm43e7tybgGlr5ZUpYqtRZq0g0Tfupe8jIzLolpvQLNUt1zS8Mgt6goTbUk5YH7Fkv16jkykg==}
|
||||
|
||||
'@vicons/ionicons5@0.13.0':
|
||||
resolution: {integrity: sha512-zvZKBPjEXKN7AXNo2Na2uy+nvuv6SP4KAMQxpKL2vfHMj0fSvuw7JZcOPCjQC3e7ayssKnaoFVAhbYcW6v41qQ==}
|
||||
|
||||
@ -4012,6 +4026,11 @@ snapshots:
|
||||
'@nodelib/fs.scandir': 2.1.5
|
||||
fastq: 1.19.1
|
||||
|
||||
'@onlyoffice/document-editor-vue@1.5.0(vue@3.5.13(typescript@5.2.2))':
|
||||
dependencies:
|
||||
lodash: 4.17.21
|
||||
vue: 3.5.13(typescript@5.2.2)
|
||||
|
||||
'@parcel/watcher-android-arm64@2.5.1':
|
||||
optional: true
|
||||
|
||||
@ -4390,6 +4409,8 @@ snapshots:
|
||||
dependencies:
|
||||
vue: 3.5.13(typescript@5.2.2)
|
||||
|
||||
'@vicons/fluent@0.13.0': {}
|
||||
|
||||
'@vicons/ionicons5@0.13.0': {}
|
||||
|
||||
'@vitejs/plugin-vue-jsx@3.1.0(vite@6.3.5(@types/node@18.19.99)(jiti@1.21.7)(less@4.3.0)(sass@1.88.0)(terser@5.39.2))(vue@3.5.13(typescript@5.2.2))':
|
||||
|
@ -206,7 +206,7 @@ textarea {
|
||||
border-radius: 2px;
|
||||
cursor: default;
|
||||
user-select: none;
|
||||
background-color: #dee0e3;
|
||||
|
||||
transform: scale(0.84);
|
||||
transform-origin: left;
|
||||
flex-shrink: 0;
|
||||
|
BIN
src/assets/image/dofd.png
Normal file
BIN
src/assets/image/dofd.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 396 B |
BIN
src/assets/image/xxxx@2x.png
Normal file
BIN
src/assets/image/xxxx@2x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 684 B |
@ -7,7 +7,8 @@ import excelText from '@/assets/image/excel-text.png'
|
||||
import wordText from '@/assets/image/word-text.png'
|
||||
import pdfText from '@/assets/image/pdf-text.png'
|
||||
import fileText from '@/assets/image/file-text.png'
|
||||
|
||||
import { ArrowDownload16Filled } from '@vicons/fluent'
|
||||
import { download } from '@/utils/functions.js'
|
||||
// 定义组件属性
|
||||
const props = defineProps({
|
||||
// 文件的额外信息
|
||||
@ -92,6 +93,20 @@ const handleClick = () => {
|
||||
'width=1200,height=900,left=200,top=200,toolbar=no,menubar=no,scrollbars=yes,resizable=yes,location=no,status=no'
|
||||
);
|
||||
}
|
||||
|
||||
// 处理下载事件
|
||||
const handleDownload = () => {
|
||||
download(props.data.msg_id)
|
||||
// const url = props.extra.path;
|
||||
// if (!url) return;
|
||||
// const a = document.createElement('a');
|
||||
// a.href = url;
|
||||
// a.download = url.split('/').pop() || 'download';
|
||||
// document.body.appendChild(a);
|
||||
// a.click();
|
||||
// document.body.removeChild(a);
|
||||
console.log('data',props.data)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -145,7 +160,14 @@ const handleClick = () => {
|
||||
</div>
|
||||
</div>
|
||||
<!-- 文件大小信息 -->
|
||||
<div class="flex justify-between items-center">
|
||||
<div class="file-size">{{ fileFormatSize(extra.size) }}</div>
|
||||
<div class="flex items-center">
|
||||
<div class="flex items-center" @click.stop="handleDownload"> <img class="w-11.7px h-11.74px mr-7px" src="@/assets/image/dofd.png" alt=""> <span class="text-12px text-#46299D">下载</span></div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -43,7 +43,7 @@ textContent = textReplaceEmoji(textContent)
|
||||
min-height: 30px;
|
||||
padding: 3px;
|
||||
color: var(--im-message-left-text-color);
|
||||
background: var(--im-message-left-bg-color);
|
||||
background: #F4F4FC;
|
||||
border-radius: 0px 10px 10px 10px;
|
||||
font-size: 14px;
|
||||
&.right {
|
||||
|
@ -1,17 +1,5 @@
|
||||
import { reactive, nextTick, computed, h, inject } from 'vue'
|
||||
import { ISession } from '@/types/chat'
|
||||
import { renderIcon } from '@/utils/util'
|
||||
import {
|
||||
ArrowUp,
|
||||
ArrowDown,
|
||||
Logout,
|
||||
Delete,
|
||||
Clear,
|
||||
Remind,
|
||||
CloseRemind,
|
||||
EditTwo,
|
||||
IdCard
|
||||
} from '@icon-park/vue-next'
|
||||
import { ServeTopTalkList, ServeDeleteTalkList, ServeSetNotDisturb } from '@/api/chat'
|
||||
import { useDialogueStore, useTalkStore } from '@/store'
|
||||
import { ServeSecedeGroup } from '@/api/group'
|
||||
@ -52,45 +40,45 @@ export function useSessionMenu() {
|
||||
|
||||
if (item.talk_type == 1) {
|
||||
options.push({
|
||||
icon: renderIcon(IdCard),
|
||||
|
||||
label: '好友信息',
|
||||
key: 'info'
|
||||
})
|
||||
|
||||
options.push({
|
||||
icon: renderIcon(EditTwo),
|
||||
|
||||
label: '修改备注',
|
||||
key: 'remark'
|
||||
})
|
||||
}
|
||||
|
||||
options.push({
|
||||
icon: renderIcon(item.is_top ? ArrowDown : ArrowUp),
|
||||
|
||||
label: item.is_top ? '取消置顶' : '会话置顶',
|
||||
key: 'top'
|
||||
})
|
||||
|
||||
options.push({
|
||||
icon: renderIcon(item.is_disturb ? Remind : CloseRemind),
|
||||
|
||||
label: item.is_disturb ? '关闭免打扰' : '开启免打扰',
|
||||
key: 'disturb'
|
||||
})
|
||||
|
||||
options.push({
|
||||
icon: renderIcon(Clear),
|
||||
|
||||
label: '移除会话',
|
||||
key: 'remove'
|
||||
})
|
||||
|
||||
if (item.talk_type == 1) {
|
||||
options.push({
|
||||
icon: renderIcon(Delete),
|
||||
|
||||
label: '删除好友',
|
||||
key: 'delete_contact'
|
||||
})
|
||||
} else {
|
||||
options.push({
|
||||
icon: renderIcon(Logout),
|
||||
|
||||
label: '退出群聊',
|
||||
key: 'signout_group'
|
||||
})
|
||||
|
@ -93,6 +93,7 @@ export const useTalkStore = defineStore('talk', {
|
||||
|
||||
resp.then(({ code, data }) => {
|
||||
if (code == 200) {
|
||||
|
||||
this.items = data.items.map((item: any) => {
|
||||
const value = formatTalkItem(item)
|
||||
|
||||
@ -104,7 +105,6 @@ export const useTalkStore = defineStore('talk', {
|
||||
if (value.is_robot == 1) {
|
||||
value.is_online = 1
|
||||
}
|
||||
|
||||
return value
|
||||
})
|
||||
|
||||
|
@ -229,15 +229,22 @@ const state = reactive({
|
||||
})
|
||||
|
||||
const items = computed((): ISession[] => {
|
||||
if (searchKeyword.value.length === 0) {
|
||||
return talkStore.talkItems
|
||||
}
|
||||
let filtered = talkStore.talkItems
|
||||
|
||||
return talkStore.talkItems.filter((item: ISession) => {
|
||||
if (searchKeyword.value.length > 0) {
|
||||
filtered = filtered.filter((item: ISession) => {
|
||||
let keyword = item.remark || item.name
|
||||
|
||||
return keyword.toLowerCase().indexOf(searchKeyword.value.toLowerCase()) != -1
|
||||
})
|
||||
}
|
||||
|
||||
// 置顶和非置顶分组
|
||||
const topItems = filtered
|
||||
.filter(item => item.is_top === 1)
|
||||
.sort((a, b) => new Date(b.updated_at).getTime() - new Date(a.updated_at).getTime())
|
||||
const normalItems = filtered.filter(item => item.is_top !== 1)
|
||||
|
||||
return [...topItems, ...normalItems]
|
||||
})
|
||||
watch(
|
||||
() => talkStore,
|
||||
|
@ -19,7 +19,7 @@ const labelColor=[
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="talk pointer" :class="{ actived: active }" @click="emit('tab-talk', data)">
|
||||
<div :class="`talk pointer ${data.is_top === 1 ? 'bg-#F3F3F3' : ''} ${active ? 'actived' : ''}`" @click="emit('tab-talk', data)">
|
||||
<div class="avatar-box relative">
|
||||
|
||||
<avatarModule showGroupType :mode="data?.group_type === 0 ? 1 : 2"
|
||||
@ -57,11 +57,13 @@ const labelColor=[
|
||||
</div>
|
||||
|
||||
<div class="tip">
|
||||
<div v-if="data.is_disturb" class="disturb">
|
||||
<div v-if="data.is_disturb" class="disturb flex justify-center items-center">
|
||||
<!-- <n-icon :component="CloseRemind" /> -->
|
||||
|
||||
<span class="badge">
|
||||
{{ data.unread_num > 99 ? '99+' : data.unread_num }}
|
||||
<span class="badge w-50px">
|
||||
<!-- {{ data.unread_num > 99 ? '99+' : data.unread_num }} -->
|
||||
<img src="@/assets/image/xxxx@2x.png" class="w-11.1px h-13px mr-6px" alt="">
|
||||
<span v-if="data.unread_num>0" class="w-10px h-10px bg-#D03050 rounded-50%"></span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@ -193,7 +195,6 @@ const labelColor=[
|
||||
display: flex;
|
||||
padding-left: 5px;
|
||||
align-items: center;
|
||||
|
||||
.unread {
|
||||
color: #8f959e;
|
||||
font-size: 12px;
|
||||
@ -216,7 +217,7 @@ const labelColor=[
|
||||
}
|
||||
}
|
||||
|
||||
--actived-bg: #ececec;
|
||||
--actived-bg: #EEE9F8;
|
||||
|
||||
&:hover,
|
||||
&.actived {
|
||||
|
@ -313,7 +313,7 @@ onMounted(() => {
|
||||
'multi-select-check': item.isCheck
|
||||
}">
|
||||
<!-- 多选按钮 -->
|
||||
<aside v-if="dialogueStore.isOpenMultiSelect" class="checkbox-column">
|
||||
<aside v-if="dialogueStore.isOpenMultiSelect" class="checkbox-column shrink-0">
|
||||
<n-checkbox size="small" :checked="item.isCheck" @update:checked="item.isCheck = !item.isCheck" />
|
||||
</aside>
|
||||
<!-- 头像信息 -->
|
||||
|
@ -1,23 +1,28 @@
|
||||
<template>
|
||||
<div id="office-div" ></div>
|
||||
<DocumentEditor
|
||||
id="docEditor"
|
||||
:documentServerUrl="documentServerUrl"
|
||||
:config="config"
|
||||
:events_onDocumentReady="onDocumentReady"
|
||||
:onLoadComponentError="onLoadComponentError"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { DocumentEditor } from "@onlyoffice/document-editor-vue"
|
||||
|
||||
const placeholderRef = ref(null)
|
||||
const documentServerUrl = 'https://onlyoffice.fontree.cn'
|
||||
|
||||
// 动态加载 OnlyOffice API 脚本
|
||||
function loadScript(src) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const script = document.createElement('script')
|
||||
script.type = 'text/javascript'
|
||||
script.src = src
|
||||
script.onload = resolve
|
||||
script.onerror = reject
|
||||
document.head.appendChild(script)
|
||||
})
|
||||
}
|
||||
onMounted(() => {
|
||||
// 动态插入 Content-Security-Policy meta 标签,只在本页面生效
|
||||
if (!document.querySelector('meta[http-equiv="Content-Security-Policy"]')) {
|
||||
const meta = document.createElement('meta')
|
||||
meta.httpEquiv = 'Content-Security-Policy'
|
||||
meta.content = 'upgrade-insecure-requests'
|
||||
document.head.appendChild(meta)
|
||||
}
|
||||
})
|
||||
|
||||
// 获取 URL 参数
|
||||
function getUrlParameter(name) {
|
||||
@ -42,24 +47,14 @@ function getDocumentTypes(url) {
|
||||
return types[extension] || { fileType: 'docx', documentType: 'word' }
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
// 动态插入 Content-Security-Policy meta 标签,只在本页面生效
|
||||
if (!document.querySelector('meta[http-equiv="Content-Security-Policy"]')) {
|
||||
const meta = document.createElement('meta')
|
||||
meta.httpEquiv = 'Content-Security-Policy'
|
||||
meta.content = 'upgrade-insecure-requests'
|
||||
document.head.appendChild(meta)
|
||||
}
|
||||
await loadScript('https://onlyoffice.fontree.cn/web-apps/apps/api/documents/api.js')
|
||||
const url = getUrlParameter('url')
|
||||
if (!url) {
|
||||
const url = getUrlParameter('url')
|
||||
if (!url) {
|
||||
alert('请提供文档 URL 参数')
|
||||
return
|
||||
}
|
||||
const fileName = url.split('/').pop()
|
||||
const { fileType, documentType } = getDocumentTypes(url)
|
||||
// eslint-disable-next-line no-undef
|
||||
new window.DocsAPI.DocEditor('office-div', {
|
||||
}
|
||||
const fileName = url ? url.split('/').pop() : ''
|
||||
const { fileType, documentType } = getDocumentTypes(url || '')
|
||||
|
||||
const config = {
|
||||
document: {
|
||||
fileType,
|
||||
key: 'doc_' + Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15),
|
||||
@ -80,14 +75,39 @@ onMounted(async () => {
|
||||
compactToolbar: true,
|
||||
hideRightMenu: false,
|
||||
compatibility: true,
|
||||
showReviewChanges: false
|
||||
showReviewChanges: false,
|
||||
loaderLogo: '', // 设置为空字符串来隐藏加载 logo
|
||||
logo: {
|
||||
image: '', // 设置为空字符串
|
||||
imageDark: '', // 设置为空字符串
|
||||
url: '', // 设置为空字符串
|
||||
visible: false // 设置为 false 来隐藏 logo
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const onDocumentReady = () => {
|
||||
console.log("文档加载完成")
|
||||
}
|
||||
|
||||
const onLoadComponentError = (errorCode, errorDescription) => {
|
||||
switch(errorCode) {
|
||||
case -1: // 加载组件时发生未知错误
|
||||
console.log(errorDescription)
|
||||
break
|
||||
case -2: // 从文档服务器加载 DocsAPI 时发生错误
|
||||
console.log(errorDescription)
|
||||
break
|
||||
case -3: // DocsAPI 未定义
|
||||
console.log(errorDescription)
|
||||
break
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
iframe[name="frameEditor"] {
|
||||
iframe[name="frameEditor"] {
|
||||
width: 100% !important;
|
||||
height: 100vh !important;
|
||||
min-height: 100vh !important;
|
||||
|
Loading…
Reference in New Issue
Block a user