pref: 专题收藏快捷操作与样式优化

This commit is contained in:
xiaozzzi 2024-04-05 01:35:31 +08:00
parent 4c4fcd3a1d
commit 67cb162184
13 changed files with 66 additions and 81 deletions

View File

@ -7,9 +7,9 @@ import com.blossom.backend.base.auth.annotation.AuthIgnore;
import com.blossom.backend.config.BlConstants;
import com.blossom.backend.server.article.draft.pojo.ArticleUpdTagReq;
import com.blossom.backend.server.doc.DocService;
import com.blossom.backend.server.doc.DocSortChecker;
import com.blossom.backend.server.folder.pojo.*;
import com.blossom.backend.server.utils.DocUtil;
import com.blossom.common.base.enums.YesNo;
import com.blossom.common.base.exception.XzException404;
import com.blossom.common.base.pojo.DelReq;
import com.blossom.common.base.pojo.R;
@ -34,7 +34,6 @@ import java.util.Objects;
public class FolderController {
private final FolderService baseService;
private final DocService docService;
private final DocSortChecker docSortChecker;
/**
* 查询专题列表 [OP]
@ -47,21 +46,24 @@ public class FolderController {
if (userId == null) {
return R.ok(new ArrayList<>());
}
return R.ok(baseService.subjects(userId, null));
return R.ok(baseService.subjects(userId, YesNo.YES));
}
/**
* 查询专题列表
*
* @param starStatus 公开状态,
*/
@GetMapping("/subjects")
public R<List<FolderSubjectRes>> listSubject(@RequestParam("starStatus") Integer starStatus) {
return R.ok(baseService.subjects(AuthContext.getUserId(), starStatus));
return R.ok(baseService.subjects(AuthContext.getUserId(), YesNo.getValue(starStatus)));
}
/**
* 星标目录
* 星标文件夹
*
* @param req 目录对象
* @param req 目录文件夹
* @since 1.14.0
*/
@PostMapping("/star")
public R<Long> star(@Validated @RequestBody FolderStarReq req) {

View File

@ -12,6 +12,7 @@ import com.blossom.backend.server.folder.pojo.FolderSubjectRes;
import com.blossom.backend.server.picture.PictureMapper;
import com.blossom.backend.server.picture.pojo.PictureEntity;
import com.blossom.backend.server.utils.DocUtil;
import com.blossom.common.base.enums.YesNo;
import com.blossom.common.base.exception.XzException400;
import com.blossom.common.base.exception.XzException404;
import com.blossom.common.base.exception.XzException500;
@ -19,10 +20,10 @@ import com.blossom.common.base.util.DateUtils;
import com.blossom.common.base.util.PrimaryKeyUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@ -51,17 +52,16 @@ public class FolderService extends ServiceImpl<FolderMapper, FolderEntity> {
* <p>4. 相同专题的所有文件夹ID归为一组.
* <p>5. 通过文件夹ID获取到专题下的所有文章, 从而统计文章的总字数, 修改时间, 创建时间等.
* <p>6. 如果文章包含 TOC 标签, 则该文章为专题的目录, 专题的默认跳转会跳转至该目录
*
* @param userId 用户ID
* @param starStatus 公开状态
*/
public List<FolderSubjectRes> subjects(Long userId, @Nullable Integer starStatus) {
public List<FolderSubjectRes> subjects(Long userId, @NotNull YesNo starStatus) {
// 1. 查询所有专题
FolderEntity where = new FolderEntity();
where.setTags(TagEnum.subject.name());
where.setUserId(userId);
if (null != starStatus && (starStatus.equals(1) || starStatus.equals(0))) {
where.setStarStatus(starStatus);
} else {
where.setStarStatus(0);
}
where.setStarStatus(starStatus.getValue());
List<FolderEntity> allOpenSubject = baseMapper.listAll(where);
if (CollUtil.isEmpty(allOpenSubject)) {
return new ArrayList<>();
@ -204,9 +204,6 @@ public class FolderService extends ServiceImpl<FolderMapper, FolderEntity> {
*/
private void updateStorePath(FolderEntity folder) {
// 处理文件夹的存储地址
XzException404.throwBy(folder.getId() == null, "ID不得为空");
XzException400.throwBy(folder.getId().equals(folder.getPid()), "上级文件夹不能是自己");
// 如果
if (StrUtil.isNotBlank(folder.getStorePath())) {
final FolderEntity oldFolder = selectById(folder.getId());
// 获取所有子文件夹

View File

@ -109,19 +109,4 @@ public class FolderEntity extends AbstractPOJO implements Serializable {
private List<Long> pids;
//endregion
@Override
public int hashCode() {
return Long.hashCode(this.getId());
}
@Override
public boolean equals(Object obj) {
if (obj instanceof FolderEntity) {
return this.id.equals(((FolderEntity)obj).getId());
}
return false;
}
}

View File

@ -148,7 +148,7 @@ public class DocUtil {
tree.setS(folder.getSort());
tree.setN(folder.getName());
tree.setSp(folder.getStorePath());
tree.setStar(0);
tree.setStar(folder.getStarStatus());
tree.setTy(folder.getType());
tree.setIcon(folder.getIcon());
if (StrUtil.isBlank(folder.getTags())) {

View File

@ -8,7 +8,7 @@
fontWeight: props.weight
}">
<!-- {{ !!slots.default }}| -->
<span v-if="props.icon" :class="['tag-iconbl iconbl', props.icon, !!slots.default ? 'tag-icon-margin' : '']" />
<span v-if="props.icon" :class="['tag-iconbl iconbl', props.icon]" />
<span class="tag-content">
<slot />
</span>
@ -16,10 +16,6 @@
</template>
<script setup lang="ts">
import { useSlots } from 'vue'
const slots = useSlots()
const props = defineProps({
/**
* background-color
@ -54,7 +50,7 @@ const props = defineProps({
<style scoped lang="scss">
.tag-root {
@include flex(row, center, center);
@include themeShadow(2px 2px 3px 0 #bbbbbb, 1px 2px 3px #0F0F0F);
@include themeShadow(2px 1px 3px 0 #bbbbbb, 1px 1px 3px #0f0f0f);
border-radius: 4px;
padding: 1px 4px;
margin: 3px;
@ -67,10 +63,6 @@ const props = defineProps({
font-size: 12px;
}
.tag-icon-margin {
margin-right: 2px;
}
.tag-content {
line-height: 12px;
}

View File

@ -225,6 +225,7 @@ import { Document } from '@element-plus/icons-vue'
import { provideKeyDocTree, getCDocsByPid, getDocById } from '@renderer/views/doc/doc'
import { useUserStore } from '@renderer/stores/user'
import {
folderStarApi,
folderInfoApi,
folderAddApi,
folderUpdApi,
@ -239,7 +240,6 @@ import {
import { isNotBlank, isNull } from '@renderer/assets/utils/obj'
import { openExtenal, openNewIconWindow } from '@renderer/assets/utils/electron'
import Notify from '@renderer/scripts/notify'
import {folderStarApi} from "../../api/blossom";
//#region --------------------------------------------------< >--------------------------------------------------
const userStore = useUserStore()

View File

@ -65,9 +65,7 @@
<template #default="{ node, data }">
<div class="menu-item-wrapper" @click.right="handleClickRightMenu($event, data)">
<div :class="[viewStyle.isShowSubjectStyle ? (data.t?.includes('subject') ? 'subject-title' : 'doc-title') : 'doc-title']">
<bl-tag v-if="isShowSort" class="sort" :bgColor="getColor(node)">
{{ data.s }}
</bl-tag>
<div v-if="isShowSort" class="sort-tag" :style="{ backgroundColor: getColor(node) }">{{ data.s }}</div>
<div class="doc-name">
<img class="menu-icon-img" v-if="isShowImg(data, viewStyle)" :src="data.icon" />
<svg v-else-if="isShowSvg(data, viewStyle)" class="icon menu-icon" aria-hidden="true">
@ -83,7 +81,7 @@
<div v-else class="name-wrapper" :style="{ maxWidth: isNotBlank(data.icon) ? 'calc(100% - 25px)' : '100%' }">
{{ data.n }}
</div>
<bl-tag v-for="tag in tags(data, viewStyle)" style="margin-top: 5px" :bg-color="tag.bgColor" :icon="tag.icon">
<bl-tag v-for="tag in tags(data, viewStyle)" style="margin-top: 4px" :bg-color="tag.bgColor" :color="tag.color" :icon="tag.icon">
{{ tag.content }}
</bl-tag>
</div>
@ -124,8 +122,8 @@
<div class="tree-menu-level2" :style="rMenuLevel2">
<div v-if="curDoc.o === 0" @click="open(1)"><span class="iconbl bl-a-cloudupload-line"></span>公开</div>
<div v-if="curDoc.o === 1" @click="open(0)"><span class="iconbl bl-a-clouddownload-line"></span>取消公开</div>
<div v-if="curDoc.star === 0 && curDoc.ty === 3" @click="star(1)"><span class="iconbl bl-star-fill"></span>收藏</div>
<div v-if="curDoc.star === 1 && curDoc.ty === 3" @click="star(0)"><span class="iconbl bl-star-line"></span>取消收藏</div>
<div v-if="curDoc.star === 0" @click="star(1)"><span class="iconbl bl-star-fill"></span>收藏</div>
<div v-if="curDoc.star === 1" @click="star(0)"><span class="iconbl bl-star-line"></span>取消收藏</div>
<div v-if="curDoc.ty === 3 && !curDoc.t.includes('toc')" @click="addArticleTag('toc')">
<span class="iconbl bl-list-ordered"></span>设为专题目录
</div>
@ -272,6 +270,7 @@ import {
articleDownloadHtmlApi,
articleOpenApi,
articleStarApi,
folderStarApi,
folderAddApi,
folderUpdTagApi,
folderDelApi,
@ -930,10 +929,17 @@ const open = (openStatus: 0 | 1) => {
* 收藏/取消收藏
*/
const star = (starStatus: 0 | 1) => {
if (curDoc.value.ty === 3) {
articleStarApi({ id: curDoc.value.i, starStatus: starStatus }).then(() => {
curDoc.value.star = starStatus
Notify.success(starStatus === 0 ? '取消 Star 成功' : 'Star 成功')
})
} else if (curDoc.value.ty === 1) {
folderStarApi({ id: curDoc.value.i, starStatus: starStatus }).then(() => {
curDoc.value.star = starStatus
Notify.success(starStatus === 0 ? '取消文件夹 Star 成功' : '文件夹 Star 成功')
})
}
}
/**

View File

@ -31,14 +31,6 @@ $icon-size: 17px;
line-height: 23px;
}
}
.sort {
position: absolute;
padding: 0 2px;
right: 2px;
top: 2px;
z-index: 10;
}
}
// 专题样式, 包括边框和文字样式
@ -76,11 +68,18 @@ $icon-size: 17px;
min-width: calc(100% - 25px);
}
}
.sort {
position: absolute;
right: 1px;
}
.sort-tag {
font-size: 12px;
color: #fff;
border-radius: 4px;
padding: 0 2px;
margin-top: 3px;
position: absolute;
right: 3px;
top: 2px;
z-index: 10;
}
// 在左侧显示

View File

@ -27,6 +27,9 @@ export const tags = (doc: DocTree, viewStyle: { isShowArticleTocTag: boolean; is
icons.unshift({ bgColor: 'var(--bl-tag-color-open)', icon: 'bl-cloud-line' })
}
}
if (doc.ty === 1 && doc.star === 1) {
icons.unshift({ bgColor: 'rgb(220 192 36)', color: '#6a5b00', icon: 'bl-star-line' })
}
return icons
}
@ -35,6 +38,7 @@ export const tags = (doc: DocTree, viewStyle: { isShowArticleTocTag: boolean; is
*/
export const tagLins = (doc: DocTree) => {
let lines: string[] = []
if (doc.ty === 3) {
if (doc.star === 1) {
lines.push('star-line')
}
@ -44,6 +48,7 @@ export const tagLins = (doc: DocTree) => {
if (doc.vd === 1) {
lines.push('sync-line')
}
}
return lines
}

View File

@ -106,7 +106,8 @@
.doc-tree {
@include box(100%, 100%);
padding-left: 5px;
padding-left: 6px;
padding-right: 2px;
// --el-transition-duration: .1s; // 折叠展开的动画效果
.menu-divider {

View File

@ -1,5 +1,5 @@
<template>
<bl-row class="container-name">收藏/关注</bl-row>
<bl-row class="container-name">文章收藏</bl-row>
<bl-row class="container-sub-name" just="space-between">
Article Star
<span v-if="configViewStyle.isHomeStarCard" class="iconbl bl-array-line container-operator" @click="showStarCard(false)" />

View File

@ -1,7 +1,7 @@
<template>
<bl-row class="container-name">专题</bl-row>
<bl-row class="container-name">专题收藏</bl-row>
<bl-row class="container-sub-name" just="space-between">
<span>Article Subjects</span>
<span>Subject Star</span>
<span v-if="configViewStyle.isHomeSubjectCard" class="iconbl bl-array-line container-operator" @click="showSubjectCard(false)" />
<span v-else class="iconbl bl-article-line container-operator" @click="showSubjectCard(true)" />
</bl-row>

View File

@ -61,9 +61,7 @@
<div v-if="data.ty === 11" class="menu-divider"></div>
<div v-else class="menu-item-wrapper" @click.right="handleClickRightMenu($event, data)">
<div class="doc-title">
<bl-tag v-if="isShowSort && data.ty === 2" class="sort" :bgColor="getColor(node)">
{{ data.s }}
</bl-tag>
<div v-if="isShowSort" class="sort-tag" :style="{ backgroundColor: getColor(node) }">{{ data.s }}</div>
<div class="doc-name">
<img class="menu-icon-img" v-if="isShowImg(data, viewStyle)" :src="data.icon" />
<svg v-else-if="isShowSvg(data, viewStyle)" class="icon menu-icon" aria-hidden="true">
@ -79,7 +77,7 @@
<div v-else class="name-wrapper" :style="{ maxWidth: isNotBlank(data.icon) ? 'calc(100% - 25px)' : '100%' }">
{{ data.n }}
</div>
<bl-tag v-for="tag in tags(data, viewStyle)" style="margin-top: 5px" :bg-color="tag.bgColor" :icon="tag.icon">
<bl-tag v-for="tag in tags(data, viewStyle)" style="margin-top: 4px" :bg-color="tag.bgColor" :icon="tag.icon">
{{ tag.content }}
</bl-tag>
</div>