feat: 支持同步文章到云端
This commit is contained in:
parent
991ca62c68
commit
58012dbbd3
@ -20,7 +20,7 @@
|
||||
</NormalToolbar>
|
||||
<ExportPDF :modelValue="editorState.text" :customize="customizePDF"
|
||||
@onProgress="handleExportProgress" />
|
||||
<NormalToolbar title="发布文章" @onClick="publish">
|
||||
<NormalToolbar title="同步到云端" @onClick="uploadCloud">
|
||||
<template #trigger>
|
||||
<Icon class="md-editor-icon" type="md-cloud-upload" size="22" />
|
||||
</template>
|
||||
@ -55,8 +55,9 @@ import { ThemeSwitch, PreviewThemeSwitch, ExportPDF } from '@vavt/v3-extension';
|
||||
import { lineNumbers } from '@codemirror/view';
|
||||
import LinkAttr from 'markdown-it-link-attributes';
|
||||
import { ref, reactive, watch, nextTick, onMounted } from "vue";
|
||||
import { Message } from 'view-ui-plus'
|
||||
import { Message, Modal } from 'view-ui-plus'
|
||||
import { encode as plantumlEncoder } from 'plantuml-encoder';
|
||||
import { SubmitArticle, UpdateArticle } from '/src/utils/userHandler';
|
||||
|
||||
// fetchScript 用于将其他 JS 脚本加载进来
|
||||
const fetchScript = (url) => new Promise((resolve) => scriptjs(url, () => resolve()));
|
||||
@ -317,9 +318,69 @@ const handleExportProgress = (progress) => {
|
||||
}
|
||||
};
|
||||
|
||||
const publish = () => {
|
||||
// TODO 调用接口将 markdown 源码或者 HTML 代码发布到云端
|
||||
Message.warning('抱歉,该功能暂未开放');
|
||||
const uploadCloud = () => {
|
||||
// 找到 markdown 代码第一行,第一行前面的空行都剔除掉
|
||||
const markdownLines = editorState.text.split('\n');
|
||||
let firstLine = 0;
|
||||
for (let index = 0; index < markdownLines.length; index++) {
|
||||
if (markdownLines[index].trim().length > 0) {
|
||||
firstLine = index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (let index = 0; index < firstLine; index++) {
|
||||
markdownLines.shift();
|
||||
}
|
||||
const firstLineText = markdownLines[0].trim();
|
||||
if (!firstLineText.startsWith('# ')) {
|
||||
Message.warning('第一行请以 “# 文章标题” 作为开头');
|
||||
return;
|
||||
}
|
||||
|
||||
// 从第一行里提取文章标题和文章 ID
|
||||
let title = firstLineText.slice(2).trim();
|
||||
let articleID = '';
|
||||
const match = title.match(/^\[(.*?)\]\((.*?)\)$/);
|
||||
if (match) {
|
||||
title = match[1].trim(); // "标题"
|
||||
articleID = match[2].trim(); // "链接,例如 https://github.com"
|
||||
}
|
||||
|
||||
// 如果存在文章 ID,则更新该文章;否则发布该文章,并在文章 ID 中加入链接
|
||||
if (articleID.length > 0 && !isNaN(Number(articleID, 10))) {
|
||||
editorState.text = markdownLines.join('\n');
|
||||
// 直接调用更新文章的接口
|
||||
UpdateArticle(parseInt(articleID, 10), title, editorState.text)
|
||||
.then((data) => {
|
||||
Modal.remove();
|
||||
Message.success('同步成功');
|
||||
onSave(editorState.text);
|
||||
})
|
||||
.catch((error) => {
|
||||
Message.error(`同步异常: ${error}`);
|
||||
});
|
||||
} else {
|
||||
// 询问是否要用 title 作为标题发布文章
|
||||
Modal.confirm({
|
||||
title: '发布前确认',
|
||||
content: `<p>确认使用《${title}》作为文章标题将其同步到云端。<br/>点击确认之后,会同步文章,并修改第一行嵌入文章 ID,最后将当前内容保存操作到本地。</p>`,
|
||||
loading: true,
|
||||
onOk: () => {
|
||||
SubmitArticle(title, markdownLines.join('\n'))
|
||||
.then((data) => {
|
||||
articleID = data.id;
|
||||
markdownLines[0] = '# [' + title + '](' + articleID + ')';
|
||||
editorState.text = markdownLines.join('\n');
|
||||
Modal.remove();
|
||||
Message.success('同步成功');
|
||||
onSave(editorState.text);
|
||||
})
|
||||
.catch((error) => {
|
||||
Message.error(`同步异常: ${error}`);
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const uploadImgForm = reactive({
|
||||
|
||||
@ -3,7 +3,9 @@ import md5 from 'js-md5';
|
||||
// 由于是跨域登录,需要手动设置并携带 Cookie
|
||||
const setPHPSessionToCookie = (sessionID) => {
|
||||
if (sessionID) {
|
||||
document.cookie = `PHPSESSID=${sessionID}; max-age=604800; SameSite=None; secure; path=/`;
|
||||
// 使用 SameSite=None 和 secure 属性,在 tauri 环境会设置失败
|
||||
// document.cookie = `PHPSESSID=${sessionID}; max-age=604800; SameSite=None; secure; path=/`;
|
||||
document.cookie = `PHPSESSID=${sessionID}; max-age=604800; path=/`;
|
||||
}
|
||||
}
|
||||
|
||||
@ -149,10 +151,63 @@ const Logout = () => {
|
||||
});
|
||||
}
|
||||
|
||||
const SubmitArticle = (title, mdCode) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const PHPSESSID = getPHPSessionFromCookie();
|
||||
fetch('https://myafei.cn/php/ajax.php?PHPSESSID=' + PHPSESSID, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
'func': 'submit_article',
|
||||
'title': title,
|
||||
'mdCode': mdCode,
|
||||
}),
|
||||
}).then(response => {
|
||||
if (!response.ok) throw new Error(`HTTP 错误: ${response.status}`);
|
||||
return response.json();
|
||||
}).then(data => {
|
||||
if (data.status == 0) {
|
||||
resolve(data);
|
||||
} else {
|
||||
reject(new Error(data.error));
|
||||
}
|
||||
}).catch(error => {
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const UpdateArticle = (id, title, mdCode) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const PHPSESSID = getPHPSessionFromCookie();
|
||||
fetch('https://myafei.cn/php/ajax.php?PHPSESSID=' + PHPSESSID, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
'func': 'update_article',
|
||||
'id': id,
|
||||
'title': title,
|
||||
'mdCode': mdCode,
|
||||
}),
|
||||
}).then(response => {
|
||||
if (!response.ok) throw new Error(`HTTP 错误: ${response.status}`);
|
||||
return response.json();
|
||||
}).then(data => {
|
||||
if (data.status == 0) {
|
||||
resolve(data);
|
||||
} else {
|
||||
reject(new Error(data.error));
|
||||
}
|
||||
}).catch(error => {
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export {
|
||||
SignIn,
|
||||
SignUp,
|
||||
SendSignUpEmail,
|
||||
CheckLoginStatus,
|
||||
Logout,
|
||||
SubmitArticle,
|
||||
UpdateArticle,
|
||||
};
|
||||
Loading…
x
Reference in New Issue
Block a user