mirror of
https://gitee.com/durcframework/SOP.git
synced 2025-08-11 21:57:56 +08:00
新增帮助文档管理
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
package com.gitee.sop.website.dao.entity;
|
||||
|
||||
import com.gitee.fastmybatis.annotation.Column;
|
||||
import com.gitee.fastmybatis.annotation.Pk;
|
||||
import com.gitee.fastmybatis.annotation.PkStrategy;
|
||||
import com.gitee.fastmybatis.annotation.Table;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Table(name = "help_doc", pk = @Pk(name = "id", strategy = PkStrategy.INCREMENT))
|
||||
@Data
|
||||
public class HelpDoc {
|
||||
/**
|
||||
* 主键ID,唯一标识每条帮助文档记录
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 文档名称,显示用的标题或标签
|
||||
*/
|
||||
private String label;
|
||||
|
||||
/**
|
||||
* 排序字段,用于控制文档在列表中的显示顺序
|
||||
*/
|
||||
private Integer sort;
|
||||
|
||||
@Column(logicDelete = true)
|
||||
private Integer isDeleted;
|
||||
|
||||
/**
|
||||
* 状态字段,表示文档是否启用
|
||||
* 1:启用,2:禁用
|
||||
*/
|
||||
private Byte status;
|
||||
|
||||
/**
|
||||
* 内容字段,存储文档的具体内容
|
||||
*/
|
||||
private String content;
|
||||
|
||||
/**
|
||||
* 内容类型,区分内容的格式
|
||||
* 1:Markdown,2:富文本
|
||||
*/
|
||||
private Byte contentType;
|
||||
|
||||
/**
|
||||
* 父级ID,用于构建文档的层级结构
|
||||
*/
|
||||
private Long parentId;
|
||||
|
||||
/**
|
||||
* 添加时间,记录文档首次创建的时间
|
||||
*/
|
||||
private LocalDateTime addTime;
|
||||
|
||||
/**
|
||||
* 更新时间,记录文档最后一次修改的时间
|
||||
*/
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
/**
|
||||
* 创建人ID,记录创建该文档的用户ID
|
||||
*/
|
||||
private Long addBy;
|
||||
|
||||
/**
|
||||
* 修改人ID,记录最后一次修改该文档的用户ID
|
||||
*/
|
||||
private Long updateBy;
|
||||
|
||||
}
|
@@ -0,0 +1,12 @@
|
||||
package com.gitee.sop.website.dao.mapper;
|
||||
|
||||
import com.gitee.fastmybatis.core.mapper.BaseMapper;
|
||||
import com.gitee.sop.website.dao.entity.HelpDoc;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* @author 六如
|
||||
*/
|
||||
@Mapper
|
||||
public interface HelpDocMapper extends BaseMapper<HelpDoc> {
|
||||
}
|
@@ -0,0 +1,29 @@
|
||||
package com.gitee.sop.website.service.common;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* @author 六如
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum StatusEnum {
|
||||
NONE(0),
|
||||
ENABLE(1),
|
||||
DISABLE(2);
|
||||
|
||||
private final int value;
|
||||
|
||||
public static StatusEnum of(Number number) {
|
||||
if (number == null) {
|
||||
return NONE;
|
||||
}
|
||||
for (StatusEnum value : StatusEnum.values()) {
|
||||
if (value.value == number.intValue()) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return NONE;
|
||||
}
|
||||
}
|
@@ -0,0 +1,30 @@
|
||||
package com.gitee.sop.website.service.help;
|
||||
|
||||
import com.gitee.fastmybatis.core.support.LambdaService;
|
||||
import com.gitee.sop.website.common.util.CopyUtil;
|
||||
import com.gitee.sop.website.dao.entity.HelpDoc;
|
||||
import com.gitee.sop.website.dao.mapper.HelpDocMapper;
|
||||
import com.gitee.sop.website.service.common.StatusEnum;
|
||||
import com.gitee.sop.website.service.help.dto.HelpDocDTO;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author 六如
|
||||
*/
|
||||
@Service
|
||||
public class HelpDocService implements LambdaService<HelpDoc, HelpDocMapper> {
|
||||
|
||||
public List<HelpDocDTO> listTree() {
|
||||
|
||||
return this.query()
|
||||
.select(HelpDoc::getId, HelpDoc::getLabel, HelpDoc::getParentId,
|
||||
HelpDoc::getAddTime,
|
||||
HelpDoc::getUpdateTime)
|
||||
.eq(HelpDoc::getStatus, StatusEnum.ENABLE.getValue())
|
||||
.orderByAsc(HelpDoc::getSort)
|
||||
.list(data -> CopyUtil.copyBean(data, HelpDocDTO::new));
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,66 @@
|
||||
package com.gitee.sop.website.service.help.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
public class HelpDocDTO {
|
||||
/**
|
||||
* 主键ID,唯一标识每条帮助文档记录
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 文档名称,显示用的标题或标签
|
||||
*/
|
||||
private String label;
|
||||
|
||||
/**
|
||||
* 排序字段,用于控制文档在列表中的显示顺序
|
||||
*/
|
||||
private Integer sort;
|
||||
|
||||
/**
|
||||
* 状态字段,表示文档是否启用
|
||||
* 1:启用,2:禁用
|
||||
*/
|
||||
private Byte status;
|
||||
|
||||
/**
|
||||
* 内容字段,存储文档的具体内容
|
||||
*/
|
||||
private String content;
|
||||
|
||||
/**
|
||||
* 内容类型,区分内容的格式
|
||||
* 1:Markdown,2:富文本
|
||||
*/
|
||||
private Byte contentType;
|
||||
|
||||
/**
|
||||
* 父级ID,用于构建文档的层级结构
|
||||
*/
|
||||
private Long parentId;
|
||||
|
||||
/**
|
||||
* 添加时间,记录文档首次创建的时间
|
||||
*/
|
||||
private LocalDateTime addTime;
|
||||
|
||||
/**
|
||||
* 更新时间,记录文档最后一次修改的时间
|
||||
*/
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
/**
|
||||
* 创建人ID,记录创建该文档的用户ID
|
||||
*/
|
||||
private Long addBy;
|
||||
|
||||
/**
|
||||
* 修改人ID,记录最后一次修改该文档的用户ID
|
||||
*/
|
||||
private Long updateBy;
|
||||
|
||||
}
|
@@ -0,0 +1,55 @@
|
||||
package com.gitee.sop.website.controller.website;
|
||||
|
||||
import com.gitee.sop.website.common.resp.Result;
|
||||
import com.gitee.sop.website.common.util.CopyUtil;
|
||||
import com.gitee.sop.website.controller.website.vo.HelpDocVO;
|
||||
import com.gitee.sop.website.dao.entity.HelpDoc;
|
||||
import com.gitee.sop.website.service.common.StatusEnum;
|
||||
import com.gitee.sop.website.service.help.HelpDocService;
|
||||
import com.gitee.sop.website.service.help.dto.HelpDocDTO;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author 六如
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("website/help/doc")
|
||||
public class WebsiteHelpController {
|
||||
|
||||
@Autowired
|
||||
private HelpDocService helpDocService;
|
||||
|
||||
/**
|
||||
* 查询帮助文档树状结构
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("tree")
|
||||
public Result<List<HelpDocVO>> listTree() {
|
||||
List<HelpDocDTO> list = helpDocService.listTree();
|
||||
List<HelpDocVO> retList = CopyUtil.copyList(list, HelpDocVO::new);
|
||||
return Result.ok(retList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询帮助文档
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("detail")
|
||||
public Result<HelpDocVO> doc(Long id) {
|
||||
HelpDoc helpDoc = helpDocService.getById(id);
|
||||
if (Objects.equals(helpDoc.getStatus(), StatusEnum.DISABLE.getValue())) {
|
||||
throw new RuntimeException("文档不存在");
|
||||
}
|
||||
HelpDocVO helpDocVO = CopyUtil.copyBean(helpDoc, HelpDocVO::new);
|
||||
return Result.ok(helpDocVO);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,66 @@
|
||||
package com.gitee.sop.website.controller.website.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
public class HelpDocVO {
|
||||
/**
|
||||
* 主键ID,唯一标识每条帮助文档记录
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 文档名称,显示用的标题或标签
|
||||
*/
|
||||
private String label;
|
||||
|
||||
/**
|
||||
* 排序字段,用于控制文档在列表中的显示顺序
|
||||
*/
|
||||
private Integer sort;
|
||||
|
||||
/**
|
||||
* 状态字段,表示文档是否启用
|
||||
* 1:启用,2:禁用
|
||||
*/
|
||||
private Byte status;
|
||||
|
||||
/**
|
||||
* 内容字段,存储文档的具体内容
|
||||
*/
|
||||
private String content;
|
||||
|
||||
/**
|
||||
* 内容类型,区分内容的格式
|
||||
* 1:Markdown,2:富文本
|
||||
*/
|
||||
private Byte contentType;
|
||||
|
||||
/**
|
||||
* 父级ID,用于构建文档的层级结构
|
||||
*/
|
||||
private Long parentId;
|
||||
|
||||
/**
|
||||
* 添加时间,记录文档首次创建的时间
|
||||
*/
|
||||
private LocalDateTime addTime;
|
||||
|
||||
/**
|
||||
* 更新时间,记录文档最后一次修改的时间
|
||||
*/
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
/**
|
||||
* 创建人ID,记录创建该文档的用户ID
|
||||
*/
|
||||
private Long addBy;
|
||||
|
||||
/**
|
||||
* 修改人ID,记录最后一次修改该文档的用户ID
|
||||
*/
|
||||
private Long updateBy;
|
||||
|
||||
}
|
@@ -40,6 +40,25 @@ const permissionRouter = {
|
||||
]
|
||||
};
|
||||
|
||||
const helpRouter = {
|
||||
path: "/help",
|
||||
name: "Help",
|
||||
meta: {
|
||||
title: "帮助",
|
||||
icon: "ep:question",
|
||||
rank: 10
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: "/help",
|
||||
name: "Help",
|
||||
meta: {
|
||||
title: "帮助"
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
export default defineFakeRoute([
|
||||
{
|
||||
url: "/get-async-routes",
|
||||
@@ -47,7 +66,7 @@ export default defineFakeRoute([
|
||||
response: () => {
|
||||
return {
|
||||
success: true,
|
||||
data: [permissionRouter]
|
||||
data: [permissionRouter, helpRouter]
|
||||
};
|
||||
}
|
||||
}
|
||||
|
41
sop-website/sop-website-frontend/src/api/help.ts
Normal file
41
sop-website/sop-website-frontend/src/api/help.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import { createUrl, http } from "@/utils/http";
|
||||
import type { Result } from "@/model";
|
||||
|
||||
// 后端请求接口
|
||||
const apiUrl: any = createUrl({
|
||||
listHelpTree: "/website/help/doc/tree",
|
||||
getDoc: "/website/help/doc/detail"
|
||||
});
|
||||
|
||||
export interface HelpDoc {
|
||||
id: number;
|
||||
label: string;
|
||||
parentId: number;
|
||||
content: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 接口管理
|
||||
*/
|
||||
export const api: any = {
|
||||
/**
|
||||
* 查询帮助树
|
||||
* @param data
|
||||
*/
|
||||
listHelpTree(params: object) {
|
||||
return http.get<Result<Array<HelpDoc>>, any>(apiUrl.listHelpTree, {
|
||||
params
|
||||
});
|
||||
},
|
||||
/**
|
||||
* 文档详情
|
||||
* @param data
|
||||
*/
|
||||
getDoc(id: any) {
|
||||
return http.get<Result<any>, any>(apiUrl.getDoc, {
|
||||
params: {
|
||||
id
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
@@ -0,0 +1,69 @@
|
||||
<template>
|
||||
<template v-for="item in rootItems" :key="item.id">
|
||||
<el-sub-menu v-if="hasChildren(item.id)" :index="item.id.toString()">
|
||||
<template #title>
|
||||
<el-icon><Document /></el-icon>
|
||||
<span>{{ item.label }}</span>
|
||||
</template>
|
||||
<template v-for="child in getChildren(item.id)" :key="child.id">
|
||||
<el-sub-menu v-if="hasChildren(child.id)" :index="child.id.toString()">
|
||||
<template #title>
|
||||
<el-icon><Document /></el-icon>
|
||||
<span>{{ child.label }}</span>
|
||||
</template>
|
||||
<el-menu-item
|
||||
v-for="grandChild in getChildren(child.id)"
|
||||
:key="grandChild.id"
|
||||
:index="grandChild.id.toString()"
|
||||
>
|
||||
<el-icon><Document /></el-icon>
|
||||
<span>{{ grandChild.label }}</span>
|
||||
</el-menu-item>
|
||||
</el-sub-menu>
|
||||
<el-menu-item v-else :index="child.id.toString()">
|
||||
<el-icon><Document /></el-icon>
|
||||
<span>{{ child.label }}</span>
|
||||
</el-menu-item>
|
||||
</template>
|
||||
</el-sub-menu>
|
||||
<el-menu-item v-else :index="item.id.toString()">
|
||||
<el-icon><Document /></el-icon>
|
||||
<span>{{ item.label }}</span>
|
||||
</el-menu-item>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, PropType, computed } from "vue";
|
||||
import type { HelpDoc } from "@/api/help";
|
||||
import { Document } from "@element-plus/icons-vue";
|
||||
|
||||
export default defineComponent({
|
||||
name: "RecursiveMenu",
|
||||
components: {
|
||||
Document
|
||||
},
|
||||
props: {
|
||||
items: {
|
||||
type: Array as PropType<HelpDoc[]>,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
setup(props) {
|
||||
const rootItems = computed(() => {
|
||||
return props.items.filter(item => item.parentId === 0);
|
||||
});
|
||||
const getChildren = (parentId: number) => {
|
||||
return props.items.filter(item => item.parentId === parentId);
|
||||
};
|
||||
const hasChildren = (parentId: number) => {
|
||||
return props.items.some(item => item.parentId === parentId);
|
||||
};
|
||||
return {
|
||||
rootItems,
|
||||
getChildren,
|
||||
hasChildren
|
||||
};
|
||||
}
|
||||
});
|
||||
</script>
|
27
sop-website/sop-website-frontend/src/views/help/index.ts
Normal file
27
sop-website/sop-website-frontend/src/views/help/index.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { api, type HelpDoc } from "@/api/help";
|
||||
import { onMounted, ref } from "vue";
|
||||
|
||||
export function useHelp() {
|
||||
const menuItems = ref<Array<HelpDoc>>([]);
|
||||
|
||||
const getMenuItems = async () => {
|
||||
const res = await api.listHelpTree({});
|
||||
// console.log(res);
|
||||
menuItems.value = res.data;
|
||||
};
|
||||
|
||||
const getDoc = async (id: any) => {
|
||||
const res = await api.getDoc(id);
|
||||
// console.log(res);
|
||||
return res.data;
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
await getMenuItems();
|
||||
});
|
||||
|
||||
return {
|
||||
menuItems,
|
||||
getDoc
|
||||
};
|
||||
}
|
51
sop-website/sop-website-frontend/src/views/help/index.vue
Normal file
51
sop-website/sop-website-frontend/src/views/help/index.vue
Normal file
@@ -0,0 +1,51 @@
|
||||
<template>
|
||||
<el-container>
|
||||
<el-aside width="200px">
|
||||
<el-menu default-active="1" class="help-menu" @select="handleSelect">
|
||||
<recursive-menu :items="menuItems" />
|
||||
</el-menu>
|
||||
</el-aside>
|
||||
<el-main>
|
||||
<div class="help-content">
|
||||
<h2>{{ docInfo.label }}</h2>
|
||||
<MarkdownEditor :value="docInfo.content" readonly />
|
||||
</div>
|
||||
</el-main>
|
||||
</el-container>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { QuestionFilled } from "@element-plus/icons-vue";
|
||||
import { useHelp } from "@/views/help/index";
|
||||
import RecursiveMenu from "@/components/RecursiveMenu.vue";
|
||||
import { ref } from "vue";
|
||||
import MarkdownEditor from "@/components/MarkdownEditor";
|
||||
|
||||
const { menuItems, getDoc } = useHelp();
|
||||
const docInfo = ref({
|
||||
label: "",
|
||||
content: ""
|
||||
});
|
||||
|
||||
const handleSelect = async (key: string) => {
|
||||
const doc = await getDoc(key);
|
||||
docInfo.value.label = doc.label;
|
||||
docInfo.value.content = doc.content;
|
||||
console.log(docInfo.value);
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.help-menu {
|
||||
height: 100%;
|
||||
border-right: solid 1px var(--el-menu-border-color);
|
||||
}
|
||||
|
||||
.el-aside {
|
||||
background-color: var(--el-menu-bg-color);
|
||||
}
|
||||
|
||||
.el-main {
|
||||
padding: 20px;
|
||||
}
|
||||
</style>
|
Reference in New Issue
Block a user