mirror of
https://github.com/kuaifan/dootask.git
synced 2025-12-11 02:12:53 +00:00
feat: 移除未使用的消息处理函数和Markdown插件任务创建功能,优化代码结构
This commit is contained in:
parent
944824b552
commit
cf78766a37
@ -3245,55 +3245,6 @@ class DialogController extends AbstractController
|
|||||||
return Base::retSuccess('success', $topMsg);
|
return Base::retSuccess('success', $topMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @api {get} api/dialog/msg/applied 标记消息已应用
|
|
||||||
*
|
|
||||||
* @apiDescription 需要token身份
|
|
||||||
* @apiVersion 1.0.0
|
|
||||||
* @apiGroup dialog
|
|
||||||
* @apiName msg__applied
|
|
||||||
*
|
|
||||||
* @apiParam {Number} index 索引
|
|
||||||
* @apiParam {Number} msg_id 消息ID
|
|
||||||
*
|
|
||||||
* @apiSuccess {Number} ret 返回状态码(1正确、0错误)
|
|
||||||
* @apiSuccess {String} msg 返回信息(错误描述)
|
|
||||||
* @apiSuccess {Object} data 返回数据
|
|
||||||
*/
|
|
||||||
public function msg__applied()
|
|
||||||
{
|
|
||||||
User::auth();
|
|
||||||
//
|
|
||||||
$msg_id = intval(Request::input('msg_id'));
|
|
||||||
$index = intval(Request::input('index'));
|
|
||||||
//
|
|
||||||
$msg = WebSocketDialogMsg::whereId($msg_id)->first();
|
|
||||||
if (empty($msg)) {
|
|
||||||
return Base::retError("消息不存在或已被删除");
|
|
||||||
}
|
|
||||||
WebSocketDialog::checkDialog($msg->dialog_id);
|
|
||||||
//
|
|
||||||
$originalMsg = $msg->getRawOriginal('msg');
|
|
||||||
$pattern = '/:::\s*(create-task-list|create-subtask-list)(?:\s+(\S+))?/';
|
|
||||||
$count = -1;
|
|
||||||
$updatedMsg = preg_replace_callback($pattern, function($matches) use (&$count, $index) {
|
|
||||||
$count++;
|
|
||||||
if ($count === $index || ($index === 0 && $count === 1)) {
|
|
||||||
return "::: {$matches[1]} applied";
|
|
||||||
}
|
|
||||||
return $matches[0];
|
|
||||||
}, $originalMsg);
|
|
||||||
|
|
||||||
if ($count === -1) {
|
|
||||||
return Base::retError("未找到可应用的规则");
|
|
||||||
}
|
|
||||||
|
|
||||||
$msg->msg = $updatedMsg;
|
|
||||||
$msg->save();
|
|
||||||
//
|
|
||||||
return Base::retSuccess("success");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @api {get} api/dialog/sticker/search 搜索在线表情
|
* @api {get} api/dialog/sticker/search 搜索在线表情
|
||||||
*
|
*
|
||||||
|
|||||||
@ -695,7 +695,6 @@ class WebSocketDialogMsg extends AbstractModel
|
|||||||
$text = $title;
|
$text = $title;
|
||||||
} else {
|
} else {
|
||||||
$text = Base::markdown2html($text);
|
$text = Base::markdown2html($text);
|
||||||
$text = self::previewConvertTaskList($text);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$text = preg_replace("/<img\s+class=\"emoticon\"[^>]*?alt=\"(\S+)\"[^>]*?>/", "[$1]", $text);
|
$text = preg_replace("/<img\s+class=\"emoticon\"[^>]*?alt=\"(\S+)\"[^>]*?>/", "[$1]", $text);
|
||||||
@ -711,36 +710,6 @@ class WebSocketDialogMsg extends AbstractModel
|
|||||||
return $text;
|
return $text;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 转换任务列表
|
|
||||||
* @param $text
|
|
||||||
* @return array|string|string[]|null
|
|
||||||
*/
|
|
||||||
private static function previewConvertTaskList($text) {
|
|
||||||
$pattern = '/:::\s*(create-task-list|create-subtask-list)(.*?):::/s';
|
|
||||||
$replacement = function($matches) {
|
|
||||||
$content = $matches[2];
|
|
||||||
$lines = explode("\n", trim($content));
|
|
||||||
$result = [];
|
|
||||||
$currentTitle = '';
|
|
||||||
foreach ($lines as $line) {
|
|
||||||
$line = trim($line);
|
|
||||||
if (empty($line)) continue;
|
|
||||||
|
|
||||||
if (preg_match('/^title:\s*(.+)$/', $line, $titleMatch)) {
|
|
||||||
$currentTitle = $titleMatch[1];
|
|
||||||
$result[] = $currentTitle;
|
|
||||||
} elseif (preg_match('/^desc:\s*(.+)$/', $line, $descMatch)) {
|
|
||||||
if (!empty($currentTitle)) {
|
|
||||||
$result[] = $descMatch[1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return implode("\n", $result);
|
|
||||||
};
|
|
||||||
return preg_replace_callback($pattern, $replacement, $text);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 预览文件消息
|
* 预览文件消息
|
||||||
* @param $msg
|
* @param $msg
|
||||||
|
|||||||
@ -3499,135 +3499,6 @@ export default {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
applyCreateBefore(type, event, el) {
|
|
||||||
$A.modalConfirm({
|
|
||||||
content: `你确定要创建${type === 'task' ? '任务' : '子任务'}吗?`,
|
|
||||||
onOk: () => {
|
|
||||||
this.applyCreateTask(type, event, el);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
async applyCreateTask(type, event, el) {
|
|
||||||
const currentTarget = event.target;
|
|
||||||
if (currentTarget.classList.contains('applying') || currentTarget.classList.contains('applied')) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
currentTarget.classList.add('applying')
|
|
||||||
|
|
||||||
if (type === 'task') {
|
|
||||||
if (this.dialogData.group_type !== 'project') {
|
|
||||||
currentTarget.classList.remove('applying')
|
|
||||||
$A.modalError('只有在项目中才能创建任务')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (!this.dialogData.group_info) {
|
|
||||||
currentTarget.classList.remove('applying')
|
|
||||||
$A.modalError('项目不存在')
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else if (type === 'subtask') {
|
|
||||||
if (this.dialogData.group_type !== 'task') {
|
|
||||||
currentTarget.classList.remove('applying')
|
|
||||||
$A.modalError('只有在任务中才能创建子任务')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (!this.dialogData.group_info) {
|
|
||||||
currentTarget.classList.remove('applying')
|
|
||||||
$A.modalError('任务不存在')
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
currentTarget.classList.remove('applying')
|
|
||||||
$A.modalError('未知类型')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let target = event.target;
|
|
||||||
while (target) {
|
|
||||||
if (target.classList.contains('apply-create-task')) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (target.classList.contains('dialog-scroller')) {
|
|
||||||
target = null;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
target = target.parentElement;
|
|
||||||
}
|
|
||||||
if (!target) {
|
|
||||||
currentTarget.classList.remove('applying')
|
|
||||||
$A.modalError('未找到内容')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const allTaskElements = el.querySelectorAll('.apply-create-task');
|
|
||||||
const taskIndex = Array.from(allTaskElements).indexOf(target);
|
|
||||||
const taskList = Array.from(target.querySelectorAll('li'))
|
|
||||||
.map(item => {
|
|
||||||
const title = item.querySelector('.title')?.innerText?.trim();
|
|
||||||
if (!title) return null;
|
|
||||||
|
|
||||||
const desc = item.querySelector('.desc')?.innerText?.trim() || '';
|
|
||||||
const content = desc ? desc.split('\n')
|
|
||||||
.filter(Boolean)
|
|
||||||
.map(line => `<p>${line.trim()}</p>`)
|
|
||||||
.join('') : '';
|
|
||||||
|
|
||||||
if (type === 'subtask') {
|
|
||||||
return {
|
|
||||||
task_id: this.dialogData.group_info.id,
|
|
||||||
name: title,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
project_id: this.dialogData.group_info.id,
|
|
||||||
name: title,
|
|
||||||
content
|
|
||||||
};
|
|
||||||
})
|
|
||||||
.filter(Boolean);
|
|
||||||
|
|
||||||
const typeCall = type === 'subtask' ? 'taskAddSub' : 'taskAdd';
|
|
||||||
const typeLabel = type === 'subtask' ? '子任务' : '任务';
|
|
||||||
const results = [];
|
|
||||||
for (const item of taskList) {
|
|
||||||
try {
|
|
||||||
const success = await this.$store.dispatch(typeCall, item);
|
|
||||||
results.push({ success: true, data: success });
|
|
||||||
} catch (error) {
|
|
||||||
results.push({ success: false, error: error });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const successTasks = results.filter(r => r.success).map(r => r.data);
|
|
||||||
const failedTasks = results.filter(r => !r.success).map(r => r.error);
|
|
||||||
let notice = `${this.$store.state.userInfo.nickname} 成功创建 ${successTasks.length} 个${typeLabel}`;
|
|
||||||
if (failedTasks.length > 0) {
|
|
||||||
notice += `,${failedTasks.length} 个${typeLabel}创建失败`;
|
|
||||||
}
|
|
||||||
|
|
||||||
currentTarget.classList.remove('applying')
|
|
||||||
currentTarget.classList.add('applied')
|
|
||||||
|
|
||||||
const {data} = await this.$store.dispatch("call", {
|
|
||||||
url: 'dialog/msg/sendnotice',
|
|
||||||
data: {
|
|
||||||
dialog_id: this.dialogId,
|
|
||||||
source: 'ai',
|
|
||||||
notice,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
this.sendSuccess(data)
|
|
||||||
|
|
||||||
|
|
||||||
await this.$store.dispatch("call", {
|
|
||||||
url: 'dialog/msg/applied',
|
|
||||||
data: {
|
|
||||||
msg_id: this.operateItem.id,
|
|
||||||
index: taskIndex,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
openTranslationMenu(event) {
|
openTranslationMenu(event) {
|
||||||
const list = Object.keys(languageList).map(item => ({
|
const list = Object.keys(languageList).map(item => ({
|
||||||
label: languageList[item],
|
label: languageList[item],
|
||||||
@ -3761,20 +3632,6 @@ export default {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建任务
|
|
||||||
if (target.classList.contains('apply-create-task-button')) {
|
|
||||||
this.operateItem = this.findMsgByElement(el)
|
|
||||||
this.applyCreateBefore('task', event, el)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建子任务
|
|
||||||
if (target.classList.contains('apply-create-subtask-button')) {
|
|
||||||
this.operateItem = this.findMsgByElement(el)
|
|
||||||
this.applyCreateBefore('subtask', event, el)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 点击切换翻译
|
// 点击切换翻译
|
||||||
if (target.classList.contains('translation-label')) {
|
if (target.classList.contains('translation-label')) {
|
||||||
this.operateItem = this.findMsgByElement(el)
|
this.operateItem = this.findMsgByElement(el)
|
||||||
|
|||||||
127
resources/assets/js/utils/markdown.js
vendored
127
resources/assets/js/utils/markdown.js
vendored
@ -175,17 +175,6 @@ const MarkdownUtils = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const MarkdownPluginUtils = {
|
const MarkdownPluginUtils = {
|
||||||
// 配置选项
|
|
||||||
config: {
|
|
||||||
maxItems: 200,
|
|
||||||
maxTitleLength: 200,
|
|
||||||
maxDescLength: 1000,
|
|
||||||
buttonLabels: {
|
|
||||||
task: '创建任务',
|
|
||||||
subtask: '创建子任务'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// HTML转义函数
|
// HTML转义函数
|
||||||
escapeHtml(unsafe) {
|
escapeHtml(unsafe) {
|
||||||
return unsafe
|
return unsafe
|
||||||
@ -274,120 +263,6 @@ const MarkdownPluginUtils = {
|
|||||||
state.line = nextLine + 1;
|
state.line = nextLine + 1;
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
},
|
|
||||||
|
|
||||||
// 修改初始化插件函数(创建任务)
|
|
||||||
initCreateTaskPlugin(md) {
|
|
||||||
md.block.ruler.before('fence', 'create-task', (state, startLine, endLine, silent) => {
|
|
||||||
const start = state.bMarks[startLine] + state.tShift[startLine];
|
|
||||||
const max = state.eMarks[startLine];
|
|
||||||
const firstLine = state.src.slice(start, max).trim();
|
|
||||||
|
|
||||||
// 检查开始标记,并获取status值
|
|
||||||
const match = firstLine.match(/^:::\s*(create-task-list|create-subtask-list)(?:\s+(\S+))?$/);
|
|
||||||
if (!match) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (silent) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取按钮标题和状态
|
|
||||||
const listType = match[1] === 'create-task-list' ? 'task' : 'subtask';
|
|
||||||
const buttonTitle = this.config.buttonLabels[listType] || '';
|
|
||||||
const status = match[2] || '';
|
|
||||||
|
|
||||||
let nextLine = startLine + 1;
|
|
||||||
let content = [];
|
|
||||||
|
|
||||||
// 查找结束标记
|
|
||||||
while (nextLine < endLine) {
|
|
||||||
const lineStart = state.bMarks[nextLine] + state.tShift[nextLine];
|
|
||||||
const lineMax = state.eMarks[nextLine];
|
|
||||||
const line = state.src.slice(lineStart, lineMax);
|
|
||||||
|
|
||||||
if (line.trim() === ':::') {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
content.push(line);
|
|
||||||
nextLine++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 解析任务
|
|
||||||
const tasks = [];
|
|
||||||
let currentTask = null;
|
|
||||||
let isCollectingDesc = false;
|
|
||||||
let descLines = [];
|
|
||||||
|
|
||||||
content.forEach(line => {
|
|
||||||
const titleMatch = line.trim().match(/^title:\s*(.+)$/);
|
|
||||||
const descMatch = line.trim().match(/^desc:\s*(.*)$/);
|
|
||||||
|
|
||||||
if (titleMatch) {
|
|
||||||
// 如果已经有一个任务在处理中,保存它
|
|
||||||
if (currentTask) {
|
|
||||||
if (descLines.length > 0) {
|
|
||||||
currentTask.desc = descLines.join('\n');
|
|
||||||
}
|
|
||||||
tasks.push(currentTask);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 开始新的任务
|
|
||||||
currentTask = {title: titleMatch[1]};
|
|
||||||
isCollectingDesc = false;
|
|
||||||
descLines = [];
|
|
||||||
} else if (descMatch) {
|
|
||||||
isCollectingDesc = true;
|
|
||||||
if (descMatch[1]) {
|
|
||||||
descLines.push(descMatch[1]);
|
|
||||||
}
|
|
||||||
} else if (isCollectingDesc && line.trim() && !line.trim().startsWith('title:')) {
|
|
||||||
// 收集多行描述,但不包括空行和新的title行
|
|
||||||
descLines.push(line.trim());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 处理最后一个任务
|
|
||||||
if (currentTask) {
|
|
||||||
if (descLines.length > 0) {
|
|
||||||
currentTask.desc = descLines.join('\n');
|
|
||||||
}
|
|
||||||
tasks.push(currentTask);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 生成HTML
|
|
||||||
const showIndex = tasks.length > 1;
|
|
||||||
const taskItems = tasks.slice(0, this.config.maxItems).map((task, index) => [
|
|
||||||
'<li>',
|
|
||||||
showIndex ? `<div class="task-index">${index + 1}.</div>` : '',
|
|
||||||
'<div class="task-item">',
|
|
||||||
`<div class="title">${this.escapeHtml(this.validateInput(task.title, this.config.maxTitleLength))}</div>`,
|
|
||||||
task.desc && match[1] === 'create-task-list' ? `<div class="desc">${this.escapeHtml(this.validateInput(task.desc, this.config.maxDescLength))}</div>` : '',
|
|
||||||
'</div>',
|
|
||||||
'</li>'
|
|
||||||
].join(''));
|
|
||||||
|
|
||||||
const htmls = [
|
|
||||||
'<div class="apply-create-task">',
|
|
||||||
'<ul>',
|
|
||||||
taskItems.join(''),
|
|
||||||
'</ul>',
|
|
||||||
'<div class="apply-button">',
|
|
||||||
`<div class="apply-create-${listType}-button${status ? ' ' + status : ''}">${$A.L(buttonTitle)}</div>`,
|
|
||||||
'</div>',
|
|
||||||
'</div>'
|
|
||||||
];
|
|
||||||
|
|
||||||
// 添加token
|
|
||||||
const token = state.push('html_block', '', 0);
|
|
||||||
token.content = htmls.join('');
|
|
||||||
token.map = [startLine, nextLine];
|
|
||||||
|
|
||||||
state.line = nextLine + 1;
|
|
||||||
return true;
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -415,7 +290,6 @@ export function MarkdownConver(text) {
|
|||||||
MarkdownUtils.mdi.use(mila, {attrs: {target: '_blank', rel: 'noopener noreferrer'}})
|
MarkdownUtils.mdi.use(mila, {attrs: {target: '_blank', rel: 'noopener noreferrer'}})
|
||||||
MarkdownUtils.mdi.use(mdKatex, {blockClass: 'katexmath-block rounded-md p-[10px]', errorColor: ' #cc0000'})
|
MarkdownUtils.mdi.use(mdKatex, {blockClass: 'katexmath-block rounded-md p-[10px]', errorColor: ' #cc0000'})
|
||||||
MarkdownPluginUtils.initReasoningPlugin(MarkdownUtils.mdi);
|
MarkdownPluginUtils.initReasoningPlugin(MarkdownUtils.mdi);
|
||||||
MarkdownPluginUtils.initCreateTaskPlugin(MarkdownUtils.mdi);
|
|
||||||
}
|
}
|
||||||
text = MarkdownPluginUtils.clearEmptyReasoning(text);
|
text = MarkdownPluginUtils.clearEmptyReasoning(text);
|
||||||
text = MarkdownUtils.mdi.render(text);
|
text = MarkdownUtils.mdi.render(text);
|
||||||
@ -426,7 +300,6 @@ export function MarkdownPreview(text) {
|
|||||||
if (MarkdownUtils.mds === null) {
|
if (MarkdownUtils.mds === null) {
|
||||||
MarkdownUtils.mds = MarkdownIt()
|
MarkdownUtils.mds = MarkdownIt()
|
||||||
MarkdownPluginUtils.initReasoningPlugin(MarkdownUtils.mds);
|
MarkdownPluginUtils.initReasoningPlugin(MarkdownUtils.mds);
|
||||||
MarkdownPluginUtils.initCreateTaskPlugin(MarkdownUtils.mds);
|
|
||||||
}
|
}
|
||||||
text = MarkdownPluginUtils.clearEmptyReasoning(text);
|
text = MarkdownPluginUtils.clearEmptyReasoning(text);
|
||||||
return MarkdownUtils.mds.render(text)
|
return MarkdownUtils.mds.render(text)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user