mirror of
https://github.com/nsnail/NetAdmin.git
synced 2025-04-20 05:02:50 +08:00
parent
71bfdaafa8
commit
7ed30406c9
@ -18,7 +18,6 @@
|
||||
作业名称
|
||||
作业状态
|
||||
保密
|
||||
保密
|
||||
信息
|
||||
倒序排序
|
||||
全部数据
|
||||
@ -43,7 +42,6 @@
|
||||
大于
|
||||
大于等于
|
||||
女
|
||||
女
|
||||
字典内容导出
|
||||
宕机
|
||||
客户端IP
|
||||
@ -74,6 +72,9 @@
|
||||
插入种子数据
|
||||
操作系统
|
||||
数据范围
|
||||
文档内容
|
||||
文档内容导出
|
||||
文档标题
|
||||
无效操作
|
||||
无效输入
|
||||
无限权限
|
||||
@ -100,7 +101,6 @@
|
||||
用户导出
|
||||
电子邮箱
|
||||
男
|
||||
男
|
||||
登录
|
||||
登录名
|
||||
登录日志导出
|
||||
@ -110,8 +110,6 @@
|
||||
空闲
|
||||
站内信导出
|
||||
等于
|
||||
等于
|
||||
等于
|
||||
等待发送
|
||||
管理模块
|
||||
系统模块
|
||||
|
@ -19,15 +19,10 @@ XML注释文件不存在
|
||||
字典名称不能为空
|
||||
字典目录不存在
|
||||
字典目录编号不能为空
|
||||
字典目录编号不能为空
|
||||
字典编码不能为空
|
||||
学历不正确
|
||||
完全公开
|
||||
密码不能为空
|
||||
密码不能为空
|
||||
密码不能为空
|
||||
密码不能为空
|
||||
已处理完毕
|
||||
已处理完毕
|
||||
已处理完毕
|
||||
并发冲突_请稍后重试
|
||||
开始事务
|
||||
@ -41,6 +36,12 @@ XML注释文件不存在
|
||||
数据库服务器时钟偏移
|
||||
数据库结构同步完成
|
||||
文件不能为空
|
||||
文档内容不能为空
|
||||
文档分类不存在
|
||||
文档分类名称不能为空
|
||||
文档分类编号不能为空
|
||||
文档分类编码不能为空
|
||||
文档标题不能为空
|
||||
新密码不能为空
|
||||
新手机号码验证码不正确
|
||||
无效端口号
|
||||
@ -53,28 +54,24 @@ XML注释文件不存在
|
||||
时间计划不能为空
|
||||
未指定部门
|
||||
未获取到待执行任务
|
||||
档案可见性不正确
|
||||
模块名称不能为空
|
||||
模块类型不能为空
|
||||
模块说明不能为空
|
||||
此节点已下线
|
||||
此节点已下线
|
||||
民族不正确
|
||||
消息主题不能为空
|
||||
消息内容不能为空
|
||||
父节点不存在
|
||||
用户不存在
|
||||
用户名不能为空
|
||||
用户名不能为空
|
||||
用户名不能为空
|
||||
用户名不能是手机号码
|
||||
用户名或密码错误
|
||||
用户名长度4位以上
|
||||
用户头像不能为空
|
||||
用户编号不存在
|
||||
登录用户
|
||||
目标设备不能为空
|
||||
目标设备不能为空
|
||||
短信验证请求不能为空
|
||||
短信验证请求不能为空
|
||||
短信验证请求不能为空
|
||||
种子数据插入完成
|
||||
站内信不存在
|
||||
@ -82,8 +79,7 @@ XML注释文件不存在
|
||||
站内信类型不正确
|
||||
缓存键不能为空
|
||||
网络地址不正确
|
||||
网络地址不正确
|
||||
网络地址不正确
|
||||
自己可见
|
||||
菜单名称不能为空
|
||||
菜单标题不能为空
|
||||
菜单类型不正确
|
||||
@ -109,11 +105,11 @@ XML注释文件不存在
|
||||
邀请码不正确
|
||||
邮箱验证码不正确
|
||||
部门不存在
|
||||
部门可见
|
||||
部门名称不能为空
|
||||
配置文件初始化完毕
|
||||
键值不能为空
|
||||
键名称不能为空
|
||||
键名称不能为空
|
||||
随机延时结束时间不正确
|
||||
随机延时起始时间不正确
|
||||
非JSON字符串
|
||||
|
@ -140,13 +140,34 @@
|
||||
"Title": "缓存管理",
|
||||
"Type": 1
|
||||
},
|
||||
// ------------------------------ 档案管理 ------------------------------
|
||||
{
|
||||
"Icon": "sc-icon-App",
|
||||
"Id": 616214756757512,
|
||||
"Name": "archive",
|
||||
"Path": "/archive",
|
||||
"Sort": 98,
|
||||
"Title": "档案管理",
|
||||
"Type": 1
|
||||
},
|
||||
{
|
||||
"Component": "sys/doc",
|
||||
"Icon": "el-icon-set-up",
|
||||
"Id": 616214756757516,
|
||||
"Name": "archive/doc",
|
||||
"ParentId": 616214756757512,
|
||||
"Path": "/archive/doc",
|
||||
"Sort": 100,
|
||||
"Title": "文档管理",
|
||||
"Type": 1
|
||||
},
|
||||
// ------------------------------ 日志管理 ------------------------------
|
||||
{
|
||||
"Icon": "el-icon-tickets",
|
||||
"Id": 374792687640581,
|
||||
"Name": "log",
|
||||
"Path": "/log",
|
||||
"Sort": 98,
|
||||
"Sort": 97,
|
||||
"Title": "日志管理",
|
||||
"Type": 1
|
||||
},
|
||||
@ -178,7 +199,7 @@
|
||||
"Id": 373838105399301,
|
||||
"Name": "dev",
|
||||
"Path": "/dev",
|
||||
"Sort": 97,
|
||||
"Sort": 96,
|
||||
"Title": "开发管理",
|
||||
"Type": 1
|
||||
},
|
||||
|
@ -3,7 +3,7 @@
|
||||
"devDependencies": {
|
||||
"cz-git": "^1.11.0",
|
||||
"commitizen": "^4.3.1",
|
||||
"prettier": "^3.3.3",
|
||||
"prettier": "^3.4.0",
|
||||
"standard-version": "^9.5.0"
|
||||
},
|
||||
"config": {
|
||||
@ -11,4 +11,4 @@
|
||||
"path": "node_modules/cz-git"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -8,7 +8,7 @@ public static class UnitOfWorkManagerExtensions
|
||||
/// <summary>
|
||||
/// 事务操作
|
||||
/// </summary>
|
||||
public static async Task AtomicOperateAsync(this UnitOfWorkManager me, Func<Task> handle)
|
||||
public static async Task AtomicOperateAsync(this UnitOfWorkManager me, Func<Task> handle, Func<Task> onErrorHandle = null)
|
||||
{
|
||||
var logger = LogHelper.Get<UnitOfWorkManager>();
|
||||
using var unitOfWork = me.Begin();
|
||||
@ -25,6 +25,11 @@ public static class UnitOfWorkManagerExtensions
|
||||
logger?.Warn(ex);
|
||||
unitOfWork.Rollback();
|
||||
logger?.Warn($"{Ln.事务已回滚}: {hashCode}");
|
||||
|
||||
if (onErrorHandle != null) {
|
||||
await onErrorHandle().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ public record Sys_DicCatalog : VersionEntity
|
||||
public IEnumerable<Sys_DicCatalog> Children { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 字典编码
|
||||
/// 字典目录编码
|
||||
/// </summary>
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_63)]
|
||||
[CsvIgnore]
|
||||
@ -32,7 +32,7 @@ public record Sys_DicCatalog : VersionEntity
|
||||
public ICollection<Sys_DicContent> Contents { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 字典名称
|
||||
/// 字典目录名称
|
||||
/// </summary>
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_63)]
|
||||
[CsvIgnore]
|
||||
|
@ -0,0 +1,73 @@
|
||||
namespace NetAdmin.Domain.DbMaps.Sys;
|
||||
|
||||
/// <summary>
|
||||
/// 文档分类表
|
||||
/// </summary>
|
||||
[SqlIndex(Chars.FLG_DB_INDEX_PREFIX + nameof(Code), nameof(Code), true)]
|
||||
[Table(Name = Chars.FLG_DB_TABLE_NAME_PREFIX + nameof(Sys_DocCatalog))]
|
||||
public record Sys_DocCatalog : VersionEntity, IFieldOwner
|
||||
{
|
||||
/// <summary>
|
||||
/// 子节点
|
||||
/// </summary>
|
||||
[CsvIgnore]
|
||||
[JsonIgnore]
|
||||
[Navigate(nameof(ParentId))]
|
||||
public IEnumerable<Sys_DocCatalog> Children { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 文档分类编码
|
||||
/// </summary>
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_63)]
|
||||
[CsvIgnore]
|
||||
[JsonIgnore]
|
||||
public virtual string Code { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 文档内容集合
|
||||
/// </summary>
|
||||
[CsvIgnore]
|
||||
[JsonIgnore]
|
||||
[Navigate(nameof(Sys_DocContent.CatalogId))]
|
||||
public ICollection<Sys_DocContent> Contents { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 文档分类名称
|
||||
/// </summary>
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_63)]
|
||||
[CsvIgnore]
|
||||
[JsonIgnore]
|
||||
public virtual string Name { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 拥有者
|
||||
/// </summary>
|
||||
[CsvIgnore]
|
||||
[JsonIgnore]
|
||||
[Navigate(nameof(OwnerId))]
|
||||
public Sys_User Owner { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 拥有者部门编号
|
||||
/// </summary>
|
||||
[Column]
|
||||
[CsvIgnore]
|
||||
[JsonIgnore]
|
||||
public virtual long? OwnerDeptId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 拥有者用户编号
|
||||
/// </summary>
|
||||
[Column]
|
||||
[CsvIgnore]
|
||||
[JsonIgnore]
|
||||
public virtual long? OwnerId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 父编号
|
||||
/// </summary>
|
||||
[Column]
|
||||
[CsvIgnore]
|
||||
[JsonIgnore]
|
||||
public virtual long ParentId { get; init; }
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
using NetAdmin.Domain.Enums.Sys;
|
||||
|
||||
namespace NetAdmin.Domain.DbMaps.Sys;
|
||||
|
||||
/// <summary>
|
||||
/// 文档内容表
|
||||
/// </summary>
|
||||
[Table(Name = Chars.FLG_DB_TABLE_NAME_PREFIX + nameof(Sys_DocContent))]
|
||||
public record Sys_DocContent : VersionEntity, IFieldEnabled, IFieldOwner
|
||||
{
|
||||
/// <summary>
|
||||
/// 文档正文
|
||||
/// </summary>
|
||||
#if DBTYPE_SQLSERVER
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_MAX)]
|
||||
#else
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||
#endif
|
||||
[CsvIgnore]
|
||||
[JsonIgnore]
|
||||
public virtual string Body { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 文档分类
|
||||
/// </summary>
|
||||
[CsvIgnore]
|
||||
[JsonIgnore]
|
||||
[Navigate(nameof(CatalogId))]
|
||||
public Sys_DocCatalog Catalog { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 文档分类编号
|
||||
/// </summary>
|
||||
[Column]
|
||||
[CsvIgnore]
|
||||
[JsonIgnore]
|
||||
public virtual long CatalogId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否启用
|
||||
/// </summary>
|
||||
[Column]
|
||||
[CsvIgnore]
|
||||
[JsonIgnore]
|
||||
public virtual bool Enabled { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 拥有者
|
||||
/// </summary>
|
||||
[CsvIgnore]
|
||||
[JsonIgnore]
|
||||
[Navigate(nameof(OwnerId))]
|
||||
public Sys_User Owner { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 拥有者部门编号
|
||||
/// </summary>
|
||||
[Column]
|
||||
[CsvIgnore]
|
||||
[JsonIgnore]
|
||||
public virtual long? OwnerDeptId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 拥有者用户编号
|
||||
/// </summary>
|
||||
[Column]
|
||||
[CsvIgnore]
|
||||
[JsonIgnore]
|
||||
public virtual long? OwnerId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 文档标题
|
||||
/// </summary>
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||
[CsvIgnore]
|
||||
[JsonIgnore]
|
||||
public virtual string Title { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 可见性
|
||||
/// </summary>
|
||||
[Column]
|
||||
[CsvIgnore]
|
||||
[JsonIgnore]
|
||||
public virtual ArchiveVisibilities Visibility { get; init; }
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
using NetAdmin.Domain.DbMaps.Sys;
|
||||
|
||||
namespace NetAdmin.Domain.Dto.Sys.Doc.Catalog;
|
||||
|
||||
/// <summary>
|
||||
/// 请求:创建文档分类
|
||||
/// </summary>
|
||||
public record CreateDocCatalogReq : Sys_DocCatalog
|
||||
{
|
||||
/// <inheritdoc cref="Sys_DocCatalog.Code" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
[Required(ErrorMessageResourceType = typeof(Ln), ErrorMessageResourceName = nameof(Ln.文档分类编码不能为空))]
|
||||
public override string Code { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_DocCatalog.Name" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
[Required(ErrorMessageResourceType = typeof(Ln), ErrorMessageResourceName = nameof(Ln.文档分类名称不能为空))]
|
||||
public override string Name { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_DocCatalog.ParentId" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override long ParentId { get; init; }
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
namespace NetAdmin.Domain.Dto.Sys.Doc.Catalog;
|
||||
|
||||
/// <summary>
|
||||
/// 请求:编辑文档分类
|
||||
/// </summary>
|
||||
public sealed record EditDocCatalogReq : CreateDocCatalogReq
|
||||
{
|
||||
/// <inheritdoc cref="IFieldVersion.Version" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override long Version { get; init; }
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
using NetAdmin.Domain.DbMaps.Sys;
|
||||
|
||||
namespace NetAdmin.Domain.Dto.Sys.Doc.Catalog;
|
||||
|
||||
/// <summary>
|
||||
/// 请求:查询文档分类
|
||||
/// </summary>
|
||||
public sealed record QueryDocCatalogReq : Sys_DocCatalog;
|
@ -0,0 +1,32 @@
|
||||
using NetAdmin.Domain.DbMaps.Sys;
|
||||
|
||||
namespace NetAdmin.Domain.Dto.Sys.Doc.Catalog;
|
||||
|
||||
/// <summary>
|
||||
/// 响应:查询文档分类
|
||||
/// </summary>
|
||||
public sealed record QueryDocCatalogRsp : Sys_DocCatalog
|
||||
{
|
||||
/// <inheritdoc cref="Sys_DocCatalog.Children" />
|
||||
public new IEnumerable<QueryDocCatalogRsp> Children { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_DocCatalog.Code" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public override string Code { get; init; }
|
||||
|
||||
/// <inheritdoc cref="EntityBase{T}.Id" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override long Id { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_DocCatalog.Name" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public override string Name { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_DocCatalog.ParentId" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override long ParentId { get; init; }
|
||||
|
||||
/// <inheritdoc cref="IFieldVersion.Version" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override long Version { get; init; }
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
using NetAdmin.Domain.DbMaps.Sys;
|
||||
using NetAdmin.Domain.Enums.Sys;
|
||||
|
||||
namespace NetAdmin.Domain.Dto.Sys.Doc.Content;
|
||||
|
||||
/// <summary>
|
||||
/// 请求:创建文档内容
|
||||
/// </summary>
|
||||
public record CreateDocContentReq : Sys_DocContent
|
||||
{
|
||||
/// <inheritdoc cref="Sys_DocContent.Body" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
[Required(ErrorMessageResourceType = typeof(Ln), ErrorMessageResourceName = nameof(Ln.文档内容不能为空))]
|
||||
public override string Body { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_DocContent.CatalogId" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
[Required(ErrorMessageResourceType = typeof(Ln), ErrorMessageResourceName = nameof(Ln.文档分类编号不能为空))]
|
||||
public override long CatalogId { get; init; }
|
||||
|
||||
/// <inheritdoc cref="IFieldEnabled.Enabled" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override bool Enabled { get; init; } = true;
|
||||
|
||||
/// <inheritdoc cref="Sys_DocContent.Title" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
[Required(ErrorMessageResourceType = typeof(Ln), ErrorMessageResourceName = nameof(Ln.文档标题不能为空))]
|
||||
public override string Title { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_DocContent.Visibility" />
|
||||
[EnumDataType(typeof(ArchiveVisibilities), ErrorMessageResourceType = typeof(Ln), ErrorMessageResourceName = nameof(Ln.档案可见性不正确))]
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override ArchiveVisibilities Visibility { get; init; }
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
namespace NetAdmin.Domain.Dto.Sys.Doc.Content;
|
||||
|
||||
/// <summary>
|
||||
/// 请求:编辑文档内容
|
||||
/// </summary>
|
||||
public sealed record EditDocContentReq : CreateDocContentReq
|
||||
{
|
||||
/// <inheritdoc cref="IFieldVersion.Version" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override long Version { get; init; }
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
namespace NetAdmin.Domain.Dto.Sys.Doc.Content;
|
||||
|
||||
/// <summary>
|
||||
/// 响应:导出文档内容
|
||||
/// </summary>
|
||||
public sealed record ExportDocContentRsp : QueryDocContentRsp
|
||||
{
|
||||
/// <inheritdoc />
|
||||
[CsvIndex(1)]
|
||||
[CsvIgnore(false)]
|
||||
[CsvName(nameof(Ln.文档内容))]
|
||||
public override string Body { get; init; }
|
||||
|
||||
/// <inheritdoc />
|
||||
[CsvIndex(2)]
|
||||
[CsvIgnore(false)]
|
||||
[CsvName(nameof(Ln.创建时间))]
|
||||
public override DateTime CreatedTime { get; init; }
|
||||
|
||||
/// <inheritdoc />
|
||||
[CsvIndex(3)]
|
||||
[CsvIgnore(false)]
|
||||
[CsvName(nameof(Ln.是否启用))]
|
||||
public override bool Enabled { get; init; }
|
||||
|
||||
/// <inheritdoc />
|
||||
[CsvIndex(0)]
|
||||
[CsvIgnore(false)]
|
||||
[CsvName(nameof(Ln.文档标题))]
|
||||
public override string Title { get; init; }
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
using NetAdmin.Domain.DbMaps.Sys;
|
||||
|
||||
namespace NetAdmin.Domain.Dto.Sys.Doc.Content;
|
||||
|
||||
/// <summary>
|
||||
/// 请求:查询文档内容
|
||||
/// </summary>
|
||||
public sealed record QueryDocContentReq : Sys_DocContent;
|
@ -0,0 +1,38 @@
|
||||
using NetAdmin.Domain.DbMaps.Sys;
|
||||
using NetAdmin.Domain.Enums.Sys;
|
||||
|
||||
namespace NetAdmin.Domain.Dto.Sys.Doc.Content;
|
||||
|
||||
/// <summary>
|
||||
/// 响应:查询文档内容
|
||||
/// </summary>
|
||||
public record QueryDocContentRsp : Sys_DocContent
|
||||
{
|
||||
/// <inheritdoc cref="Sys_DocContent.Body" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public override string Body { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_DocContent.CatalogId" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override long CatalogId { get; init; }
|
||||
|
||||
/// <inheritdoc cref="IFieldCreatedTime.CreatedTime" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override DateTime CreatedTime { get; init; }
|
||||
|
||||
/// <inheritdoc cref="IFieldEnabled.Enabled" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override bool Enabled { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_DocContent.Title" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public override string Title { get; init; }
|
||||
|
||||
/// <inheritdoc cref="IFieldVersion.Version" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override long Version { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_DocContent.Visibility" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override ArchiveVisibilities Visibility { get; init; }
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
using NetAdmin.Domain.DbMaps.Sys;
|
||||
|
||||
namespace NetAdmin.Domain.Dto.Sys.Doc.Content;
|
||||
|
||||
/// <summary>
|
||||
/// 请求:设置文档内容启用状态
|
||||
/// </summary>
|
||||
public sealed record SetDocContentEnabledReq : Sys_DocContent
|
||||
{
|
||||
/// <inheritdoc cref="IFieldEnabled.Enabled" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override bool Enabled { get; init; }
|
||||
|
||||
/// <inheritdoc cref="IFieldVersion.Version" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override long Version { get; init; }
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
namespace NetAdmin.Domain.Enums.Sys;
|
||||
|
||||
/// <summary>
|
||||
/// 档案可见性
|
||||
/// </summary>
|
||||
[Export]
|
||||
public enum ArchiveVisibilities
|
||||
{
|
||||
/// <summary>
|
||||
/// 完全公开
|
||||
/// </summary>
|
||||
[ResourceDescription<Ln>(nameof(Ln.完全公开))]
|
||||
Public = 1
|
||||
|
||||
,
|
||||
|
||||
/// <summary>
|
||||
/// 登录用户
|
||||
/// </summary>
|
||||
[ResourceDescription<Ln>(nameof(Ln.登录用户))]
|
||||
LogonUser = 2
|
||||
|
||||
,
|
||||
|
||||
/// <summary>
|
||||
/// 部门可见
|
||||
/// </summary>
|
||||
[ResourceDescription<Ln>(nameof(Ln.部门可见))]
|
||||
DeptUser = 3
|
||||
|
||||
,
|
||||
|
||||
/// <summary>
|
||||
/// 自己可见
|
||||
/// </summary>
|
||||
[ResourceDescription<Ln>(nameof(Ln.自己可见))]
|
||||
Self = 4
|
||||
}
|
@ -25,7 +25,8 @@ public abstract class ApiResultHandler<T>
|
||||
{
|
||||
var naException = context.Exception switch {
|
||||
NetAdminException ex => ex
|
||||
, _ => context.Exception.Message.Contains(Chars.FLG_DB_EXCEPTION_PRIMARY_KEY_CONFLICT)
|
||||
, _ => context.Exception.Message.Contains(Chars.FLG_DB_EXCEPTION_PRIMARY_KEY_CONFLICT) ||
|
||||
context.Exception.Message.Contains(Chars.FLG_DB_EXCEPTION_UNIQUE_CONSTRAINT_CONFLICT)
|
||||
? new NetAdminInvalidOperationException(Ln.记录已存在)
|
||||
: null
|
||||
};
|
||||
|
@ -16,6 +16,7 @@ public static class Chars
|
||||
public const string FLG_CONTEXT_USER_INFO = nameof(FLG_CONTEXT_USER_INFO);
|
||||
public const string FLG_CRON_PER_SECS = "* * * * * *";
|
||||
public const string FLG_DB_EXCEPTION_PRIMARY_KEY_CONFLICT = "PRIMARY KEY";
|
||||
public const string FLG_DB_EXCEPTION_UNIQUE_CONSTRAINT_CONFLICT = "UNIQUE constraint";
|
||||
public const string FLG_DB_FIELD_TYPE_NVARCHAR = "nvarchar";
|
||||
public const string FLG_DB_FIELD_TYPE_NVARCHAR_1022 = "nvarchar(1022)";
|
||||
public const string FLG_DB_FIELD_TYPE_NVARCHAR_127 = "nvarchar(127)";
|
||||
|
@ -0,0 +1,11 @@
|
||||
using NetAdmin.Domain.Dto.Sys.Doc.Catalog;
|
||||
|
||||
namespace NetAdmin.SysComponent.Application.Modules.Sys;
|
||||
|
||||
/// <summary>
|
||||
/// 文档分类模块
|
||||
/// </summary>
|
||||
public interface IDocCatalogModule : ICrudModule<CreateDocCatalogReq, QueryDocCatalogRsp // 创建类型
|
||||
, QueryDocCatalogReq, QueryDocCatalogRsp // 查询类型
|
||||
, DelReq // 删除类型
|
||||
>;
|
@ -0,0 +1,17 @@
|
||||
using NetAdmin.Domain.Dto.Sys.Doc.Content;
|
||||
|
||||
namespace NetAdmin.SysComponent.Application.Modules.Sys;
|
||||
|
||||
/// <summary>
|
||||
/// 文档内容模块
|
||||
/// </summary>
|
||||
public interface IDocContentModule : ICrudModule<CreateDocContentReq, QueryDocContentRsp // 创建类型
|
||||
, QueryDocContentReq, QueryDocContentRsp // 查询类型
|
||||
, DelReq // 删除类型
|
||||
>
|
||||
{
|
||||
/// <summary>
|
||||
/// 启用/禁用文档内容
|
||||
/// </summary>
|
||||
Task<int> SetEnabledAsync(SetDocContentEnabledReq req);
|
||||
}
|
@ -0,0 +1,95 @@
|
||||
using NetAdmin.Domain.Dto.Sys.Doc.Catalog;
|
||||
using NetAdmin.Domain.Dto.Sys.Doc.Content;
|
||||
|
||||
namespace NetAdmin.SysComponent.Application.Modules.Sys;
|
||||
|
||||
/// <summary>
|
||||
/// 文档模块
|
||||
/// </summary>
|
||||
public interface IDocModule
|
||||
{
|
||||
/// <summary>
|
||||
/// 批量删除文档分类
|
||||
/// </summary>
|
||||
Task<int> BulkDeleteCatalogAsync(BulkReq<DelReq> req);
|
||||
|
||||
/// <summary>
|
||||
/// 批量删除文档内容
|
||||
/// </summary>
|
||||
Task<int> BulkDeleteContentAsync(BulkReq<DelReq> req);
|
||||
|
||||
/// <summary>
|
||||
/// 创建文档分类
|
||||
/// </summary>
|
||||
Task<QueryDocCatalogRsp> CreateCatalogAsync(CreateDocCatalogReq req);
|
||||
|
||||
/// <summary>
|
||||
/// 创建文档内容
|
||||
/// </summary>
|
||||
Task<QueryDocContentRsp> CreateContentAsync(CreateDocContentReq req);
|
||||
|
||||
/// <summary>
|
||||
/// 删除文档分类
|
||||
/// </summary>
|
||||
Task<int> DeleteCatalogAsync(DelReq req);
|
||||
|
||||
/// <summary>
|
||||
/// 删除文档内容
|
||||
/// </summary>
|
||||
Task<int> DeleteContentAsync(DelReq req);
|
||||
|
||||
/// <summary>
|
||||
/// 编辑文档分类
|
||||
/// </summary>
|
||||
Task<int> EditCatalogAsync(EditDocCatalogReq req);
|
||||
|
||||
/// <summary>
|
||||
/// 编辑文档内容
|
||||
/// </summary>
|
||||
Task<QueryDocContentRsp> EditContentAsync(EditDocContentReq req);
|
||||
|
||||
/// <summary>
|
||||
/// 导出文档内容
|
||||
/// </summary>
|
||||
Task<IActionResult> ExportContentAsync(QueryReq<QueryDocContentReq> req);
|
||||
|
||||
/// <summary>
|
||||
/// 获取单个文档分类
|
||||
/// </summary>
|
||||
Task<QueryDocCatalogRsp> GetCatalogAsync(QueryDocCatalogReq req);
|
||||
|
||||
/// <summary>
|
||||
/// 获取单个文档内容
|
||||
/// </summary>
|
||||
Task<QueryDocContentRsp> GetContentAsync(QueryDocContentReq req);
|
||||
|
||||
/// <summary>
|
||||
/// 分页查询文档分类
|
||||
/// </summary>
|
||||
Task<PagedQueryRsp<QueryDocCatalogRsp>> PagedQueryCatalogAsync(PagedQueryReq<QueryDocCatalogReq> req);
|
||||
|
||||
/// <summary>
|
||||
/// 分页查询文档内容
|
||||
/// </summary>
|
||||
Task<PagedQueryRsp<QueryDocContentRsp>> PagedQueryContentAsync(PagedQueryReq<QueryDocContentReq> req);
|
||||
|
||||
/// <summary>
|
||||
/// 查询文档分类
|
||||
/// </summary>
|
||||
Task<IEnumerable<QueryDocCatalogRsp>> QueryCatalogAsync(QueryReq<QueryDocCatalogReq> req);
|
||||
|
||||
/// <summary>
|
||||
/// 查询文档内容
|
||||
/// </summary>
|
||||
Task<IEnumerable<QueryDocContentRsp>> QueryContentAsync(QueryReq<QueryDocContentReq> req);
|
||||
|
||||
/// <summary>
|
||||
/// 启用/禁用文档内容
|
||||
/// </summary>
|
||||
Task<int> SetEnabledAsync(SetDocContentEnabledReq req);
|
||||
|
||||
/// <summary>
|
||||
/// 浏览文档内容
|
||||
/// </summary>
|
||||
Task<QueryDocContentRsp> ViewContentAsync(QueryDocContentReq req);
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
using NetAdmin.Domain.Dto.Sys.Doc.Catalog;
|
||||
|
||||
namespace NetAdmin.SysComponent.Application.Services.Sys.Dependency;
|
||||
|
||||
/// <summary>
|
||||
/// 文档分类服务
|
||||
/// </summary>
|
||||
public interface IDocCatalogService : IService, IDocCatalogModule
|
||||
{
|
||||
/// <summary>
|
||||
/// 编辑文档分类
|
||||
/// </summary>
|
||||
Task<int> EditAsync(EditDocCatalogReq req);
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
using NetAdmin.Domain.Dto.Sys.Doc.Content;
|
||||
|
||||
namespace NetAdmin.SysComponent.Application.Services.Sys.Dependency;
|
||||
|
||||
/// <summary>
|
||||
/// 文档内容服务
|
||||
/// </summary>
|
||||
public interface IDocContentService : IService, IDocContentModule
|
||||
{
|
||||
/// <summary>
|
||||
/// 编辑文档内容
|
||||
/// </summary>
|
||||
Task<QueryDocContentRsp> EditAsync(EditDocContentReq req);
|
||||
|
||||
/// <summary>
|
||||
/// 浏览文档内容
|
||||
/// </summary>
|
||||
Task<QueryDocContentRsp> ViewAsync(QueryDocContentReq req);
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
namespace NetAdmin.SysComponent.Application.Services.Sys.Dependency;
|
||||
|
||||
/// <summary>
|
||||
/// 文档服务
|
||||
/// </summary>
|
||||
public interface IDocService : IService, IDocModule;
|
@ -46,7 +46,14 @@ public sealed class DevService(IApiService apiService) : ServiceBase<DevService>
|
||||
var appServicesDependencyDir = Path.Combine(appServicesDir, "Dependency");
|
||||
|
||||
// 数据契约层目录
|
||||
var dataDir = GetDir($"{req.Type}.Domain");
|
||||
string dataDir;
|
||||
try {
|
||||
dataDir = GetDir($"{req.Type}.Domain");
|
||||
}
|
||||
catch (InvalidOperationException) {
|
||||
dataDir = tplDataDir;
|
||||
}
|
||||
|
||||
var dtoDir = Path.Combine(dataDir, "Dto", typeAbbr, req.ModuleName);
|
||||
var entityDir = Path.Combine(dataDir, "DbMaps", typeAbbr);
|
||||
|
||||
|
@ -26,10 +26,10 @@ public sealed class DicContentService(BasicRepository<Sys_DicContent, long> rpo)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return QueryInternal(req)
|
||||
#if DBTYPE_SQLSERVER
|
||||
#if DBTYPE_SQLSERVER
|
||||
.WithLock(SqlServerLock.NoLock | SqlServerLock.NoWait)
|
||||
#endif
|
||||
.CountAsync();
|
||||
#endif
|
||||
.CountAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@ -87,10 +87,10 @@ public sealed class DicContentService(BasicRepository<Sys_DicContent, long> rpo)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return QueryInternal(req)
|
||||
#if DBTYPE_SQLSERVER
|
||||
#if DBTYPE_SQLSERVER
|
||||
.WithLock(SqlServerLock.NoLock | SqlServerLock.NoWait)
|
||||
#endif
|
||||
.AnyAsync();
|
||||
#endif
|
||||
.AnyAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@ -162,7 +162,11 @@ public sealed class DicContentService(BasicRepository<Sys_DicContent, long> rpo)
|
||||
|
||||
private ISelect<Sys_DicContent> QueryInternal(QueryReq<QueryDicContentReq> req)
|
||||
{
|
||||
var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter).WhereDynamic(req.Filter);
|
||||
var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter)
|
||||
.WhereDynamic(req.Filter)
|
||||
.WhereIf( //
|
||||
req.Keywords?.Length > 0
|
||||
, a => a.Key.Contains(req.Keywords) || a.Value.Contains(req.Keywords) || a.Summary.Contains(req.Keywords));
|
||||
|
||||
// ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
|
||||
switch (req.Order) {
|
||||
|
@ -0,0 +1,150 @@
|
||||
using NetAdmin.Domain.DbMaps.Sys;
|
||||
using NetAdmin.Domain.Dto.Sys.Doc.Catalog;
|
||||
|
||||
namespace NetAdmin.SysComponent.Application.Services.Sys;
|
||||
|
||||
/// <inheritdoc cref="IDocCatalogService" />
|
||||
public sealed class DocCatalogService(BasicRepository<Sys_DocCatalog, long> rpo) //
|
||||
: RepositoryService<Sys_DocCatalog, long, IDocCatalogService>(rpo), IDocCatalogService
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public async Task<int> BulkDeleteAsync(BulkReq<DelReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = 0;
|
||||
|
||||
// ReSharper disable once LoopCanBeConvertedToQuery
|
||||
foreach (var item in req.Items) {
|
||||
ret += await DeleteAsync(item).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<long> CountAsync(QueryReq<QueryDocCatalogReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return QueryInternal(req)
|
||||
#if DBTYPE_SQLSERVER
|
||||
.WithLock(SqlServerLock.NoLock | SqlServerLock.NoWait)
|
||||
#endif
|
||||
.CountAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <exception cref="NetAdminInvalidOperationException">The_parent_node_does_not_exist</exception>
|
||||
public async Task<QueryDocCatalogRsp> CreateAsync(CreateDocCatalogReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
if (req.ParentId != 0 && !await Rpo.Where(a => a.Id == req.ParentId)
|
||||
#if DBTYPE_SQLSERVER
|
||||
.WithLock(SqlServerLock.NoLock | SqlServerLock.NoWait)
|
||||
#endif
|
||||
.AnyAsync()
|
||||
.ConfigureAwait(false)) {
|
||||
throw new NetAdminInvalidOperationException(Ln.父节点不存在);
|
||||
}
|
||||
|
||||
var ret = await Rpo.InsertAsync(req).ConfigureAwait(false);
|
||||
return ret.Adapt<QueryDocCatalogRsp>();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<int> DeleteAsync(DelReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await Rpo.DeleteCascadeByDatabaseAsync(a => a.Id == req.Id).ConfigureAwait(false);
|
||||
return ret.Count;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <exception cref="NetAdminInvalidOperationException">The_parent_node_does_not_exist</exception>
|
||||
public async Task<int> EditAsync(EditDocCatalogReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return req.ParentId == 0 || await Rpo.Where(a => a.Id == req.ParentId)
|
||||
#if DBTYPE_SQLSERVER
|
||||
.WithLock(SqlServerLock.NoLock | SqlServerLock.NoWait)
|
||||
#endif
|
||||
.AnyAsync()
|
||||
.ConfigureAwait(false)
|
||||
? await UpdateAsync(req, null).ConfigureAwait(false)
|
||||
: throw new NetAdminInvalidOperationException(Ln.父节点不存在);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<bool> ExistAsync(QueryReq<QueryDocCatalogReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return QueryInternal(req)
|
||||
#if DBTYPE_SQLSERVER
|
||||
.WithLock(SqlServerLock.NoLock | SqlServerLock.NoWait)
|
||||
#endif
|
||||
.AnyAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<IActionResult> ExportAsync(QueryReq<QueryDocCatalogReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<QueryDocCatalogRsp> GetAsync(QueryDocCatalogReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(new QueryReq<QueryDocCatalogReq> { Filter = req, Order = Orders.None }).ToOneAsync().ConfigureAwait(false);
|
||||
return ret.Adapt<QueryDocCatalogRsp>();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<PagedQueryRsp<QueryDocCatalogRsp>> PagedQueryAsync(PagedQueryReq<QueryDocCatalogReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var list = await QueryInternal(req)
|
||||
.Page(req.Page, req.PageSize)
|
||||
#if DBTYPE_SQLSERVER
|
||||
.WithLock(SqlServerLock.NoLock | SqlServerLock.NoWait)
|
||||
#endif
|
||||
.Count(out var total)
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
|
||||
return new PagedQueryRsp<QueryDocCatalogRsp>(req.Page, req.PageSize, total, list.Adapt<IEnumerable<QueryDocCatalogRsp>>());
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<IEnumerable<QueryDocCatalogRsp>> QueryAsync(QueryReq<QueryDocCatalogReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(req)
|
||||
#if DBTYPE_SQLSERVER
|
||||
.WithLock(SqlServerLock.NoLock | SqlServerLock.NoWait)
|
||||
#endif
|
||||
.ToTreeListAsync()
|
||||
.ConfigureAwait(false);
|
||||
return ret.Adapt<IEnumerable<QueryDocCatalogRsp>>();
|
||||
}
|
||||
|
||||
private ISelect<Sys_DocCatalog> QueryInternal(QueryReq<QueryDocCatalogReq> req)
|
||||
{
|
||||
var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter).WhereDynamic(req.Filter);
|
||||
|
||||
// ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
|
||||
switch (req.Order) {
|
||||
case Orders.None:
|
||||
return ret;
|
||||
case Orders.Random:
|
||||
return ret.OrderByRandom();
|
||||
}
|
||||
|
||||
ret = ret.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
|
||||
if (!req.Prop?.Equals(nameof(req.Filter.Id), StringComparison.OrdinalIgnoreCase) ?? true) {
|
||||
ret = ret.OrderByDescending(a => a.Id);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
@ -0,0 +1,202 @@
|
||||
using NetAdmin.Domain.DbMaps.Dependency.Fields;
|
||||
using NetAdmin.Domain.DbMaps.Sys;
|
||||
using NetAdmin.Domain.Dto.Sys.Doc.Content;
|
||||
using NetAdmin.Domain.Enums.Sys;
|
||||
|
||||
namespace NetAdmin.SysComponent.Application.Services.Sys;
|
||||
|
||||
/// <inheritdoc cref="IDocContentService" />
|
||||
public sealed class DocContentService(BasicRepository<Sys_DocContent, long> rpo) //
|
||||
: RepositoryService<Sys_DocContent, long, IDocContentService>(rpo), IDocContentService
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public async Task<int> BulkDeleteAsync(BulkReq<DelReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = 0;
|
||||
|
||||
// ReSharper disable once LoopCanBeConvertedToQuery
|
||||
foreach (var item in req.Items) {
|
||||
ret += await DeleteAsync(item).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<long> CountAsync(QueryReq<QueryDocContentReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return QueryInternal(req)
|
||||
#if DBTYPE_SQLSERVER
|
||||
.WithLock(SqlServerLock.NoLock | SqlServerLock.NoWait)
|
||||
#endif
|
||||
.CountAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <exception cref="NetAdminInvalidOperationException">Doctionary_directory_does_not_exist</exception>
|
||||
public async Task<QueryDocContentRsp> CreateAsync(CreateDocContentReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
if (!await Rpo.Orm.Select<Sys_DocCatalog>()
|
||||
.Where(a => a.Id == req.CatalogId)
|
||||
#if DBTYPE_SQLSERVER
|
||||
.WithLock(SqlServerLock.NoLock | SqlServerLock.NoWait)
|
||||
#endif
|
||||
.AnyAsync()
|
||||
.ConfigureAwait(false)) {
|
||||
throw new NetAdminInvalidOperationException(Ln.文档分类不存在);
|
||||
}
|
||||
|
||||
var ret = await Rpo.InsertAsync(req).ConfigureAwait(false);
|
||||
return ret.Adapt<QueryDocContentRsp>();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<int> DeleteAsync(DelReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return Rpo.DeleteAsync(a => a.Id == req.Id);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <exception cref="NetAdminInvalidOperationException">Doctionary_directory_does_not_exist</exception>
|
||||
public async Task<QueryDocContentRsp> EditAsync(EditDocContentReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
if (!await Rpo.Orm.Select<Sys_DocCatalog>()
|
||||
.Where(a => a.Id == req.CatalogId)
|
||||
#if DBTYPE_SQLSERVER
|
||||
.WithLock(SqlServerLock.NoLock | SqlServerLock.NoWait)
|
||||
#endif
|
||||
.AnyAsync()
|
||||
.ConfigureAwait(false)) {
|
||||
throw new NetAdminInvalidOperationException(Ln.文档分类不存在);
|
||||
}
|
||||
|
||||
#if DBTYPE_SQLSERVER
|
||||
return (await UpdateReturnListAsync(req, null).ConfigureAwait(false)).FirstOrDefault()?.Adapt<QueryDocContentRsp>();
|
||||
#else
|
||||
return await UpdateAsync(req, null, [nameof(IFieldOwner.OwnerId), nameof(IFieldOwner.OwnerDeptId)]).ConfigureAwait(false) > 0
|
||||
? await GetAsync(new QueryDocContentReq { Id = req.Id }).ConfigureAwait(false)
|
||||
: null;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<bool> ExistAsync(QueryReq<QueryDocContentReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return QueryInternal(req)
|
||||
#if DBTYPE_SQLSERVER
|
||||
.WithLock(SqlServerLock.NoLock | SqlServerLock.NoWait)
|
||||
#endif
|
||||
.AnyAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<IActionResult> ExportAsync(QueryReq<QueryDocContentReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return ExportAsync<QueryDocContentReq, ExportDocContentRsp>(QueryInternal, req, Ln.文档内容导出);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<QueryDocContentRsp> GetAsync(QueryDocContentReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(new QueryReq<QueryDocContentReq> { Filter = req, Order = Orders.None }).ToOneAsync().ConfigureAwait(false);
|
||||
return ret.Adapt<QueryDocContentRsp>();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<PagedQueryRsp<QueryDocContentRsp>> PagedQueryAsync(PagedQueryReq<QueryDocContentReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var list = await QueryInternal(req)
|
||||
.Page(req.Page, req.PageSize)
|
||||
#if DBTYPE_SQLSERVER
|
||||
.WithLock(SqlServerLock.NoLock | SqlServerLock.NoWait)
|
||||
#endif
|
||||
.Count(out var total)
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
|
||||
return new PagedQueryRsp<QueryDocContentRsp>(req.Page, req.PageSize, total, list.Adapt<IEnumerable<QueryDocContentRsp>>());
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<IEnumerable<QueryDocContentRsp>> QueryAsync(QueryReq<QueryDocContentReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(req)
|
||||
#if DBTYPE_SQLSERVER
|
||||
.WithLock(SqlServerLock.NoLock | SqlServerLock.NoWait)
|
||||
#endif
|
||||
.Take(req.Count)
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
return ret.Adapt<IEnumerable<QueryDocContentRsp>>();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<int> SetEnabledAsync(SetDocContentEnabledReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return UpdateAsync(req, [nameof(Sys_DocContent.Enabled)]);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<QueryDocContentRsp> ViewAsync(QueryDocContentReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(new QueryReq<QueryDocContentReq> { Filter = req, Order = Orders.None }).ToOneAsync().ConfigureAwait(false);
|
||||
|
||||
switch (ret?.Visibility) {
|
||||
case ArchiveVisibilities.LogonUser:
|
||||
if (UserToken == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
break;
|
||||
case ArchiveVisibilities.DeptUser:
|
||||
if (UserToken == null || UserToken.DeptId != ret.OwnerDeptId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
break;
|
||||
case ArchiveVisibilities.Self:
|
||||
if (UserToken == null || UserToken.Id != ret.OwnerId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return ret?.Enabled == false ? null : ret?.Adapt<QueryDocContentRsp>();
|
||||
}
|
||||
|
||||
private ISelect<Sys_DocContent> QueryInternal(QueryReq<QueryDocContentReq> req)
|
||||
{
|
||||
var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter)
|
||||
.WhereDynamic(req.Filter)
|
||||
.WhereIf( //
|
||||
req.Keywords?.Length > 0, a => a.Title.Contains(req.Keywords));
|
||||
|
||||
// ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
|
||||
switch (req.Order) {
|
||||
case Orders.None:
|
||||
return ret;
|
||||
case Orders.Random:
|
||||
return ret.OrderByRandom();
|
||||
}
|
||||
|
||||
ret = ret.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
|
||||
if (!req.Prop?.Equals(nameof(req.Filter.Id), StringComparison.OrdinalIgnoreCase) ?? true) {
|
||||
ret = ret.OrderByDescending(a => a.Id);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
@ -0,0 +1,128 @@
|
||||
using NetAdmin.Domain.Dto.Sys.Doc.Catalog;
|
||||
using NetAdmin.Domain.Dto.Sys.Doc.Content;
|
||||
|
||||
namespace NetAdmin.SysComponent.Application.Services.Sys;
|
||||
|
||||
/// <inheritdoc cref="IDocService" />
|
||||
public sealed class DocService(IDocCatalogService catalogService, IDocContentService contentService) //
|
||||
: ServiceBase<IDocService>, IDocService
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public Task<int> BulkDeleteCatalogAsync(BulkReq<DelReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return catalogService.BulkDeleteAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<int> BulkDeleteContentAsync(BulkReq<DelReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return contentService.BulkDeleteAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<QueryDocCatalogRsp> CreateCatalogAsync(CreateDocCatalogReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return catalogService.CreateAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<QueryDocContentRsp> CreateContentAsync(CreateDocContentReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return contentService.CreateAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<int> DeleteCatalogAsync(DelReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return catalogService.DeleteAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<int> DeleteContentAsync(DelReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return contentService.DeleteAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<int> EditCatalogAsync(EditDocCatalogReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return catalogService.EditAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<QueryDocContentRsp> EditContentAsync(EditDocContentReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return contentService.EditAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<IActionResult> ExportContentAsync(QueryReq<QueryDocContentReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return contentService.ExportAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<QueryDocCatalogRsp> GetCatalogAsync(QueryDocCatalogReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return catalogService.GetAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<QueryDocContentRsp> GetContentAsync(QueryDocContentReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return contentService.GetAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<PagedQueryRsp<QueryDocCatalogRsp>> PagedQueryCatalogAsync(PagedQueryReq<QueryDocCatalogReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return catalogService.PagedQueryAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<PagedQueryRsp<QueryDocContentRsp>> PagedQueryContentAsync(PagedQueryReq<QueryDocContentReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return contentService.PagedQueryAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<IEnumerable<QueryDocCatalogRsp>> QueryCatalogAsync(QueryReq<QueryDocCatalogReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return catalogService.QueryAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<IEnumerable<QueryDocContentRsp>> QueryContentAsync(QueryReq<QueryDocContentReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return contentService.QueryAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<int> SetEnabledAsync(SetDocContentEnabledReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return contentService.SetEnabledAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<QueryDocContentRsp> ViewContentAsync(QueryDocContentReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return contentService.ViewAsync(req);
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
namespace NetAdmin.SysComponent.Cache.Sys.Dependency;
|
||||
|
||||
/// <summary>
|
||||
/// 文档缓存
|
||||
/// </summary>
|
||||
public interface IDocCache : ICache<IDistributedCache, IDocService>, IDocModule;
|
@ -0,0 +1,6 @@
|
||||
namespace NetAdmin.SysComponent.Cache.Sys.Dependency;
|
||||
|
||||
/// <summary>
|
||||
/// 文档分类缓存
|
||||
/// </summary>
|
||||
public interface IDocCatalogCache : ICache<IDistributedCache, IDocCatalogService>, IDocCatalogModule;
|
@ -0,0 +1,6 @@
|
||||
namespace NetAdmin.SysComponent.Cache.Sys.Dependency;
|
||||
|
||||
/// <summary>
|
||||
/// 文档内容缓存
|
||||
/// </summary>
|
||||
public interface IDocContentCache : ICache<IDistributedCache, IDocContentService>, IDocContentModule;
|
111
src/backend/NetAdmin/NetAdmin.SysComponent.Cache/Sys/DocCache.cs
Normal file
111
src/backend/NetAdmin/NetAdmin.SysComponent.Cache/Sys/DocCache.cs
Normal file
@ -0,0 +1,111 @@
|
||||
using NetAdmin.Domain.Dto.Sys.Doc.Catalog;
|
||||
using NetAdmin.Domain.Dto.Sys.Doc.Content;
|
||||
|
||||
namespace NetAdmin.SysComponent.Cache.Sys;
|
||||
|
||||
/// <inheritdoc cref="IDocCache" />
|
||||
public sealed class DocCache(IDistributedCache cache, IDocService service) //
|
||||
: DistributedCache<IDocService>(cache, service), IScoped, IDocCache
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public Task<int> BulkDeleteCatalogAsync(BulkReq<DelReq> req)
|
||||
{
|
||||
return Service.BulkDeleteCatalogAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<int> BulkDeleteContentAsync(BulkReq<DelReq> req)
|
||||
{
|
||||
return Service.BulkDeleteContentAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<QueryDocCatalogRsp> CreateCatalogAsync(CreateDocCatalogReq req)
|
||||
{
|
||||
return Service.CreateCatalogAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<QueryDocContentRsp> CreateContentAsync(CreateDocContentReq req)
|
||||
{
|
||||
return Service.CreateContentAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<int> DeleteCatalogAsync(DelReq req)
|
||||
{
|
||||
return Service.DeleteCatalogAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<int> DeleteContentAsync(DelReq req)
|
||||
{
|
||||
return Service.DeleteContentAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<int> EditCatalogAsync(EditDocCatalogReq req)
|
||||
{
|
||||
return Service.EditCatalogAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<QueryDocContentRsp> EditContentAsync(EditDocContentReq req)
|
||||
{
|
||||
return Service.EditContentAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<IActionResult> ExportContentAsync(QueryReq<QueryDocContentReq> req)
|
||||
{
|
||||
return Service.ExportContentAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<QueryDocCatalogRsp> GetCatalogAsync(QueryDocCatalogReq req)
|
||||
{
|
||||
return Service.GetCatalogAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<QueryDocContentRsp> GetContentAsync(QueryDocContentReq req)
|
||||
{
|
||||
return Service.GetContentAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<PagedQueryRsp<QueryDocCatalogRsp>> PagedQueryCatalogAsync(PagedQueryReq<QueryDocCatalogReq> req)
|
||||
{
|
||||
return Service.PagedQueryCatalogAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<PagedQueryRsp<QueryDocContentRsp>> PagedQueryContentAsync(PagedQueryReq<QueryDocContentReq> req)
|
||||
{
|
||||
return Service.PagedQueryContentAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<IEnumerable<QueryDocCatalogRsp>> QueryCatalogAsync(QueryReq<QueryDocCatalogReq> req)
|
||||
{
|
||||
return Service.QueryCatalogAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<IEnumerable<QueryDocContentRsp>> QueryContentAsync(QueryReq<QueryDocContentReq> req)
|
||||
{
|
||||
return Service.QueryContentAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<int> SetEnabledAsync(SetDocContentEnabledReq req)
|
||||
{
|
||||
return Service.SetEnabledAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<QueryDocContentRsp> ViewContentAsync(QueryDocContentReq req)
|
||||
{
|
||||
return Service.ViewContentAsync(req);
|
||||
}
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
using NetAdmin.Domain.Dto.Sys.Doc.Catalog;
|
||||
|
||||
namespace NetAdmin.SysComponent.Cache.Sys;
|
||||
|
||||
/// <inheritdoc cref="IDocCatalogCache" />
|
||||
public sealed class DocCatalogCache(IDistributedCache cache, IDocCatalogService service)
|
||||
: DistributedCache<IDocCatalogService>(cache, service), IScoped, IDocCatalogCache
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public Task<int> BulkDeleteAsync(BulkReq<DelReq> req)
|
||||
{
|
||||
return Service.BulkDeleteAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<long> CountAsync(QueryReq<QueryDocCatalogReq> req)
|
||||
{
|
||||
return Service.CountAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<QueryDocCatalogRsp> CreateAsync(CreateDocCatalogReq req)
|
||||
{
|
||||
return Service.CreateAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<int> DeleteAsync(DelReq req)
|
||||
{
|
||||
return Service.DeleteAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<bool> ExistAsync(QueryReq<QueryDocCatalogReq> req)
|
||||
{
|
||||
return Service.ExistAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<IActionResult> ExportAsync(QueryReq<QueryDocCatalogReq> req)
|
||||
{
|
||||
return Service.ExportAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<QueryDocCatalogRsp> GetAsync(QueryDocCatalogReq req)
|
||||
{
|
||||
return Service.GetAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<PagedQueryRsp<QueryDocCatalogRsp>> PagedQueryAsync(PagedQueryReq<QueryDocCatalogReq> req)
|
||||
{
|
||||
return Service.PagedQueryAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<IEnumerable<QueryDocCatalogRsp>> QueryAsync(QueryReq<QueryDocCatalogReq> req)
|
||||
{
|
||||
return Service.QueryAsync(req);
|
||||
}
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
using NetAdmin.Domain.Dto.Sys.Doc.Content;
|
||||
|
||||
namespace NetAdmin.SysComponent.Cache.Sys;
|
||||
|
||||
/// <inheritdoc cref="IDocContentCache" />
|
||||
public sealed class DocContentCache(IDistributedCache cache, IDocContentService service)
|
||||
: DistributedCache<IDocContentService>(cache, service), IScoped, IDocContentCache
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public Task<int> BulkDeleteAsync(BulkReq<DelReq> req)
|
||||
{
|
||||
return Service.BulkDeleteAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<long> CountAsync(QueryReq<QueryDocContentReq> req)
|
||||
{
|
||||
return Service.CountAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<QueryDocContentRsp> CreateAsync(CreateDocContentReq req)
|
||||
{
|
||||
return Service.CreateAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<int> DeleteAsync(DelReq req)
|
||||
{
|
||||
return Service.DeleteAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<bool> ExistAsync(QueryReq<QueryDocContentReq> req)
|
||||
{
|
||||
return Service.ExistAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<IActionResult> ExportAsync(QueryReq<QueryDocContentReq> req)
|
||||
{
|
||||
return Service.ExportAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<QueryDocContentRsp> GetAsync(QueryDocContentReq req)
|
||||
{
|
||||
return Service.GetAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<PagedQueryRsp<QueryDocContentRsp>> PagedQueryAsync(PagedQueryReq<QueryDocContentReq> req)
|
||||
{
|
||||
return Service.PagedQueryAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<IEnumerable<QueryDocContentRsp>> QueryAsync(QueryReq<QueryDocContentReq> req)
|
||||
{
|
||||
return Service.QueryAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<int> SetEnabledAsync(SetDocContentEnabledReq req)
|
||||
{
|
||||
return Service.SetEnabledAsync(req);
|
||||
}
|
||||
}
|
@ -0,0 +1,157 @@
|
||||
using NetAdmin.Domain.Dto.Sys.Doc.Catalog;
|
||||
using NetAdmin.Domain.Dto.Sys.Doc.Content;
|
||||
|
||||
namespace NetAdmin.SysComponent.Host.Controllers.Sys;
|
||||
|
||||
/// <summary>
|
||||
/// 文档服务
|
||||
/// </summary>
|
||||
[ApiDescriptionSettings(nameof(Sys), Module = nameof(Sys))]
|
||||
[Produces(Chars.FLG_HTTP_HEADER_VALUE_APPLICATION_JSON)]
|
||||
public sealed class DocController(IDocCache cache) : ControllerBase<IDocCache, IDocService>(cache), IDocModule
|
||||
{
|
||||
/// <summary>
|
||||
/// 批量删除文档分类
|
||||
/// </summary>
|
||||
[Transaction]
|
||||
public Task<int> BulkDeleteCatalogAsync(BulkReq<DelReq> req)
|
||||
{
|
||||
return Cache.BulkDeleteCatalogAsync(req);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 批量删除文档内容
|
||||
/// </summary>
|
||||
[Transaction]
|
||||
public Task<int> BulkDeleteContentAsync(BulkReq<DelReq> req)
|
||||
{
|
||||
return Cache.BulkDeleteContentAsync(req);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建文档分类
|
||||
/// </summary>
|
||||
[Transaction]
|
||||
public Task<QueryDocCatalogRsp> CreateCatalogAsync(CreateDocCatalogReq req)
|
||||
{
|
||||
return Cache.CreateCatalogAsync(req);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建文档内容
|
||||
/// </summary>
|
||||
[Transaction]
|
||||
public Task<QueryDocContentRsp> CreateContentAsync(CreateDocContentReq req)
|
||||
{
|
||||
return Cache.CreateContentAsync(req);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除文档分类
|
||||
/// </summary>
|
||||
[Transaction]
|
||||
public Task<int> DeleteCatalogAsync(DelReq req)
|
||||
{
|
||||
return Cache.DeleteCatalogAsync(req);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除文档内容
|
||||
/// </summary>
|
||||
[Transaction]
|
||||
public Task<int> DeleteContentAsync(DelReq req)
|
||||
{
|
||||
return Cache.DeleteContentAsync(req);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 编辑文档分类
|
||||
/// </summary>
|
||||
[Transaction]
|
||||
public Task<int> EditCatalogAsync(EditDocCatalogReq req)
|
||||
{
|
||||
return Cache.EditCatalogAsync(req);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 编辑文档内容
|
||||
/// </summary>
|
||||
[Transaction]
|
||||
public Task<QueryDocContentRsp> EditContentAsync(EditDocContentReq req)
|
||||
{
|
||||
return Cache.EditContentAsync(req);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 导出文档内容
|
||||
/// </summary>
|
||||
public Task<IActionResult> ExportContentAsync(QueryReq<QueryDocContentReq> req)
|
||||
{
|
||||
return Cache.ExportContentAsync(req);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取单个文档分类
|
||||
/// </summary>
|
||||
public Task<QueryDocCatalogRsp> GetCatalogAsync(QueryDocCatalogReq req)
|
||||
{
|
||||
return Cache.GetCatalogAsync(req);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取单个文档内容
|
||||
/// </summary>
|
||||
public Task<QueryDocContentRsp> GetContentAsync(QueryDocContentReq req)
|
||||
{
|
||||
return Cache.GetContentAsync(req);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 分页查询文档分类
|
||||
/// </summary>
|
||||
public Task<PagedQueryRsp<QueryDocCatalogRsp>> PagedQueryCatalogAsync(PagedQueryReq<QueryDocCatalogReq> req)
|
||||
{
|
||||
return Cache.PagedQueryCatalogAsync(req);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 分页查询文档内容
|
||||
/// </summary>
|
||||
public Task<PagedQueryRsp<QueryDocContentRsp>> PagedQueryContentAsync(PagedQueryReq<QueryDocContentReq> req)
|
||||
{
|
||||
return Cache.PagedQueryContentAsync(req);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询文档分类
|
||||
/// </summary>
|
||||
public Task<IEnumerable<QueryDocCatalogRsp>> QueryCatalogAsync(QueryReq<QueryDocCatalogReq> req)
|
||||
{
|
||||
return Cache.QueryCatalogAsync(req);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询文档内容
|
||||
/// </summary>
|
||||
public Task<IEnumerable<QueryDocContentRsp>> QueryContentAsync(QueryReq<QueryDocContentReq> req)
|
||||
{
|
||||
return Cache.QueryContentAsync(req);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 启用/禁用文档内容
|
||||
/// </summary>
|
||||
public Task<int> SetEnabledAsync(SetDocContentEnabledReq req)
|
||||
{
|
||||
return Cache.SetEnabledAsync(req);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 浏览文档内容
|
||||
/// </summary>
|
||||
[AllowAnonymous]
|
||||
public Task<QueryDocContentRsp> ViewContentAsync(QueryDocContentReq req)
|
||||
{
|
||||
return Cache.ViewContentAsync(req);
|
||||
}
|
||||
}
|
@ -12,7 +12,7 @@
|
||||
"@element-plus/icons-vue": "2.3.1",
|
||||
"ace-builds": "1.36.5",
|
||||
"aieditor": "1.2.7",
|
||||
"axios": "1.7.7",
|
||||
"axios": "1.7.8",
|
||||
"crypto-js": "4.2.0",
|
||||
"echarts": "5.5.1",
|
||||
"element-plus": "2.8.8",
|
||||
@ -20,11 +20,11 @@
|
||||
"markdown-it": "14.1.0",
|
||||
"markdown-it-emoji": "3.0.0",
|
||||
"nprogress": "0.2.0",
|
||||
"sortablejs": "1.15.3",
|
||||
"sortablejs": "1.15.4",
|
||||
"vkbeautify": "0.99.3",
|
||||
"vue": "3.5.13",
|
||||
"vue-i18n": "10.0.4",
|
||||
"vue-router": "4.4.5",
|
||||
"vue-router": "4.5.0",
|
||||
"vue3-ace-editor": "2.2.4",
|
||||
"vue3-json-viewer": "2.2.2",
|
||||
"vuedraggable": "4.0.3",
|
||||
@ -32,7 +32,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "5.2.0",
|
||||
"prettier": "3.3.3",
|
||||
"prettier": "3.4.0",
|
||||
"prettier-plugin-organize-attributes": "1.0.0",
|
||||
"sass": "1.81.0",
|
||||
"terser": "5.36.0",
|
||||
|
194
src/frontend/admin/src/api/sys/doc.js
Normal file
194
src/frontend/admin/src/api/sys/doc.js
Normal file
@ -0,0 +1,194 @@
|
||||
/**
|
||||
* 文档服务
|
||||
* @module @/api/sys/doc
|
||||
*/
|
||||
import config from '@/config'
|
||||
import http from '@/utils/request'
|
||||
export default {
|
||||
/**
|
||||
* 批量删除文档分类
|
||||
*/
|
||||
bulkDeleteCatalog: {
|
||||
url: `${config.API_URL}/api/sys/doc/bulk.delete.catalog`,
|
||||
name: `批量删除文档分类`,
|
||||
post: async function (data = {}, config = {}) {
|
||||
return await http.post(this.url, data, config)
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 批量删除文档内容
|
||||
*/
|
||||
bulkDeleteContent: {
|
||||
url: `${config.API_URL}/api/sys/doc/bulk.delete.content`,
|
||||
name: `批量删除文档内容`,
|
||||
post: async function (data = {}, config = {}) {
|
||||
return await http.post(this.url, data, config)
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 创建文档分类
|
||||
*/
|
||||
createCatalog: {
|
||||
url: `${config.API_URL}/api/sys/doc/create.catalog`,
|
||||
name: `创建文档分类`,
|
||||
post: async function (data = {}, config = {}) {
|
||||
return await http.post(this.url, data, config)
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 创建文档内容
|
||||
*/
|
||||
createContent: {
|
||||
url: `${config.API_URL}/api/sys/doc/create.content`,
|
||||
name: `创建文档内容`,
|
||||
post: async function (data = {}, config = {}) {
|
||||
return await http.post(this.url, data, config)
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 删除文档分类
|
||||
*/
|
||||
deleteCatalog: {
|
||||
url: `${config.API_URL}/api/sys/doc/delete.catalog`,
|
||||
name: `删除文档分类`,
|
||||
post: async function (data = {}, config = {}) {
|
||||
return await http.post(this.url, data, config)
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 删除文档内容
|
||||
*/
|
||||
deleteContent: {
|
||||
url: `${config.API_URL}/api/sys/doc/delete.content`,
|
||||
name: `删除文档内容`,
|
||||
post: async function (data = {}, config = {}) {
|
||||
return await http.post(this.url, data, config)
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 编辑文档分类
|
||||
*/
|
||||
editCatalog: {
|
||||
url: `${config.API_URL}/api/sys/doc/edit.catalog`,
|
||||
name: `编辑文档分类`,
|
||||
post: async function (data = {}, config = {}) {
|
||||
return await http.post(this.url, data, config)
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 编辑文档内容
|
||||
*/
|
||||
editContent: {
|
||||
url: `${config.API_URL}/api/sys/doc/edit.content`,
|
||||
name: `编辑文档内容`,
|
||||
post: async function (data = {}, config = {}) {
|
||||
return await http.post(this.url, data, config)
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 导出文档内容
|
||||
*/
|
||||
exportContent: {
|
||||
url: `${config.API_URL}/api/sys/doc/export.content`,
|
||||
name: `导出文档内容`,
|
||||
post: async function (data = {}, config = {}) {
|
||||
return await http.post(this.url, data, config)
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取单个文档分类
|
||||
*/
|
||||
getCatalog: {
|
||||
url: `${config.API_URL}/api/sys/doc/get.catalog`,
|
||||
name: `获取单个文档分类`,
|
||||
post: async function (data = {}, config = {}) {
|
||||
return await http.post(this.url, data, config)
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取单个文档内容
|
||||
*/
|
||||
getContent: {
|
||||
url: `${config.API_URL}/api/sys/doc/get.content`,
|
||||
name: `获取单个文档内容`,
|
||||
post: async function (data = {}, config = {}) {
|
||||
return await http.post(this.url, data, config)
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 分页查询文档分类
|
||||
*/
|
||||
pagedQueryCatalog: {
|
||||
url: `${config.API_URL}/api/sys/doc/paged.query.catalog`,
|
||||
name: `分页查询文档分类`,
|
||||
post: async function (data = {}, config = {}) {
|
||||
return await http.post(this.url, data, config)
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 分页查询文档内容
|
||||
*/
|
||||
pagedQueryContent: {
|
||||
url: `${config.API_URL}/api/sys/doc/paged.query.content`,
|
||||
name: `分页查询文档内容`,
|
||||
post: async function (data = {}, config = {}) {
|
||||
return await http.post(this.url, data, config)
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 查询文档分类
|
||||
*/
|
||||
queryCatalog: {
|
||||
url: `${config.API_URL}/api/sys/doc/query.catalog`,
|
||||
name: `查询文档分类`,
|
||||
post: async function (data = {}, config = {}) {
|
||||
return await http.post(this.url, data, config)
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 查询文档内容
|
||||
*/
|
||||
queryContent: {
|
||||
url: `${config.API_URL}/api/sys/doc/query.content`,
|
||||
name: `查询文档内容`,
|
||||
post: async function (data = {}, config = {}) {
|
||||
return await http.post(this.url, data, config)
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 启用/禁用文档内容
|
||||
*/
|
||||
setEnabled: {
|
||||
url: `${config.API_URL}/api/sys/doc/set.enabled`,
|
||||
name: `启用/禁用文档内容`,
|
||||
post: async function (data = {}, config = {}) {
|
||||
return await http.post(this.url, data, config)
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 浏览文档内容
|
||||
*/
|
||||
viewContent: {
|
||||
url: `${config.API_URL}/api/sys/doc/view.content`,
|
||||
name: `浏览文档内容`,
|
||||
post: async function (data = {}, config = {}) {
|
||||
return await http.post(this.url, data, config)
|
||||
},
|
||||
},
|
||||
}
|
73
src/frontend/admin/src/api/sys/doccatalog.js
Normal file
73
src/frontend/admin/src/api/sys/doccatalog.js
Normal file
@ -0,0 +1,73 @@
|
||||
/**
|
||||
* 文档分类服务
|
||||
* @module @/api/sys/doc.catalog
|
||||
*/
|
||||
import config from '@/config'
|
||||
import http from '@/utils/request'
|
||||
export default {
|
||||
/**
|
||||
* 批量删除文档分类
|
||||
*/
|
||||
bulkDelete: {
|
||||
url: `${config.API_URL}/api/sys/doc.catalog/bulk.delete`,
|
||||
name: `批量删除文档分类`,
|
||||
post: async function (data = {}, config = {}) {
|
||||
return await http.post(this.url, data, config)
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 文档分类计数
|
||||
*/
|
||||
count: {
|
||||
url: `${config.API_URL}/api/sys/doc.catalog/count`,
|
||||
name: `文档分类计数`,
|
||||
post: async function (data = {}, config = {}) {
|
||||
return await http.post(this.url, data, config)
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 创建文档分类
|
||||
*/
|
||||
create: {
|
||||
url: `${config.API_URL}/api/sys/doc.catalog/create`,
|
||||
name: `创建文档分类`,
|
||||
post: async function (data = {}, config = {}) {
|
||||
return await http.post(this.url, data, config)
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 删除文档分类
|
||||
*/
|
||||
delete: {
|
||||
url: `${config.API_URL}/api/sys/doc.catalog/delete`,
|
||||
name: `删除文档分类`,
|
||||
post: async function (data = {}, config = {}) {
|
||||
return await http.post(this.url, data, config)
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取单个文档分类
|
||||
*/
|
||||
get: {
|
||||
url: `${config.API_URL}/api/sys/doc.catalog/get`,
|
||||
name: `获取单个文档分类`,
|
||||
post: async function (data = {}, config = {}) {
|
||||
return await http.post(this.url, data, config)
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 分页查询文档分类
|
||||
*/
|
||||
pagedQuery: {
|
||||
url: `${config.API_URL}/api/sys/doc.catalog/paged.query`,
|
||||
name: `分页查询文档分类`,
|
||||
post: async function (data = {}, config = {}) {
|
||||
return await http.post(this.url, data, config)
|
||||
},
|
||||
},
|
||||
}
|
84
src/frontend/admin/src/api/sys/doccontent.js
Normal file
84
src/frontend/admin/src/api/sys/doccontent.js
Normal file
@ -0,0 +1,84 @@
|
||||
/**
|
||||
* 文档内容服务
|
||||
* @module @/api/sys/doc.content
|
||||
*/
|
||||
import config from '@/config'
|
||||
import http from '@/utils/request'
|
||||
export default {
|
||||
/**
|
||||
* 批量删除文档内容
|
||||
*/
|
||||
bulkDelete: {
|
||||
url: `${config.API_URL}/api/sys/doc.content/bulk.delete`,
|
||||
name: `批量删除文档内容`,
|
||||
post: async function (data = {}, config = {}) {
|
||||
return await http.post(this.url, data, config)
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 文档内容计数
|
||||
*/
|
||||
count: {
|
||||
url: `${config.API_URL}/api/sys/doc.content/count`,
|
||||
name: `文档内容计数`,
|
||||
post: async function (data = {}, config = {}) {
|
||||
return await http.post(this.url, data, config)
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 创建文档内容
|
||||
*/
|
||||
create: {
|
||||
url: `${config.API_URL}/api/sys/doc.content/create`,
|
||||
name: `创建文档内容`,
|
||||
post: async function (data = {}, config = {}) {
|
||||
return await http.post(this.url, data, config)
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 删除文档内容
|
||||
*/
|
||||
delete: {
|
||||
url: `${config.API_URL}/api/sys/doc.content/delete`,
|
||||
name: `删除文档内容`,
|
||||
post: async function (data = {}, config = {}) {
|
||||
return await http.post(this.url, data, config)
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取单个文档内容
|
||||
*/
|
||||
get: {
|
||||
url: `${config.API_URL}/api/sys/doc.content/get`,
|
||||
name: `获取单个文档内容`,
|
||||
post: async function (data = {}, config = {}) {
|
||||
return await http.post(this.url, data, config)
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 分页查询文档内容
|
||||
*/
|
||||
pagedQuery: {
|
||||
url: `${config.API_URL}/api/sys/doc.content/paged.query`,
|
||||
name: `分页查询文档内容`,
|
||||
post: async function (data = {}, config = {}) {
|
||||
return await http.post(this.url, data, config)
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 启用/禁用文档内容
|
||||
*/
|
||||
setEnabled: {
|
||||
url: `${config.API_URL}/api/sys/doc.content/set.enabled`,
|
||||
name: `启用/禁用文档内容`,
|
||||
post: async function (data = {}, config = {}) {
|
||||
return await http.post(this.url, data, config)
|
||||
},
|
||||
},
|
||||
}
|
@ -11,7 +11,7 @@
|
||||
<p v-if="$attrs.nestProp2">{{ $TOOL.getNestedProperty(row, $attrs.nestProp2) }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<save-dialog v-if="dialog.save" @closed="dialog.save = false" ref="saveDialog"></save-dialog>
|
||||
<save-dialog v-if="dialog.save" @closed="(dialog.save = false)" ref="saveDialog"></save-dialog>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</template>
|
||||
|
@ -293,7 +293,7 @@
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<el-button @click="dialogVisible = false">{{ $t('取消') }}</el-button>
|
||||
<el-button @click="(dialogVisible = false)">{{ $t('取消') }}</el-button>
|
||||
<el-button @click="submit()" type="primary">{{ $t('确认') }}</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
@ -49,7 +49,7 @@
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button @click="clear" text>{{ $t('清除') }}</el-button>
|
||||
<el-button @click="dialogVisible = false">{{ $t('取消') }}</el-button>
|
||||
<el-button @click="(dialogVisible = false)">{{ $t('取消') }}</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
|
@ -13,7 +13,7 @@
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
<el-button @click="visible = false">{{ $t('取消') }}</el-button>
|
||||
<el-button @click="(visible = false)">{{ $t('取消') }}</el-button>
|
||||
<el-button @click="submit" type="primary">{{ $t('确定') }}</el-button>
|
||||
</template>
|
||||
</sc-dialog>
|
||||
|
@ -90,8 +90,8 @@
|
||||
:hide-after="0"
|
||||
:title="$t('列设置')"
|
||||
:width="500"
|
||||
@after-leave="customColumnShow = false"
|
||||
@show="customColumnShow = true"
|
||||
@after-leave="(customColumnShow = false)"
|
||||
@show="(customColumnShow = true)"
|
||||
placement="top"
|
||||
trigger="click">
|
||||
<template #reference>
|
||||
|
@ -51,7 +51,7 @@
|
||||
<el-dialog v-model="cropperDialogVisible" :title="$t('剪裁')" :width="580" @closed="cropperClosed" destroy-on-close draggable>
|
||||
<sc-cropper :aspectRatio="aspectRatio" :compress="compress" :src="cropperFile.tempCropperFile" ref="cropper"></sc-cropper>
|
||||
<template #footer>
|
||||
<el-button @click="cropperDialogVisible = false">{{ $t('取消') }}</el-button>
|
||||
<el-button @click="(cropperDialogVisible = false)">{{ $t('取消') }}</el-button>
|
||||
<el-button @click="cropperSave" type="primary">{{ $t('确定') }}</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
@ -55,7 +55,6 @@ import naColTags from '@/components/naColTags/index.vue'
|
||||
import naColTime from '@/components/naColTime/index.vue'
|
||||
import naColUser from '@/components/naColUser/index.vue'
|
||||
import naDept from '@/components/naDept/index.vue'
|
||||
import naDicCatalog from '@/components/naDicCatalog/index.vue'
|
||||
import naFormEmail from '@/components/naFormEmail/index.vue'
|
||||
import naSearch from '@/components/naSearch'
|
||||
import naUserSelect from '@/components/naUserSelect/index.vue'
|
||||
@ -98,7 +97,6 @@ export default {
|
||||
app.component('naColTime', naColTime)
|
||||
app.component('naColUser', naColUser)
|
||||
app.component('naDept', naDept)
|
||||
app.component('naDicCatalog', naDicCatalog)
|
||||
app.component('naFormEmail', naFormEmail)
|
||||
app.component('naSearch', naSearch)
|
||||
app.component('naUserSelect', naUserSelect)
|
||||
|
@ -53,7 +53,7 @@
|
||||
</el-footer>
|
||||
</el-container>
|
||||
|
||||
<save-dialog v-if="dialog.save" @closed="dialog.save = null" @mounted="$refs.saveDialog.open(dialog.save)" ref="saveDialog"></save-dialog>
|
||||
<save-dialog v-if="dialog.save" @closed="(dialog.save = null)" @mounted="$refs.saveDialog.open(dialog.save)" ref="saveDialog"></save-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
@ -71,11 +71,11 @@
|
||||
</div>
|
||||
|
||||
<el-dialog v-model="searchVisible" :title="$t('搜索')" :width="700" center destroy-on-close>
|
||||
<search @success="searchVisible = false"></search>
|
||||
<search @success="(searchVisible = false)"></search>
|
||||
</el-dialog>
|
||||
|
||||
<el-drawer v-model="tasksVisible" :size="450" :title="$t('作业中心')" destroy-on-close>
|
||||
<tasks :fail="failJobCnt" @closed="tasksVisible = false"></tasks>
|
||||
<tasks :fail="failJobCnt" @closed="(tasksVisible = false)"></tasks>
|
||||
</el-drawer>
|
||||
</template>
|
||||
|
||||
|
@ -84,7 +84,7 @@ export default {
|
||||
失败: 'Failed',
|
||||
头像: 'Avatar',
|
||||
婚姻状况: 'Marital status',
|
||||
字典分类: 'Dictionary Classification',
|
||||
字典目录: 'Dictionary catalog',
|
||||
客户端IP: 'Client IP',
|
||||
密码: 'Password',
|
||||
小: 'Small',
|
||||
@ -380,7 +380,7 @@ export default {
|
||||
响应体: 'Response body',
|
||||
响应头: 'Response header',
|
||||
执行时间编号: 'Execution time ID',
|
||||
新增字典: 'Add dictionary',
|
||||
新增字典目录: 'Add dictionary catalog',
|
||||
字典名称: 'Dictionary name',
|
||||
字典编码: 'Dictionary code',
|
||||
父路径: 'Parent path',
|
||||
|
@ -84,7 +84,7 @@ export default {
|
||||
失败: '失败',
|
||||
头像: '头像',
|
||||
婚姻状况: '婚姻状况',
|
||||
字典分类: '字典分类',
|
||||
字典目录: '字典目录',
|
||||
客户端IP: '客户端IP',
|
||||
密码: '密码',
|
||||
小: '小',
|
||||
@ -379,7 +379,7 @@ export default {
|
||||
响应体: '响应体',
|
||||
响应头: '响应头',
|
||||
执行时间编号: '执行时间编号',
|
||||
新增字典: '新增字典',
|
||||
新增字典目录: '新增字典目录',
|
||||
字典名称: '字典名称',
|
||||
字典编码: '字典编码',
|
||||
父路径: '父路径',
|
||||
|
@ -68,6 +68,13 @@ const routes = [
|
||||
title: '重置密码',
|
||||
},
|
||||
},
|
||||
{
|
||||
path: '/guest/view-doc/:id',
|
||||
component: () => import(/* webpackChunkName: "view-doc" */ '@/views/guest/view-doc'),
|
||||
meta: {
|
||||
title: '查看文档',
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
export default routes
|
@ -31,7 +31,7 @@
|
||||
</el-form-item>
|
||||
<el-form-item label="" prop="agree">
|
||||
<el-checkbox v-model="form.agree" label="">{{ $t('我已阅读并同意') }}</el-checkbox>
|
||||
<span @click="showAgree = true" class="link">《{{ $t('平台服务协议') }}》</span>
|
||||
<span @click="(showAgree = true)" class="link">《{{ $t('平台服务协议') }}》</span>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-form v-if="stepActive === 1" :model="form" :rules="rules" ref="stepForm_1" size="large">
|
||||
@ -57,7 +57,7 @@
|
||||
</el-form>
|
||||
<el-dialog v-model="showAgree" :title="$t('平台服务协议')" destroy-on-close>
|
||||
<template #footer>
|
||||
<el-button @click="showAgree = false">{{ $t('取消') }}</el-button>
|
||||
<el-button @click="(showAgree = false)">{{ $t('取消') }}</el-button>
|
||||
<el-button
|
||||
@click="
|
||||
() => {
|
||||
|
61
src/frontend/admin/src/views/guest/view-doc.vue
Normal file
61
src/frontend/admin/src/views/guest/view-doc.vue
Normal file
@ -0,0 +1,61 @@
|
||||
<template>
|
||||
<article v-if="doc" v-loading="loading" class="article">
|
||||
<h1>{{ doc.title }}</h1>
|
||||
<section
|
||||
:class="this.$TOOL.data.get('APP_SET_DARK') || this.$CONFIG.APP_SET_DARK ? 'aie-theme-dark' : 'aie-theme-light'"
|
||||
ref="editor"></section>
|
||||
</article>
|
||||
<not-found v-else></not-found>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { AiEditor } from 'aieditor'
|
||||
import 'aieditor/dist/style.css'
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
const notFound = defineAsyncComponent(() => import('@/layout/other/404.vue'))
|
||||
import sysConfig from '@/config'
|
||||
import tool from '@/utils/tool'
|
||||
|
||||
export default {
|
||||
components: { notFound },
|
||||
data() {
|
||||
return {
|
||||
loading: true,
|
||||
doc: { title: '' },
|
||||
}
|
||||
},
|
||||
async created() {
|
||||
const res = await this.$API.sys_doc.viewContent.post({ id: this.$route.params.id })
|
||||
this.doc = res.data
|
||||
this.loading = false
|
||||
if (this.doc) {
|
||||
document.title = this.doc.title
|
||||
const aiEditor = new AiEditor({
|
||||
element: this.$refs.editor,
|
||||
content: this.doc.body,
|
||||
onChange: (body) => {
|
||||
this.doc.body = body.getHtml()
|
||||
},
|
||||
})
|
||||
aiEditor.changeLang(this.$TOOL.data.get('APP_SET_LANG') || sysConfig.APP_SET_LANG)
|
||||
} else {
|
||||
await tool.data.set('LOGIN_REDIRECT', window.location.href)
|
||||
}
|
||||
},
|
||||
methods: {},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.article {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
flex-direction: column;
|
||||
> h1 {
|
||||
padding: 1rem;
|
||||
}
|
||||
> section {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -77,7 +77,7 @@
|
||||
</div>
|
||||
</el-header>
|
||||
<el-header style="height: auto">
|
||||
<el-button @click="this.dialog.customLayout = { title: '添加自定义布局' }" style="margin: 0 auto">添加自定义布局</el-button>
|
||||
<el-button @click="(this.dialog.customLayout = { title: '添加自定义布局' })" style="margin: 0 auto">添加自定义布局</el-button>
|
||||
</el-header>
|
||||
<el-main class="nopadding">
|
||||
<div class="widgets-list">
|
||||
@ -115,7 +115,7 @@
|
||||
|
||||
<custom-layout-dialog
|
||||
v-if="dialog.customLayout"
|
||||
@closed="dialog.customLayout = null"
|
||||
@closed="(dialog.customLayout = null)"
|
||||
@mounted="$refs.customLayoutDialog.open(dialog.customLayout)"
|
||||
@onCustomLayout="(l) => (customLayouts = [l])"
|
||||
ref="customLayoutDialog"></custom-layout-dialog>
|
||||
|
@ -52,7 +52,7 @@
|
||||
</draggable>
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button @click="modsDrawer = false">{{ $t('取消') }}</el-button>
|
||||
<el-button @click="(modsDrawer = false)">{{ $t('取消') }}</el-button>
|
||||
<el-button @click="saveMods" type="primary">{{ $t('保存') }}</el-button>
|
||||
</template>
|
||||
</el-drawer>
|
||||
|
@ -36,18 +36,18 @@
|
||||
|
||||
<set-mobile-dialog
|
||||
v-if="dialog.setMobile"
|
||||
@closed="dialog.setMobile = null"
|
||||
@closed="(dialog.setMobile = null)"
|
||||
@mounted="$refs.setMobileDialog.open(dialog.setMobile)"
|
||||
@success="setSuccess"
|
||||
ref="setMobileDialog"></set-mobile-dialog>
|
||||
<set-password-dialog
|
||||
v-if="dialog.setPassword"
|
||||
@closed="dialog.setPassword = null"
|
||||
@closed="(dialog.setPassword = null)"
|
||||
@mounted="$refs.setPasswordDialog.open(dialog.setPassword)"
|
||||
ref="setPasswordDialog"></set-password-dialog>
|
||||
<set-email-dialog
|
||||
v-if="dialog.setEmail"
|
||||
@closed="dialog.setEmail = null"
|
||||
@closed="(dialog.setEmail = null)"
|
||||
@mounted="$refs.setEmailDialog.open(dialog.setEmail)"
|
||||
@success="setSuccess"
|
||||
ref="setEmailDialog"></set-email-dialog>
|
||||
|
@ -28,7 +28,7 @@
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
<el-button @click="visible = false">{{ $t('取消') }}</el-button>
|
||||
<el-button @click="(visible = false)">{{ $t('取消') }}</el-button>
|
||||
<el-button :disabled="loading" :loading="loading" @click="submit" type="primary">{{ $t('保存') }}</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
@ -33,7 +33,7 @@
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
<el-button @click="visible = false">{{ $t('取消') }}</el-button>
|
||||
<el-button @click="(visible = false)">{{ $t('取消') }}</el-button>
|
||||
<el-button :disabled="loading" :loading="loading" @click="submit" type="primary">{{ $t('保存') }}</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
@ -34,7 +34,7 @@
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
<el-button @click="visible = false">{{ $t('取消') }}</el-button>
|
||||
<el-button @click="(visible = false)">{{ $t('取消') }}</el-button>
|
||||
<el-button :disabled="loading" :loading="loading" @click="submit" type="primary">{{ $t('保存') }}</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
@ -39,7 +39,7 @@
|
||||
ref="search" />
|
||||
</div>
|
||||
<div class="right-panel">
|
||||
<el-button @click="this.dialog.save = { mode: 'add' }" icon="el-icon-plus" type="primary"></el-button>
|
||||
<el-button @click="(this.dialog.save = { mode: 'add' })" icon="el-icon-plus" type="primary"></el-button>
|
||||
<na-button-bulk-del :api="$API.sys_config.bulkDelete" :vue="this" />
|
||||
<el-dropdown v-show="this.selection.length > 0">
|
||||
<el-button type="primary">
|
||||
@ -106,7 +106,7 @@
|
||||
|
||||
<save-dialog
|
||||
v-if="dialog.save"
|
||||
@closed="dialog.save = null"
|
||||
@closed="(dialog.save = null)"
|
||||
@mounted="$refs.saveDialog.open(dialog.save)"
|
||||
@success="(data, mode) => $refs.table.upData()"
|
||||
ref="saveDialog"></save-dialog>
|
||||
|
@ -44,7 +44,7 @@
|
||||
</el-tabs>
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button @click="visible = false">{{ $t('取消') }}</el-button>
|
||||
<el-button @click="(visible = false)">{{ $t('取消') }}</el-button>
|
||||
<el-button v-if="mode !== 'view'" :disabled="loading" :loading="loading" @click="submit" type="primary">{{ $t('保存') }}</el-button>
|
||||
</template>
|
||||
</sc-dialog>
|
||||
|
@ -46,7 +46,7 @@
|
||||
ref="search" />
|
||||
</div>
|
||||
<div class="right-panel">
|
||||
<el-button @click="this.dialog.save = { mode: 'add' }" icon="el-icon-plus" type="primary"></el-button>
|
||||
<el-button @click="(this.dialog.save = { mode: 'add' })" icon="el-icon-plus" type="primary"></el-button>
|
||||
<na-button-bulk-del :api="$API.sys_dept.bulkDelete" :vue="this" />
|
||||
<el-dropdown v-show="this.selection.length > 0">
|
||||
<el-button type="primary">
|
||||
@ -113,7 +113,7 @@
|
||||
|
||||
<save-dialog
|
||||
v-if="dialog.save"
|
||||
@closed="dialog.save = null"
|
||||
@closed="(dialog.save = null)"
|
||||
@mounted="$refs.saveDialog.open(dialog.save)"
|
||||
@success="(data, mode) => table.handleUpdate($refs.table, data, mode)"
|
||||
ref="saveDialog"></save-dialog>
|
||||
|
@ -42,7 +42,7 @@
|
||||
</el-tabs>
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button @click="visible = false">{{ $t('取消') }}</el-button>
|
||||
<el-button @click="(visible = false)">{{ $t('取消') }}</el-button>
|
||||
<el-button v-if="mode !== 'view'" :disabled="loading" :loading="loading" @click="submit" type="primary">{{ $t('保存') }}</el-button>
|
||||
</template>
|
||||
</sc-dialog>
|
||||
|
@ -38,7 +38,7 @@
|
||||
</el-main>
|
||||
<el-footer>
|
||||
<el-button @click="add(form.catalogId)" icon="el-icon-plus" size="small" style="width: 100%" type="primary">{{
|
||||
$t('字典分类')
|
||||
$t('字典目录')
|
||||
}}</el-button>
|
||||
</el-footer>
|
||||
</el-container>
|
||||
@ -48,7 +48,7 @@
|
||||
|
||||
<save-dialog
|
||||
v-if="dialog.save"
|
||||
@closed="dialog.save = null"
|
||||
@closed="(dialog.save = null)"
|
||||
@mounted="$refs.saveDialog.open(dialog.save)"
|
||||
@success="(data, mode) => getData()"
|
||||
ref="saveDialog"></save-dialog>
|
||||
@ -106,7 +106,7 @@ export default {
|
||||
},
|
||||
//字典目录增加
|
||||
async add(id, code) {
|
||||
this.dialog.save = { mode: 'add', data: { catalogId: id, code: code + '>' } }
|
||||
this.dialog.save = { mode: 'add', data: { catalogId: id, code: code ? code + '>' : '' } }
|
||||
},
|
||||
//字典目录编辑
|
||||
async edit(data) {
|
||||
|
@ -23,8 +23,8 @@
|
||||
:controls="[
|
||||
{
|
||||
type: 'input',
|
||||
field: ['dy', 'keywords'],
|
||||
placeholder: $t('项名 / 项值'),
|
||||
field: ['root', 'keywords'],
|
||||
placeholder: $t('项名 / 项值 / 备注'),
|
||||
style: 'width:20rem',
|
||||
},
|
||||
]"
|
||||
@ -38,7 +38,7 @@
|
||||
</div>
|
||||
<div class="right-panel">
|
||||
<el-button
|
||||
@click="this.dialog.save = { mode: 'add', data: { catalogId: this.catalogId } }"
|
||||
@click="(this.dialog.save = { mode: 'add', data: { catalogId: this.catalogId } })"
|
||||
icon="el-icon-plus"
|
||||
type="primary"></el-button>
|
||||
<na-button-bulk-del :api="$API.sys_dic.bulkDeleteContent" :vue="this" />
|
||||
@ -53,7 +53,7 @@
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item @click="setEnabled(true)">{{ $t('启用') }}</el-dropdown-item>
|
||||
<el-dropdown-item @click="setEnabled(false)">{{ $t('禁用') }}</el-dropdown-item>
|
||||
<el-dropdown-item @click="this.dialog.savebatch = { mode: 'batchedit', data: { catalogId: this.catalogId } }">{{
|
||||
<el-dropdown-item @click="(this.dialog.savebatch = { mode: 'batchedit', data: { catalogId: this.catalogId } })">{{
|
||||
$t('设置项值')
|
||||
}}</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
@ -64,7 +64,7 @@
|
||||
<el-main class="nopadding">
|
||||
<sc-table
|
||||
:before-post="(data) => data.dynamicFilter.filters.length > 0"
|
||||
:context-menus="['key', 'value', 'enabled', 'createdTime']"
|
||||
:context-menus="['key', 'value', 'enabled', 'createdTime', 'id', 'summary']"
|
||||
:default-sort="{ prop: 'createdTime', order: 'descending' }"
|
||||
:export-api="$API.sys_dic.exportContent"
|
||||
:params="query"
|
||||
@ -80,6 +80,7 @@
|
||||
row-key="id"
|
||||
stripe>
|
||||
<el-table-column type="selection" width="50" />
|
||||
<na-col-id :label="$t('唯一编码')" prop="id" sortable="custom" width="170" />
|
||||
<el-table-column :label="$t('项名')" prop="key" sortable="custom" />
|
||||
<el-table-column :label="$t('项值')" prop="value" sortable="custom" />
|
||||
<el-table-column :label="$t('备注')" prop="summary" sortable="custom" />
|
||||
@ -88,7 +89,6 @@
|
||||
<el-switch v-model="row.enabled" @change="changeSwitch($event, row)"></el-switch>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('创建时间')" align="right" prop="createdTime" sortable="custom" width="170" />
|
||||
<na-col-operation
|
||||
:buttons="
|
||||
naColOperation.buttons.concat({
|
||||
@ -107,14 +107,14 @@
|
||||
|
||||
<save-dialog
|
||||
v-if="dialog.save"
|
||||
@closed="dialog.save = null"
|
||||
@closed="(dialog.save = null)"
|
||||
@mounted="$refs.saveDialog.open(dialog.save)"
|
||||
@success="(data, mode) => table.handleUpdate($refs.table, data, mode)"
|
||||
ref="saveDialog"></save-dialog>
|
||||
|
||||
<savebatch-dialog
|
||||
v-if="dialog.savebatch"
|
||||
@closed="dialog.savebatch = null"
|
||||
@closed="(dialog.savebatch = null)"
|
||||
@mounted="$refs.savebatchDialog.open(dialog.savebatch)"
|
||||
@success="(data, mode) => batchsuccess(data, mode)"
|
||||
ref="savebatchDialog"></savebatch-dialog>
|
||||
@ -222,25 +222,7 @@ export default {
|
||||
this.query.dynamicFilter.filters.push({
|
||||
field: 'createdTime',
|
||||
operator: 'dateRange',
|
||||
value: form.dy.createdTime,
|
||||
})
|
||||
}
|
||||
|
||||
if (form.dy.keywords) {
|
||||
this.query.dynamicFilter.filters.push({
|
||||
logic: 'or',
|
||||
filters: [
|
||||
{
|
||||
field: 'key',
|
||||
operator: 'contains',
|
||||
value: form.dy.keywords,
|
||||
},
|
||||
{
|
||||
field: 'value',
|
||||
operator: 'contains',
|
||||
value: form.dy.keywords,
|
||||
},
|
||||
],
|
||||
value: form.dy.createdTime.map((x) => x.replace(/ 00:00:00$/, '')),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -4,8 +4,8 @@
|
||||
<el-tabs tab-position="top">
|
||||
<el-tab-pane :label="$t('基本信息')">
|
||||
<el-form :disabled="mode === 'view'" :model="form" :rules="rules" label-width="10rem" ref="dialogForm">
|
||||
<el-form-item :label="$t('所属字典')" prop="catalogId">
|
||||
<na-dic-catalog v-model="form.catalogId" class="w100p" />
|
||||
<el-form-item :label="$t('所属字典目录')" prop="catalogId">
|
||||
<catalog-select v-model="form.catalogId" class="w100p" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('项名')" prop="key">
|
||||
<el-input v-model="form.key" clearable></el-input>
|
||||
@ -30,15 +30,17 @@
|
||||
</el-tabs>
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button @click="visible = false">{{ $t('取消') }}</el-button>
|
||||
<el-button @click="(visible = false)">{{ $t('取消') }}</el-button>
|
||||
<el-button v-if="mode !== 'view'" :disabled="loading" :loading="loading" @click="submit" type="primary">{{ $t('保存') }}</el-button>
|
||||
</template>
|
||||
</sc-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
const catalogSelect = defineAsyncComponent(() => import('../components/catalog-select.vue'))
|
||||
export default {
|
||||
components: {},
|
||||
components: { catalogSelect },
|
||||
data() {
|
||||
return {
|
||||
//表单数据
|
||||
@ -47,7 +49,7 @@ export default {
|
||||
mode: 'add',
|
||||
//验证规则
|
||||
rules: {
|
||||
catalogId: [{ required: true, message: '请选择所属字典' }],
|
||||
catalogId: [{ required: true, message: '请选择所属字典目录' }],
|
||||
key: [{ required: true, message: '请输入项名' }],
|
||||
value: [{ required: true, message: '请输入项值' }],
|
||||
},
|
||||
|
@ -21,7 +21,7 @@
|
||||
</el-tabs>
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button @click="visible = false">{{ $t('取消') }}</el-button>
|
||||
<el-button @click="(visible = false)">{{ $t('取消') }}</el-button>
|
||||
<el-button v-if="mode !== 'view'" :disabled="loading" :loading="loading" @click="submit" type="primary">{{ $t('保存') }}</el-button>
|
||||
</template>
|
||||
</sc-dialog>
|
||||
|
@ -1,25 +1,28 @@
|
||||
<template>
|
||||
<sc-dialog v-model="visible" :title="`${titleMap[mode]}:${form?.id ?? '...'}`" @closed="$emit('closed')" destroy-on-close>
|
||||
<el-form v-loading="loading" :model="form" :rules="rules" label-width="10rem" ref="dialogForm">
|
||||
<el-form-item :label="$t('字典名称')" prop="name">
|
||||
<el-input v-model="form.name" :placeholder="$t('字典名称')" clearable></el-input>
|
||||
<el-form-item :label="$t('字典目录名称')" prop="name">
|
||||
<el-input v-model="form.name" :placeholder="$t('字典目录名称')" clearable></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('字典编码')" prop="code">
|
||||
<el-input v-model="form.code" :placeholder="$t('字典编码')" clearable></el-input>
|
||||
<el-form-item :label="$t('字典目录编码')" prop="code">
|
||||
<el-input v-model="form.code" :placeholder="$t('字典目录编码')" clearable></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('父路径')" prop="parentId">
|
||||
<na-dic-catalog v-model="form.parentId" class="w100p" />
|
||||
<catalog-select v-model="form.parentId" class="w100p" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="visible = false">{{ $t('取消') }}</el-button>
|
||||
<el-button @click="(visible = false)">{{ $t('取消') }}</el-button>
|
||||
<el-button v-if="mode !== 'view'" :disabled="loading" :loading="loading" @click="submit" type="primary">{{ $t('保存') }}</el-button>
|
||||
</template>
|
||||
</sc-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
const catalogSelect = defineAsyncComponent(() => import('./components/catalog-select.vue'))
|
||||
export default {
|
||||
components: { catalogSelect },
|
||||
data() {
|
||||
return {
|
||||
//表单数据
|
||||
@ -28,12 +31,12 @@ export default {
|
||||
mode: 'add',
|
||||
//验证规则
|
||||
rules: {
|
||||
code: [{ required: true, message: '请输入编码' }],
|
||||
name: [{ required: true, message: '请输入字典名称' }],
|
||||
code: [{ required: true, message: '请输入字典目录编码' }],
|
||||
name: [{ required: true, message: '请输入字典目录名称' }],
|
||||
},
|
||||
titleMap: {
|
||||
add: this.$t('新增字典'),
|
||||
edit: this.$t('编辑字典'),
|
||||
add: this.$t('新增字典目录'),
|
||||
edit: this.$t('编辑字典目录'),
|
||||
},
|
||||
visible: false,
|
||||
}
|
||||
|
@ -0,0 +1,52 @@
|
||||
<template>
|
||||
<el-cascader
|
||||
v-bind="$attrs"
|
||||
v-model="data"
|
||||
:options="options"
|
||||
:placeholder="placeholder"
|
||||
:props="{
|
||||
value: 'id',
|
||||
label: 'name',
|
||||
emitPath: false,
|
||||
checkStrictly: true,
|
||||
expandTrigger: 'hover',
|
||||
}"
|
||||
clearable></el-cascader>
|
||||
</template>
|
||||
<style scoped></style>
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
modelValue: { type: Object },
|
||||
placeholder: { type: String },
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loaded: false,
|
||||
data: null,
|
||||
options: [],
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
data(n) {
|
||||
this.$emit('update:modelValue', n)
|
||||
},
|
||||
|
||||
modelValue: {
|
||||
immediate: true,
|
||||
deep: true,
|
||||
handler(n) {
|
||||
this.data = n ?? null
|
||||
},
|
||||
},
|
||||
},
|
||||
mounted() {},
|
||||
async created() {
|
||||
const res = await this.$API.sys_doc.queryCatalog.post()
|
||||
this.options = res.data
|
||||
},
|
||||
components: {},
|
||||
computed: {},
|
||||
methods: {},
|
||||
}
|
||||
</script>
|
167
src/frontend/admin/src/views/sys/doc/index.vue
Normal file
167
src/frontend/admin/src/views/sys/doc/index.vue
Normal file
@ -0,0 +1,167 @@
|
||||
<template>
|
||||
<el-container>
|
||||
<el-aside v-loading="loading" width="40rem">
|
||||
<el-container>
|
||||
<el-header>
|
||||
<el-input v-model="filterText" :placeholder="$t('输入关键字进行过滤')" clearable></el-input>
|
||||
</el-header>
|
||||
<el-main class="nopadding">
|
||||
<el-tree
|
||||
:data="data"
|
||||
:expand-on-click-node="false"
|
||||
:filter-node-method="filterNode"
|
||||
:highlight-current="true"
|
||||
:props="{
|
||||
label: 'name',
|
||||
}"
|
||||
@node-click="click"
|
||||
default-expand-all
|
||||
node-key="id"
|
||||
ref="doc">
|
||||
<template #default="{ _, data }">
|
||||
<div class="custom-tree-node">
|
||||
<span>{{ data.name }} {{ data.code }}</span>
|
||||
<span class="btn">
|
||||
<el-button-group size="small">
|
||||
<el-button @click.stop="add(data.id, data.code)" icon="el-icon-plus"></el-button>
|
||||
<el-button @click.stop="edit(data)" icon="el-icon-edit"></el-button>
|
||||
<el-popconfirm :title="$t('确定删除 {item} 吗?', { item: data.name })" @confirm="del(data)" width="20rem">
|
||||
<template #reference>
|
||||
<el-button @click.stop="() => {}" icon="el-icon-delete"></el-button>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</el-button-group>
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-tree>
|
||||
</el-main>
|
||||
<el-footer>
|
||||
<el-button @click="add(form.catalogId)" icon="el-icon-plus" size="small" style="width: 100%" type="primary">{{
|
||||
$t('文档分类')
|
||||
}}</el-button>
|
||||
</el-footer>
|
||||
</el-container>
|
||||
</el-aside>
|
||||
<list :catalogId="form.catalogId" />
|
||||
</el-container>
|
||||
|
||||
<save-dialog
|
||||
v-if="dialog.save"
|
||||
@closed="(dialog.save = null)"
|
||||
@mounted="$refs.saveDialog.open(dialog.save)"
|
||||
@success="(data, mode) => getData()"
|
||||
ref="saveDialog"></save-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
import list from './list'
|
||||
|
||||
const saveDialog = defineAsyncComponent(() => import('./save.vue'))
|
||||
export default {
|
||||
components: {
|
||||
list,
|
||||
saveDialog,
|
||||
},
|
||||
computed: {},
|
||||
created() {},
|
||||
data() {
|
||||
return {
|
||||
data: [],
|
||||
dialog: {},
|
||||
filterText: '',
|
||||
form: {},
|
||||
loading: false,
|
||||
query: {
|
||||
dynamicFilter: {
|
||||
filters: [],
|
||||
},
|
||||
filter: {},
|
||||
keywords: this.keywords,
|
||||
},
|
||||
}
|
||||
},
|
||||
inject: ['reload'],
|
||||
methods: {
|
||||
// 获取文档分类
|
||||
async getData() {
|
||||
this.loading = true
|
||||
const res = await this.$API.sys_doc.queryCatalog.post({ prop: 'name', order: 'ascending' })
|
||||
this.loading = false
|
||||
this.data = res.data
|
||||
|
||||
//获取第一个节点,设置选中 & 加载明细列表
|
||||
if (this.data.length > 0) {
|
||||
await this.$nextTick()
|
||||
this.$refs.doc.setCurrentKey(this.data[0].id)
|
||||
this.form.catalogId = this.data[0].id
|
||||
}
|
||||
},
|
||||
//文档分类过滤
|
||||
filterNode(value, data) {
|
||||
if (!value) return true
|
||||
const targetText = data.name + data.code
|
||||
return targetText.indexOf(value) !== -1
|
||||
},
|
||||
//文档分类增加
|
||||
async add(id, code) {
|
||||
this.dialog.save = { mode: 'add', data: { catalogId: id, code: code ? code + '>' : '' } }
|
||||
},
|
||||
//文档分类编辑
|
||||
async edit(data) {
|
||||
this.dialog.save = { mode: 'edit', row: data }
|
||||
},
|
||||
//文档分类点击
|
||||
click(data) {
|
||||
this.form.catalogId = data.id
|
||||
},
|
||||
//文档分类删除
|
||||
async del(data) {
|
||||
this.loading = true
|
||||
try {
|
||||
await this.$API.sys_doc.deleteCatalog.post({
|
||||
id: data.id,
|
||||
})
|
||||
this.$message.success(this.$t('操作成功'))
|
||||
} catch {
|
||||
//
|
||||
}
|
||||
this.loading = false
|
||||
await this.getData()
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.getData()
|
||||
},
|
||||
props: ['keywords'],
|
||||
watch: {
|
||||
filterText(val) {
|
||||
this.$refs.doc.filter(val)
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.custom-tree-node {
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-right: 2rem;
|
||||
|
||||
.btn {
|
||||
display: none;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
&:hover .btn {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep .el-tree-node__content {
|
||||
height: 3rem;
|
||||
}
|
||||
</style>
|
266
src/frontend/admin/src/views/sys/doc/list/index.vue
Normal file
266
src/frontend/admin/src/views/sys/doc/list/index.vue
Normal file
@ -0,0 +1,266 @@
|
||||
<template>
|
||||
<el-container>
|
||||
<el-header style="height: auto; padding: 0 1rem">
|
||||
<sc-select-filter
|
||||
:data="[
|
||||
{
|
||||
title: $t('启用状态'),
|
||||
key: 'enabled',
|
||||
options: [
|
||||
{ label: $t('全部'), value: '' },
|
||||
{ label: $t('启用'), value: true },
|
||||
{ label: $t('禁用'), value: false },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: $t('档案可见性'),
|
||||
key: 'visibility',
|
||||
options: [
|
||||
{ label: $t('全部'), value: '' },
|
||||
...Object.entries(this.$GLOBAL.enums.archiveVisibilities).map((x) => {
|
||||
return { value: x[0], label: x[1][1] }
|
||||
}),
|
||||
],
|
||||
},
|
||||
]"
|
||||
:label-width="6"
|
||||
@on-change="filterChange"
|
||||
ref="selectFilter"></sc-select-filter>
|
||||
</el-header>
|
||||
<el-header>
|
||||
<div class="left-panel">
|
||||
<na-search
|
||||
:controls="[
|
||||
{
|
||||
type: 'input',
|
||||
field: ['root', 'keywords'],
|
||||
placeholder: $t('文档标题'),
|
||||
style: 'width:20rem',
|
||||
},
|
||||
]"
|
||||
:vue="this"
|
||||
@reset="onReset"
|
||||
@search="onSearch"
|
||||
dateFormat="YYYY-MM-DD HH:mm:ss"
|
||||
dateType="datetimerange"
|
||||
dateValueFormat="YYYY-MM-DD HH:mm:ss"
|
||||
ref="search" />
|
||||
</div>
|
||||
<div class="right-panel">
|
||||
<el-button
|
||||
@click="(this.dialog.save = { mode: 'add', data: { catalogId: this.catalogId } })"
|
||||
icon="el-icon-plus"
|
||||
type="primary"></el-button>
|
||||
<na-button-bulk-del :api="$API.sys_doc.bulkDeleteContent" :vue="this" />
|
||||
<el-dropdown v-show="this.selection.length > 0">
|
||||
<el-button type="primary">
|
||||
{{ $t('批量操作') }}
|
||||
<el-icon>
|
||||
<el-icon-arrow-down />
|
||||
</el-icon>
|
||||
</el-button>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item @click="setEnabled(true)">{{ $t('启用') }}</el-dropdown-item>
|
||||
<el-dropdown-item @click="setEnabled(false)">{{ $t('禁用') }}</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
</el-header>
|
||||
<el-main class="nopadding">
|
||||
<sc-table
|
||||
:before-post="(data) => data.dynamicFilter.filters.length > 0"
|
||||
:context-menus="['title', 'enabled', 'createdTime', 'id', 'visibility']"
|
||||
:default-sort="{ prop: 'createdTime', order: 'descending' }"
|
||||
:export-api="$API.sys_doc.exportContent"
|
||||
:params="query"
|
||||
:query-api="$API.sys_doc.pagedQueryContent"
|
||||
:vue="this"
|
||||
@selection-change="
|
||||
(items) => {
|
||||
selection = items
|
||||
}
|
||||
"
|
||||
ref="table"
|
||||
remote-sort
|
||||
row-key="id"
|
||||
stripe>
|
||||
<el-table-column type="selection" width="50" />
|
||||
<na-col-id :label="$t('唯一编码')" prop="id" sortable="custom" width="170" />
|
||||
<el-table-column :label="$t('文档标题')" prop="title" sortable="custom" />
|
||||
<na-col-indicator
|
||||
:label="$t('档案可见性')"
|
||||
:options="
|
||||
Object.entries(this.$GLOBAL.enums.archiveVisibilities).map((x) => {
|
||||
return { value: x[0], text: x[1][1], type: x[1][2] }
|
||||
})
|
||||
"
|
||||
align="center"
|
||||
prop="visibility"
|
||||
sortable="custom"
|
||||
width="150" />
|
||||
<el-table-column :label="$t('启用')" align="center" prop="enabled" sortable="custom" width="100">
|
||||
<template #default="{ row }">
|
||||
<el-switch v-model="row.enabled" @change="changeSwitch($event, row)"></el-switch>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<na-col-operation
|
||||
:buttons="
|
||||
naColOperation.buttons.concat({
|
||||
icon: 'el-icon-delete',
|
||||
confirm: true,
|
||||
title: '删除文档',
|
||||
click: rowDel,
|
||||
type: 'danger',
|
||||
})
|
||||
"
|
||||
:vue="this"
|
||||
width="150" />
|
||||
</sc-table>
|
||||
</el-main>
|
||||
</el-container>
|
||||
|
||||
<save-dialog
|
||||
v-if="dialog.save"
|
||||
@closed="(dialog.save = null)"
|
||||
@mounted="$refs.saveDialog.open(dialog.save)"
|
||||
@success="(data, mode) => table.handleUpdate($refs.table, data, mode)"
|
||||
ref="saveDialog"></save-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
import table from '@/config/table'
|
||||
import naColOperation from '@/config/naColOperation'
|
||||
|
||||
const saveDialog = defineAsyncComponent(() => import('./save.vue'))
|
||||
export default {
|
||||
components: {
|
||||
saveDialog,
|
||||
},
|
||||
computed: {
|
||||
naColOperation() {
|
||||
return naColOperation
|
||||
},
|
||||
table() {
|
||||
return table
|
||||
},
|
||||
},
|
||||
created() {},
|
||||
data() {
|
||||
return {
|
||||
dialog: {},
|
||||
loading: false,
|
||||
query: {
|
||||
dynamicFilter: {
|
||||
filters: [],
|
||||
},
|
||||
filter: {},
|
||||
keywords: this.keywords,
|
||||
},
|
||||
selection: [],
|
||||
}
|
||||
},
|
||||
inject: ['reload'],
|
||||
methods: {
|
||||
filterChange(data) {
|
||||
Object.entries(data).forEach(([key, value]) => {
|
||||
this.$refs.search.form.dy[key] = value === 'true' ? true : value === 'false' ? false : value
|
||||
})
|
||||
this.$refs.search.search()
|
||||
},
|
||||
//表格内开关事件
|
||||
async changeSwitch(event, row) {
|
||||
try {
|
||||
await this.$API.sys_doc.setEnabled.post(row)
|
||||
this.$message.success(`操作成功`)
|
||||
} catch {
|
||||
//
|
||||
}
|
||||
this.$refs.table.refresh()
|
||||
},
|
||||
async setEnabled(enabled) {
|
||||
let loading
|
||||
try {
|
||||
await this.$confirm(`确定${enabled ? '启用' : '禁用'}选中的 ${this.selection.length} 项吗?`, '提示', {
|
||||
type: 'warning',
|
||||
})
|
||||
loading = this.$loading()
|
||||
const res = await Promise.all(this.selection.map((x) => this.$API.sys_doc.setEnabled.post(Object.assign(x, { enabled: enabled }))))
|
||||
this.$message.success(`操作成功 ${res.map((x) => x.data ?? 0).reduce((a, b) => a + b, 0)}/${this.selection.length} 条`)
|
||||
} catch {
|
||||
//
|
||||
}
|
||||
this.$refs.table.refresh()
|
||||
loading?.close()
|
||||
},
|
||||
onReset() {
|
||||
Object.entries(this.$refs.selectFilter.selected).forEach(([key, _]) => (this.$refs.selectFilter.selected[key] = ['']))
|
||||
},
|
||||
//搜索
|
||||
onSearch(form) {
|
||||
this.query.dynamicFilter.filters.push({
|
||||
field: 'catalogId',
|
||||
value: this.catalogId,
|
||||
operator: 'eq',
|
||||
})
|
||||
|
||||
if (Array.isArray(form.dy.createdTime)) {
|
||||
this.query.dynamicFilter.filters.push({
|
||||
field: 'createdTime',
|
||||
operator: 'dateRange',
|
||||
value: form.dy.createdTime.map((x) => x.replace(/ 00:00:00$/, '')),
|
||||
})
|
||||
}
|
||||
|
||||
if (typeof form.dy.enabled === 'boolean') {
|
||||
this.query.dynamicFilter.filters.push({
|
||||
field: 'enabled',
|
||||
operator: 'eq',
|
||||
value: form.dy.enabled,
|
||||
})
|
||||
}
|
||||
|
||||
if (typeof form.dy.visibility === 'string' && form.dy.visibility.trim() !== '') {
|
||||
this.query.dynamicFilter.filters.push({
|
||||
field: 'visibility',
|
||||
operator: 'eq',
|
||||
value: form.dy.visibility,
|
||||
})
|
||||
}
|
||||
|
||||
this.$refs.table.upData()
|
||||
},
|
||||
|
||||
//删除
|
||||
async rowDel(row) {
|
||||
try {
|
||||
const res = await this.$API.sys_doc.deleteContent.post({ id: row.id })
|
||||
this.$message.success(this.$t('删除 {count} 项', { count: res.data }))
|
||||
} catch {
|
||||
//
|
||||
}
|
||||
this.$refs.table.refresh()
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
if (this.keywords) {
|
||||
this.$refs.search.form.root.keywords = this.keywords
|
||||
this.$refs.search.keeps.push({
|
||||
field: 'keywords',
|
||||
value: this.keywords,
|
||||
type: 'root',
|
||||
})
|
||||
}
|
||||
},
|
||||
props: { catalogId: Number, keywords: String },
|
||||
watch: {
|
||||
catalogId() {
|
||||
this.$refs.search.reset()
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
133
src/frontend/admin/src/views/sys/doc/list/save.vue
Normal file
133
src/frontend/admin/src/views/sys/doc/list/save.vue
Normal file
@ -0,0 +1,133 @@
|
||||
<template>
|
||||
<sc-dialog v-model="visible" :title="`${titleMap[mode]}:${form?.id ?? '...'}`" @closed="$emit('closed')" destroy-on-close full-screen>
|
||||
<div v-loading="loading">
|
||||
<el-tabs tab-position="top">
|
||||
<el-tab-pane :label="$t('基本信息')">
|
||||
<el-form :disabled="mode === 'view'" :model="form" :rules="rules" label-width="10rem" ref="dialogForm">
|
||||
<el-form-item :label="$t('所属文档分类')" prop="catalogId">
|
||||
<catalog-select v-model="form.catalogId" class="w100p" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('文档标题')" prop="title">
|
||||
<el-input v-model="form.title" clearable></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('档案可见性')" prop="visibility">
|
||||
<el-select v-model="form.visibility" clearable filterable>
|
||||
<el-option v-for="(item, i) in $GLOBAL.enums.archiveVisibilities" :key="i" :label="item[1]" :value="i" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('文档内容')" prop="body">
|
||||
<div
|
||||
:class="
|
||||
this.$TOOL.data.get('APP_SET_DARK') || this.$CONFIG.APP_SET_DARK
|
||||
? 'aie-theme-dark editor'
|
||||
: 'aie-theme-light editor'
|
||||
"
|
||||
ref="editor"></div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane v-if="mode === 'view'" :label="$t('原始数据')">
|
||||
<json-viewer
|
||||
:expand-depth="5"
|
||||
:theme="this.$TOOL.data.get('APP_SET_DARK') || this.$CONFIG.APP_SET_DARK ? 'dark' : 'light'"
|
||||
:value="form"
|
||||
copyable
|
||||
expanded
|
||||
sort></json-viewer>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button @click="(visible = false)">{{ $t('取消') }}</el-button>
|
||||
<el-button v-if="mode !== 'view'" :disabled="loading" :loading="loading" @click="submit" type="primary">{{ $t('保存') }}</el-button>
|
||||
</template>
|
||||
</sc-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
import { AiEditor } from 'aieditor'
|
||||
import 'aieditor/dist/style.css'
|
||||
import sysConfig from '@/config'
|
||||
const catalogSelect = defineAsyncComponent(() => import('../components/catalog-select.vue'))
|
||||
export default {
|
||||
components: { catalogSelect },
|
||||
data() {
|
||||
return {
|
||||
//表单数据
|
||||
form: {},
|
||||
loading: true,
|
||||
mode: 'add',
|
||||
//验证规则
|
||||
rules: {
|
||||
catalogId: [{ required: true, message: '请选择所属文档分类' }],
|
||||
title: [{ required: true, message: '请输入文档标题' }],
|
||||
body: [{ required: true, message: '请输入文档内容' }],
|
||||
visibility: [{ required: true, message: '请选择档案可见性' }],
|
||||
},
|
||||
titleMap: {
|
||||
add: this.$t('新增文档'),
|
||||
edit: this.$t('编辑文档'),
|
||||
view: this.$t('查看文档'),
|
||||
},
|
||||
visible: false,
|
||||
}
|
||||
},
|
||||
emits: ['success', 'closed', 'mounted'],
|
||||
methods: {
|
||||
//显示
|
||||
async open(data) {
|
||||
this.visible = true
|
||||
this.loading = true
|
||||
this.mode = data.mode
|
||||
this.form.catalogId = data.data?.catalogId
|
||||
if (data.row?.id) {
|
||||
const res = await this.$API.sys_doc.getContent.post({ id: data.row.id })
|
||||
Object.assign(this.form, res.data)
|
||||
}
|
||||
this.loading = false
|
||||
|
||||
await this.$nextTick()
|
||||
const aiEditor = new AiEditor({
|
||||
element: this.$refs.editor,
|
||||
placeholder: this.$t('请输入消息内容...'),
|
||||
content: this.form.body,
|
||||
onChange: (body) => {
|
||||
this.form.body = body.getHtml()
|
||||
},
|
||||
})
|
||||
aiEditor.changeLang(this.$TOOL.data.get('APP_SET_LANG') || sysConfig.APP_SET_LANG)
|
||||
|
||||
return this
|
||||
},
|
||||
|
||||
//表单提交方法
|
||||
async submit() {
|
||||
const valid = await this.$refs.dialogForm.validate().catch(() => {})
|
||||
if (!valid) {
|
||||
return false
|
||||
}
|
||||
this.loading = true
|
||||
|
||||
const method = this.mode === 'add' ? this.$API.sys_doc.createContent : this.$API.sys_doc.editContent
|
||||
try {
|
||||
const res = await method.post(this.form)
|
||||
this.$emit('success', res.data, this.mode)
|
||||
this.visible = false
|
||||
this.$message.success(this.$t('操作成功'))
|
||||
} catch {}
|
||||
this.loading = false
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.$emit('mounted')
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.editor {
|
||||
width: 100%;
|
||||
height: 50rem;
|
||||
}
|
||||
</style>
|
84
src/frontend/admin/src/views/sys/doc/save.vue
Normal file
84
src/frontend/admin/src/views/sys/doc/save.vue
Normal file
@ -0,0 +1,84 @@
|
||||
<template>
|
||||
<sc-dialog v-model="visible" :title="`${titleMap[mode]}:${form?.id ?? '...'}`" @closed="$emit('closed')" destroy-on-close>
|
||||
<el-form v-loading="loading" :model="form" :rules="rules" label-width="10rem" ref="dialogForm">
|
||||
<el-form-item :label="$t('文档分类名称')" prop="name">
|
||||
<el-input v-model="form.name" :placeholder="$t('文档分类名称')" clearable></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('文档分类编码')" prop="code">
|
||||
<el-input v-model="form.code" :placeholder="$t('文档分类编码')" clearable></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('父路径')" prop="parentId">
|
||||
<catalog-select v-model="form.parentId" class="w100p" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="(visible = false)">{{ $t('取消') }}</el-button>
|
||||
<el-button v-if="mode !== 'view'" :disabled="loading" :loading="loading" @click="submit" type="primary">{{ $t('保存') }}</el-button>
|
||||
</template>
|
||||
</sc-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
const catalogSelect = defineAsyncComponent(() => import('./components/catalog-select.vue'))
|
||||
export default {
|
||||
components: { catalogSelect },
|
||||
data() {
|
||||
return {
|
||||
//表单数据
|
||||
form: {},
|
||||
loading: true,
|
||||
mode: 'add',
|
||||
//验证规则
|
||||
rules: {
|
||||
code: [{ required: true, message: '请输入文档分类编码' }],
|
||||
name: [{ required: true, message: '请输入文档分类名称' }],
|
||||
},
|
||||
titleMap: {
|
||||
add: this.$t('新增文档分类'),
|
||||
edit: this.$t('编辑文档分类'),
|
||||
},
|
||||
visible: false,
|
||||
}
|
||||
},
|
||||
emits: ['success', 'closed', 'mounted'],
|
||||
methods: {
|
||||
//显示
|
||||
async open(data) {
|
||||
this.visible = true
|
||||
this.loading = true
|
||||
this.mode = data.mode
|
||||
this.form.parentId = data.data?.catalogId
|
||||
this.form.code = data.data?.code
|
||||
if (data.row?.id) {
|
||||
const res = await this.$API.sys_doc.getCatalog.post({ id: data.row.id })
|
||||
Object.assign(this.form, res.data)
|
||||
}
|
||||
this.loading = false
|
||||
return this
|
||||
},
|
||||
|
||||
//表单提交方法
|
||||
async submit() {
|
||||
const valid = await this.$refs.dialogForm.validate().catch(() => {})
|
||||
if (!valid) {
|
||||
return false
|
||||
}
|
||||
this.loading = true
|
||||
const method = this.mode === 'add' ? this.$API.sys_doc.createCatalog : this.$API.sys_doc.editCatalog
|
||||
try {
|
||||
const res = await method.post(this.form)
|
||||
this.$emit('success', res.data, this.mode)
|
||||
this.visible = false
|
||||
this.$message.success(this.$t('操作成功'))
|
||||
} catch {}
|
||||
this.loading = false
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.$emit('mounted')
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
@ -70,7 +70,7 @@
|
||||
ref="search" />
|
||||
</div>
|
||||
<div class="right-panel">
|
||||
<el-button @click="this.dialog.save = { mode: 'add' }" icon="el-icon-plus" type="primary"></el-button>
|
||||
<el-button @click="(this.dialog.save = { mode: 'add' })" icon="el-icon-plus" type="primary"></el-button>
|
||||
<na-button-bulk-del :api="$API.sys_job.bulkDelete" :vue="this" />
|
||||
<el-dropdown v-show="this.selection.length > 0">
|
||||
<el-button type="primary">
|
||||
@ -223,7 +223,7 @@
|
||||
|
||||
<save-dialog
|
||||
v-if="dialog.save"
|
||||
@closed="dialog.save = null"
|
||||
@closed="(dialog.save = null)"
|
||||
@mounted="$refs.saveDialog.open(dialog.save)"
|
||||
@success="(data, mode) => table.handleUpdate($refs.table, data, mode)"
|
||||
ref="saveDialog"></save-dialog>
|
||||
|
@ -45,7 +45,7 @@
|
||||
:theme="this.$TOOL.data.get('APP_SET_DARK') || this.$CONFIG.APP_SET_DARK ? 'github_dark' : 'github'"
|
||||
lang="json"
|
||||
style="height: 10rem; width: 100%" />
|
||||
<el-button @click="form.requestHeader = jsonFormat(form.requestHeader)" type="text">{{ $t('JSON 格式化') }}</el-button>
|
||||
<el-button @click="(form.requestHeader = jsonFormat(form.requestHeader))" type="text">{{ $t('JSON 格式化') }}</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('请求体')" prop="requestBody">
|
||||
<v-ace-editor
|
||||
@ -53,7 +53,7 @@
|
||||
:theme="this.$TOOL.data.get('APP_SET_DARK') || this.$CONFIG.APP_SET_DARK ? 'github_dark' : 'github'"
|
||||
lang="json"
|
||||
style="height: 15rem; width: 100%" />
|
||||
<el-button @click="form.requestBody = jsonFormat(form.requestBody)" type="text">{{ $t('JSON 格式化') }}</el-button>
|
||||
<el-button @click="(form.requestBody = jsonFormat(form.requestBody))" type="text">{{ $t('JSON 格式化') }}</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('请求的网络地址')" prop="requestUrl">
|
||||
<el-input v-model="form.requestUrl" clearable />
|
||||
@ -121,7 +121,7 @@
|
||||
</el-tabs>
|
||||
|
||||
<template #footer>
|
||||
<el-button @click="visible = false">{{ $t('取消') }}</el-button>
|
||||
<el-button @click="(visible = false)">{{ $t('取消') }}</el-button>
|
||||
<el-button v-if="mode !== 'view'" :disabled="loading" :loading="loading" @click="submit" type="primary">{{ $t('保存') }}</el-button>
|
||||
</template>
|
||||
</sc-dialog>
|
||||
|
@ -135,14 +135,14 @@
|
||||
|
||||
<save-dialog
|
||||
v-if="dialog.save"
|
||||
@closed="dialog.save = null"
|
||||
@closed="(dialog.save = null)"
|
||||
@mounted="$refs.saveDialog.open(dialog.save)"
|
||||
@success="(data, mode) => table.handleUpdate($refs.table, data, mode)"
|
||||
ref="saveDialog"></save-dialog>
|
||||
|
||||
<job-dialog
|
||||
v-if="dialog.job"
|
||||
@closed="dialog.job = null"
|
||||
@closed="(dialog.job = null)"
|
||||
@mounted="$refs.jobDialog.open(dialog.job)"
|
||||
@success="(data, mode) => table.handleUpdate($refs.table, data, mode)"
|
||||
ref="jobDialog"></job-dialog>
|
||||
|
@ -39,7 +39,7 @@
|
||||
</el-tabs>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="visible = false">{{ $t('取消') }}</el-button>
|
||||
<el-button @click="(visible = false)">{{ $t('取消') }}</el-button>
|
||||
</template>
|
||||
</sc-dialog>
|
||||
</template>
|
||||
|
@ -182,7 +182,7 @@
|
||||
<na-info v-if="dialog.info" ref="info"></na-info>
|
||||
<save-dialog
|
||||
v-if="dialog.save"
|
||||
@closed="dialog.save = null"
|
||||
@closed="(dialog.save = null)"
|
||||
@mounted="$refs.saveDialog.open(dialog.save)"
|
||||
@success="(data, mode) => table.handleUpdate($refs.table, data, mode)"
|
||||
ref="saveDialog"></save-dialog>
|
||||
|
@ -47,7 +47,7 @@
|
||||
ref="search" />
|
||||
</div>
|
||||
<div class="right-panel">
|
||||
<el-button @click="this.dialog.save = { mode: 'add' }" icon="el-icon-plus" type="primary"></el-button>
|
||||
<el-button @click="(this.dialog.save = { mode: 'add' })" icon="el-icon-plus" type="primary"></el-button>
|
||||
<na-button-bulk-del :api="$API.sys_sitemsg.bulkDelete" :vue="this" />
|
||||
</div>
|
||||
</el-header>
|
||||
@ -105,7 +105,7 @@
|
||||
|
||||
<save-dialog
|
||||
v-if="dialog.save"
|
||||
@closed="dialog.save = null"
|
||||
@closed="(dialog.save = null)"
|
||||
@mounted="$refs.saveDialog.open(dialog.save)"
|
||||
@success="(data, mode) => table.handleUpdate($refs.table, data, mode)"
|
||||
ref="saveDialog"></save-dialog>
|
||||
|
@ -65,7 +65,7 @@
|
||||
</el-tabs>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="visible = false">{{ $t('取消') }}</el-button>
|
||||
<el-button @click="(visible = false)">{{ $t('取消') }}</el-button>
|
||||
<el-button v-if="mode !== 'view'" :disabled="loading" :loading="loading" @click="submit" type="primary">{{ $t('保存') }}</el-button>
|
||||
</template>
|
||||
</sc-dialog>
|
||||
|
@ -64,7 +64,7 @@
|
||||
ref="search" />
|
||||
</div>
|
||||
<div class="right-panel">
|
||||
<el-button @click="this.dialog.save = { mode: 'add' }" icon="el-icon-plus" type="primary"></el-button>
|
||||
<el-button @click="(this.dialog.save = { mode: 'add' })" icon="el-icon-plus" type="primary"></el-button>
|
||||
<na-button-bulk-del :api="$API.sys_role.bulkDelete" :vue="this" />
|
||||
<el-dropdown v-show="this.selection.length > 0">
|
||||
<el-button type="primary">
|
||||
@ -159,7 +159,7 @@
|
||||
|
||||
<save-dialog
|
||||
v-if="dialog.save"
|
||||
@closed="dialog.save = null"
|
||||
@closed="(dialog.save = null)"
|
||||
@mounted="$refs.saveDialog.open(dialog.save)"
|
||||
@success="(data, mode) => table.handleUpdate($refs.table, data, mode)"
|
||||
ref="saveDialog"></save-dialog>
|
||||
|
@ -80,7 +80,7 @@
|
||||
:theme="this.$TOOL.data.get('APP_SET_DARK') || this.$CONFIG.APP_SET_DARK ? 'github_dark' : 'github'"
|
||||
lang="json"
|
||||
style="height: 30rem; width: 100%" />
|
||||
<el-button @click="form.dashboardLayout = jsonFormat(form.dashboardLayout)" type="text">{{
|
||||
<el-button @click="(form.dashboardLayout = jsonFormat(form.dashboardLayout))" type="text">{{
|
||||
$t('JSON 格式化')
|
||||
}}</el-button>
|
||||
</el-form-item>
|
||||
@ -101,7 +101,7 @@
|
||||
</el-tabs>
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button @click="visible = false">{{ $t('取消') }}</el-button>
|
||||
<el-button @click="(visible = false)">{{ $t('取消') }}</el-button>
|
||||
<el-button v-if="mode !== 'view'" :disabled="loading" :loading="loading" @click="submit" type="primary">{{ $t('保存') }}</el-button>
|
||||
</template>
|
||||
</sc-dialog>
|
||||
|
@ -62,7 +62,7 @@
|
||||
ref="search" />
|
||||
</div>
|
||||
<div class="right-panel">
|
||||
<el-button @click="this.dialog.save = { mode: 'add' }" icon="el-icon-plus" type="primary"></el-button>
|
||||
<el-button @click="(this.dialog.save = { mode: 'add' })" icon="el-icon-plus" type="primary"></el-button>
|
||||
<el-dropdown v-show="this.selection.length > 0">
|
||||
<el-button type="primary">
|
||||
{{ $t('批量操作') }}
|
||||
@ -132,18 +132,18 @@
|
||||
|
||||
<save-dialog
|
||||
v-if="dialog.save"
|
||||
@closed="dialog.save = null"
|
||||
@closed="(dialog.save = null)"
|
||||
@mounted="$refs.saveDialog.open(dialog.save)"
|
||||
@success="(data, mode) => table.handleUpdate($refs.table, data, mode)"
|
||||
ref="saveDialog"></save-dialog>
|
||||
<role-save-dialog
|
||||
v-if="dialog.roleSave"
|
||||
@closed="dialog.roleSave = null"
|
||||
@closed="(dialog.roleSave = null)"
|
||||
@mounted="$refs.roleSaveDialog.open(dialog.roleSave)"
|
||||
ref="roleSaveDialog"></role-save-dialog>
|
||||
<dept-save-dialog
|
||||
v-if="dialog.deptSave"
|
||||
@closed="dialog.deptSave = null"
|
||||
@closed="(dialog.deptSave = null)"
|
||||
@mounted="$refs.deptSaveDialog.open(dialog.deptSave)"
|
||||
ref="deptSaveDialog"></dept-save-dialog>
|
||||
</template>
|
||||
|
@ -46,7 +46,7 @@
|
||||
maxlength="16"
|
||||
oninput="value=value.replace(/[^\w]/g,'')"
|
||||
placeholder="8位以上数字字母组合"></el-input>
|
||||
<el-button @click="form.passwordText = '1234qwer'">{{ $t('初始密码') }}</el-button>
|
||||
<el-button @click="(form.passwordText = '1234qwer')">{{ $t('初始密码') }}</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
@ -249,7 +249,7 @@
|
||||
</el-tabs>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="visible = false">{{ $t('取消') }}</el-button>
|
||||
<el-button @click="(visible = false)">{{ $t('取消') }}</el-button>
|
||||
<el-button v-if="mode !== 'view'" :disabled="loading" :loading="loading" @click="submit" type="primary">{{ $t('保存') }}</el-button>
|
||||
</template>
|
||||
</sc-dialog>
|
||||
|
Loading…
x
Reference in New Issue
Block a user