mirror of
https://gitee.com/blossom-editor/blossom.git
synced 2025-12-06 16:58:26 +08:00
fix: 文章重命名与删除对双链图表的影响
This commit is contained in:
parent
479df5bc09
commit
86a07075b5
@ -139,6 +139,7 @@ public class ArticleController {
|
||||
public R<Long> insert(@Validated @RequestBody ArticleUpdReq req) {
|
||||
ArticleEntity article = req.to(ArticleEntity.class);
|
||||
article.setTags(DocUtil.toTagStr(req.getTags()));
|
||||
article.setUserId(AuthContext.getUserId());
|
||||
return R.ok(baseService.update(article));
|
||||
}
|
||||
|
||||
@ -166,6 +167,7 @@ public class ArticleController {
|
||||
@PostMapping("/upd/name")
|
||||
public R<?> updName(@Validated @RequestBody ArticleUpdNameReq name) {
|
||||
ArticleEntity article = name.to(ArticleEntity.class);
|
||||
article.setUserId(AuthContext.getUserId());
|
||||
baseService.update(article);
|
||||
return R.ok();
|
||||
}
|
||||
@ -187,6 +189,7 @@ public class ArticleController {
|
||||
}
|
||||
ArticleEntity article = req.to(ArticleEntity.class);
|
||||
article.setTags(DocUtil.toTagStr(tags));
|
||||
article.setUserId(AuthContext.getUserId());
|
||||
baseService.update(article);
|
||||
return R.ok(tags);
|
||||
}
|
||||
@ -207,7 +210,9 @@ public class ArticleController {
|
||||
*/
|
||||
@PostMapping("/star")
|
||||
public R<Long> star(@Validated @RequestBody ArticleStarReq req) {
|
||||
return R.ok(baseService.update(req.to(ArticleEntity.class)));
|
||||
ArticleEntity article = req.to(ArticleEntity.class);
|
||||
article.setUserId(AuthContext.getUserId());
|
||||
return R.ok(baseService.update(article));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -166,6 +166,7 @@ public class ArticleService extends ServiceImpl<ArticleMapper, ArticleEntity> {
|
||||
public Long update(ArticleEntity req) {
|
||||
XzException404.throwBy(req.getId() == null, "ID不得为空");
|
||||
baseMapper.updById(req);
|
||||
referenceService.updateInnerName(req.getUserId(), req.getId(), req.getName());
|
||||
return req.getId();
|
||||
}
|
||||
|
||||
@ -212,8 +213,10 @@ public class ArticleService extends ServiceImpl<ArticleMapper, ArticleEntity> {
|
||||
baseMapper.deleteById(id);
|
||||
// 删除公开文章
|
||||
openMapper.delById(id);
|
||||
// 删除引用
|
||||
// 删除主动引用
|
||||
referenceService.delete(id);
|
||||
// 将被动引用中的名称修改为未知
|
||||
referenceService.updateToUnknown(userId, id);
|
||||
// 删除访问记录
|
||||
viewService.delete(id);
|
||||
}
|
||||
|
||||
@ -16,8 +16,8 @@ import java.util.List;
|
||||
* 文章回收站 [A#Recycle]
|
||||
*
|
||||
* @author xzzz
|
||||
* @since 1.10.0
|
||||
* @order 7
|
||||
* @since 1.10.0
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@ -44,7 +44,7 @@ public class ArticleRecycleController {
|
||||
*/
|
||||
@PostMapping("/restore")
|
||||
public R<?> restore(@Validated @RequestBody ArticleRecycleRestoreReq req) {
|
||||
baseService.restore(req.getId());
|
||||
baseService.restore(AuthContext.getUserId(), req.getId());
|
||||
return R.ok();
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,6 +9,7 @@ import com.blossom.backend.base.param.pojo.ParamEntity;
|
||||
import com.blossom.backend.base.search.EnableIndex;
|
||||
import com.blossom.backend.base.search.message.IndexMsgTypeEnum;
|
||||
import com.blossom.backend.server.article.recycle.pojo.ArticleRecycleEntity;
|
||||
import com.blossom.backend.server.article.reference.ArticleReferenceService;
|
||||
import com.blossom.backend.server.folder.FolderService;
|
||||
import com.blossom.backend.server.folder.pojo.FolderEntity;
|
||||
import com.blossom.common.base.util.DateUtils;
|
||||
@ -34,6 +35,7 @@ public class ArticleRecycleService extends ServiceImpl<ArticleRecycleMapper, Art
|
||||
|
||||
private final FolderService folderService;
|
||||
private final ParamService paramService;
|
||||
private final ArticleReferenceService referenceService;
|
||||
|
||||
|
||||
/**
|
||||
@ -52,7 +54,7 @@ public class ArticleRecycleService extends ServiceImpl<ArticleRecycleMapper, Art
|
||||
*/
|
||||
@EnableIndex(type = IndexMsgTypeEnum.ADD, id = "#id")
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void restore(Long id) {
|
||||
public void restore(Long userId, Long id) {
|
||||
ArticleRecycleEntity article = baseMapper.selectById(id);
|
||||
FolderEntity folder = folderService.selectById(article.getPid());
|
||||
if (ObjUtil.isNull(folder)) {
|
||||
@ -61,10 +63,13 @@ public class ArticleRecycleService extends ServiceImpl<ArticleRecycleMapper, Art
|
||||
baseMapper.restore(id, folder.getId());
|
||||
}
|
||||
baseMapper.deleteById(id);
|
||||
// 将被动引用中的未知文章名修改为正常文章名
|
||||
referenceService.updateToKnown(userId, id, article.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* 每天凌晨4点执行
|
||||
*
|
||||
* @Scheduled(cron = "0 0/1 * * * ?")
|
||||
*/
|
||||
@Scheduled(cron = "0 0 04 * * ?")
|
||||
|
||||
@ -0,0 +1,30 @@
|
||||
package com.blossom.backend.server.article.reference;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
public enum ArticleReferenceEnum {
|
||||
/**
|
||||
* 图片
|
||||
*/
|
||||
FILE(10),
|
||||
/**
|
||||
* 内部文章
|
||||
*/
|
||||
INNER(11),
|
||||
/**
|
||||
* 未知内部文章
|
||||
*/
|
||||
INNER_UNKNOWN(12),
|
||||
|
||||
/**
|
||||
* 外部文章
|
||||
*/
|
||||
OUTSIDE(21);
|
||||
|
||||
@Getter
|
||||
private final Integer type;
|
||||
|
||||
ArticleReferenceEnum(Integer type) {
|
||||
this.type = type;
|
||||
}
|
||||
}
|
||||
@ -40,4 +40,25 @@ public interface ArticleReferenceMapper extends BaseMapper<ArticleReferenceEntit
|
||||
* @param articleId 文章ID
|
||||
*/
|
||||
List<ArticleReferenceEntity> listGraph(@Param("inner") Boolean inner, @Param("userId") Long userId, @Param("articleId") Long articleId);
|
||||
|
||||
/**
|
||||
* 修改 sourceName
|
||||
*/
|
||||
void updateSourceName(@Param("userId") Long userId, @Param("sourceId") Long sourceId, @Param("sourceName") String sourceName);
|
||||
|
||||
/**
|
||||
* 修改 targetName
|
||||
*/
|
||||
void updateTargetName(@Param("userId") Long userId, @Param("targetId") Long targetId, @Param("targetName") String targetName);
|
||||
|
||||
/**
|
||||
* 被引用的文章修改为未知
|
||||
*/
|
||||
void updateToUnknown(@Param("userId") Long userId, @Param("targetId") Long targetId, @Param("targetName") String targetName);
|
||||
|
||||
/**
|
||||
* 被引用的文章修改为未知
|
||||
*/
|
||||
void updateToKnown(@Param("userId") Long userId, @Param("targetId") Long targetId, @Param("targetName") String targetName);
|
||||
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
package com.blossom.backend.server.article.reference;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.blossom.backend.server.article.reference.pojo.ArticleReferenceEntity;
|
||||
@ -29,11 +30,15 @@ public class ArticleReferenceService extends ServiceImpl<ArticleReferenceMapper,
|
||||
|
||||
/**
|
||||
* 文章引用记录
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param sourceId 引用源
|
||||
* @param sourceName 引用源名称
|
||||
* @param references 目标
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void bind(Long userId, Long sourceId, String sourceName, List<ArticleReferenceReq> references) {
|
||||
delete(sourceId);
|
||||
|
||||
// 没有图片, 则不保存
|
||||
if (CollUtil.isEmpty(references)) {
|
||||
return;
|
||||
@ -47,11 +52,51 @@ public class ArticleReferenceService extends ServiceImpl<ArticleReferenceMapper,
|
||||
baseMapper.insertList(refs);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将文章修改为内部未知文章
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param targetId 目标文章ID
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void updateToUnknown(Long userId, Long targetId) {
|
||||
baseMapper.updateToUnknown(userId, targetId, "未知文章-" + targetId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将文章引用修改为内部具名文章
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param targetId 目标文章ID
|
||||
* @param name 文章名称
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void updateToKnown(Long userId, Long targetId, String name) {
|
||||
baseMapper.updateToKnown(userId, targetId, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* 内部链接修改名称时, 同时修改双链中的名称
|
||||
*
|
||||
* @param articleId ID
|
||||
* @param name 名称
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void updateInnerName(Long userId, Long articleId, String name) {
|
||||
if (articleId <= 0 || StrUtil.isBlank(name)) {
|
||||
return;
|
||||
}
|
||||
baseMapper.updateSourceName(userId, articleId, name);
|
||||
baseMapper.updateTargetName(userId, articleId, name);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 删除引用
|
||||
*
|
||||
* @param articleId 文章ID
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void delete(Long articleId) {
|
||||
LambdaQueryWrapper<ArticleReferenceEntity> where = new LambdaQueryWrapper<>();
|
||||
where.eq(ArticleReferenceEntity::getSourceId, articleId);
|
||||
@ -100,14 +145,15 @@ public class ArticleReferenceService extends ServiceImpl<ArticleReferenceMapper,
|
||||
|
||||
Set<Node> nodes = new HashSet<>();
|
||||
source.forEach((id, list) -> {
|
||||
Node node = new Node(list.get(0).getSourceName(), 11);
|
||||
Node node = new Node(list.get(0).getSourceName(), ArticleReferenceEnum.INNER.getType());
|
||||
node.setInner(true);
|
||||
node.setArtId(id);
|
||||
nodes.add(node);
|
||||
});
|
||||
target.forEach((name, list) -> {
|
||||
Node node = new Node(list.get(0).getTargetName(), list.get(0).getType());
|
||||
if (list.get(0).getType().equals(11)) {
|
||||
final Integer type = list.get(0).getType();
|
||||
Node node = new Node(list.get(0).getTargetName(), type);
|
||||
if (type.equals(ArticleReferenceEnum.INNER.getType()) || type.equals(ArticleReferenceEnum.INNER_UNKNOWN.getType())) {
|
||||
node.setInner(true);
|
||||
node.setArtId(list.get(0).getTargetId());
|
||||
} else {
|
||||
|
||||
@ -78,6 +78,7 @@
|
||||
upd_time = now()
|
||||
</set>
|
||||
where id = #{id}
|
||||
and user_id = #{userId}
|
||||
</update>
|
||||
|
||||
<!-- 根据ID修改 -->
|
||||
|
||||
@ -48,14 +48,43 @@
|
||||
from blossom_article_reference
|
||||
where user_id = #{userId}
|
||||
<if test="inner == true">
|
||||
and type = 11
|
||||
and type in(11,12)
|
||||
</if>
|
||||
<if test="inner == false">
|
||||
and type in (11,21)
|
||||
and type in (11,12,21)
|
||||
</if>
|
||||
<if test="articleId != null">
|
||||
and (source_id = #{articleId} or target_id = #{articleId})
|
||||
</if>
|
||||
</select>
|
||||
|
||||
<update id="updateSourceName">
|
||||
update blossom_article_reference
|
||||
set source_name = #{sourceName}
|
||||
where source_id = #{sourceId}
|
||||
and user_id = #{userId}
|
||||
</update>
|
||||
|
||||
<update id="updateTargetName">
|
||||
update blossom_article_reference
|
||||
set target_name = #{targetName}
|
||||
where target_Id = #{targetId}
|
||||
and user_id = #{userId}
|
||||
</update>
|
||||
|
||||
<update id="updateToUnknown">
|
||||
update blossom_article_reference
|
||||
set target_name = #{targetName},
|
||||
type = 12
|
||||
where target_Id = #{targetId}
|
||||
and user_id = #{userId}
|
||||
</update>
|
||||
|
||||
<update id="updateToKnown">
|
||||
update blossom_article_reference
|
||||
set target_name = #{targetName},
|
||||
type = 11
|
||||
where target_Id = #{targetId}
|
||||
and user_id = #{userId}
|
||||
</update>
|
||||
</mapper>
|
||||
@ -68,8 +68,9 @@ let stat = ref({
|
||||
outside: 0
|
||||
})
|
||||
|
||||
let inside = { itemStyle: {}, label: {} }
|
||||
let outside = { itemStyle: {}, label: {} }
|
||||
let inside: any = { itemStyle: {}, label: {} }
|
||||
let insideUnknown: any = { itemStyle: {}, label: {} }
|
||||
let outside: any = { itemStyle: {}, label: {} }
|
||||
const changeStyle = () => {
|
||||
let primaryColor = getPrimaryColor()
|
||||
// 节点数量统计
|
||||
@ -85,6 +86,17 @@ const changeStyle = () => {
|
||||
textBorderWidth: 2
|
||||
}
|
||||
}
|
||||
insideUnknown = {
|
||||
itemStyle: {
|
||||
color: isDark.value ? '#7B0000' : '#EB6969'
|
||||
},
|
||||
label: {
|
||||
fontSize: 13,
|
||||
color: isDark.value ? '#BABABA' : '#030303',
|
||||
textBorderColor: isDark.value ? '#7B0000' : '#EB6969',
|
||||
textBorderWidth: 1
|
||||
}
|
||||
}
|
||||
outside = {
|
||||
itemStyle: {
|
||||
color: isDark.value ? '#7B5E00' : '#FDC81A87'
|
||||
@ -116,6 +128,9 @@ const getArticleRefList = (onlyInner: boolean) => {
|
||||
node.itemStyle = inside.itemStyle
|
||||
node.label = inside.label
|
||||
stat.value.inside += 1
|
||||
} else if (node.artType === 12) {
|
||||
node.itemStyle = insideUnknown.itemStyle
|
||||
node.label = insideUnknown.label
|
||||
} else if (node.artType == 21) {
|
||||
node.itemStyle = outside.itemStyle
|
||||
node.label = outside.label
|
||||
@ -172,10 +187,19 @@ const renderChart = () => {
|
||||
userStore.userinfo.userParams.WEB_ARTICLE_URL + params.data.artId
|
||||
}</a></div>`
|
||||
}
|
||||
return `<div class="chart-graph-article-ref-tooltip">
|
||||
console.log(params.data)
|
||||
let type = ''
|
||||
if (params.data.artType === 11) {
|
||||
type = `<div>类型: 内部文章</div>`
|
||||
} else if (params.data.artType === 12) {
|
||||
type = `<div style="color:${insideUnknown.itemStyle.color}">类型: 未知文章, 可能是文章ID错误或已被删除</div>`
|
||||
} else if (params.data.artType === 21) {
|
||||
type = `<div>类型: 外网文章</div>`
|
||||
}
|
||||
return `<div class="chart-graph-article-ref-tooltip" style="border:1px solid ${params.data.itemStyle.color}">
|
||||
<div class="title">${params.data.name}</div>
|
||||
<div class="content">
|
||||
<div>类型: ${params.data.inner ? '内部文章' : '外网文章'}</div>
|
||||
${type}
|
||||
${url}
|
||||
</div>
|
||||
</div>`
|
||||
@ -250,7 +274,7 @@ const renderChart = () => {
|
||||
// edgeLabel: { show: false },
|
||||
},
|
||||
blur: {
|
||||
itemStyle: { opacity: 0.1 },
|
||||
// itemStyle: { opacity: 0.1 },
|
||||
lineStyle: { opacity: 0.1 },
|
||||
label: { show: false },
|
||||
edgeLabel: { show: false }
|
||||
@ -377,10 +401,10 @@ onUnmounted(() => {
|
||||
white-space: normal;
|
||||
background-color: var(--bl-html-color);
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--el-color-primary-light-5);
|
||||
color: var(--bl-text-color);
|
||||
|
||||
.title {
|
||||
@include font(15px, 300);
|
||||
@include font(15px, 500);
|
||||
border-bottom: 1px solid var(--el-color-primary-light-5);
|
||||
padding: 10px;
|
||||
overflow: hidden;
|
||||
|
||||
@ -573,11 +573,14 @@ const syncDoc = () => {
|
||||
const delDoc = () => {
|
||||
let type = curDoc.value.ty === 3 ? '文章' : '文件夹'
|
||||
ElMessageBox.confirm(
|
||||
`是否确定删除${type}: <span style="color:#C02B2B;text-decoration: underline;">${curDoc.value.n}</span>?删除后的文章可在回收站中查看。`,
|
||||
`<strong>注意:</strong><br/>
|
||||
1. 公开访问记录将永久删除。<br/>
|
||||
2. 双链引用将永久删除,还原后续重新编辑才可再次生成。<br/>
|
||||
是否继续删除${type}: <span style="color:#C02B2B;text-decoration: underline;">${curDoc.value.n}</span>?`,
|
||||
{
|
||||
confirmButtonText: '确定删除',
|
||||
cancelButtonText: '我再想想',
|
||||
type: 'info',
|
||||
// type: 'warning',
|
||||
draggable: true,
|
||||
dangerouslyUseHTMLString: true
|
||||
}
|
||||
|
||||
@ -41,7 +41,8 @@ export interface ArticleReference {
|
||||
*
|
||||
* 10 : picture
|
||||
* 11 : inner article
|
||||
* 12 : unknown inner article
|
||||
* 21 : public article
|
||||
*/
|
||||
type: 10 | 11 | 21
|
||||
type: 10 | 11 | 12 | 21
|
||||
}
|
||||
|
||||
@ -413,14 +413,18 @@ export const renderLink = (href: string | null, title: string | null, text: stri
|
||||
}
|
||||
|
||||
// 从文章列表中获取文章, 如果找到则认为是内部引用, 否则即使是内部引用格式, 也认为是个外部文章.
|
||||
// 内部引用不会使用 Markdown 中的链接名, 而是用内部文章名
|
||||
let article = getDocById(articleId.toString(), docTrees)
|
||||
if (article != undefined) {
|
||||
ref.targetId = article.i
|
||||
ref.targetName = article.n
|
||||
ref.type = 11
|
||||
} else {
|
||||
ref.targetId = articleId.toString()
|
||||
ref.targetName = '未知文章-' + articleId.toString()
|
||||
ref.type = 12
|
||||
}
|
||||
|
||||
// class="inner-link bl-tip bl-tip-bottom" data-tip="双链引用: 《${text}》"
|
||||
link = `<a target="_blank" href=${href} class="inner-link"
|
||||
onclick="onHtmlEventDispatch(this,'',event,'showArticleReferenceView','${ref.targetId}')">${text}</a>`
|
||||
} else {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user