起因
一直以来都有每天写总结的习惯(错误日志,改的到挺少🙃),每天会记录反思并对反思的内容做了一个分类比如跟任务,情绪有关的反思就划分到**任务管理,情绪管理。**但是记录的日志划分到了每一天,回头重新看的时候太麻烦,希望相同类型的日志能够按照时间汇总到一起方便浏览查看😄。
思路
使用的笔记软件是语雀 提供了对应的开放API
, 大致思路是编写日志的时候,按照设定规则去编写,在去获取对应的文章数据解析文章 结构生成目标结构的文本数据 在调用接口创建新的doc
。
具体实现
获取到勾选的所有文章数据,去提取对应的分类信息并转换成对象结构并按标题分组 ,在对每个分组的反思根据时间 和设定的规则 排序,最后在合并所有分组,并调用创建doc
接口!
vue
async function mergeDoc() {
if (targetDoc.value.filter((item) => !item.children.length).length !== 1
|| awaitMergeDocs.value.length === 0) {
return ElMessage.error("文档选择不正确");
}
isLoading.value = true;
// 得到所有的文章数据
const docs = await getSelectedDocs(toValue(awaitMergeDocs));
// 将文章转换为分类对象
const cryObj = docs.flatMap((doc) => matchSummary(doc))
//根据最早最晚得到标题
const title = getMergeTitle(cryObj)
//将分类对象进行分组
const cryGroup = generateGroup(cryObj)
//对分类对象进行排序
Object.keys(cryGroup).forEach((k) => cryGroup[k] = sortTime(cryGroup[k]))
let newDocStr = mergeSummary(cryGroup)
await createSummary(`/repos/${selectBook.value}/docs/${targetDoc.value[0].id}`, {
slug: targetDoc.value[0].id,
title: title,
body: newDocStr
})
ElMessage.success("合并成功!")
isLoading.value = false;
}
文本转换成分类对象
先调用handleRethinks
去提取出doc
里面的rethink
字符串,在调用summaryGroup
将rethink
下的二级标题以及内容转换为对象。
javascript
// 匹配一级标题日期
const matchRegex = {
matchTime: /^#\s\d{4}年\d{1,2}月.*?日/gm, //提取时间
}
let docInfo = null;
// 入口函数 返回提取的本篇文章的总结对象, 一般调用至少调用三十次,
export default function main(data) {
// 保存文章对象
docInfo = data
let summaryText = data.body; //得到md文件格式
// 表示是单元
let isStage = data.title.includes("单元");
const dates = summaryText.match(matchRegex.matchTime) ?? [];
// 提取的rethinks
let rethinks = handelRethinks(summaryText,isStage);
const stageSummary = rethinks.flatMap((item, index) =>
summaryGroupAdapter(isStage, item, dates[index]));
return stageSummary;
}
function summaryGroupAdapter(isStage,str,time){
//!不是总结
return summaryGroup(str, time, !isStage ? "\n# rethink" : "\n## rethink");
}
//!2. 将总结转换为分类对象
function summaryGroup(str, time, startStr = "\n## rethink") {
let source = str.replace(startStr, "")
//!总结的分类就是三级标题
return source.split("###").filter((item) => item !== "\n" && item).map((item) => {
let index = item.indexOf("\n");
return {
group: item.slice(0, index),//标题结尾有一个换行
content: item.slice(index).replace(`\n`,`\n `).replace(`\n\n`,`\n\n `),
time:startStr === "\n## rethink" ? time : `# ${docInfo.title}`
}
})
}
// 截取反思字符串
function handelRethinks(text, isStage) {
return isStage ? sliceRethinks(text)
: sliceRethinks(text, "\n# rethink", "\n# idea");
}
// 截取反思字符串 包括标题
function sliceRethinks(str, startStr = "\n## rethink", endStr = "\n## idea") {
let results = [];
let sourceStr = str;
while (sourceStr.search(startStr) !== -1) {
let startIndex = sourceStr.search(startStr);
let endIndex = sourceStr.search(endStr);
//
let rethinks = sourceStr.slice(startIndex, endIndex);
results.push(rethinks);
sourceStr = sourceStr.slice(endIndex + endStr.length)
}
return results;
}
分组并排序
先对整个数组反思对象进行分组,在调用sortTime
进行排序内部先对合法的字符串进行升序,在对不合法的字符串按照一定规则**排序,**最后在合并在一起。
javascript
// 阶段总结格式化
let stageFormat = {
"第一阶段": 0,
"第二阶段": 1,
"第三阶段": 2,
"第四阶段": 3,
"第五阶段": 4,
"第六阶段": 5,
"第七阶段": 6,
"第八阶段": 7,
"第九阶段": 8,
"第十阶段": 9,
"第十一阶段": 10,
"第十二阶段": 11,
"第十三阶段": 12,
"第十四阶段": 13,
"第十五阶段": 14
}
// 对数据进行分组
export function generateGroup(cates) {
return cates.reduce((pre, item) => {
if (pre[item.group]) {
pre[item.group].push(item)
} else {
pre[item.group] = [item]
}
return pre;
}, {})
}
// 定义一个函数来转换日期格式为时间戳
export function convertDateToTimestamp(dateStr) {
//exec匹配换成match匹配
const dateParts = dateStr.match(/\d+/g).map(Number);
return new Date(dateParts[0], dateParts[1] - 1, dateParts[2]).getTime();
}
// 针对数据排序的工具函数
export function sortTime(cgyData) {
let verifyDate = /^#\s\d{4}年\d{1,2}月\d{1,2}日/gm
let correctFormatData = cgyData.filter((cry) => cry.time.search(verifyDate) !== -1);
let unCorrectFormatData = cgyData.filter((cry) => cry.time.search(verifyDate) === -1);
// 按照时间进行排序
correctFormatData.sort((a, b) => {
let aTimeStr = extractTimeStr(a.time);
let bTimeStr = extractTimeStr(b.time);
return convertDateToTimestamp(aTimeStr) - convertDateToTimestamp(bTimeStr)
})
// 处理不规范的排序
unCorrectFormatData = sortUnCorrectFormat(unCorrectFormatData)
return correctFormatData.concat(unCorrectFormatData)
}
// 处理不规范格式
function sortUnCorrectFormat(cryList) {
let newArr = new Array(cryList.length).fill(0);
let staged = [] //暂存标题不合法数据
cryList.forEach((cry) => {
let time = cry.time.slice(-4);
let stageTitle = stageFormat[time];
if (stageTitle!== undefined) {
newArr[stageTitle] = cry;
} else {
staged.push(cry);
}
})
return newArr.filter((item) => item !== 0).concat(staged)
}
function sortArrayByTime(cgyData) {
//! 去掉全局和多行匹配
let verifyDate = /^#\s\d{4}年\d{1,2}月\d{1,2}日/
let correctFormatData = cgyData.filter((cry) => cry.time.search(verifyDate) !== -1);
correctFormatData.sort((a, b) => {
//!抽取复用代码
let aTimeStr = extractTimeStr(a.time);
let bTimeStr = extractTimeStr(b.time);
return convertDateToTimestamp(aTimeStr) - convertDateToTimestamp(bTimeStr)
});
return correctFormatData;
}
//!抽取的单行代码
function extractTimeStr(timeStr) {
return timeStr.split(" ").pop();
}
// 得到文章的标题
export function getMergeTitle(arr) {
let correctFormatData = sortArrayByTime(arr)
let firstElm = correctFormatData[0];
let lastElm = correctFormatData[correctFormatData.length - 1];
if (correctFormatData.length === 1) { //只有一个值
return extractTimeStr(firstElm.time)
}
return `${extractTimeStr(firstElm.time)} - ${extractTimeStr(lastElm.time)}`;
}
合并对应文档
最后根据将排序 后的数据合并在一起,得到**汇总字符串,**根据合并后端字符串创建doc
。
javascript
// 合并字符串
export function mergeSummary(groupObj) {
let summary = ""
Object.keys(groupObj).forEach((key) => {
let sayCate = ""
sayCate = groupObj[key].map((item) => `#${item.time}${item.content}`).join("")
summary += `# ${key}\n${sayCate}`; //设置上key
})
return summary
}
结果
在实现了对应的ui
界面逻辑(具体代码),并托管到netlify
上,不得不说netlify
真的强大还支持代理。
总结
拆分代码真的很重要,刚开始不注意写成一坨,后面具体拆分了一下函数以及组件。无论是扩展性,还是可读性都提高了很多!