Merge branch 'blossom-editor:dev' into dev

This commit is contained in:
Tianjiu 2024-03-15 23:40:12 +08:00 committed by GitHub
commit ab4b4a25b7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 71 additions and 28 deletions

View File

@ -56,7 +56,8 @@ docker compose -f docker/compose/blossom-mysql8.yaml up -d
Join QQ group, communicate with us and discuss problems. Join QQ group, communicate with us and discuss problems.
- Group 1522359970 (It is full) - Group 1522359970 (It is full)
- Group 2921906098 - Group 2921906098 (It is full)
- Group 3749721525
You can also contact with us by the issue , We will definitely try our best to reply to you. You can also contact with us by the issue , We will definitely try our best to reply to you.
We also welcome everyone to participate in the development and discussion of Blossom. We also welcome everyone to participate in the development and discussion of Blossom.
@ -64,6 +65,7 @@ We also welcome everyone to participate in the development and discussion of Blo
<p align="center"> <p align="center">
<img src="./doc/imgs/qq1.png" height="400"> <img src="./doc/imgs/qq1.png" height="400">
<img src="./doc/imgs/qq2.png" height="400"> <img src="./doc/imgs/qq2.png" height="400">
<img src="./doc/imgs/qq3.png" height="400">
</p> </p>
# 🤝 Sponsor Blossom # 🤝 Sponsor Blossom

View File

@ -58,11 +58,13 @@ docker compose -f docker/compose/blossom-mysql8.yaml up -d
加入群聊进行沟通,反馈问题。 加入群聊进行沟通,反馈问题。
- 1 群522359970 (即将满) - 1 群522359970 (即将满)
- 2 群921906098 - 2 群921906098 (即将满)
- 3 群749721525
<p align="center"> <p align="center">
<img src="./doc/imgs/qq1.png" height="400"> <img src="./doc/imgs/qq1.png" height="400">
<img src="./doc/imgs/qq2.png" height="400"> <img src="./doc/imgs/qq2.png" height="400">
<img src="./doc/imgs/qq3.png" height="400">
</p> </p>
# 🤝 赞助 Blossom # 🤝 赞助 Blossom

View File

@ -26,6 +26,7 @@ import com.blossom.backend.server.utils.ArticleUtil;
import com.blossom.common.base.enums.YesNo; import com.blossom.common.base.enums.YesNo;
import com.blossom.common.base.exception.XzException500; import com.blossom.common.base.exception.XzException500;
import com.blossom.common.base.util.DateUtils; import com.blossom.common.base.util.DateUtils;
import com.blossom.common.base.util.PrimaryKeyUtil;
import com.blossom.common.base.util.SortUtil; import com.blossom.common.base.util.SortUtil;
import com.blossom.common.iaas.IaasProperties; import com.blossom.common.iaas.IaasProperties;
import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnore;
@ -37,10 +38,7 @@ import org.springframework.stereotype.Component;
import java.io.File; import java.io.File;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.*;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -164,12 +162,24 @@ public class ArticleBackupService {
int idLen = String.valueOf(allContents.stream() int idLen = String.valueOf(allContents.stream()
.map(ArticleEntity::getId).max(SortUtil.longSort).orElse((1L))).length(); .map(ArticleEntity::getId).max(SortUtil.longSort).orElse((1L))).length();
// 记录已经保存的文件
Set<String> exists = new HashSet<>();
backLogs.add("┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ↓↓ 文章列表 ↓↓ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"); backLogs.add("┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ↓↓ 文章列表 ↓↓ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
backLogs.add("┃ 排序 [ID] [版本] [时间] 文章路径"); backLogs.add("┃ 排序 [ID] [版本] [时间] 文章路径");
backLogs.add("┠────────────────────────────────────────────────────────────────────────────"); backLogs.add("┠────────────────────────────────────────────────────────────────────────────");
for (DocTreeRes article : articles) { for (DocTreeRes article : articles) {
String name = clearPath(article.getN());
// 处理文章或文件夹重名的情况
if (exists.contains(name)) {
name = name + "_" + article.getI();
if (exists.contains(name)) {
name = name + "_" + PrimaryKeyUtil.nextId();
}
}
exists.add(name);
// 创建文章 file // 创建文章 file
File file = new File(backupFile.getRootPath() + "/" + clearPath(article.getN()) + getArticleSuffix(type)); File file = new File(backupFile.getRootPath() + "/" + name + getArticleSuffix(type));
// 导出的文章正文 // 导出的文章正文
ArticleEntity articleDetail = markdowns.get(article.getI()); ArticleEntity articleDetail = markdowns.get(article.getI());
if (articleDetail == null) { if (articleDetail == null) {
@ -305,7 +315,8 @@ public class ArticleBackupService {
req.setArticleId(articleId); req.setArticleId(articleId);
List<DocTreeRes> docs = docService.listTree(req); List<DocTreeRes> docs = docService.listTree(req);
List<DocTreeRes> articles = new ArrayList<>(); List<DocTreeRes> articles = new ArrayList<>();
findArticle("", docs, articles); Set<String> exists = new HashSet<>();
findArticle("", docs, articles, exists);
return articles; return articles;
} }
@ -315,15 +326,20 @@ public class ArticleBackupService {
* @param prefix 上级文件夹名称 * @param prefix 上级文件夹名称
* @param docs 文章树状列表 * @param docs 文章树状列表
* @param articles 拼接结果列表, 虽然是 DocTreeRes 对象, 但不是树状结构 * @param articles 拼接结果列表, 虽然是 DocTreeRes 对象, 但不是树状结构
* @param exists 判断文件夹是否重名
*/ */
private void findArticle(String prefix, List<DocTreeRes> docs, List<DocTreeRes> articles) { private void findArticle(String prefix, List<DocTreeRes> docs, List<DocTreeRes> articles, Set<String> exists) {
if (CollUtil.isEmpty(docs)) { if (CollUtil.isEmpty(docs)) {
return; return;
} }
for (DocTreeRes doc : docs) { for (DocTreeRes doc : docs) {
if (exists.contains(doc.getN())) {
doc.setN(doc.getN() + "_" + doc.getI());
}
exists.add(doc.getN());
doc.setN(prefix + "/" + doc.getN()); doc.setN(prefix + "/" + doc.getN());
if (CollUtil.isNotEmpty(doc.getChildren())) { if (CollUtil.isNotEmpty(doc.getChildren())) {
findArticle(doc.getN(), doc.getChildren(), articles); findArticle(doc.getN(), doc.getChildren(), articles, exists);
} }
if (doc.getTy().equals(DocTypeEnum.A.getType())) { if (doc.getTy().equals(DocTypeEnum.A.getType())) {
articles.add(doc); articles.add(doc);
@ -439,11 +455,13 @@ public class ArticleBackupService {
private String userId; private String userId;
/** /**
* 备份日期 YYYYMMDD * 备份日期 YYYYMMDD
*
* @mock 20230101 * @mock 20230101
*/ */
private String date; private String date;
/** /**
* 备份时间 HHMMSS * 备份时间 HHMMSS
*
* @mock 123001 * @mock 123001
*/ */
private String time; private String time;
@ -459,7 +477,6 @@ public class ArticleBackupService {
* 备份包路径 * 备份包路径
*/ */
private String path; private String path;
/** /**
* 本地文件 * 本地文件
*/ */

View File

@ -20,6 +20,7 @@ import com.blossom.common.base.exception.XzException400;
import com.blossom.common.base.exception.XzException404; import com.blossom.common.base.exception.XzException404;
import com.blossom.common.base.exception.XzException500; import com.blossom.common.base.exception.XzException500;
import com.blossom.common.base.util.DateUtils; import com.blossom.common.base.util.DateUtils;
import com.blossom.common.base.util.PrimaryKeyUtil;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -178,6 +179,7 @@ public class FolderService extends ServiceImpl<FolderMapper, FolderEntity> {
folder.setStorePath(parentFolder.getStorePath()); folder.setStorePath(parentFolder.getStorePath());
} }
} }
folder.setId(PrimaryKeyUtil.nextId());
baseMapper.insert(folder); baseMapper.insert(folder);
return folder; return folder;
} }

View File

@ -27,7 +27,6 @@ public class FolderEntity extends AbstractPOJO implements Serializable {
/** /**
* id * id
*/ */
@TableId(type = IdType.AUTO)
private Long id; private Long id;
/** /**
* 父id * 父id

View File

@ -1,7 +1,6 @@
package com.blossom.backend.server.utils; package com.blossom.backend.server.utils;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.blossom.backend.server.article.draft.pojo.ArticleEntity; import com.blossom.backend.server.article.draft.pojo.ArticleEntity;
import com.blossom.backend.server.doc.DocTypeEnum; import com.blossom.backend.server.doc.DocTypeEnum;
@ -10,11 +9,7 @@ import com.blossom.backend.server.folder.pojo.FolderEntity;
import com.blossom.common.base.enums.YesNo; import com.blossom.common.base.enums.YesNo;
import com.blossom.common.base.util.SortUtil; import com.blossom.common.base.util.SortUtil;
import java.util.ArrayList; import java.util.*;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
@ -37,14 +32,17 @@ public class DocUtil {
* @return 树状菜单对象 * @return 树状菜单对象
*/ */
public static List<DocTreeRes> treeWrap(List<DocTreeRes> list, boolean priorityType) { public static List<DocTreeRes> treeWrap(List<DocTreeRes> list, boolean priorityType) {
// 将原始列表进行分组 并排序每个分组的列表 // 将原始列表进行分组, 并排序每个分组的列表
Map<Long, List<DocTreeRes>> pidMapping = list.stream().collect( Map<Long, List<DocTreeRes>> pidMapping = list.stream().collect(
Collectors.groupingBy(DocTreeRes::getP, HashMap::new, Collectors.groupingBy(DocTreeRes::getP, HashMap::new,
Collectors.collectingAndThen(Collectors.toList(), Collectors.collectingAndThen(Collectors.toList(),
item -> item.stream().sorted(Comparator.comparingInt(DocTreeRes::getS)).collect(Collectors.toList())))); item -> item.stream().sorted(Comparator.comparingInt(DocTreeRes::getS)).collect(Collectors.toList()))));
// 免递归方式赋值子菜单 // 免递归方式赋值子菜单
list.parallelStream().forEach(item -> { list.parallelStream().forEach(item -> {
if (!CollectionUtil.isEmpty(pidMapping.get(item.getI()))){ if(item.getTy().equals(DocTypeEnum.A.getType())) {
return;
}
if (!CollUtil.isEmpty(pidMapping.get(item.getI()))){
item.setChildren(pidMapping.get(item.getI())); item.setChildren(pidMapping.get(item.getI()));
} }
}); });

View File

@ -29,6 +29,11 @@ export const cwTheme: any = {
backgroundColor: 'var(--bl-editor-gutters-bg-color)', backgroundColor: 'var(--bl-editor-gutters-bg-color)',
color: 'var(--el-color-primary)' color: 'var(--el-color-primary)'
}, },
'.cm-panel.cm-search [name=close]': {
fontSize: '20px !important',
marginRight: '10px',
color: 'var(--el-color-primary)'
},
'.cm-panels-top': { '.cm-panels-top': {
'z-index': '999', 'z-index': '999',
borderColor: 'var(--el-border-color)' borderColor: 'var(--el-border-color)'

View File

@ -47,7 +47,7 @@ export const keymaps = {
// https://codemirror.net/docs/ref/#commands.defaultKeymap // https://codemirror.net/docs/ref/#commands.defaultKeymap
selectLine: isMac ? '⌃ L' : 'Alt + L', selectLine: isMac ? '⌃ L' : 'Alt + L',
// https://codemirror.net/docs/ref/#search // https://codemirror.net/docs/ref/#search
toLine: isMac ? '⌥ ⌘ G' : 'Alt + G', toLine: isMac ? '⌥ ⌘ G' : 'Ctrl + Alt + G',
moveLineUp: isMac ? '⌥ ↑' : 'Alt + ↑', moveLineUp: isMac ? '⌥ ↑' : 'Alt + ↑',
moveLineDown: isMac ? '⌥ ↓' : 'Alt + ↓', moveLineDown: isMac ? '⌥ ↓' : 'Alt + ↓',
copyLineUp: isMac ? '⌥ ⇧ ↑' : 'Shift + Alt + ↑', copyLineUp: isMac ? '⌥ ⇧ ↑' : 'Shift + Alt + ↑',

View File

@ -104,15 +104,14 @@ export const renderHeading = (text: string, level: number, raw: string) => {
if (dom) { if (dom) {
id += dom.body.innerText id += dom.body.innerText
} else { } else {
id += text id += raw
} }
} else { } else {
id += text id += raw
} }
} catch { } catch {
id += text id += raw
} }
return `<h${level} id="${id}">${text}</h${level}>` return `<h${level} id="${id}">${text}</h${level}>`
} }

View File

@ -57,7 +57,7 @@
<bl-col just="center" height="fit-content"> <bl-col just="center" height="fit-content">
<div class="blod" style="margin: 80px 0 10px 0">开发者列表</div> <div class="blod" style="margin: 80px 0 10px 0">开发者列表</div>
<div class="developer"> <div class="developer">
<bl-row class="item" v-for="dever in developer" width="250px" height="70px"> <bl-row class="item" v-for="dever in developer" width="250px" height="70px" @click="toView(dever.github)">
<div> <div>
<img :src="dever.avatar" /> <img :src="dever.avatar" />
</div> </div>
@ -86,12 +86,15 @@
</ol> </ol>
</div> </div>
</bl-row> </bl-row>
<bl-row just="center" class="statement"> 本应用完全免费并开源全部源代码如果你从付费渠道获取本应用谨防上当受骗 </bl-row>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import CONFIG from '@renderer/assets/constants/system' import CONFIG from '@renderer/assets/constants/system'
import { openExtenal } from '@renderer/assets/utils/electron' import { openExtenal } from '@renderer/assets/utils/electron'
import { toView } from '@renderer/assets/utils/util'
import { useUserStore } from '@renderer/stores/user' import { useUserStore } from '@renderer/stores/user'
const userStore = useUserStore() const userStore = useUserStore()
@ -105,8 +108,15 @@ const references = [
const developer = [ const developer = [
{ {
name: '小贼贼子', name: '小贼贼子',
desc: '一个后端程序员,也是一个半吊子前端。', desc: '创建者',
github: 'https://github.com/xiaozzzi',
avatar: 'https://www.wangyunf.com/bl/pic/home/bl/img/U1/head/luban.png' avatar: 'https://www.wangyunf.com/bl/pic/home/bl/img/U1/head/luban.png'
},
{
name: 'Tianjiu',
desc: '项目成员、英文译者',
github: 'https://github.com/T1anjiu',
avatar: 'https://www.wangyunf.com/bl/pic/home/bl/img/U1/pic/blosteam/T1anjiu.jpg'
} }
] ]
@ -181,10 +191,11 @@ const getServerVersion = () => {
} }
.developer { .developer {
width: 630px;
@include flex(row, flex-start, flex-start); @include flex(row, flex-start, flex-start);
width: 630px;
align-content: flex-start; align-content: flex-start;
flex-wrap: wrap; flex-wrap: wrap;
cursor: pointer;
.item { .item {
background-color: var(--bl-bg-color); background-color: var(--bl-bg-color);
@ -199,6 +210,7 @@ const getServerVersion = () => {
} }
.name { .name {
font-size: 14px;
height: 25px; height: 25px;
} }
@ -208,6 +220,7 @@ const getServerVersion = () => {
} }
} }
} }
.reference { .reference {
width: 630px; width: 630px;
font-size: 12px; font-size: 12px;
@ -217,5 +230,11 @@ const getServerVersion = () => {
border-radius: 5px; border-radius: 5px;
color: #8b8b8b; color: #8b8b8b;
} }
.statement {
font-size: 13px;
margin-top: 20px;
color: var(--bl-text-color-light);
}
} }
</style> </style>

BIN
doc/imgs/qq3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB