mirror of
https://github.com/kuaifan/dootask.git
synced 2026-01-21 08:28:12 +00:00
- 将 dootask:// 协议链接处理逻辑从 AIAssistant 迁移到 DialogMarkdown 组件 - 新增 beforeNavigate prop 支持导航前回调(如关闭弹窗) - 后端 BotReceiveMsgTask 添加条件性资源格式指南提示词 - 前端 ai.js 新增 SEARCH_AI_SYSTEM_PROMPT 和 DOOTASK_RESOURCE_FORMAT_GUIDE - SearchBox 改用统一的 SEARCH_AI_SYSTEM_PROMPT 常量 - 重构 ai.js 代码组织,添加注释说明各常量用途
146 lines
4.5 KiB
Vue
146 lines
4.5 KiB
Vue
<template>
|
|
<div @click="onCLick" class="markdown-body" v-html="html"></div>
|
|
</template>
|
|
|
|
<script>
|
|
import '../../../../sass/pages/components/dialog-markdown/markdown.less'
|
|
import {MarkdownConver} from "../../../utils/markdown";
|
|
|
|
export default {
|
|
name: "DialogMarkdown",
|
|
props: {
|
|
text: {
|
|
type: String,
|
|
default: ''
|
|
},
|
|
// 导航前回调(如关闭弹窗)
|
|
beforeNavigate: {
|
|
type: Function,
|
|
default: null
|
|
},
|
|
},
|
|
data() {
|
|
return {
|
|
mdi: null,
|
|
}
|
|
},
|
|
|
|
mounted() {
|
|
this.copyCodeBlock()
|
|
},
|
|
|
|
updated() {
|
|
this.copyCodeBlock()
|
|
},
|
|
|
|
computed: {
|
|
html({text}) {
|
|
return MarkdownConver(text)
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
copyCodeBlock() {
|
|
const codeBlockWrapper = this.$el.querySelectorAll('.code-block-wrapper')
|
|
codeBlockWrapper.forEach((wrapper) => {
|
|
const copyBtn = wrapper.querySelector('.code-block-header__copy')
|
|
const codeBlock = wrapper.querySelector('.code-block-body')
|
|
if (copyBtn && codeBlock && copyBtn.getAttribute("data-copy") !== "click") {
|
|
copyBtn.setAttribute("data-copy", "click")
|
|
copyBtn.addEventListener('click', () => {
|
|
if (navigator.clipboard?.writeText)
|
|
navigator.clipboard.writeText(codeBlock.textContent ?? '')
|
|
else
|
|
this.copyContent({text: codeBlock.textContent ?? '', origin: true})
|
|
})
|
|
}
|
|
})
|
|
},
|
|
|
|
copyContent(options) {
|
|
const props = {origin: true, ...options}
|
|
|
|
let input
|
|
|
|
if (props.origin)
|
|
input = document.createElement('textarea')
|
|
else
|
|
input = document.createElement('input')
|
|
|
|
input.setAttribute('readonly', 'readonly')
|
|
input.value = props.text
|
|
document.body.appendChild(input)
|
|
input.select()
|
|
if (document.execCommand('copy'))
|
|
document.execCommand('copy')
|
|
document.body.removeChild(input)
|
|
},
|
|
|
|
onCLick(e) {
|
|
const target = e.target;
|
|
if (target.tagName === 'A') {
|
|
const href = target.getAttribute('href');
|
|
if (href && href.startsWith('dootask://')) {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
this.handleDooTaskLink(href);
|
|
return;
|
|
}
|
|
}
|
|
this.$emit('click', e)
|
|
},
|
|
|
|
/**
|
|
* 处理 dootask:// 协议链接
|
|
* 格式: dootask://type/id 或 dootask://type/id1/id2
|
|
*/
|
|
handleDooTaskLink(href) {
|
|
const match = href.match(/^dootask:\/\/(\w+)\/(\d+)(?:\/(\d+))?$/);
|
|
if (!match) {
|
|
return;
|
|
}
|
|
|
|
const [, type, id, id2] = match;
|
|
const numId = parseInt(id, 10);
|
|
const numId2 = id2 ? parseInt(id2, 10) : null;
|
|
|
|
switch (type) {
|
|
case 'task':
|
|
this.$store.dispatch('openTask', { id: (numId2 && numId2 > 0) ? numId2 : numId });
|
|
break;
|
|
|
|
case 'project':
|
|
this.beforeNavigate?.();
|
|
this.goForward({ name: 'manage-project', params: { projectId: numId } });
|
|
break;
|
|
|
|
case 'file':
|
|
this.beforeNavigate?.();
|
|
this.goForward({ name: 'manage-file', params: { folderId: 0, fileId: null, shakeId: numId } });
|
|
this.$store.state.fileShakeId = numId;
|
|
setTimeout(() => {
|
|
this.$store.state.fileShakeId = 0;
|
|
}, 600);
|
|
break;
|
|
|
|
case 'contact':
|
|
this.$store.dispatch('openDialogUserid', numId).catch(({ msg }) => {
|
|
$A.modalError(msg);
|
|
});
|
|
break;
|
|
|
|
case 'message':
|
|
this.$store.dispatch('openDialog', numId).then(() => {
|
|
if (numId2) {
|
|
this.$store.state.dialogSearchMsgId = numId2;
|
|
}
|
|
}).catch(({ msg }) => {
|
|
$A.modalError(msg);
|
|
});
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</script>
|