mirror of
https://github.com/kuaifan/dootask.git
synced 2026-01-20 16:08:14 +00:00
feat(ai-assistant): 添加欢迎界面快捷提示功能和交互优化
主要变更: - 新增场景化快捷提示,根据页面类型显示相关操作建议 - 重新设计欢迎界面 UI,支持图标和可点击的提示卡片 - 修复浮动按钮点击判断逻辑(移动距离<5px 且 按下时间<200ms) - 优化加载状态显示,移除冗余文案 - 支持 base64 编码格式的文件链接
This commit is contained in:
parent
70be6619e9
commit
9234fe3ed1
@ -2237,7 +2237,6 @@ Webhook事件
|
||||
用户
|
||||
|
||||
应用此内容
|
||||
生成中...
|
||||
等待 AI 回复...
|
||||
请输入你的问题...
|
||||
选择模型
|
||||
@ -2286,4 +2285,4 @@ AI 项目助手
|
||||
AI 汇报分析
|
||||
AI 整理汇报
|
||||
AI 任务助手
|
||||
AI 消息助手
|
||||
AI 消息助手
|
||||
|
||||
@ -205,8 +205,8 @@ export default {
|
||||
this.savePosition();
|
||||
this.dragging = false;
|
||||
|
||||
// 判断是否为点击(移动距离小于5px 或 按下时间小于200ms)
|
||||
if (moveDistance < 5 || duration < 200) {
|
||||
// 判断是否为点击(移动距离小于5px 且 按下时间小于200ms)
|
||||
if (moveDistance < 5 && duration < 200) {
|
||||
this.onClick();
|
||||
}
|
||||
},
|
||||
|
||||
@ -70,8 +70,8 @@
|
||||
</Button>
|
||||
</template>
|
||||
<template v-else>
|
||||
<Icon type="ios-sync" class="ai-assistant-output-icon icon-loading"/>
|
||||
<span class="ai-assistant-output-status">{{ loadingText || $L('生成中...') }}</span>
|
||||
<Icon type="ios-loading" class="ai-assistant-output-icon icon-loading"/>
|
||||
<span v-if="loadingText" class="ai-assistant-output-status">{{ loadingText }}</span>
|
||||
</template>
|
||||
</div>
|
||||
<div class="ai-assistant-output-meta">
|
||||
@ -90,13 +90,22 @@
|
||||
</div>
|
||||
<div v-else-if="displayMode === 'chat'" class="ai-assistant-welcome" @click="onFocus">
|
||||
<div class="ai-assistant-welcome-icon">
|
||||
<i class="taskfont"></i>
|
||||
<svg class="no-dark-content" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M385.80516777 713.87417358c-12.76971517 0-24.13100586-7.79328205-28.82575409-19.62404756l-48.91927648-123.9413531c-18.40341303-46.75969229-55.77360888-84.0359932-102.53330118-102.53330117l-123.94135309-48.91927649c-11.83076552-4.69474822-19.62404757-16.05603892-19.62404757-28.8257541s7.79328205-24.13100586 19.62404757-28.82575407l123.94135309-48.91927649c46.75969229-18.40341303 84.0359932-55.77360888 102.53330118-102.53330119l48.91927648-123.94135308c4.69474822-11.83076552 16.05603892-19.62404757 28.8257541-19.62404757s24.13100586 7.79328205 28.82575408 19.62404757l48.91927648 123.94135308c18.40341303 46.75969229 55.77360888 84.0359932 102.53330118 102.53330119l123.94135309 48.91927649c11.83076552 4.69474822 19.62404757 16.05603892 19.62404757 28.82575407 0 12.76971517-7.79328205 24.13100586-19.62404757 28.8257541l-123.94135309 48.91927649c-46.75969229 18.40341303-84.0359932 55.77360888-102.53330118 102.53330117l-48.91927648 123.9413531c-4.69474822 11.83076552-16.14993388 19.62404757-28.82575408 19.62404756zM177.45224165 390.12433614l50.89107073 20.0935224c62.62794129 24.69437565 112.67395736 74.74039171 137.368333 137.36833299l20.09352239 50.89107073 20.0935224-50.89107073c24.69437565-62.62794129 74.74039171-112.67395736 137.368333-137.36833299l50.89107072-20.0935224-50.89107073-20.09352239c-62.62794129-24.69437565-112.67395736-74.74039171-137.36833299-137.36833301l-20.09352239-50.89107074-20.0935224 50.89107074c-24.69437565 62.62794129-74.74039171 112.67395736-137.368333 137.36833301l-50.89107073 20.09352239zM771.33789183 957.62550131c-12.76971517 0-24.13100586-7.79328205-28.82575409-19.62404758l-26.6661699-67.6043744c-8.63833672-21.87752672-26.10280012-39.34199011-47.98032684-47.98032684l-67.60437441-26.6661699c-11.83076552-4.69474822-19.62404757-16.05603892-19.62404757-28.82575409s7.79328205-24.13100586 19.62404757-28.82575409l67.60437441-26.6661699c21.87752672-8.63833672 39.34199011-26.10280012 47.98032684-47.98032685l26.6661699-67.6043744c4.69474822-11.83076552 16.05603892-19.62404757 28.82575409-19.62404757s24.13100586 7.79328205 28.82575409 19.62404757l26.66616991 67.6043744c8.63833672 21.87752672 26.10280012 39.34199011 47.98032684 47.98032685l67.6043744 26.6661699c11.83076552 4.69474822 19.62404757 16.05603892 19.62404757 28.82575409s-7.79328205 24.13100586-19.62404757 28.82575409l-67.6043744 26.6661699c-21.87752672 8.63833672-39.34199011 26.10280012-47.98032684 47.98032684l-26.66616991 67.6043744c-4.69474822 11.83076552-16.14993388 19.62404757-28.82575409 19.62404758z m-75.58544639-190.70067281c33.61439727 14.83540438 60.75004201 41.87715415 75.49155143 75.49155143 14.83540438-33.61439727 41.87715415-60.75004201 75.49155142-75.49155143-33.61439727-14.83540438-60.75004201-41.87715415-75.49155142-75.49155143-14.74150942 33.61439727-41.87715415 60.75004201-75.49155143 75.49155143z"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="ai-assistant-welcome-title">
|
||||
欢迎使用 AI 助手
|
||||
{{ $L('欢迎使用 AI 助手') }}
|
||||
</div>
|
||||
<div class="ai-assistant-welcome-swiper">
|
||||
<!-- Swiper 容器 -->
|
||||
<div class="ai-assistant-welcome-prompts">
|
||||
<div
|
||||
v-for="(prompt, index) in welcomePrompts"
|
||||
:key="index"
|
||||
class="ai-assistant-prompt-card"
|
||||
@click="onPromptClick(prompt)">
|
||||
<span v-if="prompt.svg" class="ai-assistant-prompt-icon no-dark-content" v-html="prompt.svg"></span>
|
||||
<span>{{ prompt.text }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ai-assistant-input">
|
||||
@ -151,6 +160,7 @@ import {AIBotMap, AIModelNames} from "../../utils/ai";
|
||||
import DialogMarkdown from "../../pages/manage/components/DialogMarkdown.vue";
|
||||
import FloatButton from "./float-button.vue";
|
||||
import AssistantModal from "./modal.vue";
|
||||
import {getWelcomePrompts} from "./welcome-prompts";
|
||||
|
||||
export default {
|
||||
name: 'AIAssistant',
|
||||
@ -236,6 +246,9 @@ export default {
|
||||
hasSessionHistory() {
|
||||
return this.currentSessionList.length > 0;
|
||||
},
|
||||
welcomePrompts() {
|
||||
return getWelcomePrompts(this.$store, this.$route?.params || {});
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
inputModel(value) {
|
||||
@ -250,6 +263,19 @@ export default {
|
||||
this.$refs.inputRef?.focus();
|
||||
},
|
||||
|
||||
/**
|
||||
* 点击快捷提示,填入输入框
|
||||
*/
|
||||
onPromptClick(prompt) {
|
||||
if (!prompt || !prompt.text) {
|
||||
return;
|
||||
}
|
||||
this.inputValue = prompt.text;
|
||||
this.$nextTick(() => {
|
||||
this.onFocus();
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 挂载浮动按钮到 body
|
||||
*/
|
||||
@ -1220,7 +1246,6 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
.ai-assistant-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@ -1568,6 +1593,8 @@ export default {
|
||||
color: #999;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
&:hover {
|
||||
color: #444;
|
||||
transform: rotate(-90deg);
|
||||
@ -1596,17 +1623,93 @@ export default {
|
||||
flex-direction: column;
|
||||
|
||||
.ai-assistant-welcome {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
@media (max-height: 650px) {
|
||||
justify-content: normal;
|
||||
}
|
||||
|
||||
.ai-assistant-welcome-icon {
|
||||
margin-top: 12px;
|
||||
i {
|
||||
font-size: 24px;
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 52px;
|
||||
height: 52px;
|
||||
border-radius: 50%;
|
||||
background: #8bcf70;
|
||||
margin-bottom: 24px;
|
||||
|
||||
svg {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
fill: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.ai-assistant-welcome-title {
|
||||
margin-top: 12px;
|
||||
font-size: 16px;
|
||||
margin-bottom: 24px;
|
||||
font-weight: 500;
|
||||
color: #303133;
|
||||
}
|
||||
.ai-assistant-welcome-swiper {
|
||||
margin-top: 24px;
|
||||
|
||||
.ai-assistant-welcome-prompts {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
gap: 12px;
|
||||
max-width: 100%;
|
||||
padding: 0 8px;
|
||||
}
|
||||
|
||||
.ai-assistant-prompt-card {
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
background: #fff;
|
||||
border: 1px solid #e8e8e8;
|
||||
border-radius: 8px;
|
||||
color: #303133;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
padding: 8px 12px;
|
||||
font-size: 13px;
|
||||
|
||||
&:hover {
|
||||
border-color: #8bcf70;
|
||||
box-shadow: 0 2px 8px rgba(139, 207, 112, 0.15);
|
||||
}
|
||||
|
||||
&:active {
|
||||
transform: scale(0.98);
|
||||
}
|
||||
|
||||
.ai-assistant-prompt-icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
flex-shrink: 0;
|
||||
|
||||
svg {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
stroke: #8bcf70;
|
||||
}
|
||||
}
|
||||
|
||||
> span:last-child {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1635,6 +1738,15 @@ body.dark-mode-reverse {
|
||||
.ai-assistant-output {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.ai-assistant-prompt-card {
|
||||
background: #fff;
|
||||
border-color: #d9d9d9;
|
||||
|
||||
&:hover {
|
||||
background: rgba(102, 126, 234, 0.06);
|
||||
}
|
||||
}
|
||||
}
|
||||
.ai-assistant-chat {
|
||||
background-color: #e9e9e9;
|
||||
|
||||
402
resources/assets/js/components/AIAssistant/welcome-prompts.js
vendored
Normal file
402
resources/assets/js/components/AIAssistant/welcome-prompts.js
vendored
Normal file
@ -0,0 +1,402 @@
|
||||
/**
|
||||
* AI 助手欢迎界面快捷提示配置
|
||||
*
|
||||
* 根据不同页面场景显示相关的快捷提示,帮助用户快速开始对话
|
||||
* 提示内容基于 DooTask MCP 工具的实际能力设计
|
||||
*/
|
||||
|
||||
import {languageName} from "../../language";
|
||||
|
||||
// SVG 图标定义
|
||||
const SVG_ICONS = {
|
||||
// 任务/待办
|
||||
task: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 11l3 3L22 4"/><path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"/></svg>',
|
||||
// 列表/概览
|
||||
list: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><line x1="3" y1="6" x2="3.01" y2="6"/><line x1="3" y1="12" x2="3.01" y2="12"/><line x1="3" y1="18" x2="3.01" y2="18"/></svg>',
|
||||
// 搜索
|
||||
search: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>',
|
||||
// 日历/时间
|
||||
calendar: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></svg>',
|
||||
// 文档/报告
|
||||
document: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/></svg>',
|
||||
// 添加/新建
|
||||
plus: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>',
|
||||
// 消息/对话
|
||||
message: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>',
|
||||
// 分析/图表
|
||||
chart: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="20" x2="18" y2="10"/><line x1="12" y1="20" x2="12" y2="4"/><line x1="6" y1="20" x2="6" y2="14"/></svg>',
|
||||
// 警告/逾期
|
||||
alert: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>',
|
||||
// 文件夹
|
||||
folder: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/></svg>',
|
||||
// 编辑/优化
|
||||
edit: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/></svg>',
|
||||
// 用户/团队
|
||||
user: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>',
|
||||
// 发送
|
||||
send: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="22" y1="2" x2="11" y2="13"/><polygon points="22 2 15 22 11 13 2 9 22 2"/></svg>',
|
||||
// 时钟/截止
|
||||
clock: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>',
|
||||
// 完成/勾选
|
||||
check: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="20 6 9 17 4 12"/></svg>',
|
||||
};
|
||||
|
||||
/**
|
||||
* 根据当前语言获取文本
|
||||
*/
|
||||
function getText(textObj) {
|
||||
if (typeof textObj === 'string') {
|
||||
return textObj;
|
||||
}
|
||||
const isZh = languageName && languageName.includes('zh');
|
||||
return isZh ? textObj.zh : textObj.en;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前场景的快捷提示列表
|
||||
* @param {Object} store - Vuex store 实例
|
||||
* @param {Object} routeParams - 路由参数
|
||||
* @returns {Array} 快捷提示列表 [{ text, svg }]
|
||||
*/
|
||||
export function getWelcomePrompts(store, routeParams = {}) {
|
||||
const routeName = store.state.routeName;
|
||||
|
||||
const promptsMap = {
|
||||
// 主要管理页面
|
||||
'manage-dashboard': getDashboardPrompts,
|
||||
'manage-project': getProjectPrompts,
|
||||
'manage-messenger': getMessengerPrompts,
|
||||
'manage-calendar': getCalendarPrompts,
|
||||
'manage-file': getFilePrompts,
|
||||
// 独立页面
|
||||
'single-task': getSingleTaskPrompts,
|
||||
'single-task-content': getSingleTaskPrompts,
|
||||
'single-dialog': getSingleDialogPrompts,
|
||||
'single-file': getSingleFilePrompts,
|
||||
'single-file-task': getSingleFileTaskPrompts,
|
||||
'single-report-edit': getSingleReportEditPrompts,
|
||||
'single-report-detail': getSingleReportDetailPrompts,
|
||||
};
|
||||
|
||||
const getPrompts = promptsMap[routeName];
|
||||
const rawPrompts = getPrompts ? getPrompts(store, routeParams) : getDefaultPrompts();
|
||||
|
||||
// 转换文本为当前语言
|
||||
return rawPrompts.map(item => ({
|
||||
text: getText(item.text),
|
||||
svg: item.svg,
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* 仪表盘提示 - 聚焦任务管理和工作安排
|
||||
*/
|
||||
function getDashboardPrompts(store) {
|
||||
const dashboardTask = store.getters.dashboardTask || {};
|
||||
const prompts = [];
|
||||
|
||||
const overdueCount = dashboardTask.overdue_count || 0;
|
||||
const todayCount = dashboardTask.today_count || 0;
|
||||
|
||||
// 根据实际数据动态调整提示
|
||||
if (overdueCount > 0) {
|
||||
prompts.push({
|
||||
text: {
|
||||
zh: `列出我的 ${overdueCount} 个逾期任务`,
|
||||
en: `List my ${overdueCount} overdue tasks`,
|
||||
},
|
||||
svg: SVG_ICONS.alert,
|
||||
});
|
||||
}
|
||||
|
||||
if (todayCount > 0) {
|
||||
prompts.push({
|
||||
text: {
|
||||
zh: `今天要完成哪些任务?`,
|
||||
en: `What tasks are due today?`,
|
||||
},
|
||||
svg: SVG_ICONS.calendar,
|
||||
});
|
||||
}
|
||||
|
||||
// 补充通用提示
|
||||
prompts.push(
|
||||
{
|
||||
text: { zh: '我本周有哪些任务?', en: 'What are my tasks this week?' },
|
||||
svg: SVG_ICONS.list,
|
||||
},
|
||||
{
|
||||
text: { zh: '哪些任务需要我协助?', en: 'Which tasks need my assistance?' },
|
||||
svg: SVG_ICONS.user,
|
||||
},
|
||||
);
|
||||
|
||||
return prompts.slice(0, 4);
|
||||
}
|
||||
|
||||
/**
|
||||
* 项目页提示 - 聚焦项目任务管理
|
||||
*/
|
||||
function getProjectPrompts(store) {
|
||||
const project = store.getters.projectData || {};
|
||||
|
||||
if (!project.id) {
|
||||
// 项目列表页
|
||||
return [
|
||||
{
|
||||
text: { zh: '我参与了哪些项目?', en: 'Which projects am I involved in?' },
|
||||
svg: SVG_ICONS.folder,
|
||||
},
|
||||
{
|
||||
text: { zh: '哪个项目有逾期任务?', en: 'Which project has overdue tasks?' },
|
||||
svg: SVG_ICONS.alert,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
// 项目详情页 - 提供具体操作
|
||||
const projectName = project.name || '';
|
||||
return [
|
||||
{
|
||||
text: {
|
||||
zh: '这个项目还有多少未完成的任务?',
|
||||
en: 'How many incomplete tasks in this project?',
|
||||
},
|
||||
svg: SVG_ICONS.list,
|
||||
},
|
||||
{
|
||||
text: {
|
||||
zh: '帮我在这个项目创建一个任务',
|
||||
en: 'Help me create a task in this project',
|
||||
},
|
||||
svg: SVG_ICONS.plus,
|
||||
},
|
||||
{
|
||||
text: {
|
||||
zh: '这个项目有哪些逾期任务?',
|
||||
en: 'What tasks are overdue in this project?',
|
||||
},
|
||||
svg: SVG_ICONS.alert,
|
||||
},
|
||||
{
|
||||
text: {
|
||||
zh: '查看项目成员的任务分配',
|
||||
en: 'View task assignments by member',
|
||||
},
|
||||
svg: SVG_ICONS.user,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 消息页提示 - 聚焦沟通和消息查找
|
||||
*/
|
||||
function getMessengerPrompts(store) {
|
||||
const dialogId = store.state.dialogId;
|
||||
const dialogs = store.state.cacheDialogs || [];
|
||||
const dialog = dialogs.find(d => d.id === dialogId);
|
||||
|
||||
if (!dialog) {
|
||||
// 消息列表页
|
||||
return [
|
||||
{
|
||||
text: { zh: '给某人发送一条消息', en: 'Send a message to someone' },
|
||||
svg: SVG_ICONS.send,
|
||||
},
|
||||
{
|
||||
text: { zh: '搜索包含关键词的聊天', en: 'Search chats containing keyword' },
|
||||
svg: SVG_ICONS.search,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
// 对话详情页
|
||||
const dialogName = dialog.name || '';
|
||||
return [
|
||||
{
|
||||
text: {
|
||||
zh: '查看这个对话最近的消息',
|
||||
en: 'View recent messages in this chat',
|
||||
},
|
||||
svg: SVG_ICONS.message,
|
||||
},
|
||||
{
|
||||
text: {
|
||||
zh: '搜索对话中的文件',
|
||||
en: 'Search files in this chat',
|
||||
},
|
||||
svg: SVG_ICONS.search,
|
||||
},
|
||||
{
|
||||
text: {
|
||||
zh: '给对方发一条消息',
|
||||
en: 'Send a message',
|
||||
},
|
||||
svg: SVG_ICONS.send,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 日历页提示 - 聚焦时间维度的任务查看
|
||||
*/
|
||||
function getCalendarPrompts() {
|
||||
return [
|
||||
{
|
||||
text: { zh: '今天有哪些任务到期?', en: 'What tasks are due today?' },
|
||||
svg: SVG_ICONS.calendar,
|
||||
},
|
||||
{
|
||||
text: { zh: '本周有哪些任务要完成?', en: 'What tasks are due this week?' },
|
||||
svg: SVG_ICONS.list,
|
||||
},
|
||||
{
|
||||
text: { zh: '下周的任务安排', en: 'Tasks scheduled for next week' },
|
||||
svg: SVG_ICONS.clock,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 文件页提示 - 聚焦文件查找
|
||||
*/
|
||||
function getFilePrompts() {
|
||||
return [
|
||||
{
|
||||
text: { zh: '搜索文件名包含...', en: 'Search files named...' },
|
||||
svg: SVG_ICONS.search,
|
||||
},
|
||||
{
|
||||
text: { zh: '查看我最近的文件', en: 'View my recent files' },
|
||||
svg: SVG_ICONS.folder,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 任务详情提示 - 聚焦当前任务的操作
|
||||
*/
|
||||
function getSingleTaskPrompts() {
|
||||
return [
|
||||
{
|
||||
text: { zh: '帮我添加一个子任务', en: 'Help me add a subtask' },
|
||||
svg: SVG_ICONS.plus,
|
||||
},
|
||||
{
|
||||
text: { zh: '修改这个任务的截止时间', en: 'Change the due date of this task' },
|
||||
svg: SVG_ICONS.clock,
|
||||
},
|
||||
{
|
||||
text: { zh: '将这个任务标记为完成', en: 'Mark this task as complete' },
|
||||
svg: SVG_ICONS.check,
|
||||
},
|
||||
{
|
||||
text: { zh: '查看这个任务的附件', en: 'View attachments of this task' },
|
||||
svg: SVG_ICONS.folder,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 对话页提示
|
||||
*/
|
||||
function getSingleDialogPrompts() {
|
||||
return [
|
||||
{
|
||||
text: { zh: '查看最近的消息记录', en: 'View recent messages' },
|
||||
svg: SVG_ICONS.message,
|
||||
},
|
||||
{
|
||||
text: { zh: '发送一条消息', en: 'Send a message' },
|
||||
svg: SVG_ICONS.send,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 文件预览提示
|
||||
*/
|
||||
function getSingleFilePrompts() {
|
||||
return [
|
||||
{
|
||||
text: { zh: '查看这个文件的详情', en: 'View file details' },
|
||||
svg: SVG_ICONS.document,
|
||||
},
|
||||
{
|
||||
text: { zh: '搜索类似的文件', en: 'Search similar files' },
|
||||
svg: SVG_ICONS.search,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 任务附件提示
|
||||
*/
|
||||
function getSingleFileTaskPrompts() {
|
||||
return [
|
||||
{
|
||||
text: { zh: '查看这个任务的所有附件', en: 'View all attachments of this task' },
|
||||
svg: SVG_ICONS.folder,
|
||||
},
|
||||
{
|
||||
text: { zh: '查看任务详情', en: 'View task details' },
|
||||
svg: SVG_ICONS.task,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 汇报编辑提示 - 聚焦汇报生成
|
||||
*/
|
||||
function getSingleReportEditPrompts() {
|
||||
return [
|
||||
{
|
||||
text: { zh: '根据本周任务生成周报', en: 'Generate weekly report from tasks' },
|
||||
svg: SVG_ICONS.document,
|
||||
},
|
||||
{
|
||||
text: { zh: '根据今天任务生成日报', en: 'Generate daily report from tasks' },
|
||||
svg: SVG_ICONS.calendar,
|
||||
},
|
||||
{
|
||||
text: { zh: '查看我上周的汇报', en: 'View my last week\'s report' },
|
||||
svg: SVG_ICONS.search,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 汇报详情提示
|
||||
*/
|
||||
function getSingleReportDetailPrompts() {
|
||||
return [
|
||||
{
|
||||
text: { zh: '标记为已读', en: 'Mark as read' },
|
||||
svg: SVG_ICONS.check,
|
||||
},
|
||||
{
|
||||
text: { zh: '查看这个人的其他汇报', en: 'View other reports from this person' },
|
||||
svg: SVG_ICONS.list,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 默认提示 - 通用场景
|
||||
*/
|
||||
function getDefaultPrompts() {
|
||||
return [
|
||||
{
|
||||
text: { zh: '我有哪些未完成的任务?', en: 'What tasks do I have pending?' },
|
||||
svg: SVG_ICONS.task,
|
||||
},
|
||||
{
|
||||
text: { zh: '搜索任务或项目', en: 'Search tasks or projects' },
|
||||
svg: SVG_ICONS.search,
|
||||
},
|
||||
{
|
||||
text: { zh: '帮我写一份工作汇报', en: 'Help me write a work report' },
|
||||
svg: SVG_ICONS.document,
|
||||
},
|
||||
];
|
||||
}
|
||||
@ -93,15 +93,17 @@ export default {
|
||||
/**
|
||||
* 处理 dootask:// 协议链接
|
||||
* 格式: dootask://type/id 或 dootask://type/id1/id2
|
||||
* 文件链接支持: dootask://file/123 (数字ID) 或 dootask://file/OSwxLHY3ZlN2R245 (base64编码)
|
||||
*/
|
||||
handleDooTaskLink(href) {
|
||||
const match = href.match(/^dootask:\/\/(\w+)\/(\d+)(?:\/(\d+))?$/);
|
||||
const match = href.match(/^dootask:\/\/(\w+)\/([^/]+)(?:\/(\d+))?$/);
|
||||
if (!match) {
|
||||
return;
|
||||
}
|
||||
|
||||
const [, type, id, id2] = match;
|
||||
const numId = parseInt(id, 10);
|
||||
const isNumericId = /^\d+$/.test(id);
|
||||
const numId = isNumericId ? parseInt(id, 10) : null;
|
||||
const numId2 = id2 ? parseInt(id2, 10) : null;
|
||||
|
||||
switch (type) {
|
||||
@ -115,12 +117,18 @@ export default {
|
||||
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);
|
||||
if (isNumericId) {
|
||||
// 数字ID:跳转到文件列表并高亮
|
||||
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);
|
||||
} else {
|
||||
// 非数字ID(如base64编码):打开新窗口预览
|
||||
window.open($A.mainUrl('single/file/' + id));
|
||||
}
|
||||
break;
|
||||
|
||||
case 'contact':
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user