mirror of
https://github.com/kuaifan/dootask.git
synced 2025-12-10 18:02:55 +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);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 搜索在线表情
|
||||
*
|
||||
|
||||
@ -695,7 +695,6 @@ class WebSocketDialogMsg extends AbstractModel
|
||||
$text = $title;
|
||||
} else {
|
||||
$text = Base::markdown2html($text);
|
||||
$text = self::previewConvertTaskList($text);
|
||||
}
|
||||
}
|
||||
$text = preg_replace("/<img\s+class=\"emoticon\"[^>]*?alt=\"(\S+)\"[^>]*?>/", "[$1]", $text);
|
||||
@ -711,36 +710,6 @@ class WebSocketDialogMsg extends AbstractModel
|
||||
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
|
||||
|
||||
@ -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) {
|
||||
const list = Object.keys(languageList).map(item => ({
|
||||
label: languageList[item],
|
||||
@ -3761,20 +3632,6 @@ export default {
|
||||
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')) {
|
||||
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 = {
|
||||
// 配置选项
|
||||
config: {
|
||||
maxItems: 200,
|
||||
maxTitleLength: 200,
|
||||
maxDescLength: 1000,
|
||||
buttonLabels: {
|
||||
task: '创建任务',
|
||||
subtask: '创建子任务'
|
||||
}
|
||||
},
|
||||
|
||||
// HTML转义函数
|
||||
escapeHtml(unsafe) {
|
||||
return unsafe
|
||||
@ -274,120 +263,6 @@ const MarkdownPluginUtils = {
|
||||
state.line = nextLine + 1;
|
||||
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(mdKatex, {blockClass: 'katexmath-block rounded-md p-[10px]', errorColor: ' #cc0000'})
|
||||
MarkdownPluginUtils.initReasoningPlugin(MarkdownUtils.mdi);
|
||||
MarkdownPluginUtils.initCreateTaskPlugin(MarkdownUtils.mdi);
|
||||
}
|
||||
text = MarkdownPluginUtils.clearEmptyReasoning(text);
|
||||
text = MarkdownUtils.mdi.render(text);
|
||||
@ -426,7 +300,6 @@ export function MarkdownPreview(text) {
|
||||
if (MarkdownUtils.mds === null) {
|
||||
MarkdownUtils.mds = MarkdownIt()
|
||||
MarkdownPluginUtils.initReasoningPlugin(MarkdownUtils.mds);
|
||||
MarkdownPluginUtils.initCreateTaskPlugin(MarkdownUtils.mds);
|
||||
}
|
||||
text = MarkdownPluginUtils.clearEmptyReasoning(text);
|
||||
return MarkdownUtils.mds.render(text)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user