mirror of
https://github.com/kuaifan/dootask.git
synced 2026-01-12 00:48:11 +00:00
feat: Enhance AIAssistant and SearchBox components with improved link handling and search functionality
- Updated AIAssistant to support parsing of additional message links in the format dootask://message/id1/id2. - Modified search methods in SearchBox to streamline API calls and remove AI search logic, improving performance and clarity. - Cleaned up unused AI search code and adjusted search result handling for better data presentation. - Updated documentation to reflect new link formats for tasks, projects, files, and messages.
This commit is contained in:
parent
1e94ce501e
commit
a52dc14369
@ -918,25 +918,28 @@ export default {
|
||||
e.stopPropagation();
|
||||
|
||||
// 解析 dootask:// 协议链接
|
||||
// 格式: dootask://type/id 例如 dootask://task/123
|
||||
const match = href.match(/^dootask:\/\/(\w+)\/(\d+)$/);
|
||||
// 格式: dootask://type/id 或 dootask://type/id1/id2 例如 dootask://task/123 或 dootask://message/789/1234
|
||||
const match = href.match(/^dootask:\/\/(\w+)\/(\d+)(?:\/(\d+))?$/);
|
||||
if (!match) {
|
||||
return;
|
||||
}
|
||||
|
||||
const [, type, id] = match;
|
||||
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: numId});
|
||||
this.$store.dispatch('openTask', {id: (numId2 && numId2 > 0) ? numId2 : numId});
|
||||
break;
|
||||
|
||||
case 'project':
|
||||
this.showModal = false;
|
||||
this.goForward({name: 'manage-project', params: {projectId: numId}});
|
||||
break;
|
||||
|
||||
case 'file':
|
||||
this.showModal = false;
|
||||
this.goForward({name: 'manage-file', params: {folderId: 0, fileId: null, shakeId: numId}});
|
||||
this.$store.state.fileShakeId = numId;
|
||||
setTimeout(() => {
|
||||
@ -949,6 +952,16 @@ export default {
|
||||
$A.modalError(msg || this.$L('打开会话失败'));
|
||||
});
|
||||
break;
|
||||
|
||||
case 'message':
|
||||
this.$store.dispatch('openDialog', numId).then(() => {
|
||||
if (numId2) {
|
||||
this.$store.state.dialogSearchMsgId = numId2;
|
||||
}
|
||||
}).catch(({msg}) => {
|
||||
$A.modalError(msg || this.$L('打开会话失败'));
|
||||
});
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
<Form class="search-form" action="javascript:void(0)" @submit.native.prevent="$A.eeuiAppKeyboardHide">
|
||||
<Input type="search" ref="searchKey" v-model="searchKey" :placeholder="$L('请输入关键字')"/>
|
||||
</Form>
|
||||
<div v-if="aiSearchAvailable" class="search-ai" :class="{active: aiSearch}" @click="toggleAiSearch">
|
||||
<div v-if="aiSearchAvailable" class="search-ai" @click="toggleAiSearch">
|
||||
<i class="taskfont"></i>
|
||||
<span>{{ $L('AI 搜索') }}</span>
|
||||
</div>
|
||||
@ -91,7 +91,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {mapState, mapGetters} from "vuex";
|
||||
import {mapState} from "vuex";
|
||||
import emitter from "../store/events";
|
||||
import transformEmojiToHtml from "../utils/emoji";
|
||||
|
||||
@ -120,8 +120,6 @@ export default {
|
||||
{type: 'file', name: '文件', icon: ''},
|
||||
],
|
||||
action: '',
|
||||
|
||||
aiSearch: false,
|
||||
}
|
||||
},
|
||||
|
||||
@ -347,16 +345,7 @@ export default {
|
||||
|
||||
searchTask(key) {
|
||||
this.loadIng++;
|
||||
// 如果开启了 AI 搜索,使用新的 AI 搜索接口
|
||||
const useAiSearch = this.aiSearchAvailable && this.aiSearch;
|
||||
const requestConfig = useAiSearch ? {
|
||||
url: 'search/task',
|
||||
data: {
|
||||
key,
|
||||
search_type: 'hybrid',
|
||||
take: this.action ? 50 : 10,
|
||||
},
|
||||
} : {
|
||||
this.$store.dispatch("call", {
|
||||
url: 'project/task/lists',
|
||||
data: {
|
||||
keys: {name: key},
|
||||
@ -364,19 +353,10 @@ export default {
|
||||
scope: 'all_project',
|
||||
pagesize: this.action ? 50 : 10,
|
||||
},
|
||||
};
|
||||
this.$store.dispatch("call", requestConfig).then(({data}) => {
|
||||
}).then(({data}) => {
|
||||
const nowTime = $A.dayjs().unix()
|
||||
const rawData = useAiSearch ? data : data.data;
|
||||
const items = rawData.map(item => {
|
||||
const items = data.data.map(item => {
|
||||
const tags = [];
|
||||
// AI 搜索标记
|
||||
if (useAiSearch && item.content_preview) {
|
||||
tags.push({
|
||||
name: 'AI',
|
||||
style: 'background-color:#4F46E5',
|
||||
})
|
||||
}
|
||||
if (item.complete_at) {
|
||||
tags.push({
|
||||
name: this.$L('已完成'),
|
||||
@ -407,7 +387,7 @@ export default {
|
||||
|
||||
id: item.id,
|
||||
title: item.name,
|
||||
desc: item.content_preview ? this.truncateContent(item.content_preview) : item.desc,
|
||||
desc: item.desc,
|
||||
activity: item.end_at,
|
||||
|
||||
rawData: item,
|
||||
@ -421,16 +401,7 @@ export default {
|
||||
|
||||
searchProject(key) {
|
||||
this.loadIng++;
|
||||
// 如果开启了 AI 搜索,使用新的 AI 搜索接口
|
||||
const useAiSearch = this.aiSearchAvailable && this.aiSearch;
|
||||
const requestConfig = useAiSearch ? {
|
||||
url: 'search/project',
|
||||
data: {
|
||||
key,
|
||||
search_type: 'hybrid',
|
||||
take: this.action ? 50 : 10,
|
||||
},
|
||||
} : {
|
||||
this.$store.dispatch("call", {
|
||||
url: 'project/lists',
|
||||
data: {
|
||||
keys: {
|
||||
@ -439,18 +410,9 @@ export default {
|
||||
archived: 'all',
|
||||
pagesize: this.action ? 50 : 10,
|
||||
},
|
||||
};
|
||||
this.$store.dispatch("call", requestConfig).then(({data}) => {
|
||||
const rawData = useAiSearch ? data : data.data;
|
||||
const items = rawData.map(item => {
|
||||
}).then(({data}) => {
|
||||
const items = data.data.map(item => {
|
||||
const tags = [];
|
||||
// AI 搜索标记
|
||||
if (useAiSearch && item.desc_preview) {
|
||||
tags.push({
|
||||
name: 'AI',
|
||||
style: 'background-color:#4F46E5',
|
||||
})
|
||||
}
|
||||
if (item.owner) {
|
||||
tags.push({
|
||||
name: this.$L('负责人'),
|
||||
@ -471,7 +433,7 @@ export default {
|
||||
|
||||
id: item.id,
|
||||
title: item.name,
|
||||
desc: item.desc_preview ? this.truncateContent(item.desc_preview) : (item.desc || ''),
|
||||
desc: item.desc || '',
|
||||
activity: item.updated_at,
|
||||
|
||||
rawData: item,
|
||||
@ -535,43 +497,23 @@ export default {
|
||||
|
||||
searchContact(key) {
|
||||
this.loadIng++;
|
||||
// 如果开启了 AI 搜索,使用新的 AI 搜索接口
|
||||
const useAiSearch = this.aiSearchAvailable && this.aiSearch;
|
||||
const requestConfig = useAiSearch ? {
|
||||
url: 'search/contact',
|
||||
data: {
|
||||
key,
|
||||
search_type: 'hybrid',
|
||||
take: this.action ? 50 : 10,
|
||||
},
|
||||
} : {
|
||||
this.$store.dispatch("call", {
|
||||
url: 'users/search',
|
||||
data: {
|
||||
keys: {key},
|
||||
pagesize: this.action ? 50 : 10,
|
||||
},
|
||||
};
|
||||
this.$store.dispatch("call", requestConfig).then(({data}) => {
|
||||
}).then(({data}) => {
|
||||
const items = data.map(item => {
|
||||
const tags = [];
|
||||
// AI 搜索标记
|
||||
if (useAiSearch && item.introduction_preview) {
|
||||
tags.push({
|
||||
name: 'AI',
|
||||
style: 'background-color:#4F46E5',
|
||||
})
|
||||
}
|
||||
return {
|
||||
key,
|
||||
type: 'contact',
|
||||
icons: ['user', item.userid],
|
||||
tags,
|
||||
tags: [],
|
||||
|
||||
id: item.userid,
|
||||
title: item.nickname,
|
||||
desc: item.introduction_preview
|
||||
? this.truncateContent(item.introduction_preview)
|
||||
: (item.profession || ''),
|
||||
desc: item.profession || '',
|
||||
activity: item.line_at,
|
||||
|
||||
rawData: item,
|
||||
@ -585,23 +527,13 @@ export default {
|
||||
|
||||
searchFile(key) {
|
||||
this.loadIng++;
|
||||
// 如果开启了 AI 搜索,使用统一的 AI 搜索接口
|
||||
const useAiSearch = this.aiSearchAvailable && this.aiSearch;
|
||||
const requestConfig = useAiSearch ? {
|
||||
url: 'search/file',
|
||||
data: {
|
||||
key,
|
||||
search_type: 'hybrid',
|
||||
take: this.action ? 50 : 10,
|
||||
},
|
||||
} : {
|
||||
this.$store.dispatch("call", {
|
||||
url: 'file/search',
|
||||
data: {
|
||||
key,
|
||||
take: this.action ? 50 : 10,
|
||||
},
|
||||
};
|
||||
this.$store.dispatch("call", requestConfig).then(({data}) => {
|
||||
}).then(({data}) => {
|
||||
const items = data.map(item => {
|
||||
const tags = [];
|
||||
if (item.share) {
|
||||
@ -610,13 +542,6 @@ export default {
|
||||
style: 'background-color:#0bc037',
|
||||
})
|
||||
}
|
||||
// AI 搜索标记
|
||||
if (useAiSearch && item.content_preview) {
|
||||
tags.push({
|
||||
name: 'AI',
|
||||
style: 'background-color:#4F46E5',
|
||||
})
|
||||
}
|
||||
return {
|
||||
key,
|
||||
type: 'file',
|
||||
@ -625,9 +550,7 @@ export default {
|
||||
|
||||
id: item.id,
|
||||
title: item.name,
|
||||
desc: item.content_preview
|
||||
? this.truncateContent(item.content_preview)
|
||||
: (item.type === 'folder' ? '' : $A.bytesToSize(item.size)),
|
||||
desc: item.type === 'folder' ? '' : $A.bytesToSize(item.size),
|
||||
activity: item.updated_at,
|
||||
|
||||
rawData: item,
|
||||
@ -639,13 +562,6 @@ export default {
|
||||
})
|
||||
},
|
||||
|
||||
truncateContent(content) {
|
||||
if (!content) return '';
|
||||
const maxLen = 100;
|
||||
const text = content.replace(/\s+/g, ' ').trim();
|
||||
return text.length > maxLen ? text.substring(0, maxLen) + '...' : text;
|
||||
},
|
||||
|
||||
toggleAiSearch() {
|
||||
const keyword = this.searchKey.trim();
|
||||
emitter.emit('openAIAssistant', {
|
||||
@ -675,14 +591,17 @@ export default {
|
||||
'',
|
||||
'## 链接格式要求',
|
||||
'在返回结果时,请使用以下格式创建可点击的链接:',
|
||||
'- 任务: [任务名称](dootask://task/任务ID)',
|
||||
'- 任务: [任务名称](dootask://task/任务ID/主任务ID)',
|
||||
'- 项目: [项目名称](dootask://project/项目ID)',
|
||||
'- 文件: [文件名称](dootask://file/文件ID)',
|
||||
'- 联系人: [联系人名称](dootask://contact/用户ID)',
|
||||
'- 消息: [消息内容预览](dootask://message/对话ID/消息ID)',
|
||||
'',
|
||||
'示例:',
|
||||
'- [完成项目报告](dootask://task/123)',
|
||||
'- [完成项目报告](dootask://task/123/0)(主任务)',
|
||||
'- [编写测试用例](dootask://task/456/123)(子任务)',
|
||||
'- [产品开发项目](dootask://project/456)',
|
||||
'- [关于报销的讨论](dootask://message/789/1234)',
|
||||
].join('\n');
|
||||
|
||||
const prepared = [
|
||||
|
||||
@ -106,11 +106,6 @@
|
||||
&:hover {
|
||||
background-color: #e8e8e8;
|
||||
}
|
||||
|
||||
&.active {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
9
resources/assets/sass/dark.scss
vendored
9
resources/assets/sass/dark.scss
vendored
@ -715,15 +715,6 @@ body.dark-mode-reverse {
|
||||
.ivu-modal {
|
||||
.ivu-modal-content {
|
||||
.ivu-modal-body {
|
||||
.search-header {
|
||||
.search-input {
|
||||
.search-ai {
|
||||
&.active {
|
||||
color: #000;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.search-body {
|
||||
border-top-color: #e9e9e9;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user