Merge remote-tracking branch 'source/main' into main
This commit is contained in:
commit
8ab703ff8b
@ -17,27 +17,27 @@
|
||||
<PackageReference Include="AngleSharp" Version="1.1.2" />
|
||||
<PackageReference Include="AspectCore.Extensions.Reflection" Version="2.4.0" />
|
||||
<PackageReference Include="AspNetCoreRateLimit" Version="5.0.0" />
|
||||
<PackageReference Include="Elastic.Clients.Elasticsearch" Version="8.14.3" />
|
||||
<PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.4.2" />
|
||||
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.4.2" />
|
||||
<PackageReference Include="Furion.Pure" Version="4.9.4.2" />
|
||||
<PackageReference Include="Elastic.Clients.Elasticsearch" Version="8.14.4" />
|
||||
<PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.4.3" />
|
||||
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.4.3" />
|
||||
<PackageReference Include="Furion.Pure" Version="4.9.4.3" />
|
||||
<PackageReference Include="IPTools.China" Version="1.6.0" />
|
||||
<PackageReference Include="IPTools.International" Version="1.6.0" />
|
||||
<PackageReference Include="Magicodes.IE.Excel" Version="2.7.5.1" />
|
||||
<PackageReference Include="Magicodes.IE.Pdf" Version="2.7.5.1" />
|
||||
<PackageReference Include="Magicodes.IE.Word" Version="2.7.5.1" />
|
||||
<PackageReference Include="MailKit" Version="4.6.0" />
|
||||
<PackageReference Include="NewLife.Redis" Version="5.7.2024.602" />
|
||||
<PackageReference Include="MailKit" Version="4.7.0" />
|
||||
<PackageReference Include="NewLife.Redis" Version="5.7.2024.701" />
|
||||
<PackageReference Include="Novell.Directory.Ldap.NETStandard" Version="3.6.0" />
|
||||
<PackageReference Include="QRCoder" Version="1.5.1" />
|
||||
<PackageReference Include="QRCoder" Version="1.6.0" />
|
||||
<PackageReference Include="RabbitMQ.Client" Version="6.8.1" />
|
||||
<PackageReference Include="SixLabors.ImageSharp.Web" Version="3.1.2" />
|
||||
<PackageReference Include="SKIT.FlurlHttpClient.Wechat.Api" Version="3.3.0" />
|
||||
<PackageReference Include="SKIT.FlurlHttpClient.Wechat.TenpayV3" Version="3.5.0" />
|
||||
<PackageReference Include="SqlSugarCore" Version="5.1.4.160" />
|
||||
<PackageReference Include="SSH.NET" Version="2024.0.0" />
|
||||
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.4.2" />
|
||||
<PackageReference Include="TencentCloudSDK.Sms" Version="3.0.1036" />
|
||||
<PackageReference Include="SSH.NET" Version="2024.1.0" />
|
||||
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.4.3" />
|
||||
<PackageReference Include="TencentCloudSDK.Sms" Version="3.0.1038" />
|
||||
<PackageReference Include="UAParser" Version="3.1.47" />
|
||||
<PackageReference Include="Yitter.IdGenerator" Version="1.0.14" />
|
||||
</ItemGroup>
|
||||
|
||||
@ -1,41 +0,0 @@
|
||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||
//
|
||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||
//
|
||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||
|
||||
using System.Net;
|
||||
|
||||
namespace Admin.NET.Core;
|
||||
|
||||
/// <summary>
|
||||
/// HttpContext拓展
|
||||
/// </summary>
|
||||
[SuppressSniffer]
|
||||
public static partial class HttpContextExtension
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取客户端真实 IP 地址
|
||||
/// </summary>
|
||||
/// <returns>bool</returns>
|
||||
public static string GetRemoteIp(this HttpContext httpContext)
|
||||
{
|
||||
var ip = string.Empty;
|
||||
try
|
||||
{
|
||||
// 从 X-Forwarded-For 头获取 IP
|
||||
ip = httpContext.Request.Headers["X-Forwarded-For"];
|
||||
if (string.IsNullOrEmpty(ip))
|
||||
{
|
||||
ip = httpContext.GetRemoteIpAddressToIPv4();
|
||||
}
|
||||
// 验证 IP 地址有效性
|
||||
if (!IPAddress.TryParse(ip, out _))
|
||||
{
|
||||
ip = null;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
return ip;
|
||||
}
|
||||
}
|
||||
@ -167,6 +167,13 @@ public class SysMenuSeedData : ISqlSugarEntitySeedData<SysMenu>
|
||||
|
||||
new SysMenu{ Id=1310000000431, Pid=1310000000301, Title="系统配置", Path="/platform/infoSetting", Name="sysInfoSetting", Component="/system/infoSetting/index", Icon="ele-Setting", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=220 },
|
||||
|
||||
new SysMenu{ Id=1310000000441, Pid=1310000000301, Title="微信支付", Path="/platform/wechatpay", Name="sysWechatPay", Component="/system/weChatPay/index", Icon="ele-Coin", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=230 },
|
||||
new SysMenu{ Id=1310000000442, Pid=1310000000441, Title="微信支付下单Native", Permission="sysWechatPay:payTransactionNative", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
|
||||
new SysMenu{ Id=1310000000443, Pid=1310000000441, Title="查询退款信息", Permission="sysWechatPay:listRefund", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
|
||||
new SysMenu{ Id=1310000000444, Pid=1310000000441, Title="获取支付订单详情(本地库)", Permission="sysWechatPay:payInfo", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
|
||||
new SysMenu{ Id=1310000000445, Pid=1310000000441, Title="获取支付订单详情(微信接口)", Permission="sysWechatPay:payInfoFromWechat", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
|
||||
new SysMenu{ Id=1310000000446, Pid=1310000000441, Title="退款申请", Permission="sysWechatPay:refundDomestic", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
|
||||
|
||||
new SysMenu{ Id=1310000000501, Pid=0, Title="日志管理", Path="/log", Name="log", Component="Layout", Icon="ele-DocumentCopy", Type=MenuTypeEnum.Dir, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=12000 },
|
||||
new SysMenu{ Id=1310000000511, Pid=1310000000501, Title="访问日志", Path="/log/vislog", Name="sysVisLog", Component="/system/log/vislog/index", Icon="ele-Document", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
|
||||
new SysMenu{ Id=1310000000512, Pid=1310000000511, Title="查询", Permission="sysVislog:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
|
||||
|
||||
@ -238,7 +238,7 @@ public class SysAuthService : IDynamicApiController, ITransient
|
||||
// ke.global.setAllHeader('Authorization', 'Bearer ' + ke.response.headers['access-token']);
|
||||
|
||||
// 更新用户登录信息
|
||||
user.LastLoginIp = _httpContextAccessor.HttpContext.GetRemoteIp();
|
||||
user.LastLoginIp = _httpContextAccessor.HttpContext.GetRemoteIpAddressToIPv4(true);
|
||||
(user.LastLoginAddress, double? longitude, double? latitude) = CommonUtil.GetIpAddress(user.LastLoginIp);
|
||||
user.LastLoginTime = DateTime.Now;
|
||||
user.LastLoginDevice = CommonUtil.GetClientDeviceInfo(_httpContextAccessor.HttpContext?.Request?.Headers?.UserAgent);
|
||||
|
||||
@ -64,33 +64,6 @@ public class SysFileService : IDynamicApiController, ITransient
|
||||
return await HandleUploadFile(input.File, input.Path, fileType: input.FileType);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 上传文件Base64
|
||||
/// </summary>
|
||||
/// <param name="strBase64"></param>
|
||||
/// <param name="fileName"></param>
|
||||
/// <param name="contentType"></param>
|
||||
/// <param name="path"></param>
|
||||
/// <param name="fileType"></param>
|
||||
/// <returns></returns>
|
||||
private async Task<SysFile> UploadFileFromBase64(string strBase64, string fileName, string contentType, string? path, string? fileType)
|
||||
{
|
||||
byte[] fileData = Convert.FromBase64String(strBase64);
|
||||
var ms = new MemoryStream();
|
||||
ms.Write(fileData);
|
||||
ms.Seek(0, SeekOrigin.Begin);
|
||||
if (string.IsNullOrEmpty(fileName))
|
||||
fileName = $"{YitIdHelper.NextId()}.jpg";
|
||||
if (string.IsNullOrEmpty(contentType))
|
||||
contentType = "image/jpg";
|
||||
IFormFile formFile = new FormFile(ms, 0, fileData.Length, "file", fileName)
|
||||
{
|
||||
Headers = new HeaderDictionary(),
|
||||
ContentType = contentType
|
||||
};
|
||||
return await UploadFile(new FileUploadInput { File = formFile, Path = path, FileType = fileType });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 上传文件Base64 🔖
|
||||
/// </summary>
|
||||
@ -99,7 +72,20 @@ public class SysFileService : IDynamicApiController, ITransient
|
||||
[DisplayName("上传文件Base64")]
|
||||
public async Task<SysFile> UploadFileFromBase64(UploadFileFromBase64Input input)
|
||||
{
|
||||
return await UploadFileFromBase64(input.FileDataBase64, input.FileName, input.ContentType, input.Path, input.FileType);
|
||||
byte[] fileData = Convert.FromBase64String(input.FileDataBase64);
|
||||
var ms = new MemoryStream();
|
||||
ms.Write(fileData);
|
||||
ms.Seek(0, SeekOrigin.Begin);
|
||||
if (string.IsNullOrEmpty(input.FileName))
|
||||
input.FileName = $"{YitIdHelper.NextId()}.jpg";
|
||||
if (string.IsNullOrEmpty(input.ContentType))
|
||||
input.ContentType = "image/jpg";
|
||||
IFormFile formFile = new FormFile(ms, 0, fileData.Length, "file", input.FileName)
|
||||
{
|
||||
Headers = new HeaderDictionary(),
|
||||
ContentType = input.ContentType
|
||||
};
|
||||
return await UploadFile(new FileUploadInput { File = formFile, Path = input.Path, FileType = input.FileType });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -335,7 +321,7 @@ public class SysFileService : IDynamicApiController, ITransient
|
||||
|
||||
// 获取文件后缀
|
||||
var suffix = Path.GetExtension(file.FileName).ToLower(); // 后缀
|
||||
if (string.IsNullOrWhiteSpace(suffix))
|
||||
if (!string.IsNullOrWhiteSpace(suffix))
|
||||
{
|
||||
var contentTypeProvider = FS.GetFileExtensionContentTypeProvider();
|
||||
suffix = contentTypeProvider.Mappings.FirstOrDefault(u => u.Value == file.ContentType).Key;
|
||||
|
||||
@ -51,7 +51,7 @@ public class JobClusterServer : IJobClusterServer
|
||||
|
||||
try
|
||||
{
|
||||
ICache _cache = App.GetRequiredService<ICache>();
|
||||
ICache _cache = App.GetRequiredService<ICacheProvider>().Cache;
|
||||
// 使用分布式锁
|
||||
using (_cache.AcquireLock("lock:JobClusterServer:WaitingForAsync", 1000))
|
||||
{
|
||||
|
||||
@ -168,8 +168,11 @@ public class Startup : AppStartup
|
||||
services.AddViewEngine();
|
||||
|
||||
// 即时通讯
|
||||
services.AddSignalR(SetNewtonsoftJsonSetting);
|
||||
//services.AddSingleton<IUserIdProvider, UserIdProvider>();
|
||||
services.AddSignalR(options =>
|
||||
{
|
||||
options.KeepAliveInterval = TimeSpan.FromSeconds(5);
|
||||
}).AddNewtonsoftJsonProtocol(options => SetNewtonsoftJsonSetting(options.PayloadSerializerSettings));
|
||||
|
||||
// 系统日志
|
||||
services.AddLoggingSetup();
|
||||
|
||||
@ -199,6 +199,7 @@ if(@column.EffectType == "fk" && (@column.WhetherAddUpdate == "Y" || column.Quer
|
||||
@:/// </summary>
|
||||
@:/// <returns></returns>
|
||||
@:[ApiDescriptionSettings(Name = "@(@column.FkEntityName)@(@column.PropertyName)Dropdown"), HttpGet]
|
||||
@:[DisplayName("获取@(@column.ColumnComment)列表")]
|
||||
@:public async Task<dynamic> @(@column.FkEntityName)@(@column.PropertyName)Dropdown()
|
||||
@:{
|
||||
@:return await _rep.Context.Queryable<@(@column.FkEntityName)>()
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
@{
|
||||
@{
|
||||
var pkField = Model.TableField.Where(c => c.ColumnKey == "True").FirstOrDefault();
|
||||
string pkFieldName = null;
|
||||
if(pkField != null && !string.IsNullOrEmpty(pkField.PropertyName))
|
||||
@ -192,7 +192,7 @@
|
||||
v-model:page-size="tableParams.pageSize"
|
||||
:total="tableParams.total"
|
||||
:page-sizes="[10, 20, 50, 100, 200, 500]"
|
||||
small=""
|
||||
size="small"
|
||||
background=""
|
||||
@@size-change="handleSizeChange"
|
||||
@@current-change="handleCurrentChange"
|
||||
|
||||
@ -49,7 +49,7 @@
|
||||
"print-js": "^1.6.0",
|
||||
"push.js": "^1.0.12",
|
||||
"qrcodejs2-fixes": "^0.0.2",
|
||||
"qs": "^6.12.1",
|
||||
"qs": "^6.12.2",
|
||||
"relation-graph": "^2.2.1",
|
||||
"screenfull": "^6.0.2",
|
||||
"sm-crypto-v2": "^1.9.0",
|
||||
@ -68,11 +68,11 @@
|
||||
"vue-signature-pad": "^3.0.2",
|
||||
"vue3-tree-org": "^4.2.2",
|
||||
"vuedraggable": "4.0.3",
|
||||
"vxe-pc-ui": "^4.0.42",
|
||||
"vxe-table": "^4.7.39",
|
||||
"vxe-pc-ui": "^4.0.44",
|
||||
"vxe-table": "^4.7.40",
|
||||
"vxe-table-plugin-element": "^4.0.4",
|
||||
"vxe-table-plugin-export-xlsx": "^4.0.4",
|
||||
"xe-utils": "^3.5.27",
|
||||
"xe-utils": "^3.5.28",
|
||||
"xlsx-js-style": "^1.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
@ -81,8 +81,8 @@
|
||||
"@types/node": "^20.14.9",
|
||||
"@types/nprogress": "^0.2.3",
|
||||
"@types/sortablejs": "^1.15.8",
|
||||
"@typescript-eslint/eslint-plugin": "^7.14.1",
|
||||
"@typescript-eslint/parser": "^7.14.1",
|
||||
"@typescript-eslint/eslint-plugin": "^7.15.0",
|
||||
"@typescript-eslint/parser": "^7.15.0",
|
||||
"@vitejs/plugin-vue": "^5.0.5",
|
||||
"@vitejs/plugin-vue-jsx": "^4.0.0",
|
||||
"@vue/compiler-sfc": "^3.4.31",
|
||||
@ -94,10 +94,10 @@
|
||||
"rollup-plugin-visualizer": "^5.12.0",
|
||||
"sass": "^1.77.6",
|
||||
"terser": "^5.31.1",
|
||||
"typescript": "^5.5.2",
|
||||
"typescript": "^5.5.3",
|
||||
"vite": "^5.3.2",
|
||||
"vite-plugin-cdn-import": "^1.0.1",
|
||||
"vite-plugin-compression2": "^1.1.1",
|
||||
"vite-plugin-compression2": "^1.1.2",
|
||||
"vite-plugin-vue-setup-extend": "^0.4.0",
|
||||
"vue-eslint-parser": "^9.4.3"
|
||||
},
|
||||
|
||||
17
Web/src/views/system/cache/index.vue
vendored
17
Web/src/views/system/cache/index.vue
vendored
@ -1,9 +1,9 @@
|
||||
<template>
|
||||
<div class="sys-cache-container">
|
||||
<NoticeBar text="系统缓存数据管理,请慎重操作!" leftIcon="iconfont icon-tongzhi2" background="var(--el-color-primary-light-9)" color="var(--el-color-primary)" />
|
||||
<el-row :gutter="8" style="width: 100%">
|
||||
<el-row :gutter="5" class="mt5">
|
||||
<el-col :span="8" :xs="24">
|
||||
<el-card shadow="hover" header="缓存列表" v-loading="state.loading" class="mt8">
|
||||
<el-card shadow="hover" header="缓存列表" style="height: calc(100vh - 156px)" v-loading="state.loading" body-style="height:100%;overflow:auto;padding:5px 5px 50px 5px;">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>缓存列表</span>
|
||||
@ -21,12 +21,11 @@
|
||||
highlight-current
|
||||
check-strictly
|
||||
default-expand-all
|
||||
accordion
|
||||
/>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="16" :xs="24">
|
||||
<el-card shadow="hover" header="缓存数据" v-loading="state.loading1" class="mt8">
|
||||
<el-card shadow="hover" header="缓存数据" style="height: calc(100vh - 156px)" v-loading="state.loadingData" body-style="height:calc(100% - 36px);overflow:auto;">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>{{ `缓存数据${state.cacheKey ? `【${state.cacheKey}】` : ''}` }}</span>
|
||||
@ -54,12 +53,13 @@ const treeRef = ref<InstanceType<typeof ElTree>>();
|
||||
const currentNode = ref<any>({});
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
loading1: false,
|
||||
loadingData: false,
|
||||
cacheData: [] as any,
|
||||
cacheValue: undefined as any,
|
||||
cacheKey: undefined,
|
||||
});
|
||||
|
||||
// 页面初始化
|
||||
onMounted(async () => {
|
||||
handleQuery();
|
||||
});
|
||||
@ -122,7 +122,7 @@ const nodeClick = async (node: any) => {
|
||||
if (node.id == 0) return;
|
||||
|
||||
currentNode.value = node;
|
||||
state.loading1 = true;
|
||||
state.loadingData = true;
|
||||
var res = await getAPI(SysCacheApi).apiSysCacheValueKeyGet(node.id);
|
||||
// state.cacheValue = JSON.parse(res.data.result);
|
||||
var result = res.data.result;
|
||||
@ -142,7 +142,7 @@ const nodeClick = async (node: any) => {
|
||||
}
|
||||
|
||||
state.cacheKey = node.id;
|
||||
state.loading1 = false;
|
||||
state.loadingData = false;
|
||||
};
|
||||
</script>
|
||||
|
||||
@ -152,4 +152,7 @@ const nodeClick = async (node: any) => {
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
:deep(.el-card__header) {
|
||||
padding: 6px !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<el-form :model="state.ruleForm" ref="ruleFormRef" label-width="auto">
|
||||
<el-row :gutter="35">
|
||||
<el-row :gutter="10">
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
||||
<el-form-item label="库定位器" prop="configId">
|
||||
<el-select v-model="state.ruleForm.configId" placeholder="库名" filterable @change="dbChanged()" class="w100">
|
||||
@ -258,6 +258,11 @@ const submit = () => {
|
||||
});
|
||||
};
|
||||
|
||||
const isOrNotSelect = () => [
|
||||
{ label: '是', value: 1 },
|
||||
{ label: '否', value: 0 },
|
||||
];
|
||||
|
||||
// 导出对象
|
||||
defineExpose({ openDialog });
|
||||
</script>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="sys-codeGenFk-container">
|
||||
<el-dialog v-model="state.isShowDialog" draggable :close-on-click-modal="false" width="700px" destroy-on-close>
|
||||
<el-dialog v-model="state.isShowDialog" draggable :close-on-click-modal="false" width="700px">
|
||||
<template #header>
|
||||
<div style="color: #fff">
|
||||
<el-icon size="16" style="margin-right: 3px; display: inline; vertical-align: middle"> <ele-Edit /> </el-icon>
|
||||
@ -8,7 +8,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<el-form :model="state.ruleForm" ref="ruleFormRef" label-width="auto">
|
||||
<el-row :gutter="35">
|
||||
<el-row :gutter="10">
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
|
||||
<el-form-item label="库定位器" prop="configId">
|
||||
<el-select clearable v-model="state.ruleForm.configId" placeholder="库名" filterable @change="DbChanged()" class="w100">
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="sys-codeGenConfig-container">
|
||||
<el-dialog v-model="state.isShowDialog" draggable :close-on-click-modal="false" width="1500px">
|
||||
<el-dialog v-model="state.isShowDialog" draggable :close-on-click-modal="false" width="80vw">
|
||||
<template #header>
|
||||
<div style="color: #fff">
|
||||
<el-icon size="16" style="margin-right: 3px; display: inline; vertical-align: middle"> <ele-Edit /> </el-icon>
|
||||
@ -8,9 +8,9 @@
|
||||
</div>
|
||||
</template>
|
||||
<el-table :data="state.tableData" style="width: 100%" v-loading="state.loading" border>
|
||||
<el-table-column type="index" label="序号" width="55" align="center" />
|
||||
<el-table-column prop="propertyName" label="实体属性" width="180" show-overflow-tooltip />
|
||||
<el-table-column prop="columnComment" label="描述" width="180" show-overflow-tooltip>
|
||||
<el-table-column type="index" label="序号" width="50" align="center" />
|
||||
<el-table-column prop="columnName" label="字段" width="160" show-overflow-tooltip />
|
||||
<el-table-column prop="columnComment" label="描述" width="160" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-input v-model="scope.row.columnComment" autocomplete="off" />
|
||||
</template>
|
||||
@ -31,17 +31,17 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="whetherTable" label="列表显示" width="85" align="center" show-overflow-tooltip>
|
||||
<el-table-column prop="whetherTable" label="列表显示" width="70" align="center" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-checkbox v-model="scope.row.whetherTable" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="whetherAddUpdate" label="增改" width="80" align="center" show-overflow-tooltip>
|
||||
<el-table-column prop="whetherAddUpdate" label="增改" width="70" align="center" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-checkbox v-model="scope.row.whetherAddUpdate" :disabled="judgeColumns(scope.row)" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="whetherRequired" label="必填" width="80" align="center" show-overflow-tooltip>
|
||||
<el-table-column prop="whetherRequired" label="必填" width="70" align="center" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-checkbox v-model="scope.row.whetherRequired" :disabled="judgeColumns(scope.row)" />
|
||||
</template>
|
||||
@ -85,6 +85,7 @@
|
||||
<script lang="ts" setup name="sysCodeGenConfig">
|
||||
import { onMounted, onUnmounted, reactive, ref } from 'vue';
|
||||
import mittBus from '/@/utils/mitt';
|
||||
|
||||
import fkDialog from '/@/views/system/codeGen/component/fkDialog.vue';
|
||||
import treeDialog from '/@/views/system/codeGen/component/treeDialog.vue';
|
||||
|
||||
@ -276,18 +277,10 @@ const convertDbType = (dbType: number) => {
|
||||
return result;
|
||||
};
|
||||
|
||||
const isOrNotSelect = () => {
|
||||
return [
|
||||
{
|
||||
label: '是',
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
label: '否',
|
||||
value: 0,
|
||||
},
|
||||
];
|
||||
};
|
||||
const isOrNotSelect = () => [
|
||||
{ label: '是', value: 1 },
|
||||
{ label: '否', value: 0 },
|
||||
];
|
||||
|
||||
// 导出对象
|
||||
defineExpose({ openDialog });
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="sys-codeGenPreview-container">
|
||||
<el-dialog v-model="state.isShowDialog" draggable :close-on-click-modal="false" width="70%">
|
||||
<el-dialog v-model="state.isShowDialog" draggable :close-on-click-modal="false" width="80vw">
|
||||
<template #header>
|
||||
<div style="color: #fff">
|
||||
<el-icon size="16" style="margin-right: 3px; display: inline; vertical-align: middle"> <ele-Edit /> </el-icon>
|
||||
@ -17,7 +17,7 @@
|
||||
</template>
|
||||
</el-segmented>
|
||||
</div>
|
||||
<div ref="monacoEditorRef" style="width: 100%; height: 700px;"></div>
|
||||
<div ref="monacoEditorRef" style="width: 100%; height: 700px; margin-top: 6px"></div>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button icon="ele-Close" @click="cancel">关 闭</el-button>
|
||||
@ -123,11 +123,14 @@ defineExpose({ openDialog });
|
||||
<style scoped>
|
||||
.cs-style .el-segmented {
|
||||
--el-segmented-item-selected-bg-color: #5c2d91;
|
||||
--el-border-radius-base: 6px;
|
||||
}
|
||||
.vue-style .el-segmented {
|
||||
--el-segmented-item-selected-bg-color: #42b883;
|
||||
--el-border-radius-base: 6px;
|
||||
}
|
||||
.js-style .el-segmented {
|
||||
--el-segmented-item-selected-bg-color: #e44d26;
|
||||
--el-border-radius-base: 6px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<el-form :model="state.ruleForm" ref="ruleFormRef" label-width="auto">
|
||||
<el-row :gutter="35">
|
||||
<el-row :gutter="10">
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
|
||||
<el-form-item label="库定位器" prop="configId">
|
||||
<el-select clearable v-model="state.ruleForm.configId" placeholder="库名" filterable @change="DbChanged()" class="w100">
|
||||
|
||||
@ -1,94 +1,108 @@
|
||||
<template>
|
||||
<div class="sys-codeGen-container">
|
||||
<el-card shadow="hover" :body-style="{ paddingBottom: '0' }">
|
||||
<el-form :model="state.queryParams" ref="queryForm" :inline="true">
|
||||
<el-form-item label="业务名">
|
||||
<el-input placeholder="业务名" clearable @keyup.enter="handleQuery" v-model="state.queryParams.busName" />
|
||||
</el-form-item>
|
||||
<el-form-item label="数据库表名">
|
||||
<el-input placeholder="数据库表名" clearable @keyup.enter="handleQuery" v-model="state.queryParams.tableName" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button-group>
|
||||
<el-button type="primary" icon="ele-Search" @click="handleQuery" v-auth="'sysMenu:list'"> 查询 </el-button>
|
||||
<el-button icon="ele-Refresh" @click="resetQuery"> 重置 </el-button>
|
||||
</el-button-group>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="ele-Plus" @click="openAddDialog"> 增加 </el-button>
|
||||
</el-form-item>
|
||||
<div class="sys-codeGen-container" v-loading="options.loading">
|
||||
<el-card shadow="hover" :body-style="{ padding: '5px 5px 0 5px', display: 'flex', width: '100%', height: '100%', alignItems: 'start' }">
|
||||
<el-form :model="state.queryParams" ref="queryForm" :show-message="false" :inlineMessage="true" :label-width="'60px'" style="flex: 1 1 0%">
|
||||
<el-row :gutter="10">
|
||||
<el-col class="mb5" :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
|
||||
<el-form-item label="业务名" prop="busName">
|
||||
<el-input placeholder="业务名" clearable @keyup.enter="handleQuery" v-model="state.queryParams.busName" @keyup.enter.native="handleQuery(true)" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col class="mb5" :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
|
||||
<el-form-item label="数据库表名" prop="tableName">
|
||||
<el-input placeholder="数据库表名" clearable @keyup.enter="handleQuery" v-model="state.queryParams.tableName" @keyup.enter.native="handleQuery(true)" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
|
||||
<el-divider style="height: calc(100% - 5px); margin: 0 10px" direction="vertical" />
|
||||
|
||||
<el-row>
|
||||
<el-col>
|
||||
<el-button-group>
|
||||
<el-button type="primary" icon="ele-Search" @click="handleQuery(true)" :loading="options.loading"> 查询 </el-button>
|
||||
<el-button icon="ele-Refresh" @click="resetQuery" :loading="options.loading"> 重置 </el-button>
|
||||
</el-button-group>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
|
||||
<el-card class="full-table" shadow="hover" style="margin-top: 5px">
|
||||
<el-table :data="state.tableData" style="width: 100%" v-loading="state.loading" border>
|
||||
<el-table-column type="index" label="序号" width="55" align="center" />
|
||||
<el-table-column prop="configId" label="库定位器" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="tableName" label="表名称" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="busName" label="业务名" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="nameSpace" label="命名空间" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="authorName" label="作者姓名" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="generateType" label="生成方式" align="center" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-tag v-if="scope.row.generateType == 100"> 下载压缩包 </el-tag>
|
||||
<el-tag v-else-if="scope.row.generateType == 111"> 下载压缩包(前端) </el-tag>
|
||||
<el-tag v-else-if="scope.row.generateType == 121"> 下载压缩包(后端) </el-tag>
|
||||
<el-tag v-else-if="scope.row.generateType == 211"> 生成到本项目(前端) </el-tag>
|
||||
<el-tag v-else-if="scope.row.generateType == 221"> 生成到本项目(后端) </el-tag>
|
||||
<el-tag type="danger" v-else> 生成到本项目 </el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="350" fixed="right" align="center" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-button icon="ele-Position" size="small" text type="primary" @click="handleGenerate(scope.row)">开始生成</el-button>
|
||||
<el-button icon="ele-View" size="small" text type="primary" @click="handlePreview(scope.row)">预览</el-button>
|
||||
<el-button icon="ele-Setting" size="small" text type="primary" @click="openConfigDialog(scope.row)">配置</el-button>
|
||||
<el-button icon="ele-Edit" size="small" text type="primary" @click="openEditDialog(scope.row)">编辑</el-button>
|
||||
<el-button icon="ele-Delete" size="small" text type="danger" @click="deleConfig(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
v-model:currentPage="state.tableParams.page"
|
||||
v-model:page-size="state.tableParams.pageSize"
|
||||
:total="state.tableParams.total"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
small
|
||||
background
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
/>
|
||||
<vxe-grid ref="xGrid" class="xGrid-style" v-bind="options" @sort-change="sortChange">
|
||||
<template #toolbar_buttons>
|
||||
<el-button type="primary" icon="ele-Plus" @click="handleAdd"> 新增 </el-button>
|
||||
</template>
|
||||
<template #toolbar_tools> </template>
|
||||
<template #empty>
|
||||
<el-empty :image-size="200" />
|
||||
</template>
|
||||
<template #row_generateType="{ row }">
|
||||
<el-tag v-if="row.generateType == 100"> 下载压缩包 </el-tag>
|
||||
<el-tag v-else-if="row.generateType == 111"> 下载压缩包(前端) </el-tag>
|
||||
<el-tag v-else-if="row.generateType == 121"> 下载压缩包(后端) </el-tag>
|
||||
<el-tag v-else-if="row.generateType == 211"> 生成到本项目(前端) </el-tag>
|
||||
<el-tag v-else-if="row.generateType == 221"> 生成到本项目(后端) </el-tag>
|
||||
<el-tag type="danger" v-else> 生成到本项目 </el-tag>
|
||||
</template>
|
||||
<template #row_buttons="{ row }">
|
||||
<el-tooltip content="编辑" placement="top">
|
||||
<el-button icon="ele-Edit" text type="primary" @click="handleEdit(row)"> </el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="删除" placement="top">
|
||||
<el-button icon="ele-Delete" text type="danger" @click="handleDelete(row)"> </el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="配置" placement="top">
|
||||
<el-button icon="ele-Setting" text type="danger" @click="handleConfig(row)">配置</el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="预览" placement="top">
|
||||
<el-button icon="ele-Camera" text type="primary" @click="handlePreview(row)">预览</el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="开始生成" placement="top">
|
||||
<el-button icon="ele-Cpu" text type="primary" @click="handleGenerate(row)">生成</el-button>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
<template #pager>
|
||||
<vxe-pager
|
||||
:loading="options.loading"
|
||||
v-model:current-page="state.tableParams.page"
|
||||
v-model:page-size="state.tableParams.pageSize"
|
||||
:total="state.tableParams.total"
|
||||
@page-change="pageChange"
|
||||
/>
|
||||
</template>
|
||||
</vxe-grid>
|
||||
</el-card>
|
||||
|
||||
<EditCodeGenDialog :title="state.editMenuTitle" ref="EditCodeGenRef" @handleQuery="handleQuery" :application-namespaces="state.applicationNamespaces" />
|
||||
<EditCodeGenDialog :title="state.title" ref="EditCodeGenRef" @handleQuery="handleQuery" :application-namespaces="state.applicationNamespaces" />
|
||||
<CodeConfigDialog ref="CodeConfigRef" @handleQuery="handleQuery" />
|
||||
<PreviewDialog :title="state.editMenuTitle" ref="PreviewRef" />
|
||||
<PreviewDialog :title="state.title" ref="PreviewRef" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="sysCodeGen">
|
||||
import { onMounted, reactive, ref, defineAsyncComponent } from 'vue';
|
||||
import { ElMessageBox, ElMessage } from 'element-plus';
|
||||
import { auth } from '/@/utils/authFunction';
|
||||
import { VxeGridInstance, VxePagerEvents, VxePagerDefines } from 'vxe-table';
|
||||
import { useVxeTable } from '/@/hooks/vxeTableOptionsHook';
|
||||
import { downloadByUrl } from '/@/utils/download';
|
||||
|
||||
import EditCodeGenDialog from './component/editCodeGenDialog.vue';
|
||||
import CodeConfigDialog from './component/genConfigDialog.vue';
|
||||
import { downloadByUrl } from '/@/utils/download';
|
||||
|
||||
import { getAPI } from '/@/utils/axios-utils';
|
||||
import { SysCodeGenApi } from '/@/api-services/api';
|
||||
import { SysCodeGen } from '/@/api-services/models';
|
||||
|
||||
const PreviewDialog = defineAsyncComponent(() => import('./component/previewDialog.vue'));
|
||||
|
||||
const xGrid = ref<VxeGridInstance>();
|
||||
const EditCodeGenRef = ref<InstanceType<typeof EditCodeGenDialog>>();
|
||||
const CodeConfigRef = ref<InstanceType<typeof CodeConfigDialog>>();
|
||||
const PreviewRef = ref<InstanceType<typeof PreviewDialog>>();
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
loading1: false,
|
||||
dbData: [] as any,
|
||||
configId: '',
|
||||
tableData: [] as Array<SysCodeGen>,
|
||||
tableName: '',
|
||||
queryParams: {
|
||||
name: undefined,
|
||||
@ -98,56 +112,88 @@ const state = reactive({
|
||||
},
|
||||
tableParams: {
|
||||
page: 1,
|
||||
pageSize: 10,
|
||||
pageSize: 50,
|
||||
field: 'id', // 默认的排序字段
|
||||
order: 'aes', // 排序方向
|
||||
descStr: 'desc', // 降序排序的关键字符
|
||||
total: 0 as any,
|
||||
},
|
||||
editMenuTitle: '',
|
||||
visible: false,
|
||||
title: '',
|
||||
applicationNamespaces: [] as Array<string>,
|
||||
});
|
||||
|
||||
onMounted(async () => {
|
||||
handleQuery();
|
||||
// 表格参数配置
|
||||
const options = useVxeTable<SysCodeGen>({
|
||||
id: 'sysCodeGen',
|
||||
name: '代码生成',
|
||||
columns: [
|
||||
// { type: 'checkbox', width: 40, fixed: 'left' },
|
||||
{ type: 'seq', title: '序号', width: 60, fixed: 'left' },
|
||||
{ field: 'configId', title: '库定位器', minWidth: 200, showOverflow: 'tooltip' },
|
||||
{ field: 'tableName', title: '表名称', minWidth: 200, showOverflow: 'tooltip' },
|
||||
{ field: 'busName', title: '业务名', minWidth: 200, showOverflow: 'tooltip' },
|
||||
{ field: 'nameSpace', title: '命名空间', minWidth: 200, showOverflow: 'tooltip' },
|
||||
{ field: 'authorName', title: '作者姓名', minWidth: 200, showOverflow: 'tooltip' },
|
||||
{ field: 'generateType', title: '生成方式', minWidth: 140, showOverflow: 'tooltip', slots: { default: 'row_generateType' } },
|
||||
{ title: '操作', fixed: 'right', width: 280, showOverflow: true, slots: { default: 'row_buttons' } },
|
||||
],
|
||||
enableExport: auth('sysCodeGen:export'),
|
||||
searchCallback: () => handleQuery(),
|
||||
queryAllCallback: () => fetchData({ pageSize: 99999 }),
|
||||
});
|
||||
|
||||
// 页面初始化
|
||||
onMounted(async () => {
|
||||
await handleQuery();
|
||||
let res = await getAPI(SysCodeGenApi).apiSysCodeGenApplicationNamespacesGet();
|
||||
state.applicationNamespaces = res.data.result as Array<string>;
|
||||
});
|
||||
|
||||
const openConfigDialog = (row: any) => {
|
||||
CodeConfigRef.value?.openDialog(row);
|
||||
// 查询操作
|
||||
const handleQuery = async (reset = false) => {
|
||||
options.loading = true;
|
||||
if (reset) state.tableParams.page = 1;
|
||||
var res = await fetchData(null);
|
||||
xGrid.value?.loadData(res.data.result?.items ?? []);
|
||||
state.tableParams.total = res.data.result?.total;
|
||||
options.loading = false;
|
||||
};
|
||||
|
||||
// 表查询操作
|
||||
const handleQuery = async () => {
|
||||
state.loading = true;
|
||||
let params = Object.assign(state.queryParams, state.tableParams);
|
||||
let res = await getAPI(SysCodeGenApi).apiSysCodeGenPagePost(params);
|
||||
state.tableData = res.data.result?.items ?? [];
|
||||
state.tableParams.total = res.data.result?.total;
|
||||
state.loading = false;
|
||||
// 获取数据
|
||||
const fetchData = async (tableParams: any) => {
|
||||
let params = Object.assign(state.queryParams, state.tableParams, tableParams);
|
||||
return getAPI(SysCodeGenApi).apiSysCodeGenPagePost(params);
|
||||
};
|
||||
|
||||
// 重置操作
|
||||
const resetQuery = () => {
|
||||
state.queryParams.busName = undefined;
|
||||
state.queryParams.tableName = undefined;
|
||||
handleQuery(true);
|
||||
};
|
||||
|
||||
const handleConfig = (row: any) => {
|
||||
CodeConfigRef.value?.openDialog(row);
|
||||
};
|
||||
|
||||
// 改变页码序号或页面容量
|
||||
const pageChange: VxePagerEvents.PageChange = ({ currentPage, pageSize }: VxePagerDefines.PageChangeEventParams) => {
|
||||
state.tableParams.page = currentPage;
|
||||
state.tableParams.pageSize = pageSize;
|
||||
handleQuery();
|
||||
};
|
||||
|
||||
// 改变页面容量
|
||||
const handleSizeChange = (val: number) => {
|
||||
state.tableParams.pageSize = val;
|
||||
// 列排序
|
||||
const sortChange = (options: any) => {
|
||||
state.tableParams.field = options.field;
|
||||
state.tableParams.order = options.order;
|
||||
handleQuery();
|
||||
};
|
||||
|
||||
// 改变页码序号
|
||||
const handleCurrentChange = (val: number) => {
|
||||
state.tableParams.page = val;
|
||||
handleQuery();
|
||||
};
|
||||
|
||||
// 打开表增加页面
|
||||
const openAddDialog = () => {
|
||||
state.editMenuTitle = '增加';
|
||||
// 打开新增页面
|
||||
const handleAdd = () => {
|
||||
state.title = '增加';
|
||||
EditCodeGenRef.value?.openDialog({
|
||||
authorName: 'Admin.NET',
|
||||
generateType: '200',
|
||||
@ -155,18 +201,18 @@ const openAddDialog = () => {
|
||||
menuIcon: 'ele-Menu',
|
||||
pagePath: 'main',
|
||||
nameSpace: state.applicationNamespaces[0],
|
||||
generateMenu: true,
|
||||
generateMenu: false,
|
||||
});
|
||||
};
|
||||
|
||||
// 打开表编辑页面
|
||||
const openEditDialog = (row: any) => {
|
||||
state.editMenuTitle = '编辑';
|
||||
// 打开编辑页面
|
||||
const handleEdit = (row: any) => {
|
||||
state.title = '编辑';
|
||||
EditCodeGenRef.value?.openDialog(row);
|
||||
};
|
||||
|
||||
// 删除表
|
||||
const deleConfig = (row: any) => {
|
||||
// 删除
|
||||
const handleDelete = (row: any) => {
|
||||
ElMessageBox.confirm(`确定删除吗?`, '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
@ -198,7 +244,7 @@ const handleGenerate = (row: any) => {
|
||||
|
||||
// 预览代码
|
||||
const handlePreview = (row: any) => {
|
||||
state.editMenuTitle = '预览代码';
|
||||
state.title = '预览代码';
|
||||
PreviewRef.value?.openDialog(row);
|
||||
};
|
||||
</script>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="sys-config-container">
|
||||
<el-dialog v-model="state.isShowDialog" draggable :close-on-click-modal="false" width="700px">
|
||||
<el-dialog v-model="state.isShowDialog" draggable overflow destroy-on-close width="700px">
|
||||
<template #header>
|
||||
<div style="color: #fff">
|
||||
<el-icon size="16" style="margin-right: 3px; display: inline; vertical-align: middle"> <ele-Edit /> </el-icon>
|
||||
@ -8,7 +8,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<el-form :model="state.ruleForm" ref="ruleFormRef" label-width="auto">
|
||||
<el-row :gutter="35">
|
||||
<el-row :gutter="10">
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
|
||||
<el-form-item label="配置名称" prop="name" :rules="[{ required: true, message: '配置名称不能为空', trigger: 'blur' }]">
|
||||
<el-input v-model="state.ruleForm.name" placeholder="配置名称" clearable />
|
||||
|
||||
@ -1,170 +1,208 @@
|
||||
<template>
|
||||
<div class="sys-config-container">
|
||||
<el-card shadow="hover" :body-style="{ paddingBottom: '0' }">
|
||||
<TableSearch :search="tb.tableData.search" @search="onSearch" />
|
||||
<div class="sys-config-container" v-loading="options.loading">
|
||||
<el-card shadow="hover" :body-style="{ padding: '5px 5px 0 5px', display: 'flex', width: '100%', height: '100%', alignItems: 'start' }">
|
||||
<el-form :model="state.queryParams" ref="queryForm" :show-message="false" :inlineMessage="true" :label-width="'60px'" style="flex: 1 1 0%">
|
||||
<el-row :gutter="10">
|
||||
<el-col class="mb5" :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
|
||||
<el-form-item label="配置名称" prop="name">
|
||||
<el-input v-model="state.queryParams.name" placeholder="配置名称" clearable @keyup.enter.native="handleQuery(true)" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col class="mb5" :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
|
||||
<el-form-item label="配置编码" prop="code">
|
||||
<el-input v-model="state.queryParams.code" placeholder="配置编码" clearable @keyup.enter.native="handleQuery(true)" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col class="mb5" :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
|
||||
<el-form-item label="分组编码" prop="groupCode">
|
||||
<el-select v-model="state.queryParams.groupCode" clearable placeholder="分组编码" @clear="state.queryParams.groupCode = undefined">
|
||||
<el-option v-for="item in state.groupList" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
|
||||
<el-divider style="height: calc(100% - 5px); margin: 0 10px" direction="vertical" />
|
||||
|
||||
<el-row>
|
||||
<el-col>
|
||||
<el-button-group>
|
||||
<el-button type="primary" icon="ele-Search" @click="handleQuery(true)" v-auth="'sysConfig:page'" :loading="options.loading"> 查询 </el-button>
|
||||
<el-button icon="ele-Refresh" @click="resetQuery" :loading="options.loading"> 重置 </el-button>
|
||||
</el-button-group>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
|
||||
<el-card class="full-table" shadow="hover" style="margin-top: 5px">
|
||||
<Table ref="tableRef" v-bind="tb.tableData" :getData="getData" :exportChangeData="exportChangeData" @sortHeader="onSortHeader" @selectionChange="tableSelection" border>
|
||||
<template #command>
|
||||
<el-button type="primary" icon="ele-Plus" @click="openAddConfig" v-auth="'sysConfig:add'"> 新增 </el-button>
|
||||
|
||||
<el-button v-if="state.selectlist.length > 0" type="danger" icon="ele-Delete" @click="bacthDelete" v-auth="'sysConfig:batchDelete'"> 批量删除 </el-button>
|
||||
<vxe-grid ref="xGrid" class="xGrid-style" v-bind="options" @sort-change="sortChange" @checkbox-all="handleSelectChange" @checkbox-change="handleSelectChange">
|
||||
<template #toolbar_buttons>
|
||||
<el-button type="primary" icon="ele-Plus" @click="handleAdd" v-auth="'sysConfig:add'"> 新增 </el-button>
|
||||
<!-- <el-button v-if="state.selectList.length > 0" type="danger" icon="ele-Delete" @click="handleBacthDelete" > 批量删除 </el-button> -->
|
||||
</template>
|
||||
<template #sysFlag="scope">
|
||||
<el-tag v-if="scope.row.sysFlag === 1"> 是 </el-tag>
|
||||
<el-tag type="danger" v-else> 否 </el-tag>
|
||||
<template #toolbar_tools> </template>
|
||||
<template #empty>
|
||||
<el-empty :image-size="200" />
|
||||
</template>
|
||||
<template #remark="scope">
|
||||
<ModifyRecord :data="scope.row" />
|
||||
<template #row_sysFlag="{ row }">
|
||||
<el-tag v-if="row.sysFlag === 1" type="success">是</el-tag>
|
||||
<el-tag v-else type="danger">否</el-tag>
|
||||
</template>
|
||||
<template #action="scope">
|
||||
<el-button icon="ele-Edit" size="small" text type="primary" @click="openEditConfig(scope.row)" v-auth="'sysConfig:update'"> 编辑 </el-button>
|
||||
<el-button icon="ele-Delete" size="small" text type="danger" @click="delConfig(scope.row)" v-auth="'sysConfig:delete'" :disabled="scope.row.sysFlag === 1"> 删除 </el-button>
|
||||
<template #row_record="{ row }">
|
||||
<ModifyRecord :data="row" />
|
||||
</template>
|
||||
</Table>
|
||||
<template #row_buttons="{ row }">
|
||||
<el-tooltip content="编辑" placement="top">
|
||||
<el-button icon="ele-Edit" text type="primary" v-auth="'sysConfig:update'" @click="handleEdit(row)"> </el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="删除" placement="top">
|
||||
<el-button icon="ele-Delete" text type="danger" v-auth="'sysConfig:delete'" :disabled="row.sysFlag === 1" @click="handleDelete(row)"> </el-button>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
<template #pager>
|
||||
<vxe-pager
|
||||
:loading="options.loading"
|
||||
v-model:current-page="state.tableParams.page"
|
||||
v-model:page-size="state.tableParams.pageSize"
|
||||
:total="state.tableParams.total"
|
||||
@page-change="pageChange"
|
||||
/>
|
||||
</template>
|
||||
</vxe-grid>
|
||||
</el-card>
|
||||
|
||||
<EditConfig ref="editConfigRef" :title="state.editConfigTitle" :groupList="state.groupList" @updateData="updateData" />
|
||||
<EditConfig ref="editConfigRef" :title="state.title" :groupList="state.groupList" @updateData="updateData" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="sysConfig">
|
||||
import { onMounted, onUnmounted, reactive, ref, defineAsyncComponent, nextTick } from 'vue';
|
||||
import { onMounted, reactive, ref } from 'vue';
|
||||
import { ElMessageBox, ElMessage } from 'element-plus';
|
||||
import { auth } from '/@/utils/authFunction';
|
||||
import { VxeGridInstance, VxePagerEvents, VxePagerDefines } from 'vxe-table';
|
||||
import { useVxeTable } from '/@/hooks/vxeTableOptionsHook';
|
||||
|
||||
import EditConfig from '/@/views/system/config/component/editConfig.vue';
|
||||
import ModifyRecord from '/@/components/table/modifyRecord.vue';
|
||||
|
||||
import { getAPI } from '/@/utils/axios-utils';
|
||||
import { SysConfigApi } from '/@/api-services/api';
|
||||
import { auth } from '/@/utils/authFunction';
|
||||
import { SysConfig } from '/@/api-services/models';
|
||||
|
||||
// 引入组件
|
||||
const Table = defineAsyncComponent(() => import('/@/components/table/index.vue'));
|
||||
const TableSearch = defineAsyncComponent(() => import('/@/components/table/search.vue'));
|
||||
const xGrid = ref<VxeGridInstance>();
|
||||
const editConfigRef = ref<InstanceType<typeof EditConfig>>();
|
||||
const tableRef = ref<RefType>();
|
||||
|
||||
const state = reactive({
|
||||
editConfigTitle: '',
|
||||
selectlist: [] as EmptyObjectType[],
|
||||
groupList: [] as Array<String>,
|
||||
});
|
||||
|
||||
const tb = reactive<TableDemoState>({
|
||||
tableData: {
|
||||
// 表头内容(必传,注意格式)
|
||||
columns: [
|
||||
{ prop: 'name', minWidth: 150, label: '配置名称', headerAlign: 'center', sortable: 'custom', isCheck: true, hideCheck: true },
|
||||
{ prop: 'code', minWidth: 150, label: '配置编码', headerAlign: 'center', toolTip: true, sortable: 'custom', isCheck: true },
|
||||
{ prop: 'value', minWidth: 150, label: '属性值', headerAlign: 'center', isCheck: true },
|
||||
{ prop: 'sysFlag', width: 100, label: '内置参数', align: 'center', isCheck: true },
|
||||
{ prop: 'groupCode', width: 120, label: '分组编码', align: 'center', sortable: 'custom', isCheck: true },
|
||||
{ prop: 'orderNo', width: 80, label: '排序', align: 'center', sortable: 'custom', isCheck: true },
|
||||
{ prop: 'remark', width: 100, label: '修改记录', align: 'center', headerAlign: 'center', showOverflowTooltip: true, isCheck: true },
|
||||
{ prop: 'action', width: 140, label: '操作', type: 'action', align: 'center', isCheck: true, fixed: 'right', hideCheck: true },
|
||||
],
|
||||
// 配置项(必传)
|
||||
config: {
|
||||
isStripe: true, // 是否显示表格斑马纹
|
||||
isBorder: false, // 是否显示表格边框
|
||||
isSerialNo: true, // 是否显示表格序号
|
||||
isSelection: true, // 是否勾选表格多选
|
||||
showSelection: auth('sysConfig:batchDelete'), //是否显示表格多选
|
||||
pageSize: 20, // 每页条数
|
||||
hideExport: false, //是否隐藏导出按钮
|
||||
exportFileName: '系统参数', //导出报表的文件名,不填写取应用名称
|
||||
},
|
||||
// 搜索表单,动态生成(传空数组时,将不显示搜索,type有3种类型:input,date,select)
|
||||
search: [
|
||||
{ label: '配置名称', prop: 'name', placeholder: '搜索配置名称', required: false, type: 'input' },
|
||||
{ label: '配置编码', prop: 'code', placeholder: '搜索配置编码', required: false, type: 'input' },
|
||||
// { label: '创建时间', prop: 'time', placeholder: '请选择', required: false, type: 'date' },
|
||||
],
|
||||
param: {},
|
||||
defaultSort: {
|
||||
prop: 'orderNo',
|
||||
order: 'ascending',
|
||||
},
|
||||
queryParams: {
|
||||
name: undefined,
|
||||
code: undefined,
|
||||
groupCode: undefined,
|
||||
},
|
||||
tableParams: {
|
||||
page: 1,
|
||||
pageSize: 50,
|
||||
field: 'orderNo', // 默认的排序字段
|
||||
order: 'aes', // 排序方向
|
||||
descStr: 'desc', // 降序排序的关键字符
|
||||
total: 0 as any,
|
||||
},
|
||||
visible: false,
|
||||
title: '',
|
||||
groupList: [] as string[],
|
||||
selectList: [] as SysConfig[],
|
||||
});
|
||||
//表格参数配置
|
||||
const options = useVxeTable<SysConfig>({
|
||||
id: 'sysConfig',
|
||||
name: '参数配置',
|
||||
columns: [
|
||||
// { type: 'checkbox', width: 40, fixed: 'left' },
|
||||
{ type: 'seq', title: '序号', width: 60, fixed: 'left' },
|
||||
{ field: 'name', title: '配置名称', minWidth: 200, showOverflow: 'tooltip', sortable: true },
|
||||
{ field: 'code', title: '配置编码', minWidth: 200, showOverflow: 'tooltip', sortable: true },
|
||||
{ field: 'value', title: '属性值', minWidth: 150, showOverflow: 'tooltip', sortable: true },
|
||||
{ field: 'sysFlag', title: '内置参数', width: 80, showOverflow: 'tooltip', sortable: true, slots: { default: 'row_sysFlag' } },
|
||||
{ field: 'groupCode', title: '分组编码', minWidth: 120, showOverflow: 'tooltip', sortable: true },
|
||||
{ field: 'orderNo', title: '排序', width: 80, showOverflow: 'tooltip', sortable: true },
|
||||
{ field: 'remark', title: '备注', minWidth: 300, showOverflow: 'tooltip', sortable: true },
|
||||
{ field: '', title: '修改记录', width: 100, showOverflow: 'tooltip', slots: { default: 'row_record' } },
|
||||
{ title: '操作', fixed: 'right', width: 100, showOverflow: true, slots: { default: 'row_buttons' } },
|
||||
],
|
||||
enableExport: auth('sysConfig:export'),
|
||||
searchCallback: () => handleQuery(),
|
||||
queryAllCallback: () => fetchData({ pageSize: 99999 }),
|
||||
});
|
||||
const getData = (param: any) => {
|
||||
return getAPI(SysConfigApi)
|
||||
.apiSysConfigPagePost(param)
|
||||
.then((res) => {
|
||||
return res.data;
|
||||
});
|
||||
};
|
||||
const exportChangeData = (data: Array<EmptyObjectType>) => {
|
||||
data.forEach((item) => {
|
||||
item.sysFlag = item.sysFlag == 1 ? '是' : '否';
|
||||
});
|
||||
return data;
|
||||
};
|
||||
// 拖动显示列排序回调
|
||||
const onSortHeader = (data: object[]) => {
|
||||
tb.tableData.columns = data;
|
||||
};
|
||||
// 搜索点击时表单回调
|
||||
const onSearch = (data: EmptyObjectType) => {
|
||||
tb.tableData.param = Object.assign({}, tb.tableData.param, { ...data });
|
||||
nextTick(() => {
|
||||
tableRef.value.pageReset();
|
||||
});
|
||||
};
|
||||
|
||||
const getGroupList = async () => {
|
||||
const res = await getAPI(SysConfigApi).apiSysConfigGroupListGet();
|
||||
const groupSearch = {
|
||||
label: '分组编码',
|
||||
prop: 'groupCode',
|
||||
placeholder: '请选择',
|
||||
required: false,
|
||||
type: 'select',
|
||||
options: [],
|
||||
} as TableSearchType;
|
||||
state.groupList = res.data.result ?? [];
|
||||
res.data.result?.forEach((item) => {
|
||||
groupSearch.options?.push({ label: item, value: item });
|
||||
});
|
||||
let group = tb.tableData.search.filter((item) => {
|
||||
return item.prop == 'groupCode';
|
||||
});
|
||||
if (group.length == 0) {
|
||||
tb.tableData.search.push(groupSearch);
|
||||
} else {
|
||||
group[0] = groupSearch;
|
||||
}
|
||||
};
|
||||
|
||||
//表格多选事件
|
||||
const tableSelection = (data: EmptyObjectType[]) => {
|
||||
state.selectlist = data;
|
||||
};
|
||||
|
||||
// 页面初始化
|
||||
onMounted(async () => {
|
||||
getGroupList();
|
||||
await handleQuery();
|
||||
fetchGroupData();
|
||||
});
|
||||
|
||||
// 更新数据
|
||||
const updateData = () => {
|
||||
tableRef.value.handleList();
|
||||
getGroupList();
|
||||
// 查询操作
|
||||
const handleQuery = async (reset = false) => {
|
||||
options.loading = true;
|
||||
if (reset) state.tableParams.page = 1;
|
||||
var res = await fetchData(null);
|
||||
xGrid.value?.loadData(res.data.result?.items ?? []);
|
||||
state.tableParams.total = res.data.result?.total;
|
||||
state.selectList = [];
|
||||
options.loading = false;
|
||||
};
|
||||
|
||||
// 获取数据
|
||||
const fetchData = async (tableParams: any) => {
|
||||
let params = Object.assign(state.queryParams, state.tableParams, tableParams);
|
||||
return getAPI(SysConfigApi).apiSysConfigPagePost(params);
|
||||
};
|
||||
|
||||
const fetchGroupData = async () => {
|
||||
const res = await getAPI(SysConfigApi).apiSysConfigGroupListGet();
|
||||
state.groupList = res.data.result ?? [];
|
||||
};
|
||||
|
||||
// 重置操作
|
||||
const resetQuery = () => {
|
||||
state.queryParams.code = undefined;
|
||||
state.queryParams.name = undefined;
|
||||
state.queryParams.groupCode = undefined;
|
||||
handleQuery(true);
|
||||
};
|
||||
|
||||
// 改变页码序号或页面容量
|
||||
const pageChange: VxePagerEvents.PageChange = ({ currentPage, pageSize }: VxePagerDefines.PageChangeEventParams) => {
|
||||
state.tableParams.page = currentPage;
|
||||
state.tableParams.pageSize = pageSize;
|
||||
handleQuery();
|
||||
};
|
||||
|
||||
// 列排序
|
||||
const sortChange = (options: any) => {
|
||||
state.tableParams.field = options.field;
|
||||
state.tableParams.order = options.order;
|
||||
handleQuery();
|
||||
};
|
||||
|
||||
// 打开新增页面
|
||||
const openAddConfig = () => {
|
||||
state.editConfigTitle = '添加配置';
|
||||
const handleAdd = () => {
|
||||
state.title = '添加配置';
|
||||
editConfigRef.value?.openDialog({ sysFlag: 2, orderNo: 100 });
|
||||
};
|
||||
|
||||
// 打开编辑页面
|
||||
const openEditConfig = (row: any) => {
|
||||
state.editConfigTitle = '编辑配置';
|
||||
const handleEdit = (row: any) => {
|
||||
state.title = '编辑配置';
|
||||
editConfigRef.value?.openDialog(row);
|
||||
};
|
||||
|
||||
// 更新数据
|
||||
const updateData = async () => {
|
||||
await handleQuery();
|
||||
fetchGroupData();
|
||||
};
|
||||
|
||||
// 删除
|
||||
const delConfig = (row: any) => {
|
||||
const handleDelete = (row: any) => {
|
||||
ElMessageBox.confirm(`确定删除配置:【${row.name}】?`, '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
@ -172,26 +210,28 @@ const delConfig = (row: any) => {
|
||||
})
|
||||
.then(async () => {
|
||||
await getAPI(SysConfigApi).apiSysConfigDeletePost({ id: row.id });
|
||||
tableRef.value.handleList();
|
||||
handleQuery();
|
||||
ElMessage.success('删除成功');
|
||||
})
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
//批量删除
|
||||
const bacthDelete = () => {
|
||||
if (state.selectlist.length == 0) return false;
|
||||
ElMessageBox.confirm(`确定批量删除【${state.selectlist[0].name}】等${state.selectlist.length}个配置?`, '提示', {
|
||||
const handleSelectChange = () => {
|
||||
state.selectList = xGrid.value?.getCheckboxRecords() ?? [];
|
||||
};
|
||||
|
||||
// 批量删除
|
||||
const handleBacthDelete = () => {
|
||||
if (state.selectList.length == 0) return false;
|
||||
ElMessageBox.confirm(`确定批量删除【${state.selectList[0].name}】等${state.selectList.length}个配置?`, '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
})
|
||||
.then(async () => {
|
||||
const ids = state.selectlist.map((item) => {
|
||||
return item.id;
|
||||
});
|
||||
const ids = state.selectList.map((item: any) => item.id);
|
||||
var res = await getAPI(SysConfigApi).apiSysConfigBatchDeletePost(ids);
|
||||
tableRef.value.pageReset();
|
||||
handleQuery();
|
||||
ElMessage.success('删除成功');
|
||||
})
|
||||
.catch(() => {});
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<el-form :model="state.ruleForm" ref="ruleFormRef" label-width="auto">
|
||||
<el-row :gutter="35">
|
||||
<el-row :gutter="10">
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
|
||||
<el-form-item label="列名" prop="dbColumnName" :rules="[{ required: true, message: '名称不能为空', trigger: 'blur' }]">
|
||||
<el-input v-model="state.ruleForm.dbColumnName" placeholder="列名称" clearable />
|
||||
@ -72,10 +72,11 @@
|
||||
<script lang="ts" setup name="sysAddColumn">
|
||||
import { reactive, ref } from 'vue';
|
||||
|
||||
import { dataTypeList, yesNoSelect } from '../database';
|
||||
|
||||
import { getAPI } from '/@/utils/axios-utils';
|
||||
import { SysDatabaseApi } from '/@/api-services/api';
|
||||
import { DbColumnInput } from '/@/api-services/models';
|
||||
import { dataTypeList, yesNoSelect } from '../database';
|
||||
|
||||
const emits = defineEmits(['handleQueryColumn']);
|
||||
const ruleFormRef = ref();
|
||||
|
||||
@ -1,15 +1,15 @@
|
||||
<template>
|
||||
<div class="sys-dbTable-container">
|
||||
<el-dialog v-model="state.isShowDialog" draggable :close-on-click-modal="false" width="1400px">
|
||||
<el-dialog v-model="state.visible" :z-index="2008" draggable :close-on-click-modal="false" width="70vw">
|
||||
<template #header>
|
||||
<div style="color: #fff">
|
||||
<el-icon size="16" style="margin-right: 3px; display: inline; vertical-align: middle"> <ele-Edit /> </el-icon>
|
||||
<span> 增加表 </span>
|
||||
</div>
|
||||
</template>
|
||||
<el-divider content-position="left">数据表信息</el-divider>
|
||||
<el-divider content-position="left" style="margin: 10px 0 18px 0">数据表信息</el-divider>
|
||||
<el-form :model="state.ruleForm" ref="ruleFormRef" label-width="auto">
|
||||
<el-row :gutter="35">
|
||||
<el-row :gutter="10">
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
|
||||
<el-form-item label="表名称" prop="tableName" :rules="[{ required: true, message: '名称不能为空', trigger: 'blur' }]">
|
||||
<el-input v-model="state.ruleForm.tableName" placeholder="表名称" clearable />
|
||||
@ -22,69 +22,21 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<el-divider content-position="left">数据列信息</el-divider>
|
||||
<el-table :data="state.tableData" style="width: 100%" max-height="400">
|
||||
<el-table-column prop="dbColumnName" label="字段名" width="220" fixed>
|
||||
<template #default="scope">
|
||||
<el-input v-model="scope.row.dbColumnName" autocomplete="off" />
|
||||
<el-divider content-position="left" style="margin: 10px 0 18px 0">数据列信息</el-divider>
|
||||
<div style="height: calc(90vh - 252px)">
|
||||
<vxe-grid ref="xGrid" class="xGrid-table-style" v-bind="options">
|
||||
<template #toolbar_buttons>
|
||||
<el-button icon="ele-Plus" @click="addPrimaryColumn">新增主键字段</el-button>
|
||||
<el-button icon="ele-Plus" @click="addColumn">新增普通字段</el-button>
|
||||
<el-button icon="ele-Plus" @click="addTenantColumn">新增租户字段</el-button>
|
||||
<el-button icon="ele-Plus" @click="addBaseColumn">新增基础字段</el-button>
|
||||
<el-button icon="ele-Delete" type="danger" @click="deleteSelected">删除选中</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="columnDescription" label="描述" width="220">
|
||||
<template #default="scope">
|
||||
<el-input v-model="scope.row.columnDescription" autocomplete="off" />
|
||||
<template #toolbar_tools> </template>
|
||||
<template #empty>
|
||||
<el-empty :image-size="200" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="isPrimarykey" label="主键" width="100">
|
||||
<template #default="scope">
|
||||
<el-select v-model="scope.row.isPrimarykey" class="m-2" placeholder="Select">
|
||||
<el-option v-for="item in yesNoSelect" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="isIdentity" label="自增" width="100">
|
||||
<template #default="scope">
|
||||
<el-select v-model="scope.row.isIdentity" class="m-2" placeholder="Select">
|
||||
<el-option v-for="item in yesNoSelect" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="dataType" label="类型" width="150">
|
||||
<template #default="scope">
|
||||
<el-select v-model="scope.row.dataType" class="m-2" placeholder="Select">
|
||||
<el-option v-for="item in dataTypeList" :key="item.value" :label="item.value" :value="item.value" />
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="isNullable" label="可空" width="100">
|
||||
<template #default="scope">
|
||||
<el-select v-model="scope.row.isNullable" class="m-2" placeholder="Select">
|
||||
<el-option v-for="item in yesNoSelect" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="length" label="长度" width="100">
|
||||
<template #default="scope">
|
||||
<el-input-number v-model="scope.row.length" controls-position="right" class="w100" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="decimalDigits" label="小数位" width="100">
|
||||
<template #default="scope">
|
||||
<el-input-number v-model="scope.row.decimalDigits" controls-position="right" class="w100" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" min-width="200" align="center" fixed="right">
|
||||
<template #default="scope">
|
||||
<el-button link type="primary" icon="el-icon-delete" @click.prevent="handleColDelete(scope.$index)">删除</el-button>
|
||||
<el-button v-if="state.tableData.length > 1" link type="primary" icon="ele-Top" @click.prevent="handleColUp(scope.row, scope.$index)">上移</el-button>
|
||||
<el-button v-if="state.tableData.length > 1" link type="primary" icon="ele-Bottom" @click.prevent="handleColDown(scope.row, scope.$index)">下移</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div style="text-align: left; margin-top: 10px">
|
||||
<el-button icon="ele-Plus" @click="addPrimaryColumn">新增主键字段</el-button>
|
||||
<el-button icon="ele-Plus" @click="addColumn">新增普通字段</el-button>
|
||||
<el-button icon="ele-Plus" @click="addTenantColumn">新增租户字段</el-button>
|
||||
<el-button icon="ele-Plus" @click="addBaseColumn">新增基础字段</el-button>
|
||||
</vxe-grid>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
@ -97,56 +49,251 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="sysAddTable">
|
||||
import { reactive, ref } from 'vue';
|
||||
import { ElMessage } from 'element-plus';
|
||||
<script lang="tsx" setup name="sysAddTable">
|
||||
import { nextTick, reactive, ref } from 'vue';
|
||||
import { ElMessage, dayjs } from 'element-plus';
|
||||
import { VxeGridInstance, VxeGridProps } from 'vxe-table';
|
||||
import { Rank } from '@element-plus/icons-vue';
|
||||
import Sortable from 'sortablejs';
|
||||
import { dataTypeList } from '../database';
|
||||
|
||||
import { getAPI } from '/@/utils/axios-utils';
|
||||
import { SysDatabaseApi } from '/@/api-services/api';
|
||||
import { UpdateDbTableInput } from '/@/api-services/models';
|
||||
import { dataTypeList, EditRecordRow, yesNoSelect } from '../database';
|
||||
|
||||
var colIndex = 0;
|
||||
const xGrid = ref<VxeGridInstance>();
|
||||
let initTime: any;
|
||||
const emits = defineEmits(['addTableSubmitted']);
|
||||
const ruleFormRef = ref();
|
||||
const state = reactive({
|
||||
isShowDialog: false,
|
||||
visible: false,
|
||||
ruleForm: {} as UpdateDbTableInput,
|
||||
tableData: [] as any,
|
||||
sortable: undefined as any,
|
||||
});
|
||||
|
||||
// 表格参数配置
|
||||
const options = reactive<VxeGridProps>({
|
||||
id: 'sysAddTable',
|
||||
height: 'auto',
|
||||
autoResize: true,
|
||||
size: 'mini',
|
||||
loading: false,
|
||||
align: 'center', // 自动监听父元素的变化去重新计算表格(对于父元素可能存在动态变化、显示隐藏的容器中、列宽异常等场景中的可能会用到)
|
||||
data: [] as Array<any>,
|
||||
rowConfig: { useKey: true },
|
||||
seqConfig: { seqMethod: ({ row }) => row.orderNo },
|
||||
columns: [
|
||||
{
|
||||
width: 80,
|
||||
slots: {
|
||||
default: () => (
|
||||
<span class="drag-btn">
|
||||
<el-icon>
|
||||
<Rank />
|
||||
</el-icon>
|
||||
</span>
|
||||
),
|
||||
},
|
||||
},
|
||||
{ type: 'seq', title: '序号', width: 50 },
|
||||
{ type: 'checkbox', width: 40 },
|
||||
{
|
||||
field: 'dbColumnName',
|
||||
title: '字段名',
|
||||
minWidth: 160,
|
||||
showOverflow: 'tooltip',
|
||||
editRender: { name: '$input', props: { clearable: true, placeholder: '请输入字段名' } },
|
||||
},
|
||||
{
|
||||
field: 'columnDescription',
|
||||
title: '描述',
|
||||
minWidth: 220,
|
||||
showOverflow: 'tooltip',
|
||||
editRender: { name: '$input', props: { clearable: true, placeholder: '请输入描述' } },
|
||||
},
|
||||
{
|
||||
field: 'isPrimarykey',
|
||||
title: '主键',
|
||||
minWidth: 100,
|
||||
editRender: { name: '$switch', props: { openValue: 1, closeValue: 0, openLabel: '是', closeLabel: '否' } },
|
||||
slots: {
|
||||
default: (scope) => <vxe-switch vModel={scope.row.isPrimarykey} open-label="是" close-label="否" openValue={1} closeValue={0}></vxe-switch>,
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'isIdentity',
|
||||
title: '自增',
|
||||
minWidth: 100,
|
||||
editRender: { name: '$switch', props: { openValue: 1, closeValue: 0, openLabel: '是', closeLabel: '否' } },
|
||||
slots: {
|
||||
default: (scope) => <vxe-switch vModel={scope.row.isIdentity} open-label="是" close-label="否" openValue={1} closeValue={0}></vxe-switch>,
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'dataType',
|
||||
title: '类型',
|
||||
minWidth: 100,
|
||||
editRender: {
|
||||
name: '$select',
|
||||
options: dataTypeList,
|
||||
optionProps: { value: 'value', label: 'value' },
|
||||
props: { optionProps: { value: 'value', label: 'value' }, placeholder: '请选择类型', popupClassName: 'zIndex2023' },
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'isNullable',
|
||||
title: '可空',
|
||||
minWidth: 100,
|
||||
editRender: { name: '$switch', props: { openValue: 1, closeValue: 0, openLabel: '是', closeLabel: '否' } },
|
||||
slots: {
|
||||
default: (scope) => <vxe-switch vModel={scope.row.isNullable} open-label="是" close-label="否" openValue={1} closeValue={0}></vxe-switch>,
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'length',
|
||||
title: '长度',
|
||||
minWidth: 100,
|
||||
showOverflow: 'tooltip',
|
||||
editRender: { name: '$input', props: { type: 'integer', clearable: true, placeholder: '请输入长度' } },
|
||||
},
|
||||
{
|
||||
field: 'decimalDigits',
|
||||
title: '小数位',
|
||||
minWidth: 100,
|
||||
showOverflow: 'tooltip',
|
||||
editRender: { name: '$input', props: { type: 'integer', clearable: true, placeholder: '请输入小数位' } },
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
width: 80,
|
||||
showOverflow: true,
|
||||
fixed: 'right',
|
||||
slots: {
|
||||
default: (scope) => <el-button icon="ele-Delete" text type="danger" onClick={() => deleteRow(scope.row)}></el-button>,
|
||||
},
|
||||
},
|
||||
],
|
||||
editRules: {
|
||||
dbColumnName: [{ required: true, message: '字段名必填' }],
|
||||
dataType: [{ required: true, message: '类型必填' }],
|
||||
},
|
||||
toolbarConfig: {
|
||||
size: 'small',
|
||||
slots: { buttons: 'toolbar_buttons', tools: 'toolbar_tools' },
|
||||
refresh: false,
|
||||
export: true,
|
||||
print: true,
|
||||
zoom: true,
|
||||
custom: false,
|
||||
},
|
||||
checkboxConfig: { range: true },
|
||||
sortConfig: {
|
||||
trigger: 'cell',
|
||||
remote: false,
|
||||
},
|
||||
editConfig: { trigger: 'click', mode: 'row', showStatus: true },
|
||||
exportConfig: {
|
||||
remote: false, //设置使用服务端导出
|
||||
filename: `数据列信息导出_${dayjs().format('YYMMDDHHmmss')}`,
|
||||
exportMethod: ({ options }) => handleExport(options), //服务器导出方法
|
||||
},
|
||||
printConfig: { sheetName: '' },
|
||||
proxyConfig: {
|
||||
props: {
|
||||
list: 'data.result.items', //不分页时
|
||||
// result: 'data.result.items', //分页时
|
||||
total: 'data.result.total',
|
||||
message: 'data.message',
|
||||
},
|
||||
ajax: {
|
||||
query: () => Promise.resolve(), //不加会报错
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// 打开弹窗
|
||||
const openDialog = (row: any) => {
|
||||
state.ruleForm = row;
|
||||
state.isShowDialog = true;
|
||||
state.visible = true;
|
||||
ruleFormRef.value?.resetFields();
|
||||
nextTick(() => {
|
||||
rowDrop();
|
||||
});
|
||||
};
|
||||
|
||||
const rowDrop = () => {
|
||||
const el = document.querySelector('.xGrid-table-style .vxe-table--body tbody') as HTMLElement;
|
||||
state.sortable = Sortable.create(el, {
|
||||
animation: 300,
|
||||
handle: '.drag-btn',
|
||||
onEnd: (sortableEvent: any) => {
|
||||
const fullData = xGrid.value?.getTableData().fullData;
|
||||
const newIndex = sortableEvent.newIndex as number;
|
||||
const oldIndex = sortableEvent.oldIndex as number;
|
||||
// 往前移动
|
||||
if (oldIndex > newIndex) {
|
||||
const moveRow = fullData?.find((e) => e.orderNo == oldIndex + 1);
|
||||
for (let i = oldIndex; i > newIndex; i--) {
|
||||
const row = fullData?.find((e) => e.orderNo == i);
|
||||
row.orderNo += 1;
|
||||
}
|
||||
moveRow.orderNo = newIndex + 1;
|
||||
} else {
|
||||
// 往后移动
|
||||
const moveRow = fullData?.find((e) => e.orderNo == oldIndex + 1);
|
||||
for (let i = oldIndex; i < newIndex; i++) {
|
||||
const row = fullData?.find((e) => e.orderNo == i + 2);
|
||||
row.orderNo -= 1;
|
||||
}
|
||||
moveRow.orderNo = newIndex + 1;
|
||||
}
|
||||
xGrid.value?.updateData();
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
// 关闭弹窗
|
||||
const closeDialog = () => {
|
||||
emits('addTableSubmitted', state.ruleForm.tableName ?? '');
|
||||
state.tableData = [];
|
||||
state.isShowDialog = false;
|
||||
cancel();
|
||||
};
|
||||
|
||||
// 取消
|
||||
const cancel = () => {
|
||||
state.isShowDialog = false;
|
||||
xGrid.value?.loadData([]);
|
||||
state.visible = false;
|
||||
clearTimeout(initTime);
|
||||
if (state.sortable) {
|
||||
state.sortable.destroy();
|
||||
}
|
||||
};
|
||||
|
||||
// 导出日志(服务端导出)
|
||||
const handleExport = async (opts: any) => {
|
||||
console.log(opts);
|
||||
options.loading = true;
|
||||
// var res = await getAPI(SysLogExApi).apiSysLogExExportPost(state.queryParams as any, { responseType: 'blob' });
|
||||
options.loading = false;
|
||||
// VXETable.saveFile({ filename: getFileName(res.headers), type: 'xlsx', content: res.data as any });
|
||||
return Promise.resolve();
|
||||
};
|
||||
|
||||
// 提交
|
||||
const submit = () => {
|
||||
ruleFormRef.value.validate(async (valid: boolean) => {
|
||||
if (!valid) return;
|
||||
if (state.tableData.length === 0) {
|
||||
ElMessage({
|
||||
type: 'error',
|
||||
message: `请添加列!`,
|
||||
});
|
||||
const tableData = xGrid.value?.getTableData().fullData ?? [];
|
||||
if (tableData.length === 0) {
|
||||
ElMessage({ type: 'error', message: `请添加列!` });
|
||||
return;
|
||||
}
|
||||
const rowValid = await xGrid.value?.validate(true);
|
||||
if (rowValid) {
|
||||
ElMessage.error('校验不通过');
|
||||
return;
|
||||
}
|
||||
const params: any = {
|
||||
dbColumnInfoList: state.tableData,
|
||||
dbColumnInfoList: tableData,
|
||||
...state.ruleForm,
|
||||
};
|
||||
await getAPI(SysDatabaseApi).apiSysDatabaseAddTablePost(params);
|
||||
@ -155,164 +302,146 @@ const submit = () => {
|
||||
};
|
||||
|
||||
// 增加主键列
|
||||
function addPrimaryColumn() {
|
||||
state.tableData.push({
|
||||
columnDescription: '主键Id',
|
||||
dataType: 'bigint',
|
||||
dbColumnName: 'Id',
|
||||
decimalDigits: 0,
|
||||
isIdentity: 0,
|
||||
isNullable: 0,
|
||||
isPrimarykey: 1,
|
||||
length: 0,
|
||||
key: colIndex,
|
||||
editable: true,
|
||||
isNew: true,
|
||||
});
|
||||
colIndex++;
|
||||
}
|
||||
|
||||
// 增加普通列
|
||||
function addColumn() {
|
||||
state.tableData.push({
|
||||
columnDescription: '',
|
||||
dataType: 'varchar',
|
||||
dbColumnName: '',
|
||||
decimalDigits: 0,
|
||||
isIdentity: 0,
|
||||
isNullable: 1,
|
||||
isPrimarykey: 0,
|
||||
length: 32,
|
||||
key: colIndex,
|
||||
editable: true,
|
||||
isNew: true,
|
||||
});
|
||||
colIndex++;
|
||||
}
|
||||
|
||||
// 增加租户列
|
||||
function addTenantColumn() {
|
||||
state.tableData.push({
|
||||
columnDescription: '租户Id',
|
||||
dataType: 'bigint',
|
||||
dbColumnName: 'TenantId',
|
||||
decimalDigits: 0,
|
||||
isIdentity: 0,
|
||||
isNullable: 1,
|
||||
isPrimarykey: 0,
|
||||
length: 0,
|
||||
key: colIndex,
|
||||
editable: true,
|
||||
isNew: true,
|
||||
});
|
||||
colIndex++;
|
||||
}
|
||||
|
||||
// 增加通用基础列
|
||||
function addBaseColumn() {
|
||||
const fileds = [
|
||||
{
|
||||
dataType: 'datetime',
|
||||
name: 'CreateTime',
|
||||
desc: '创建时间',
|
||||
},
|
||||
{
|
||||
dataType: 'datetime',
|
||||
name: 'UpdateTime',
|
||||
desc: '更新时间',
|
||||
},
|
||||
const addPrimaryColumn = async () => {
|
||||
const fullData = xGrid.value?.getTableData().fullData;
|
||||
const colIndex = (fullData?.length ?? 0) + 1;
|
||||
const temp = await xGrid.value?.insertAt(
|
||||
{
|
||||
columnDescription: '主键Id',
|
||||
dataType: 'bigint',
|
||||
name: 'CreateUserId',
|
||||
desc: '创建者Id',
|
||||
},
|
||||
{
|
||||
dataType: 'varchar',
|
||||
name: 'CreateUserName',
|
||||
desc: '创建者姓名',
|
||||
length: 64,
|
||||
},
|
||||
{
|
||||
dataType: 'bigint',
|
||||
name: 'UpdateUserId',
|
||||
desc: '修改者Id',
|
||||
},
|
||||
{
|
||||
dataType: 'varchar',
|
||||
name: 'UpdateUserName',
|
||||
desc: '修改者姓名',
|
||||
length: 64,
|
||||
},
|
||||
{
|
||||
dataType: 'bigint',
|
||||
name: 'CreateOrgId',
|
||||
desc: '创建者部门Id',
|
||||
},
|
||||
{
|
||||
dataType: 'varchar',
|
||||
name: 'CreateOrgName',
|
||||
desc: '创建者部门名称',
|
||||
length: 64,
|
||||
},
|
||||
{
|
||||
dataType: 'bit',
|
||||
name: 'IsDelete',
|
||||
desc: '软删除',
|
||||
isNullable: 0,
|
||||
},
|
||||
];
|
||||
|
||||
fileds.forEach((m: any) => {
|
||||
state.tableData.push({
|
||||
columnDescription: m.desc,
|
||||
dataType: m.dataType,
|
||||
dbColumnName: m.name,
|
||||
dbColumnName: 'Id',
|
||||
decimalDigits: 0,
|
||||
isIdentity: 0,
|
||||
isNullable: m.isNullable === 0 ? 0 : 1,
|
||||
isPrimarykey: 0,
|
||||
length: m.length || 0,
|
||||
key: colIndex,
|
||||
isNullable: 0,
|
||||
isPrimarykey: 1,
|
||||
length: 0,
|
||||
orderNo: colIndex,
|
||||
editable: true,
|
||||
isNew: true,
|
||||
});
|
||||
},
|
||||
-1
|
||||
);
|
||||
if (temp && temp.row) await xGrid.value?.setEditCell(temp?.row, 'dbColumnName');
|
||||
};
|
||||
|
||||
// 增加普通列
|
||||
const addColumn = async () => {
|
||||
const fullData = xGrid.value?.getTableData().fullData;
|
||||
const colIndex = (fullData?.length ?? 0) + 1;
|
||||
const temp = await xGrid.value?.insertAt(
|
||||
{
|
||||
columnDescription: '',
|
||||
dataType: 'varchar',
|
||||
dbColumnName: '',
|
||||
decimalDigits: 0,
|
||||
isIdentity: 0,
|
||||
isNullable: 1,
|
||||
isPrimarykey: 0,
|
||||
length: 32,
|
||||
orderNo: colIndex,
|
||||
editable: true,
|
||||
isNew: true,
|
||||
},
|
||||
-1
|
||||
);
|
||||
if (temp && temp.row) await xGrid.value?.setEditCell(temp?.row, 'dbColumnName');
|
||||
};
|
||||
|
||||
// 增加租户列
|
||||
const addTenantColumn = async () => {
|
||||
const fullData = xGrid.value?.getTableData().fullData;
|
||||
const colIndex = (fullData?.length ?? 0) + 1;
|
||||
const temp = await xGrid.value?.insertAt(
|
||||
{
|
||||
columnDescription: '租户Id',
|
||||
dataType: 'bigint',
|
||||
dbColumnName: 'TenantId',
|
||||
decimalDigits: 0,
|
||||
isIdentity: 0,
|
||||
isNullable: 1,
|
||||
isPrimarykey: 0,
|
||||
length: 0,
|
||||
orderNo: colIndex,
|
||||
editable: true,
|
||||
isNew: true,
|
||||
},
|
||||
-1
|
||||
);
|
||||
if (temp && temp.row) await xGrid.value?.setEditCell(temp?.row, 'dbColumnName');
|
||||
};
|
||||
|
||||
// 增加通用基础列
|
||||
const addBaseColumn = async () => {
|
||||
const fileds = [
|
||||
{ dataType: 'datetime', name: 'CreateTime', desc: '创建时间' },
|
||||
{ dataType: 'datetime', name: 'UpdateTime', desc: '更新时间' },
|
||||
{ dataType: 'bigint', name: 'CreateUserId', desc: '创建者Id' },
|
||||
{ dataType: 'varchar', name: 'CreateUserName', desc: '创建者姓名', length: 64 },
|
||||
{ dataType: 'bigint', name: 'UpdateUserId', desc: '修改者Id' },
|
||||
{ dataType: 'varchar', name: 'UpdateUserName', desc: '修改者姓名', length: 64 },
|
||||
{ dataType: 'bigint', name: 'CreateOrgId', desc: '创建者部门Id' },
|
||||
{ dataType: 'varchar', name: 'CreateOrgName', desc: '创建者部门名称', length: 64 },
|
||||
{ dataType: 'bit', name: 'IsDelete', desc: '软删除', isNullable: 0 },
|
||||
];
|
||||
let temp = {} as any;
|
||||
const fullData = xGrid.value?.getTableData().fullData;
|
||||
let colIndex = (fullData?.length ?? 0) + 1;
|
||||
for (let i = 0; i < fileds.length; i++) {
|
||||
temp = await xGrid.value?.insertAt(
|
||||
{
|
||||
columnDescription: fileds[i].desc,
|
||||
dataType: fileds[i].dataType,
|
||||
dbColumnName: fileds[i].name,
|
||||
decimalDigits: 0,
|
||||
isIdentity: 0,
|
||||
isNullable: fileds[i].isNullable === 0 ? 0 : 1,
|
||||
isPrimarykey: 0,
|
||||
length: (fileds[i] as any).length || 0,
|
||||
orderNo: colIndex,
|
||||
editable: true,
|
||||
isNew: true,
|
||||
},
|
||||
-1
|
||||
);
|
||||
colIndex++;
|
||||
});
|
||||
}
|
||||
|
||||
function handleColDelete(index: number) {
|
||||
state.tableData.splice(index, 1);
|
||||
}
|
||||
|
||||
// 上移
|
||||
function handleColUp(record: EditRecordRow, index: number) {
|
||||
if (record.isNew) {
|
||||
var data1 = ChangeExForArray(index, index - 1, state.tableData);
|
||||
return data1;
|
||||
}
|
||||
}
|
||||
if (temp && temp.row) await xGrid.value?.setEditCell(temp?.row, 'dbColumnName');
|
||||
};
|
||||
|
||||
// 下移
|
||||
function handleColDown(record: EditRecordRow, index: number) {
|
||||
if (record.isNew) {
|
||||
return ChangeExForArray(index, index + 1, state.tableData);
|
||||
}
|
||||
}
|
||||
// 删除行
|
||||
const deleteRow = (row: any) => {
|
||||
const fullData = xGrid.value?.getTableData().fullData;
|
||||
fullData?.filter((e: any) => e.orderNo > row.orderNo)?.forEach((e: any) => (e.orderNo = e.orderNo - 1));
|
||||
xGrid.value?.remove(row);
|
||||
};
|
||||
|
||||
function ChangeExForArray(index1: number, index2: number, array: Array<EditRecordRow>) {
|
||||
let maxIndex = state.tableData.length - 1; //最大索引
|
||||
if (index2 > maxIndex) {
|
||||
index2 = 0;
|
||||
// 删除选中行
|
||||
const deleteSelected = () => {
|
||||
const selected = xGrid.value?.getCheckboxRecords();
|
||||
const fullData = xGrid.value?.getTableData().fullData;
|
||||
// 更新序号
|
||||
for (let i = 0; i < selected!.length; i++) {
|
||||
fullData?.filter((e: any) => e.orderNo > selected![i].orderNo)?.forEach((e: any) => (e.orderNo = e.orderNo - 1));
|
||||
}
|
||||
if (index2 < 0) {
|
||||
index2 = maxIndex;
|
||||
}
|
||||
let temp = array[index1];
|
||||
array[index1] = array[index2];
|
||||
array[index2] = temp;
|
||||
return array;
|
||||
}
|
||||
// 移除选中
|
||||
xGrid.value?.removeCheckboxRow();
|
||||
};
|
||||
|
||||
// 导出对象
|
||||
defineExpose({ openDialog });
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.sys-dbTable-container :deep(.el-dialog__body) {
|
||||
height: 90vh;
|
||||
max-height: 90vh;
|
||||
}
|
||||
.xGrid-table-style .drag-btn {
|
||||
cursor: move;
|
||||
font-size: 20px;
|
||||
}
|
||||
.xGrid-table-style .vxe-body--row.sortable-ghost,
|
||||
.xGrid-table-style .vxe-body--row.sortable-chosen {
|
||||
background-color: #e40000 !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<el-form :model="state.ruleForm" ref="ruleFormRef" label-width="auto">
|
||||
<el-row :gutter="35">
|
||||
<el-row :gutter="10">
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
|
||||
<el-form-item label="列名称" prop="columnName" :rules="[{ required: true, message: '名称不能为空', trigger: 'blur' }]">
|
||||
<el-input v-model="state.ruleForm.columnName" placeholder="列名称" clearable />
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="sys-dbTable-container">
|
||||
<el-dialog v-model="state.isShowDialog" draggable :close-on-click-modal="false" width="700px">
|
||||
<el-dialog v-model="state.isShowDialog" draggable :close-on-click-modal="false" width="500px">
|
||||
<template #header>
|
||||
<div style="color: #fff">
|
||||
<el-icon size="16" style="margin-right: 3px; display: inline; vertical-align: middle"> <ele-Edit /> </el-icon>
|
||||
@ -8,7 +8,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<el-form :model="state.ruleForm" ref="ruleFormRef" label-width="auto">
|
||||
<el-row :gutter="35">
|
||||
<el-row :gutter="10">
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
|
||||
<el-form-item label="表名称" prop="tableName" :rules="[{ required: true, message: '名称不能为空', trigger: 'blur' }]">
|
||||
<el-input v-model="state.ruleForm.tableName" placeholder="表名称" clearable />
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<el-form :model="state.ruleForm" ref="ruleFormRef" label-width="auto">
|
||||
<el-row :gutter="35">
|
||||
<el-row :gutter="10">
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
|
||||
<el-form-item label="表名" prop="tableName" :rules="[{ required: true, message: '表名不能为空', trigger: 'blur' }]">
|
||||
<el-input disabled v-model="state.ruleForm.tableName" placeholder="表名" clearable />
|
||||
@ -49,6 +49,7 @@
|
||||
<script lang="ts" setup name="sysGenEntity">
|
||||
import { onMounted, reactive, ref } from 'vue';
|
||||
import { camelCase, upperFirst } from 'lodash-es';
|
||||
|
||||
import { getAPI } from '/@/utils/axios-utils';
|
||||
import { SysDatabaseApi, SysDictTypeApi } from '/@/api-services/api';
|
||||
|
||||
|
||||
@ -4,11 +4,11 @@
|
||||
<template #header>
|
||||
<div style="color: #fff">
|
||||
<el-icon size="16" style="margin-right: 3px; display: inline; vertical-align: middle"> <ele-Cpu /> </el-icon>
|
||||
<span> 生成种子数据 </span>
|
||||
<span> 生成种子数据【生成实体后必须重启服务才生效】</span>
|
||||
</div>
|
||||
</template>
|
||||
<el-form :model="state.ruleForm" ref="ruleFormRef" label-width="auto" :rules="state.rules">
|
||||
<el-row :gutter="35">
|
||||
<el-row :gutter="10">
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
|
||||
<el-form-item label="表名" prop="tableName" :rules="[{ required: true, message: '表名不能为空', trigger: 'blur' }]">
|
||||
<el-input disabled v-model="state.ruleForm.tableName" placeholder="表名" clearable />
|
||||
@ -46,7 +46,6 @@ import { getAPI } from '/@/utils/axios-utils';
|
||||
import { SysDatabaseApi, SysDictTypeApi } from '/@/api-services/api';
|
||||
|
||||
const emits = defineEmits(['handleQueryColumn']);
|
||||
|
||||
const props = defineProps({
|
||||
applicationNamespaces: { type: Array },
|
||||
});
|
||||
|
||||
@ -1,74 +1,73 @@
|
||||
<template>
|
||||
<div class="sys-database-container">
|
||||
<el-card shadow="hover" :body-style="{ paddingBottom: '0' }">
|
||||
<el-form :model="state.queryParams" ref="queryForm" :inline="true" v-loading="state.loading">
|
||||
<el-form-item label="库名">
|
||||
<el-select v-model="state.configId" placeholder="库名" filterable @change="handleQueryTable">
|
||||
<el-option v-for="item in state.dbData" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="表名">
|
||||
<el-select v-model="state.tableName" placeholder="表名" filterable clearable @change="handleQueryColumn">
|
||||
<el-option v-for="item in state.tableData" :key="item.name" :label="item.name + '[' + item.description + ']'" :value="item.name" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button-group>
|
||||
<el-button icon="ele-Plus" type="primary" @click="openAddTable"> 增加表 </el-button>
|
||||
<el-button icon="ele-Edit" @click="openEditTable"> 编辑表 </el-button>
|
||||
<el-button icon="ele-Delete" type="danger" @click="delTable" disabled> 删除表 </el-button>
|
||||
<el-button icon="ele-View" @click="visualTable"> 可视化 </el-button>
|
||||
</el-button-group>
|
||||
<el-button-group style="padding-left: 10px">
|
||||
<el-button icon="ele-Plus" @click="openAddColumn"> 增加列 </el-button>
|
||||
<el-button icon="ele-Plus" @click="openGenDialog"> 生成实体 </el-button>
|
||||
<el-button icon="ele-Plus" @click="openGenSeedDataDialog"> 生成种子 </el-button>
|
||||
</el-button-group>
|
||||
</el-form-item>
|
||||
<div class="sys-database-container" v-loading="options.loading">
|
||||
<el-card shadow="hover" :body-style="{ padding: '5px 5px 0 5px', display: 'flex', width: '100%', height: '100%', alignItems: 'start' }">
|
||||
<el-form :model="state.queryParams" ref="queryForm" :show-message="false" :inlineMessage="true" :label-width="'60px'" style="flex: 1 1 0%">
|
||||
<el-row :gutter="10">
|
||||
<el-col class="mb5" :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
|
||||
<el-form-item label="库名" prop="configId">
|
||||
<el-select v-model="state.configId" placeholder="库名" filterable @change="handleQueryTable">
|
||||
<el-option v-for="item in state.dbData" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col class="mb5" :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
|
||||
<el-form-item label="表名" prop="tableName">
|
||||
<el-select v-model="state.tableName" placeholder="表名" filterable clearable @change="handleQueryColumn">
|
||||
<el-option v-for="item in state.tableData" :key="item.name" :label="`${item.name}${item.description ? '[' + item.description + ']' : ''}`" :value="item.name" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<el-card class="full-table" shadow="hover" style="margin-top: 5px">
|
||||
<el-table :data="state.columnData" style="width: 100%" v-loading="state.loading1" border>
|
||||
<el-table-column type="index" label="序号" width="55" align="center" />
|
||||
<el-table-column prop="dbColumnName" label="字段名" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="dataType" label="数据类型" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="isPrimarykey" label="主键" width="70" align="center" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-tag type="success" v-if="scope.row.isPrimarykey === true">是</el-tag>
|
||||
<el-tag type="info" v-else>否</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="isIdentity" label="自增" width="70" align="center" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-tag type="success" v-if="scope.row.isIdentity === true">是</el-tag>
|
||||
<el-tag type="info" v-else>否</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="isNullable" label="可空" width="70" align="center" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-tag v-if="scope.row.isNullable === true">是</el-tag>
|
||||
<el-tag type="info" v-else>否</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="length" label="长度" width="70" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="decimalDigits" label="精度" width="70" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="defaultValue" label="默认值" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="columnDescription" label="描述" header-align="center" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="145" fixed="right" align="center" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-button icon="ele-Edit" size="small" text type="primary" @click="openEditColumn(scope.row)"> 编辑 </el-button>
|
||||
<el-button icon="ele-Delete" size="small" text type="danger" @click="delColumn(scope.row)"> 删除 </el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<vxe-grid ref="xGrid" class="xGrid-style" v-bind="options">
|
||||
<template #toolbar_buttons>
|
||||
<el-button-group>
|
||||
<el-button icon="ele-Plus" type="primary" @click="handleAddTable"> 增加表 </el-button>
|
||||
<el-button icon="ele-Edit" type="primary" @click="showEditTable"> 编辑表 </el-button>
|
||||
<el-button icon="ele-Delete" type="danger" @click="handleDeleteTable"> 删除表 </el-button>
|
||||
</el-button-group>
|
||||
<el-button-group style="padding-left: 12px; padding-right: 12px">
|
||||
<el-button icon="ele-Plus" @click="showAddColumn"> 增加列 </el-button>
|
||||
<el-button icon="ele-Plus" @click="showGenDialog"> 生成实体 </el-button>
|
||||
<el-button icon="ele-Plus" @click="showGenSeedDataDialog"> 生成种子 </el-button>
|
||||
</el-button-group>
|
||||
<el-button icon="ele-View" type="primary" @click="visualTable" plain> 可视化 </el-button>
|
||||
</template>
|
||||
<template #toolbar_tools> </template>
|
||||
<template #empty>
|
||||
<el-empty :image-size="200" />
|
||||
</template>
|
||||
<template #row_isPrimarykey="{ row }">
|
||||
<el-tag type="success" v-if="row.isPrimarykey === true">是</el-tag>
|
||||
<el-tag type="info" v-else>否</el-tag>
|
||||
</template>
|
||||
<template #row_isIdentity="{ row }">
|
||||
<el-tag type="success" v-if="row.isIdentity === true">是</el-tag>
|
||||
<el-tag type="info" v-else>否</el-tag>
|
||||
</template>
|
||||
<template #row_isNullable="{ row }">
|
||||
<el-tag v-if="row.isNullable === true">是</el-tag>
|
||||
<el-tag type="info" v-else>否</el-tag>
|
||||
</template>
|
||||
<template #row_buttons="{ row }">
|
||||
<el-tooltip content="编辑" placement="top">
|
||||
<el-button icon="ele-Edit" text type="primary" @click="showEditColumn(row)"> </el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="删除" placement="top">
|
||||
<el-button icon="ele-Delete" text type="danger" @click="handleDeleteColumn(row)"> </el-button>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
</vxe-grid>
|
||||
</el-card>
|
||||
|
||||
<EditTable ref="editTableRef" @handleQueryTable="handleQueryTable" />
|
||||
<EditColumn ref="editColumnRef" @handleQueryColumn="handleQueryColumn" />
|
||||
<AddTable ref="addTableRef" @addTableSubmitted="addTableSubmitted" />
|
||||
<AddColumn ref="addColumnRef" @handleQueryColumn="handleQueryColumn" />
|
||||
<GenEntity ref="genEntityRef" @handleQueryColumn="handleQueryColumn" :application-namespaces="state.appNamespaces" />
|
||||
<GenEntity ref="genEntityRef" @handleQueryColumn="handleQueryColumn" />
|
||||
<GenSeedData ref="genSeedDataRef" :application-namespaces="state.appNamespaces" />
|
||||
</div>
|
||||
</template>
|
||||
@ -77,6 +76,9 @@
|
||||
import { onMounted, reactive, ref } from 'vue';
|
||||
import { ElMessageBox, ElMessage } from 'element-plus';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { VxeGridInstance } from 'vxe-table';
|
||||
import { useVxeTable } from '/@/hooks/vxeTableOptionsHook';
|
||||
|
||||
import EditTable from '/@/views/system/database/component/editTable.vue';
|
||||
import EditColumn from '/@/views/system/database/component/editColumn.vue';
|
||||
import AddTable from '/@/views/system/database/component/addTable.vue';
|
||||
@ -88,6 +90,7 @@ import { getAPI } from '/@/utils/axios-utils';
|
||||
import { SysDatabaseApi, SysCodeGenApi } from '/@/api-services/api';
|
||||
import { DbColumnOutput, DbTableInfo, DbColumnInput, DeleteDbTableInput, DeleteDbColumnInput } from '/@/api-services/models';
|
||||
|
||||
const xGrid = ref<VxeGridInstance>();
|
||||
const editTableRef = ref<InstanceType<typeof EditTable>>();
|
||||
const editColumnRef = ref<InstanceType<typeof EditColumn>>();
|
||||
const addTableRef = ref<InstanceType<typeof AddTable>>();
|
||||
@ -97,72 +100,98 @@ const genSeedDataRef = ref<InstanceType<typeof GenSeedData>>();
|
||||
const router = useRouter();
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
loading1: false,
|
||||
dbData: [] as any,
|
||||
configId: '',
|
||||
tableData: [] as Array<DbTableInfo>,
|
||||
tableName: '',
|
||||
columnData: [] as Array<DbColumnOutput>,
|
||||
queryParams: {
|
||||
name: undefined,
|
||||
code: undefined,
|
||||
},
|
||||
visible: false,
|
||||
title: '',
|
||||
appNamespaces: [] as Array<String>, // 存储位置
|
||||
});
|
||||
|
||||
// 表格参数配置
|
||||
const options = useVxeTable<DbColumnOutput>({
|
||||
id: 'sysDatabase',
|
||||
name: '库表信息',
|
||||
columns: [
|
||||
// { type: 'checkbox', width: 40, fixed: 'left' },
|
||||
{ type: 'seq', title: '序号', width: 50, fixed: 'left' },
|
||||
{ field: 'dbColumnName', title: '字段名', minWidth: 200, showOverflow: 'tooltip' },
|
||||
{ field: 'dataType', title: '数据类型', minWidth: 120, showOverflow: 'tooltip' },
|
||||
{ field: 'isPrimarykey', title: '主键', minWidth: 70, slots: { default: 'row_isPrimarykey' } },
|
||||
{ field: 'isIdentity', title: '自增', minWidth: 70, slots: { default: 'row_isIdentity' } },
|
||||
{ field: 'isNullable', title: '可空', minWidth: 70, slots: { default: 'row_isNullable' } },
|
||||
{ field: 'length', title: '长度', minWidth: 80, showOverflow: 'tooltip' },
|
||||
{ field: 'decimalDigits', title: '精度', minWidth: 80, showOverflow: 'tooltip' },
|
||||
{ field: 'defaultValue', title: '默认值', minWidth: 80, showOverflow: 'tooltip' },
|
||||
{ field: 'columnDescription', title: '描述', minWidth: 200, showOverflow: 'tooltip' },
|
||||
{ title: '操作', fixed: 'right', width: 100, showOverflow: true, slots: { default: 'row_buttons' } },
|
||||
],
|
||||
enableExport: true,
|
||||
searchCallback: () => handleQueryColumn(),
|
||||
queryAllCallback: () => fetchData({ pageSize: 99999 }),
|
||||
});
|
||||
|
||||
// 页面初始化
|
||||
onMounted(async () => {
|
||||
state.loading = true;
|
||||
options.loading = true;
|
||||
var res = await getAPI(SysDatabaseApi).apiSysDatabaseListGet();
|
||||
state.dbData = res.data.result;
|
||||
state.loading = false;
|
||||
|
||||
options.loading = false;
|
||||
let appNamesRes = await getAPI(SysCodeGenApi).apiSysCodeGenApplicationNamespacesGet();
|
||||
state.appNamespaces = appNamesRes.data.result as Array<string>;
|
||||
});
|
||||
|
||||
// 查询操作
|
||||
const handleQueryColumn = async () => {
|
||||
if (state.tableName == '' || typeof state.tableName == 'undefined') {
|
||||
await xGrid.value?.loadData([]);
|
||||
options.loading = false;
|
||||
return;
|
||||
}
|
||||
options.loading = true;
|
||||
var res = await fetchData();
|
||||
await xGrid.value?.loadData(res.data.result ?? []);
|
||||
options.loading = false;
|
||||
};
|
||||
|
||||
// 获取数据
|
||||
const fetchData = async (tableParams?: any) => {
|
||||
return getAPI(SysDatabaseApi).apiSysDatabaseColumnListTableNameConfigIdGet(state.tableName, state.configId);
|
||||
};
|
||||
|
||||
// 增加表
|
||||
const addTableSubmitted = (e: any) => {
|
||||
handleQueryTable();
|
||||
const addTableSubmitted = async (e: any) => {
|
||||
await handleQueryTable();
|
||||
state.tableName = e;
|
||||
handleQueryColumn();
|
||||
await handleQueryColumn();
|
||||
};
|
||||
|
||||
// 表查询操作
|
||||
const handleQueryTable = async () => {
|
||||
state.tableName = '';
|
||||
state.columnData = [];
|
||||
state.loading = true;
|
||||
|
||||
xGrid.value?.loadData([]);
|
||||
options.loading = true;
|
||||
var res = await getAPI(SysDatabaseApi).apiSysDatabaseTableListConfigIdGet(state.configId);
|
||||
let tableData = res.data.result ?? [];
|
||||
state.tableData = [];
|
||||
tableData.forEach((element: any) => {
|
||||
//排除zero_开头的表
|
||||
// 排除zero_开头的表
|
||||
if (!element.name.startsWith('zero_')) {
|
||||
state.tableData.push(element);
|
||||
}
|
||||
});
|
||||
state.loading = false;
|
||||
};
|
||||
|
||||
// 列查询操作
|
||||
const handleQueryColumn = async () => {
|
||||
state.columnData = [];
|
||||
if (state.tableName == '' || typeof state.tableName == 'undefined') return;
|
||||
|
||||
state.loading1 = true;
|
||||
var res = await getAPI(SysDatabaseApi).apiSysDatabaseColumnListTableNameConfigIdGet(state.tableName, state.configId);
|
||||
state.columnData = res.data.result ?? [];
|
||||
state.loading1 = false;
|
||||
options.loading = false;
|
||||
};
|
||||
|
||||
// 打开表编辑页面
|
||||
const openEditTable = () => {
|
||||
const showEditTable = () => {
|
||||
if (state.configId == '' || state.tableName == '') {
|
||||
ElMessage({
|
||||
type: 'error',
|
||||
message: `请选择库名和表名!`,
|
||||
});
|
||||
ElMessage({ type: 'error', message: `请选择库名和表名!` });
|
||||
return;
|
||||
}
|
||||
var res = state.tableData.filter((u: any) => u.name == state.tableName);
|
||||
@ -176,12 +205,9 @@ const openEditTable = () => {
|
||||
};
|
||||
|
||||
// 打开实体生成页面
|
||||
const openGenDialog = () => {
|
||||
const showGenDialog = () => {
|
||||
if (state.configId == '' || state.tableName == '') {
|
||||
ElMessage({
|
||||
type: 'error',
|
||||
message: `请选择库名和表名!`,
|
||||
});
|
||||
ElMessage({ type: 'error', message: `请选择库名和表名!` });
|
||||
return;
|
||||
}
|
||||
// var res = state.tableData.filter((u: any) => u.name == state.tableName);
|
||||
@ -194,12 +220,9 @@ const openGenDialog = () => {
|
||||
};
|
||||
|
||||
// 生成种子数据页面
|
||||
const openGenSeedDataDialog = () => {
|
||||
const showGenSeedDataDialog = () => {
|
||||
if (state.configId == '' || state.tableName == '') {
|
||||
ElMessage({
|
||||
type: 'error',
|
||||
message: `请选择库名和表名!`,
|
||||
});
|
||||
ElMessage({ type: 'error', message: `请选择库名和表名!` });
|
||||
return;
|
||||
}
|
||||
var table: any = {
|
||||
@ -211,12 +234,9 @@ const openGenSeedDataDialog = () => {
|
||||
};
|
||||
|
||||
// 打开表增加页面
|
||||
const openAddTable = () => {
|
||||
const handleAddTable = () => {
|
||||
if (state.configId == '') {
|
||||
ElMessage({
|
||||
type: 'error',
|
||||
message: `请选择库名!`,
|
||||
});
|
||||
ElMessage({ type: 'error', message: `请选择库名!` });
|
||||
return;
|
||||
}
|
||||
var table: any = {
|
||||
@ -229,7 +249,7 @@ const openAddTable = () => {
|
||||
};
|
||||
|
||||
// 打开列编辑页面
|
||||
const openEditColumn = (row: any) => {
|
||||
const showEditColumn = (row: any) => {
|
||||
var column: any = {
|
||||
configId: state.configId,
|
||||
tableName: row.tableName,
|
||||
@ -241,12 +261,9 @@ const openEditColumn = (row: any) => {
|
||||
};
|
||||
|
||||
// 打开列增加页面
|
||||
const openAddColumn = () => {
|
||||
const showAddColumn = () => {
|
||||
if (state.configId == '' || state.tableName == '') {
|
||||
ElMessage({
|
||||
type: 'error',
|
||||
message: `请选择库名和表名!`,
|
||||
});
|
||||
ElMessage({ type: 'error', message: `请选择库名和表名!` });
|
||||
return;
|
||||
}
|
||||
const addRow: DbColumnInput = {
|
||||
@ -268,12 +285,9 @@ const openAddColumn = () => {
|
||||
};
|
||||
|
||||
// 删除表
|
||||
const delTable = () => {
|
||||
const handleDeleteTable = () => {
|
||||
if (state.tableName == '') {
|
||||
ElMessage({
|
||||
type: 'error',
|
||||
message: `请选择表名!`,
|
||||
});
|
||||
ElMessage({ type: 'error', message: `请选择表名!` });
|
||||
return;
|
||||
}
|
||||
ElMessageBox.confirm(`确定删除表:【${state.tableName}】?`, '提示', {
|
||||
@ -287,14 +301,14 @@ const delTable = () => {
|
||||
tableName: state.tableName,
|
||||
};
|
||||
await getAPI(SysDatabaseApi).apiSysDatabaseDeleteTablePost(deleteDbTableInput);
|
||||
handleQueryTable();
|
||||
await handleQueryTable();
|
||||
ElMessage.success('表删除成功');
|
||||
})
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
// 删除列
|
||||
const delColumn = (row: any) => {
|
||||
const handleDeleteColumn = (row: any) => {
|
||||
ElMessageBox.confirm(`确定删除列:【${row.dbColumnName}】?`, '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
@ -307,7 +321,7 @@ const delColumn = (row: any) => {
|
||||
dbColumnName: row.dbColumnName,
|
||||
};
|
||||
await getAPI(SysDatabaseApi).apiSysDatabaseDeleteColumnPost(eleteDbColumnInput);
|
||||
handleQueryTable();
|
||||
await handleQueryTable();
|
||||
ElMessage.success('列删除成功');
|
||||
})
|
||||
.catch(() => {});
|
||||
@ -316,10 +330,7 @@ const delColumn = (row: any) => {
|
||||
// 可视化表
|
||||
const visualTable = () => {
|
||||
if (state.configId == '') {
|
||||
ElMessage({
|
||||
type: 'error',
|
||||
message: `请选择库名!`,
|
||||
});
|
||||
ElMessage({ type: 'error', message: `请选择库名!` });
|
||||
return;
|
||||
}
|
||||
router.push(`/develop/database/visual?configId=${state.configId}`);
|
||||
|
||||
@ -1,14 +1,14 @@
|
||||
<template>
|
||||
<div class="sys-dictData-container">
|
||||
<el-dialog v-model="state.isShowDialog" draggable :close-on-click-modal="false" width="700px">
|
||||
<el-dialog v-model="state.visible" draggable overflow destroy-on-close width="700px">
|
||||
<template #header>
|
||||
<div style="color: #fff">
|
||||
<el-icon size="16" style="margin-right: 3px; display: inline; vertical-align: middle"> <ele-Edit /> </el-icon>
|
||||
<span> {{ props.title }} </span>
|
||||
</div>
|
||||
</template>
|
||||
<el-form :model="state.ruleForm" ref="ruleFormRef" label-width="auto">
|
||||
<el-row :gutter="35">
|
||||
<el-form :model="state.ruleForm" ref="formRef" label-width="auto">
|
||||
<el-row :gutter="10">
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
||||
<el-form-item label="字典值" prop="value" :rules="[{ required: true, message: '字典值不能为空', trigger: 'blur' }]">
|
||||
<el-input v-model="state.ruleForm.value" placeholder="字典值" clearable />
|
||||
@ -31,7 +31,7 @@
|
||||
<el-radio value="success"><el-tag type="success">success</el-tag></el-radio>
|
||||
<el-radio value="info"><el-tag type="info">info</el-tag></el-radio>
|
||||
<el-radio value="warning"><el-tag type="warning">warning</el-tag></el-radio>
|
||||
<el-radio value="danger"><el-tag type="danger" style="font:">danger</el-tag></el-radio>
|
||||
<el-radio value="danger"><el-tag type="danger">danger</el-tag></el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
@ -92,9 +92,9 @@ const props = defineProps({
|
||||
dictTypeId: Number,
|
||||
});
|
||||
const emits = defineEmits(['handleQuery', 'handleUpdate']);
|
||||
const ruleFormRef = ref();
|
||||
const formRef = ref();
|
||||
const state = reactive({
|
||||
isShowDialog: false,
|
||||
visible: false,
|
||||
ruleForm: {} as UpdateDictDataInput,
|
||||
});
|
||||
|
||||
@ -104,24 +104,24 @@ const openDialog = (row: any) => {
|
||||
if (JSON.stringify(row) == '{}') {
|
||||
state.ruleForm.dictTypeId = props.dictTypeId;
|
||||
}
|
||||
state.isShowDialog = true;
|
||||
ruleFormRef.value?.resetFields();
|
||||
state.visible = true;
|
||||
formRef.value?.resetFields();
|
||||
};
|
||||
|
||||
// 关闭弹窗
|
||||
const closeDialog = () => {
|
||||
emits('handleQuery');
|
||||
state.isShowDialog = false;
|
||||
state.visible = false;
|
||||
};
|
||||
|
||||
// 取消
|
||||
const cancel = () => {
|
||||
state.isShowDialog = false;
|
||||
state.visible = false;
|
||||
};
|
||||
|
||||
// 提交
|
||||
const submit = () => {
|
||||
ruleFormRef.value.validate(async (valid: boolean) => {
|
||||
formRef.value.validate(async (valid: boolean) => {
|
||||
if (!valid) return;
|
||||
if (state.ruleForm.id != undefined && state.ruleForm.id > 0) {
|
||||
await getAPI(SysDictDataApi).apiSysDictDataUpdatePost(state.ruleForm);
|
||||
|
||||
@ -1,14 +1,14 @@
|
||||
<template>
|
||||
<div class="sys-dictType-container">
|
||||
<el-dialog v-model="state.isShowDialog" draggable :close-on-click-modal="false" width="700px">
|
||||
<el-dialog v-model="state.visible" draggable overflow destroy-on-close width="700px">
|
||||
<template #header>
|
||||
<div style="color: #fff">
|
||||
<el-icon size="16" style="margin-right: 3px; display: inline; vertical-align: middle"> <ele-Edit /> </el-icon>
|
||||
<span> {{ props.title }} </span>
|
||||
</div>
|
||||
</template>
|
||||
<el-form :model="state.ruleForm" ref="ruleFormRef" label-width="auto">
|
||||
<el-row :gutter="35">
|
||||
<el-form :model="state.ruleForm" ref="formRef" label-width="auto">
|
||||
<el-row :gutter="10">
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
|
||||
<el-form-item label="字典名称" prop="name" :rules="[{ required: true, message: '字典名称不能为空', trigger: 'blur' }]">
|
||||
<el-input v-model="state.ruleForm.name" placeholder="字典名称" clearable />
|
||||
@ -60,33 +60,33 @@ const props = defineProps({
|
||||
title: String,
|
||||
});
|
||||
const emits = defineEmits(['handleQuery', 'handleUpdate']);
|
||||
const ruleFormRef = ref();
|
||||
const formRef = ref();
|
||||
const state = reactive({
|
||||
isShowDialog: false,
|
||||
visible: false,
|
||||
ruleForm: {} as UpdateDictTypeInput,
|
||||
});
|
||||
|
||||
// 打开弹窗
|
||||
const openDialog = (row: any) => {
|
||||
state.ruleForm = JSON.parse(JSON.stringify(row));
|
||||
state.isShowDialog = true;
|
||||
ruleFormRef.value?.resetFields();
|
||||
state.visible = true;
|
||||
formRef.value?.resetFields();
|
||||
};
|
||||
|
||||
// 关闭弹窗
|
||||
const closeDialog = () => {
|
||||
emits('handleQuery');
|
||||
state.isShowDialog = false;
|
||||
state.visible = false;
|
||||
};
|
||||
|
||||
// 取消
|
||||
const cancel = () => {
|
||||
state.isShowDialog = false;
|
||||
state.visible = false;
|
||||
};
|
||||
|
||||
// 提交
|
||||
const submit = () => {
|
||||
ruleFormRef.value.validate(async (valid: boolean) => {
|
||||
formRef.value.validate(async (valid: boolean) => {
|
||||
if (!valid) return;
|
||||
if (state.ruleForm.id != undefined && state.ruleForm.id > 0) {
|
||||
await getAPI(SysDictTypeApi).apiSysDictTypeUpdatePost(state.ruleForm);
|
||||
|
||||
@ -1,279 +1,281 @@
|
||||
<template>
|
||||
<div class="sys-dict-container">
|
||||
<div class="sys-dict-container" v-loading="options.loading">
|
||||
<el-row :gutter="8" style="width: 100%; height: 100%; flex: 1">
|
||||
<el-col :span="12" :xs="24" style="display: flex; height: 100%; flex: 1">
|
||||
<el-card class="full-table" shadow="hover" :body-style="{ height: 'calc(100% - 51px)' }">
|
||||
<template #header>
|
||||
<el-icon size="16" style="margin-right: 3px; display: inline; vertical-align: middle"><ele-Collection /></el-icon>字典
|
||||
</template>
|
||||
<el-form :model="state.queryDictTypeParams" ref="queryForm" :inline="true" @submit.native.prevent>
|
||||
<el-form-item label="名称">
|
||||
<el-input v-model="state.queryDictTypeParams.name" @keyup.enter.native="handleDictTypeQuery" placeholder="字典名称" clearable />
|
||||
</el-form-item>
|
||||
<!-- <el-form-item label="字典编码">
|
||||
<el-input v-model="state.queryDictTypeParams.code" placeholder="字典编码" clearable />
|
||||
</el-form-item> -->
|
||||
<el-form-item>
|
||||
<el-button-group>
|
||||
<el-button type="primary" icon="ele-Search" @click="handleDictTypeQuery" v-auth="'sysDictType:page'"> 查询 </el-button>
|
||||
<el-button icon="ele-Refresh" @click="resetDictTypeQuery"> 重置 </el-button>
|
||||
</el-button-group>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="ele-Plus" @click="openAddDictType" v-auth="'sysDictType:add'"> 新增 </el-button>
|
||||
</el-form-item>
|
||||
<el-col :span="12" :xs="24" class="full-height">
|
||||
<el-card shadow="hover" :body-style="{ padding: '5px 5px 0 5px', display: 'flex', width: '100%', height: '100%', alignItems: 'start' }">
|
||||
<el-form :model="state.queryParams" :show-message="false" :inlineMessage="true" :label-width="'60px'" style="flex: 1 1 0%">
|
||||
<el-row :gutter="10">
|
||||
<el-col class="mb5" :xs="24" :sm="24" :md="24" :lg="12" :xl="12">
|
||||
<el-form-item label="字典名称" prop="name">
|
||||
<el-input v-model="state.queryParams.name" placeholder="字典名称" clearable @keyup.enter.native="handleQuery(true)" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col class="mb5" :xs="24" :sm="24" :md="24" :lg="12" :xl="12">
|
||||
<el-form-item label="字典编码" prop="code">
|
||||
<el-input v-model="state.queryParams.code" placeholder="字典编码" clearable @keyup.enter.native="handleQuery(true)" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<el-divider style="height: calc(100% - 5px); margin: 0 10px" direction="vertical" />
|
||||
<el-row>
|
||||
<el-col>
|
||||
<el-button-group>
|
||||
<el-button type="primary" icon="ele-Search" @click="handleQuery(true)" v-auth="'sysDictType:page'" :loading="options.loading"> 查询 </el-button>
|
||||
<el-button icon="ele-Refresh" @click="resetQuery" :loading="options.loading"> 重置 </el-button>
|
||||
</el-button-group>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
|
||||
<el-table :data="state.dictTypeData" style="width: 100%" v-loading="state.typeLoading" @row-click="handleDictType" highlight-current-row border>
|
||||
<el-table-column type="index" label="序号" width="55" align="center" />
|
||||
<el-table-column prop="name" label="字典名称" min-width="120" header-align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="code" label="字典编码" min-width="140" header-align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="status" label="状态" width="70" align="center" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-tag type="success" v-if="scope.row.status === 1">启用</el-tag>
|
||||
<el-tag type="danger" v-else>禁用</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="orderNo" label="排序" width="60" align="center" show-overflow-tooltip />
|
||||
<el-table-column label="修改记录" width="100" align="center" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<ModifyRecord :data="scope.row" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="110" fixed="right" align="center">
|
||||
<template #default="scope">
|
||||
<el-tooltip content="字典值">
|
||||
<el-button icon="ele-Memo" size="small" text type="primary" @click="openDictDataDialog(scope.row)" v-auth="'sysDictType:page'"> </el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="编辑">
|
||||
<el-button icon="ele-Edit" size="small" text type="primary" @click="openEditDictType(scope.row)" v-auth="'sysDictType:update'"> </el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="删除">
|
||||
<el-button icon="ele-Delete" size="small" text type="danger" @click="delDictType(scope.row)" v-auth="'sysDictType:delete'"> </el-button>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
v-model:currentPage="state.tableDictTypeParams.page"
|
||||
v-model:page-size="state.tableDictTypeParams.pageSize"
|
||||
:total="state.tableDictTypeParams.total"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
small
|
||||
background
|
||||
@size-change="handleDictTypeSizeChange"
|
||||
@current-change="handleDictTypeCurrentChange"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
/>
|
||||
<el-card class="full-table" shadow="hover" style="margin-top: 5px">
|
||||
<vxe-grid ref="xGrid" class="xGrid-style" v-bind="options" @sort-change="sortChange" @cell-click="handleDictData">
|
||||
<template #toolbar_buttons>
|
||||
<el-icon size="16" style="margin-right: 3px; margin-top: 2px; display: inline; vertical-align: middle"><ele-Collection /></el-icon>字典
|
||||
<el-button type="primary" style="margin-left: 10px" icon="ele-Plus" @click="handleAdd" v-auth="'sysDictType:add'"> 新增 </el-button>
|
||||
</template>
|
||||
<template #toolbar_tools> </template>
|
||||
<template #empty>
|
||||
<el-empty :image-size="200" />
|
||||
</template>
|
||||
<template #row_status="{ row }">
|
||||
<el-tag v-if="row.status === 1" type="success">启用</el-tag>
|
||||
<el-tag v-else type="danger">禁用</el-tag>
|
||||
</template>
|
||||
<template #row_record="{ row }">
|
||||
<ModifyRecord :data="row" />
|
||||
</template>
|
||||
<template #row_buttons="{ row }">
|
||||
<el-tooltip content="编辑" placement="top">
|
||||
<el-button icon="ele-Edit" text type="primary" v-auth="'sysDictType:update'" @click="handleEdit(row)"> </el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="删除" placement="top">
|
||||
<el-button icon="ele-Delete" text type="danger" v-auth="'sysDictType:delete'" @click="handleDelete(row)"> </el-button>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
<template #pager>
|
||||
<vxe-pager
|
||||
:loading="options.loading"
|
||||
v-model:current-page="state.tableParams.page"
|
||||
v-model:page-size="state.tableParams.pageSize"
|
||||
:total="state.tableParams.total"
|
||||
@page-change="pageChange"
|
||||
/>
|
||||
</template>
|
||||
</vxe-grid>
|
||||
</el-card>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="12" :xs="24" style="display: flex; height: 100%; flex: 1">
|
||||
<el-card class="full-table" shadow="hover" :body-style="{ height: 'calc(100% - 51px)' }">
|
||||
<template #header>
|
||||
<el-icon size="16" style="margin-right: 3px; display: inline; vertical-align: middle"><ele-Collection /></el-icon>字典值【{{ state.editDictTypeName }}】
|
||||
</template>
|
||||
<el-form :model="state.queryDictDataParams" ref="queryForm" :inline="true" @submit.native.prevent>
|
||||
<!-- <el-form-item label="字典值">
|
||||
<el-input v-model="state.queryDictDataParams.value" placeholder="字典值" />
|
||||
</el-form-item> -->
|
||||
<el-form-item label="编码">
|
||||
<el-input v-model="state.queryDictDataParams.code" placeholder="编码" @keyup.enter="handleDictDataQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button-group>
|
||||
<el-button type="primary" icon="ele-Search" @click="handleDictDataQuery"> 查询 </el-button>
|
||||
<el-button icon="ele-Refresh" @click="resetDictDataQuery"> 重置 </el-button>
|
||||
</el-button-group>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="ele-Plus" @click="openAddDictData"> 新增 </el-button>
|
||||
</el-form-item>
|
||||
<el-col :span="12" :xs="24" class="full-height">
|
||||
<el-card shadow="hover" :body-style="{ padding: '5px 5px 0 5px', display: 'flex', width: '100%', height: '100%', alignItems: 'start' }">
|
||||
<el-form :model="state.queryDictParams" :show-message="false" :inlineMessage="true" :label-width="'60px'" style="flex: 1 1 0%">
|
||||
<el-row :gutter="10">
|
||||
<el-col class="mb5" :xs="24" :sm="24" :md="24" :lg="12" :xl="12">
|
||||
<el-form-item label="字典值" prop="value">
|
||||
<el-input v-model="state.queryDictParams.value" placeholder="字典值" clearable @keyup.enter.native="handleDictQuery(true)" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col class="mb5" :xs="24" :sm="24" :md="24" :lg="12" :xl="12">
|
||||
<el-form-item label="编码" prop="code">
|
||||
<el-input v-model="state.queryDictParams.code" placeholder="编码" clearable @keyup.enter.native="handleDictQuery(true)" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<el-divider style="height: calc(100% - 5px); margin: 0 10px" direction="vertical" />
|
||||
<el-row>
|
||||
<el-col>
|
||||
<el-button-group>
|
||||
<el-button type="primary" icon="ele-Search" @click="handleDictQuery(true)" v-auth="'sysDictType:page'" :loading="options.loading"> 查询 </el-button>
|
||||
<el-button icon="ele-Refresh" @click="resetDictQuery" :loading="options.loading"> 重置 </el-button>
|
||||
</el-button-group>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
|
||||
<el-table :data="state.dictDataData" style="width: 100%" v-loading="state.loading" border>
|
||||
<el-table-column type="index" label="序号" width="55" align="center" />
|
||||
<el-table-column prop="value" label="字典值" header-align="center" min-width="120" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-tag :type="scope.row.tagType" :style="scope.row.styleSetting" :class="scope.row.classSetting">{{ scope.row.value }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="code" label="编码" header-align="center" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="name" label="名称" header-align="center" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="extData" label="拓展数据" width="90" align="center">
|
||||
<template #default="scope">
|
||||
<el-tag type="warning" v-if="scope.row.extData == null || scope.row.extData == ''">空</el-tag>
|
||||
<el-tag type="success" v-else>有值</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="status" label="状态" width="70" align="center" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-tag type="success" v-if="scope.row.status === 1">启用</el-tag>
|
||||
<el-tag type="danger" v-else>禁用</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="orderNo" label="排序" width="60" align="center" show-overflow-tooltip />
|
||||
<el-table-column label="修改记录" width="100" align="center" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<ModifyRecord :data="scope.row" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="80" fixed="right" align="center" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-tooltip content="编辑">
|
||||
<el-button icon="ele-Edit" size="small" text type="primary" @click="openEditDictData(scope.row)"> </el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="删除">
|
||||
<el-button icon="ele-Delete" size="small" text type="danger" @click="delDictData(scope.row)"> </el-button>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
v-model:currentPage="state.tableDictDataParams.page"
|
||||
v-model:page-size="state.tableDictDataParams.pageSize"
|
||||
:total="state.tableDictDataParams.total"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
small
|
||||
background
|
||||
@size-change="handleDictDataSizeChange"
|
||||
@current-change="handleDictDataCurrentChange"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
/>
|
||||
<el-card class="full-table" shadow="hover" style="margin-top: 5px">
|
||||
<vxe-grid ref="xDictGrid" class="xGrid-style" v-bind="dictOptions" @sort-change="dictSortChange">
|
||||
<template #toolbar_buttons>
|
||||
<el-icon size="16" style="margin-right: 3px; margin-top: 2px; display: inline; vertical-align: middle"><ele-Collection /></el-icon>字典值
|
||||
<el-button type="primary" style="margin-left: 10px" icon="ele-Plus" @click="handleDictAdd" v-auth="'sysDictType:add'"> 新增 </el-button>
|
||||
</template>
|
||||
<template #toolbar_tools> </template>
|
||||
<template #empty>
|
||||
<el-empty :image-size="200" />
|
||||
</template>
|
||||
<template #row_value="{ row }">
|
||||
<el-tag :type="row.tagType" :style="row.styleSetting" :class="row.classSetting">{{ row.value }}</el-tag>
|
||||
</template>
|
||||
<template #row_extData="{ row }">
|
||||
<el-tag type="warning" v-if="row.extData == null || row.extData == ''">空</el-tag>
|
||||
<el-tag type="success" v-else>有值</el-tag>
|
||||
</template>
|
||||
<template #row_status="{ row }">
|
||||
<el-tag v-if="row.status === 1" type="success">启用</el-tag>
|
||||
<el-tag v-else type="danger">禁用</el-tag>
|
||||
</template>
|
||||
<template #row_record="{ row }">
|
||||
<ModifyRecord :data="row" />
|
||||
</template>
|
||||
<template #row_buttons="{ row }">
|
||||
<el-tooltip content="编辑" placement="top">
|
||||
<el-button icon="ele-Edit" text type="primary" v-auth="'sysDictType:update'" @click="handleDictEdit(row)"> </el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="删除" placement="top">
|
||||
<el-button icon="ele-Delete" text type="danger" v-auth="'sysDictType:delete'" @click="handleDictDelete(row)"> </el-button>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
<template #pager>
|
||||
<vxe-pager
|
||||
:loading="dictOptions.loading"
|
||||
v-model:current-page="state.tableDictParams.page"
|
||||
v-model:page-size="state.tableDictParams.pageSize"
|
||||
:total="state.tableDictParams.total"
|
||||
@page-change="dictPageChange"
|
||||
/>
|
||||
</template>
|
||||
</vxe-grid>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<EditDictType ref="editDictTypeRef" :title="state.editDictTypeTitle" @handleQuery="handleDictTypeQuery" @handleUpdate="updateDictSession" />
|
||||
<EditDictData ref="editDictDataRef" :title="state.editDictDataTitle" @handleQuery="handleDictDataQuery" @handleUpdate="updateDictSession" />
|
||||
<EditDictType ref="editRef" :title="state.title" @handleQuery="handleQuery(false)" @handleUpdate="updateDictSession" />
|
||||
<EditDcitData ref="editDictRef" :title="state.title" @handleQuery="handleDictQuery(false)" @handleUpdate="updateDictSession" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="sysDict">
|
||||
import { onMounted, reactive, ref } from 'vue';
|
||||
import { ElMessageBox, ElMessage } from 'element-plus';
|
||||
import { auth } from '/@/utils/authFunction';
|
||||
import { VxeGridInstance, VxePagerEvents, VxePagerDefines } from 'vxe-table';
|
||||
import { useVxeTable } from '/@/hooks/vxeTableOptionsHook';
|
||||
import { useUserInfo } from '/@/stores/userInfo';
|
||||
|
||||
import EditDictType from '/@/views/system/dict/component/editDictType.vue';
|
||||
import EditDictData from '/@/views/system/dict/component/editDictData.vue';
|
||||
import EditDcitData from '/@/views/system/dict/component/editDictData.vue';
|
||||
import ModifyRecord from '/@/components/table/modifyRecord.vue';
|
||||
|
||||
import { getAPI } from '/@/utils/axios-utils';
|
||||
import { Session } from '/@/utils/storage';
|
||||
import { useUserInfo } from '/@/stores/userInfo';
|
||||
import { SysDictTypeApi, SysDictDataApi } from '/@/api-services/api';
|
||||
import { SysDictType, SysDictData } from '/@/api-services/models';
|
||||
|
||||
const editDictTypeRef = ref<InstanceType<typeof EditDictType>>();
|
||||
const editDictDataRef = ref<InstanceType<typeof EditDictData>>();
|
||||
const xGrid = ref<VxeGridInstance>();
|
||||
const xDictGrid = ref<VxeGridInstance>();
|
||||
const editRef = ref<InstanceType<typeof EditDictType>>();
|
||||
const editDictRef = ref<InstanceType<typeof EditDcitData>>();
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
typeLoading: false,
|
||||
dictTypeData: [] as Array<SysDictType>,
|
||||
dictDataData: [] as Array<SysDictData>,
|
||||
queryDictTypeParams: {
|
||||
queryParams: {
|
||||
name: undefined,
|
||||
code: undefined,
|
||||
},
|
||||
tableDictTypeParams: {
|
||||
page: 1,
|
||||
pageSize: 20,
|
||||
total: 0 as any,
|
||||
},
|
||||
queryDictDataParams: {
|
||||
queryDictParams: {
|
||||
dictTypeId: undefined,
|
||||
value: undefined,
|
||||
code: undefined,
|
||||
dictTypeId: 0, // 字典类型Id
|
||||
},
|
||||
tableDictDataParams: {
|
||||
tableParams: {
|
||||
page: 1,
|
||||
pageSize: 20,
|
||||
pageSize: 50,
|
||||
field: 'orderNo', // 默认的排序字段
|
||||
order: 'aes', // 排序方向
|
||||
descStr: 'desc', // 降序排序的关键字符
|
||||
total: 0 as any,
|
||||
},
|
||||
editDictTypeTitle: '',
|
||||
editDictDataTitle: '',
|
||||
editDictTypeName: '',
|
||||
tableDictParams: {
|
||||
page: 1,
|
||||
pageSize: 50,
|
||||
field: 'orderNo', // 默认的排序字段
|
||||
order: 'aes', // 排序方向
|
||||
descStr: 'desc', // 降序排序的关键字符
|
||||
total: 0 as any,
|
||||
},
|
||||
title: '',
|
||||
});
|
||||
|
||||
// 表格参数配置-字典类型
|
||||
const options = useVxeTable<SysDictType>(
|
||||
{
|
||||
id: 'sysDict',
|
||||
name: '字典信息',
|
||||
columns: [
|
||||
{ type: 'seq', title: '序号', width: 60, fixed: 'left' },
|
||||
{ field: 'name', title: '字典名称', minWidth: 140, showOverflow: 'tooltip' },
|
||||
{ field: 'code', title: '字典编码', minWidth: 140, showOverflow: 'tooltip' },
|
||||
{ field: 'orderNo', title: '排序', width: 80, showOverflow: 'tooltip' },
|
||||
{ field: 'status', title: '状态', width: 80, showOverflow: 'tooltip', slots: { default: 'row_status' } },
|
||||
{ field: '', title: '修改记录', width: 100, showOverflow: 'tooltip', slots: { default: 'row_record' } },
|
||||
{ title: '操作', fixed: 'right', width: 100, showOverflow: true, slots: { default: 'row_buttons' } },
|
||||
],
|
||||
enableExport: auth('sysDictType:export'),
|
||||
searchCallback: () => handleQuery(),
|
||||
queryAllCallback: () => fetchData({ pageSize: 99999 }),
|
||||
},
|
||||
{ rowConfig: { isCurrent: true, isHover: true }, checkboxConfig: { range: true, highlight: false } }
|
||||
);
|
||||
|
||||
// 页面初始化
|
||||
onMounted(async () => {
|
||||
handleDictTypeQuery();
|
||||
await handleQuery();
|
||||
});
|
||||
|
||||
// 查询字典操作
|
||||
const handleDictTypeQuery = async () => {
|
||||
state.typeLoading = true;
|
||||
let params = Object.assign(state.queryDictTypeParams, state.tableDictTypeParams);
|
||||
var res = await getAPI(SysDictTypeApi).apiSysDictTypePagePost(params);
|
||||
state.dictTypeData = res.data.result?.items ?? [];
|
||||
state.tableDictTypeParams.total = res.data.result?.total;
|
||||
state.typeLoading = false;
|
||||
// 查询操作
|
||||
const handleQuery = async (reset = false) => {
|
||||
options.loading = true;
|
||||
if (reset) state.tableParams.page = 1;
|
||||
var res = await fetchData(null);
|
||||
await xGrid.value?.loadData(res.data.result?.items ?? []);
|
||||
state.tableParams.total = res.data.result?.total;
|
||||
options.loading = false;
|
||||
};
|
||||
|
||||
// 查询字典值操作
|
||||
const handleDictDataQuery = async () => {
|
||||
state.loading = true;
|
||||
let params = Object.assign(state.queryDictDataParams, state.tableDictDataParams);
|
||||
var res = await getAPI(SysDictDataApi).apiSysDictDataPagePost(params);
|
||||
state.dictDataData = res.data.result?.items ?? [];
|
||||
state.tableDictDataParams.total = res.data.result?.total;
|
||||
state.loading = false;
|
||||
// 获取数据
|
||||
const fetchData = async (tableParams: any) => {
|
||||
let params = Object.assign(state.queryParams, state.tableParams, tableParams);
|
||||
return getAPI(SysDictTypeApi).apiSysDictTypePagePost(params);
|
||||
};
|
||||
|
||||
// 点击表格
|
||||
const handleDictType = (row: any, event: any, column: any) => {
|
||||
openDictDataDialog(row);
|
||||
// 重置操作
|
||||
const resetQuery = async () => {
|
||||
state.queryParams.code = undefined;
|
||||
state.queryParams.name = undefined;
|
||||
await handleQuery(true);
|
||||
};
|
||||
|
||||
// 重置字典操作
|
||||
const resetDictTypeQuery = () => {
|
||||
state.queryDictTypeParams.name = undefined;
|
||||
state.queryDictTypeParams.code = undefined;
|
||||
handleDictTypeQuery();
|
||||
// 改变页码序号或页面容量
|
||||
const pageChange: VxePagerEvents.PageChange = async ({ currentPage, pageSize }: VxePagerDefines.PageChangeEventParams) => {
|
||||
state.tableParams.page = currentPage;
|
||||
state.tableParams.pageSize = pageSize;
|
||||
await handleQuery();
|
||||
};
|
||||
|
||||
// 重置字典值操作
|
||||
const resetDictDataQuery = () => {
|
||||
state.queryDictDataParams.value = undefined;
|
||||
state.queryDictDataParams.code = undefined;
|
||||
handleDictDataQuery();
|
||||
// 列排序
|
||||
const sortChange = async (options: any) => {
|
||||
state.tableParams.field = options.field;
|
||||
state.tableParams.order = options.order;
|
||||
await handleQuery();
|
||||
};
|
||||
|
||||
// 打开新增字典页面
|
||||
const openAddDictType = () => {
|
||||
state.editDictTypeTitle = '添加字典';
|
||||
editDictTypeRef.value?.openDialog({ status: 1, orderNo: 100 });
|
||||
// 打开新增页面
|
||||
const handleAdd = () => {
|
||||
state.title = '添加字典';
|
||||
editRef.value?.openDialog({ status: 1, orderNo: 100 });
|
||||
};
|
||||
|
||||
// 打开新增字典值页面
|
||||
const openAddDictData = () => {
|
||||
if (!state.queryDictDataParams.dictTypeId) {
|
||||
ElMessage.warning('请选择字典');
|
||||
return;
|
||||
}
|
||||
|
||||
state.editDictDataTitle = '添加字典值';
|
||||
editDictDataRef.value?.openDialog({ status: 1, orderNo: 100, dictTypeId: state.queryDictDataParams.dictTypeId });
|
||||
// 打开编辑页面
|
||||
const handleEdit = (row: any) => {
|
||||
state.title = '编辑字典';
|
||||
editRef.value?.openDialog(row);
|
||||
};
|
||||
|
||||
// 打开编辑字典页面
|
||||
const openEditDictType = (row: any) => {
|
||||
state.editDictTypeTitle = '编辑字典';
|
||||
editDictTypeRef.value?.openDialog(row);
|
||||
// 点击表格,加载字典值表格数据
|
||||
const handleDictData = async (scope: any) => {
|
||||
state.queryDictParams.dictTypeId = scope.row.id;
|
||||
await handleDictQuery(true);
|
||||
};
|
||||
|
||||
// 打开编辑字典值页面
|
||||
const openEditDictData = (row: any) => {
|
||||
state.editDictDataTitle = '编辑字典值';
|
||||
editDictDataRef.value?.openDialog(row);
|
||||
};
|
||||
|
||||
// 打开字典值页面
|
||||
const openDictDataDialog = (row: any) => {
|
||||
state.editDictTypeName = row.name;
|
||||
state.queryDictDataParams.dictTypeId = row.id;
|
||||
handleDictDataQuery();
|
||||
};
|
||||
|
||||
// 删除字典
|
||||
const delDictType = (row: any) => {
|
||||
// 删除
|
||||
const handleDelete = (row: any) => {
|
||||
ElMessageBox.confirm(`确定删除字典:【${row.name}】?`, '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
@ -281,15 +283,78 @@ const delDictType = (row: any) => {
|
||||
})
|
||||
.then(async () => {
|
||||
await getAPI(SysDictTypeApi).apiSysDictTypeDeletePost({ id: row.id });
|
||||
handleDictTypeQuery();
|
||||
handleQuery();
|
||||
updateDictSession();
|
||||
xDictGrid.value?.loadData([]);
|
||||
state.tableDictParams.total = 0;
|
||||
ElMessage.success('删除成功');
|
||||
})
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
// 删除字典值
|
||||
const delDictData = (row: any) => {
|
||||
// 表格参数配置-字典值
|
||||
const dictOptions = useVxeTable<SysDictData>(
|
||||
{
|
||||
id: 'dictInfo',
|
||||
name: '字典值信息',
|
||||
columns: [
|
||||
{ type: 'seq', title: '序号', width: 60, fixed: 'left' },
|
||||
{ field: 'value', title: '字典值', minWidth: 90, showOverflow: 'tooltip', slots: { default: 'row_value' } },
|
||||
{ field: 'code', title: '编码', minWidth: 120, showOverflow: 'tooltip' },
|
||||
{ field: 'name', title: '名称', minWidth: 120, showOverflow: 'tooltip' },
|
||||
{ field: 'extData', title: '拓展数据', showOverflow: 'tooltip', slots: { default: 'row_extData' } },
|
||||
{ field: 'orderNo', title: '排序', width: 80, showOverflow: 'tooltip' },
|
||||
{ field: 'status', title: '状态', width: 80, showOverflow: 'tooltip', slots: { default: 'row_status' } },
|
||||
{ field: '', title: '修改记录', width: 100, showOverflow: 'tooltip', slots: { default: 'row_record' } },
|
||||
{ title: '操作', fixed: 'right', width: 100, showOverflow: true, slots: { default: 'row_buttons' } },
|
||||
],
|
||||
enableExport: auth('sysDictType:export'),
|
||||
searchCallback: () => handleDictQuery(),
|
||||
queryAllCallback: () => fetchDictData({ pageSize: 99999 }),
|
||||
},
|
||||
{ loading: false, rowConfig: { isCurrent: true, isHover: true }, checkboxConfig: { range: true, highlight: false } }
|
||||
);
|
||||
|
||||
// 查询操作
|
||||
const handleDictQuery = async (reset = false) => {
|
||||
dictOptions.loading = true;
|
||||
if (reset) state.tableDictParams.page = 1;
|
||||
var res = await fetchDictData(null);
|
||||
xDictGrid.value?.loadData(res.data.result?.items ?? []);
|
||||
state.tableDictParams.total = res.data.result?.total;
|
||||
dictOptions.loading = false;
|
||||
};
|
||||
|
||||
// 获取数据
|
||||
const fetchDictData = async (tableParams: any) => {
|
||||
let params = Object.assign(state.queryDictParams, state.tableDictParams, tableParams);
|
||||
return getAPI(SysDictDataApi).apiSysDictDataPagePost(params);
|
||||
};
|
||||
|
||||
// 重置操作
|
||||
const resetDictQuery = async () => {
|
||||
state.queryDictParams.value = undefined;
|
||||
state.queryDictParams.code = undefined;
|
||||
await handleDictQuery(true);
|
||||
};
|
||||
|
||||
const handleDictAdd = () => {
|
||||
if (!state.queryDictParams.dictTypeId) {
|
||||
ElMessage.warning('请选择字典');
|
||||
return;
|
||||
}
|
||||
state.title = '添加字典值';
|
||||
editDictRef.value?.openDialog({ status: 1, orderNo: 100, dictTypeId: state.queryDictParams.dictTypeId });
|
||||
};
|
||||
|
||||
// 打开编辑页面
|
||||
const handleDictEdit = (row: any) => {
|
||||
state.title = '编辑字典值';
|
||||
editDictRef.value?.openDialog(row);
|
||||
};
|
||||
|
||||
// 删除
|
||||
const handleDictDelete = (row: any) => {
|
||||
ElMessageBox.confirm(`确定删除字典值:【${row.value}】?`, '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
@ -297,35 +362,25 @@ const delDictData = (row: any) => {
|
||||
})
|
||||
.then(async () => {
|
||||
await getAPI(SysDictDataApi).apiSysDictDataDeletePost({ id: row.id });
|
||||
handleDictDataQuery();
|
||||
handleDictQuery();
|
||||
updateDictSession();
|
||||
ElMessage.success('删除成功');
|
||||
})
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
// 改变字典页面容量
|
||||
const handleDictTypeSizeChange = (val: number) => {
|
||||
state.tableDictTypeParams.pageSize = val;
|
||||
handleDictTypeQuery();
|
||||
// 改变字典值页码序号或页面容量
|
||||
const dictPageChange: VxePagerEvents.PageChange = async ({ currentPage, pageSize }: VxePagerDefines.PageChangeEventParams) => {
|
||||
state.tableDictParams.page = currentPage;
|
||||
state.tableDictParams.pageSize = pageSize;
|
||||
await handleDictQuery();
|
||||
};
|
||||
|
||||
// 改变字典页码序号
|
||||
const handleDictTypeCurrentChange = (val: number) => {
|
||||
state.tableDictTypeParams.page = val;
|
||||
handleDictTypeQuery();
|
||||
};
|
||||
|
||||
// 改变字典值页面容量
|
||||
const handleDictDataSizeChange = (val: number) => {
|
||||
state.tableDictDataParams.pageSize = val;
|
||||
handleDictDataQuery();
|
||||
};
|
||||
|
||||
// 改变字典值页码序号
|
||||
const handleDictDataCurrentChange = (val: number) => {
|
||||
state.tableDictDataParams.page = val;
|
||||
handleDictDataQuery();
|
||||
// 字典值列排序
|
||||
const dictSortChange = async (options: any) => {
|
||||
state.tableDictParams.field = options.field;
|
||||
state.tableDictParams.order = options.order;
|
||||
await handleDictQuery();
|
||||
};
|
||||
|
||||
// 更新前端字典缓存
|
||||
@ -337,3 +392,11 @@ const updateDictSession = async () => {
|
||||
await useUserInfo().setDictList();
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.full-height {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="sys-file-container">
|
||||
<el-dialog v-model="state.isShowDialog" draggable :close-on-click-modal="false" width="500px">
|
||||
<el-dialog v-model="state.isShowDialog" draggable overflow destroy-on-close width="500px">
|
||||
<template #header>
|
||||
<div style="color: #fff">
|
||||
<el-icon size="16" style="margin-right: 3px; display: inline; vertical-align: middle"> <ele-Edit /> </el-icon>
|
||||
|
||||
@ -1,89 +1,90 @@
|
||||
<template>
|
||||
<div class="sys-file-container">
|
||||
<el-card shadow="hover" :body-style="{ paddingBottom: '0' }">
|
||||
<el-form :model="state.queryParams" ref="queryForm" :inline="true">
|
||||
<el-form-item label="文件名称" prop="fileName">
|
||||
<el-input v-model="state.queryParams.fileName" placeholder="文件名称" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="开始时间" prop="name">
|
||||
<el-date-picker v-model="state.queryParams.startTime" type="datetime" placeholder="开始时间" value-format="YYYY-MM-DD HH:mm:ss" />
|
||||
</el-form-item>
|
||||
<el-form-item label="结束时间" prop="code">
|
||||
<el-date-picker v-model="state.queryParams.endTime" type="datetime" placeholder="结束时间" value-format="YYYY-MM-DD HH:mm:ss" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button-group>
|
||||
<el-button type="primary" icon="ele-Search" @click="handleQuery" v-auth="'sysFile:page'"> 查询 </el-button>
|
||||
<el-button icon="ele-Refresh" @click="resetQuery"> 重置 </el-button>
|
||||
</el-button-group>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="ele-Plus" @click="openUploadDialog" v-auth="'sysFile:uploadFile'"> 上传 </el-button>
|
||||
</el-form-item>
|
||||
<div class="sys-file-container" v-loading="options.loading">
|
||||
<el-card shadow="hover" :body-style="{ padding: '5px 5px 0 5px', display: 'flex', width: '100%', height: '100%', alignItems: 'start' }">
|
||||
<el-form :model="state.queryParams" ref="queryForm" :show-message="false" :inlineMessage="true" :label-width="'60px'" style="flex: 1 1 0%">
|
||||
<el-row :gutter="10">
|
||||
<el-col class="mb5" :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
|
||||
<el-form-item label="文件名称" prop="fileName">
|
||||
<el-input v-model="state.queryParams.fileName" placeholder="文件名称" clearable @keyup.enter.native="handleQuery(true)" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col class="mb5" :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
|
||||
<el-form-item label="开始时间" prop="name">
|
||||
<el-date-picker v-model="state.queryParams.startTime" type="datetime" placeholder="开始时间" value-format="YYYY-MM-DD HH:mm:ss" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col class="mb5" :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
|
||||
<el-form-item label="结束时间" prop="code">
|
||||
<el-date-picker v-model="state.queryParams.endTime" type="datetime" placeholder="结束时间" value-format="YYYY-MM-DD HH:mm:ss" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
|
||||
<el-divider style="height: calc(100% - 5px); margin: 0 10px" direction="vertical" />
|
||||
|
||||
<el-row>
|
||||
<el-col>
|
||||
<el-button-group>
|
||||
<el-button type="primary" icon="ele-Search" @click="handleQuery(true)" v-auth="'sysFile:page'" :loading="options.loading"> 查询 </el-button>
|
||||
<el-button icon="ele-Refresh" @click="resetQuery" :loading="options.loading"> 重置 </el-button>
|
||||
</el-button-group>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
|
||||
<el-card class="full-table" shadow="hover" style="margin-top: 5px">
|
||||
<el-table :data="state.fileData" style="width: 100%" v-loading="state.loading" border>
|
||||
<el-table-column type="index" label="序号" width="55" align="center" />
|
||||
<el-table-column prop="fileName" label="名称" min-width="150" header-align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="suffix" label="后缀" align="center" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-tag round>{{ scope.row.suffix }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="sizeKb" label="大小kb" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="url" label="预览" align="center">
|
||||
<template #default="scope">
|
||||
<el-image
|
||||
style="width: 60px; height: 60px"
|
||||
:src="getFileUrl(scope.row)"
|
||||
alt="无法预览"
|
||||
:lazy="true"
|
||||
:hide-on-click-modal="true"
|
||||
:preview-src-list="[getFileUrl(scope.row)]"
|
||||
:initial-index="0"
|
||||
fit="scale-down"
|
||||
preview-teleported
|
||||
>
|
||||
<template #error> </template>
|
||||
</el-image>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="bucketName" label="存储位置" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="id" label="存储标识" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="fileType" label="文件类型" min-width="100" header-align="center" show-overflow-tooltip />
|
||||
<el-table-column type="relationName" label="关联对象名称" min-width="150" align="center" />
|
||||
<el-table-column type="relationId" label="关联对象Id" align="center" />
|
||||
<el-table-column type="belongId" label="所属Id" align="center" />
|
||||
<el-table-column label="修改记录" width="100" align="center" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<ModifyRecord :data="scope.row" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="260" fixed="right" align="center" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-button icon="ele-View" size="small" text type="primary" @click="openFilePreviewDialog(scope.row)" v-auth="'sysFile:delete'"> 预览 </el-button>
|
||||
<el-button icon="ele-Download" size="small" text type="primary" @click="downloadFile(scope.row)" v-auth="'sysFile:downloadFile'"> 下载 </el-button>
|
||||
<el-button icon="ele-Delete" size="small" text type="danger" @click="delFile(scope.row)" v-auth="'sysFile:delete'"> 删除 </el-button>
|
||||
<el-button icon="ele-Edit" size="small" text type="primary" @click="openEditSysFile(scope.row)" v-auth="'sysFile:update'"> 编辑 </el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
v-model:currentPage="state.tableParams.page"
|
||||
v-model:page-size="state.tableParams.pageSize"
|
||||
:total="state.tableParams.total"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
small
|
||||
background
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
/>
|
||||
<vxe-grid ref="xGrid" class="xGrid-style" v-bind="options" @sort-change="sortChange">
|
||||
<template #toolbar_buttons>
|
||||
<el-button type="primary" icon="ele-Plus" @click="showUpload" v-auth="'sysFile:uploadFile'"> 上传 </el-button>
|
||||
</template>
|
||||
<template #toolbar_tools> </template>
|
||||
<template #empty>
|
||||
<el-empty :image-size="200" />
|
||||
</template>
|
||||
<template #row_suffix="{ row }">
|
||||
<el-tag round>{{ row.suffix }}</el-tag>
|
||||
</template>
|
||||
<template #row_url="{ row }">
|
||||
<el-image
|
||||
style="width: 60px; height: 60px"
|
||||
:src="fetchFileUrl(row)"
|
||||
alt="无法预览"
|
||||
lazy
|
||||
hide-on-click-modal
|
||||
:preview-src-list="[fetchFileUrl(row)]"
|
||||
:initial-index="0"
|
||||
fit="scale-down"
|
||||
preview-teleported
|
||||
></el-image>
|
||||
</template>
|
||||
<template #row_buttons="{ row }">
|
||||
<el-tooltip content="编辑" placement="top">
|
||||
<el-button icon="ele-Edit" size="small" text type="primary" @click="handleEdit(row)" v-auth="'sysFile:update'" />
|
||||
</el-tooltip>
|
||||
<el-tooltip content="删除" placement="top">
|
||||
<el-button icon="ele-Delete" size="small" text type="danger" @click="handleDelete(row)" v-auth="'sysFile:delete'" />
|
||||
</el-tooltip>
|
||||
<el-tooltip content="预览" placement="top">
|
||||
<el-button icon="ele-View" size="small" text type="primary" @click="showPreviewDialog(row)" v-auth="'sysFile:delete'" />
|
||||
</el-tooltip>
|
||||
<el-tooltip content="下载" placement="top">
|
||||
<el-button icon="ele-Download" size="small" text type="primary" @click="handleDownload(row)" v-auth="'sysFile:downloadFile'" />
|
||||
</el-tooltip>
|
||||
</template>
|
||||
<template #pager>
|
||||
<vxe-pager
|
||||
:loading="options.loading"
|
||||
v-model:current-page="state.tableParams.page"
|
||||
v-model:page-size="state.tableParams.pageSize"
|
||||
:total="state.tableParams.total"
|
||||
@page-change="pageChange"
|
||||
/>
|
||||
</template>
|
||||
</vxe-grid>
|
||||
</el-card>
|
||||
|
||||
<el-dialog v-model="state.dialogUploadVisible" :lock-scroll="false" draggable width="400px">
|
||||
<el-dialog v-model="state.visible" :lock-scroll="false" draggable overflow destroy-on-close width="400px">
|
||||
<template #header>
|
||||
<div style="color: #fff">
|
||||
<el-icon size="16" style="margin-right: 3px; display: inline; vertical-align: middle"> <ele-UploadFilled /> </el-icon>
|
||||
@ -108,49 +109,50 @@
|
||||
</div>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="state.dialogUploadVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="uploadFile">确定</el-button>
|
||||
<el-button @click="state.visible = false">取消</el-button>
|
||||
<el-button type="primary" @click="handleUpload">确定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<el-drawer :title="state.fileName" v-model="state.dialogDocxVisible" size="50%" destroy-on-close>
|
||||
<vue-office-docx :src="state.docxUrl" style="height: 100vh" @rendered="renderedHandler" @error="errorHandler" />
|
||||
<el-drawer :title="state.fileName" v-model="state.docxVisible" size="70%" destroy-on-close>
|
||||
<vue-office-docx :src="state.docxUrl" style="height: calc(100vh - 37px)" @rendered="handleRendered" @error="handleError" />
|
||||
</el-drawer>
|
||||
<el-drawer :title="state.fileName" v-model="state.dialogXlsxVisible" size="50%" destroy-on-close>
|
||||
<vue-office-excel :src="state.excelUrl" style="height: 100vh" @rendered="renderedHandler" @error="errorHandler" />
|
||||
<el-drawer :title="state.fileName" v-model="state.xlsxVisible" size="70%" destroy-on-close>
|
||||
<vue-office-excel :src="state.excelUrl" style="height: calc(100vh - 37px)" @rendered="handleRendered" @error="handleError" />
|
||||
</el-drawer>
|
||||
<el-drawer :title="state.fileName" v-model="state.dialogPdfVisible" size="50%" destroy-on-close>
|
||||
<vue-office-pdf :src="state.pdfUrl" style="height: 100vh" @rendered="renderedHandler" @error="errorHandler" />
|
||||
<el-drawer :title="state.fileName" v-model="state.pdfVisible" size="70%" destroy-on-close>
|
||||
<vue-office-pdf :src="state.pdfUrl" style="height: calc(100vh - 37px)" @rendered="handleRendered" @error="handleError" />
|
||||
</el-drawer>
|
||||
<el-image-viewer v-if="state.showViewer" :url-list="state.previewList" :hideOnClickModal="true" @close="state.showViewer = false"></el-image-viewer>
|
||||
<EditSysFile ref="editSysFileRef" title="编辑文件" @handleQuery="handleQuery" />
|
||||
<EditFile ref="editRef" title="编辑文件" @handleQuery="handleQuery" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="sysFile">
|
||||
import { onMounted, reactive, ref } from 'vue';
|
||||
import { ElMessageBox, ElMessage, UploadInstance } from 'element-plus';
|
||||
import { auth } from '/@/utils/authFunction';
|
||||
import { VxeGridInstance, VxePagerEvents, VxePagerDefines } from 'vxe-table';
|
||||
import { useVxeTable } from '/@/hooks/vxeTableOptionsHook';
|
||||
import { downloadByUrl } from '/@/utils/download';
|
||||
import VueOfficeDocx from '@vue-office/docx';
|
||||
import VueOfficeExcel from '@vue-office/excel';
|
||||
import VueOfficePdf from '@vue-office/pdf';
|
||||
import '@vue-office/docx/lib/index.css';
|
||||
import '@vue-office/excel/lib/index.css';
|
||||
|
||||
import EditSysFile from '/@/views/system/file/component/editSysfile.vue';
|
||||
import ModifyRecord from '/@/components/table/modifyRecord.vue';
|
||||
import EditFile from '/@/views/system/file/component/editSysfile.vue';
|
||||
|
||||
import { downloadByUrl } from '/@/utils/download';
|
||||
import { getAPI } from '/@/utils/axios-utils';
|
||||
import { SysFileApi } from '/@/api-services/api';
|
||||
import { SysFile } from '/@/api-services/models';
|
||||
|
||||
const xGrid = ref<VxeGridInstance>();
|
||||
// const baseUrl = window.__env__.VITE_API_URL;
|
||||
const uploadRef = ref<UploadInstance>();
|
||||
const editSysFileRef = ref<InstanceType<typeof EditSysFile>>();
|
||||
const editRef = ref<InstanceType<typeof EditFile>>();
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
fileData: [] as Array<SysFile>,
|
||||
queryParams: {
|
||||
fileName: undefined,
|
||||
startTime: undefined,
|
||||
@ -158,15 +160,18 @@ const state = reactive({
|
||||
},
|
||||
tableParams: {
|
||||
page: 1,
|
||||
pageSize: 10,
|
||||
pageSize: 50,
|
||||
field: 'id', // 默认的排序字段
|
||||
order: 'aes', // 排序方向
|
||||
descStr: 'desc', // 降序排序的关键字符
|
||||
total: 0 as any,
|
||||
},
|
||||
dialogUploadVisible: false,
|
||||
visible: false,
|
||||
diaglogEditFile: false,
|
||||
fileList: [] as any,
|
||||
dialogDocxVisible: false,
|
||||
dialogXlsxVisible: false,
|
||||
dialogPdfVisible: false,
|
||||
docxVisible: false,
|
||||
xlsxVisible: false,
|
||||
pdfVisible: false,
|
||||
showViewer: false,
|
||||
docxUrl: '',
|
||||
excelUrl: '',
|
||||
@ -176,21 +181,55 @@ const state = reactive({
|
||||
previewList: [] as string[],
|
||||
});
|
||||
|
||||
// 表格参数配置
|
||||
const options = useVxeTable<SysFile>(
|
||||
{
|
||||
id: 'sysFile',
|
||||
name: '文件信息',
|
||||
columns: [
|
||||
// { type: 'checkbox', width: 40, fixed: 'left' },
|
||||
{ type: 'seq', title: '序号', width: 60, fixed: 'left' },
|
||||
{ field: 'fileName', title: '名称', minWidth: 200, showOverflow: 'tooltip' },
|
||||
{ field: 'suffix', title: '后缀', minWidth: 80, showOverflow: 'tooltip', slots: { default: 'row_suffix' } },
|
||||
{ field: 'sizeKb', title: '大小(KB)', minWidth: 100, showOverflow: 'tooltip' },
|
||||
{ field: 'url', title: '预览', minWidth: 100, slots: { default: 'row_url' } },
|
||||
{ field: 'bucketName', title: '存储位置', minWidth: 180, showOverflow: 'tooltip' },
|
||||
{ field: 'id', title: '存储标识', minWidth: 120, showOverflow: 'tooltip' },
|
||||
{ field: 'fileType', title: '文件类型', minWidth: 140, showOverflow: 'tooltip' },
|
||||
{ field: 'relationName', title: '关联对象名称', minWidth: 150, showOverflow: 'tooltip' },
|
||||
{ field: 'relationId', title: '关联对象ID', minWidth: 150, showOverflow: 'tooltip' },
|
||||
{ field: 'belongId', title: '所属ID', minWidth: 120, showOverflow: 'tooltip' },
|
||||
// { field: 'userName', title: '上传者', minWidth: 150, showOverflow: 'tooltip', sortable: true },
|
||||
{ field: 'createTime', title: '创建时间', minWidth: 150, showOverflow: 'tooltip' },
|
||||
{ field: 'remark', title: '备注', minWidth: 200, showOverflow: 'tooltip' },
|
||||
{ title: '操作', fixed: 'right', width: 150, showOverflow: true, slots: { default: 'row_buttons' } },
|
||||
],
|
||||
enableExport: auth('sysFile:export'),
|
||||
searchCallback: () => handleQuery(),
|
||||
queryAllCallback: () => fetchData({ pageSize: 99999 }),
|
||||
},
|
||||
{ rowConfig: { height: 80 } }
|
||||
);
|
||||
|
||||
// 页面初始化
|
||||
onMounted(async () => {
|
||||
handleQuery();
|
||||
await handleQuery();
|
||||
});
|
||||
|
||||
// 查询操作
|
||||
const handleQuery = async () => {
|
||||
if (state.queryParams.startTime == null) state.queryParams.startTime = undefined;
|
||||
if (state.queryParams.endTime == null) state.queryParams.endTime = undefined;
|
||||
|
||||
state.loading = true;
|
||||
let params = Object.assign(state.queryParams, state.tableParams);
|
||||
var res = await getAPI(SysFileApi).apiSysFilePagePost(params);
|
||||
state.fileData = res.data.result?.items ?? [];
|
||||
const handleQuery = async (reset = false) => {
|
||||
options.loading = true;
|
||||
if (reset) state.tableParams.page = 1;
|
||||
var res = await fetchData(null);
|
||||
xGrid.value?.loadData(res.data.result?.items ?? []);
|
||||
state.tableParams.total = res.data.result?.total;
|
||||
state.loading = false;
|
||||
options.loading = false;
|
||||
};
|
||||
|
||||
// 获取数据
|
||||
const fetchData = async (tableParams: any) => {
|
||||
let params = Object.assign(state.queryParams, state.tableParams, tableParams);
|
||||
return getAPI(SysFileApi).apiSysFilePagePost(params);
|
||||
};
|
||||
|
||||
// 重置操作
|
||||
@ -198,13 +237,27 @@ const resetQuery = () => {
|
||||
state.queryParams.fileName = undefined;
|
||||
state.queryParams.startTime = undefined;
|
||||
state.queryParams.endTime = undefined;
|
||||
handleQuery(true);
|
||||
};
|
||||
|
||||
// 改变页码序号或页面容量
|
||||
const pageChange: VxePagerEvents.PageChange = ({ currentPage, pageSize }: VxePagerDefines.PageChangeEventParams) => {
|
||||
state.tableParams.page = currentPage;
|
||||
state.tableParams.pageSize = pageSize;
|
||||
handleQuery();
|
||||
};
|
||||
|
||||
// 列排序
|
||||
const sortChange = (options: any) => {
|
||||
state.tableParams.field = options.field;
|
||||
state.tableParams.order = options.order;
|
||||
handleQuery();
|
||||
};
|
||||
|
||||
// 打开上传页面
|
||||
const openUploadDialog = () => {
|
||||
const showUpload = () => {
|
||||
state.fileList = [];
|
||||
state.dialogUploadVisible = true;
|
||||
state.visible = true;
|
||||
};
|
||||
|
||||
// 通过onChanne方法获得文件列表
|
||||
@ -213,23 +266,23 @@ const handleChange = (file: any, fileList: []) => {
|
||||
};
|
||||
|
||||
// 上传
|
||||
const uploadFile = async () => {
|
||||
const handleUpload = async () => {
|
||||
if (state.fileList.length < 1) return;
|
||||
await getAPI(SysFileApi).apiSysFileUploadFilePostForm(state.fileList[0].raw, state.fileType, undefined);
|
||||
handleQuery();
|
||||
ElMessage.success('上传成功');
|
||||
state.dialogUploadVisible = false;
|
||||
state.visible = false;
|
||||
};
|
||||
|
||||
// 下载
|
||||
const downloadFile = async (row: any) => {
|
||||
const handleDownload = async (row: any) => {
|
||||
// var res = await getAPI(SysFileApi).sysFileDownloadPost({ id: row.id });
|
||||
var fileUrl = getFileUrl(row);
|
||||
var fileUrl = fetchFileUrl(row);
|
||||
downloadByUrl({ url: fileUrl });
|
||||
};
|
||||
|
||||
// 删除
|
||||
const delFile = (row: any) => {
|
||||
const handleDelete = (row: any) => {
|
||||
ElMessageBox.confirm(`确定删除文件:【${row.fileName}】?`, '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
@ -243,42 +296,30 @@ const delFile = (row: any) => {
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
// 打开文件预览页面
|
||||
const openFilePreviewDialog = async (row: any) => {
|
||||
// 打开Pdf预览页面
|
||||
const showPreviewDialog = async (row: any) => {
|
||||
if (row.suffix == '.pdf') {
|
||||
state.fileName = `【${row.fileName}${row.suffix}】`;
|
||||
state.pdfUrl = getFileUrl(row);
|
||||
state.dialogPdfVisible = true;
|
||||
state.pdfUrl = fetchFileUrl(row);
|
||||
state.pdfVisible = true;
|
||||
} else if (row.suffix == '.docx') {
|
||||
state.fileName = `【${row.fileName}${row.suffix}】`;
|
||||
state.docxUrl = getFileUrl(row);
|
||||
state.dialogDocxVisible = true;
|
||||
state.docxUrl = fetchFileUrl(row);
|
||||
state.docxVisible = true;
|
||||
} else if (row.suffix == '.xlsx') {
|
||||
state.fileName = `【${row.fileName}${row.suffix}】`;
|
||||
state.excelUrl = getFileUrl(row);
|
||||
state.dialogXlsxVisible = true;
|
||||
state.excelUrl = fetchFileUrl(row);
|
||||
state.xlsxVisible = true;
|
||||
} else if (['.jpg', '.png', '.jpeg', '.bmp'].findIndex((e) => e == row.suffix) > -1) {
|
||||
state.previewList = [getFileUrl(row)];
|
||||
state.previewList = [fetchFileUrl(row)];
|
||||
state.showViewer = true;
|
||||
} else {
|
||||
ElMessage.error('此文件格式不支持预览');
|
||||
}
|
||||
};
|
||||
|
||||
// 改变页面容量
|
||||
const handleSizeChange = (val: number) => {
|
||||
state.tableParams.pageSize = val;
|
||||
handleQuery();
|
||||
};
|
||||
|
||||
// 改变页码序号
|
||||
const handleCurrentChange = (val: number) => {
|
||||
state.tableParams.page = val;
|
||||
handleQuery();
|
||||
};
|
||||
|
||||
// 获取文件地址
|
||||
const getFileUrl = (row: SysFile): string => {
|
||||
const fetchFileUrl = (row: SysFile): string => {
|
||||
if (row.bucketName == 'Local') {
|
||||
return `/${row.filePath}/${row.id}${row.suffix}`;
|
||||
} else {
|
||||
@ -287,12 +328,13 @@ const getFileUrl = (row: SysFile): string => {
|
||||
};
|
||||
|
||||
// 打开编辑页面
|
||||
const openEditSysFile = (row: any) => {
|
||||
editSysFileRef.value?.openDialog(row);
|
||||
const handleEdit = (row: any) => {
|
||||
editRef.value?.openDialog(row);
|
||||
};
|
||||
|
||||
// 文件渲染完成
|
||||
const renderedHandler = () => {};
|
||||
const handleRendered = () => {};
|
||||
|
||||
// 文件渲染失败
|
||||
const errorHandler = () => {};
|
||||
const handleError = () => {};
|
||||
</script>
|
||||
|
||||
@ -1,4 +1,10 @@
|
||||
export const JobScriptCode = `#region using
|
||||
export const JobScriptCode = `// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||
//
|
||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||
//
|
||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||
|
||||
#region using
|
||||
|
||||
using Furion;
|
||||
using Furion.Logging;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="sys-jobDetail-container">
|
||||
<el-dialog v-model="state.isShowDialog" draggable :close-on-click-modal="false" width="900px">
|
||||
<el-dialog v-model="state.isShowDialog" draggable :close-on-click-modal="false">
|
||||
<template #header>
|
||||
<div style="color: #fff">
|
||||
<el-icon size="16" style="margin-right: 3px; display: inline; vertical-align: middle"> <ele-Edit /> </el-icon>
|
||||
@ -10,7 +10,7 @@
|
||||
<el-tabs v-model="state.selectedTabName">
|
||||
<el-tab-pane label="作业信息">
|
||||
<el-form :model="state.ruleForm" ref="ruleFormRef" label-width="auto" style="height: 500px">
|
||||
<el-row :gutter="35">
|
||||
<el-row :gutter="10">
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
||||
<el-form-item label="作业编号" prop="jobId" :rules="[{ required: true, message: '作业编号不能为空', trigger: 'blur' }]">
|
||||
<el-input v-model="state.ruleForm.jobId" placeholder="作业编号" :disabled="isEdit" clearable />
|
||||
@ -190,8 +190,8 @@ const openDialog = (row: any) => {
|
||||
|
||||
// 延迟拿值防止取不到
|
||||
setTimeout(() => {
|
||||
if (monacoEditor == null) initMonacoEditor();
|
||||
monacoEditor.setValue(row.id == undefined ? JobScriptCode : state.ruleForm.scriptCode);
|
||||
if (monacoEditor == null || monacoEditor == undefined) initMonacoEditor();
|
||||
monacoEditor.setValue(row.id == undefined ? JobScriptCode : state.ruleForm.scriptCode ?? '');
|
||||
}, 1);
|
||||
};
|
||||
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<el-form :model="state.ruleForm" ref="ruleFormRef" label-width="auto">
|
||||
<el-row :gutter="35">
|
||||
<el-row :gutter="10">
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
||||
<el-form-item label="触发器编号" prop="triggerId" :rules="[{ required: true, message: '触发器编号不能为空', trigger: 'blur' }]">
|
||||
<el-input v-model="state.ruleForm.triggerId" placeholder="触发器编号" clearable />
|
||||
@ -144,7 +144,6 @@
|
||||
import { reactive, ref, computed } from 'vue';
|
||||
import type { WritableComputedRef } from 'vue';
|
||||
import { ElMessage } from 'element-plus';
|
||||
|
||||
import vcrontab from 'vcrontab-3';
|
||||
|
||||
import { getAPI } from '/@/utils/axios-utils';
|
||||
@ -186,10 +185,8 @@ const periodValue: WritableComputedRef<number | undefined> = computed({
|
||||
// 触发器周期不是周期,返回默认值
|
||||
if (state.ruleForm.triggerType != 'Furion.Schedule.PeriodTrigger') return defaultValue;
|
||||
if (!state.ruleForm.args) return defaultValue;
|
||||
|
||||
const value: number | undefined = Number(state.ruleForm.args);
|
||||
if (Number.isNaN(value)) return defaultValue;
|
||||
|
||||
return value;
|
||||
},
|
||||
set(value: number | undefined) {
|
||||
@ -290,7 +287,7 @@ defineExpose({ openDialog });
|
||||
<style lang="scss" scoped>
|
||||
#vcrontab {
|
||||
:deep(.el-select) {
|
||||
min-width: 300px;
|
||||
min-width: 270px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="sys-jobCluster-container">
|
||||
<el-drawer v-model="state.isVisible" title="作业集群" size="40%">
|
||||
<el-table :data="state.jobClusterList" style="width: 100%; margin: 8px" v-loading="state.loading" border>
|
||||
<el-drawer v-model="state.isVisible" title="作业集群" size="65%">
|
||||
<el-table :data="state.jobClusterList" style="width: 100%" v-loading="state.loading" border>
|
||||
<el-table-column type="index" label="序号" width="55" align="center" />
|
||||
<el-table-column prop="clusterId" label="集群编号" header-align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="status" label="状态" align="center" show-overflow-tooltip>
|
||||
@ -31,6 +31,7 @@ const state = reactive({
|
||||
jobClusterList: [] as Array<SysJobCluster>,
|
||||
});
|
||||
|
||||
// 页面初始化
|
||||
onMounted(async () => {
|
||||
handleQuery();
|
||||
});
|
||||
|
||||
@ -1,23 +1,37 @@
|
||||
<template>
|
||||
<div class="sys-job-container">
|
||||
<el-card shadow="hover" :body-style="{ paddingBottom: '0' }">
|
||||
<el-form :model="state.queryParams" ref="queryForm" :inline="true">
|
||||
<el-form-item label="作业编号">
|
||||
<el-input v-model="state.queryParams.jobId" placeholder="作业编号" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="描述信息">
|
||||
<el-input v-model="state.queryParams.description" placeholder="描述信息" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<div class="sys-job-container" v-loading="options.loading">
|
||||
<el-card shadow="hover" :body-style="{ padding: '5px 5px 0 5px', display: 'flex', width: '100%', height: '100%', alignItems: 'start' }">
|
||||
<el-form :model="state.queryParams" ref="queryForm" :show-message="false" :inlineMessage="true" :label-width="'60px'" style="flex: 1 1 0%">
|
||||
<el-row :gutter="10">
|
||||
<el-col class="mb5" :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
|
||||
<el-form-item label="作业编号" prop="jobId">
|
||||
<el-input v-model="state.queryParams.jobId" placeholder="作业编号" clearable @keyup.enter.native="handleQuery(true)" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col class="mb5" :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
|
||||
<el-form-item label="描述信息" prop="description">
|
||||
<el-input v-model="state.queryParams.description" placeholder="描述信息" clearable @keyup.enter.native="handleQuery(true)" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<el-divider style="height: calc(100% - 5px); margin: 0 10px" direction="vertical" />
|
||||
<el-row>
|
||||
<el-col>
|
||||
<el-button-group>
|
||||
<el-button type="primary" icon="ele-Search" @click="handleQuery" v-auth="'sysJob:pageJobDetail'"> 查询 </el-button>
|
||||
<el-button icon="ele-Refresh" @click="resetQuery"> 重置 </el-button>
|
||||
<el-button type="primary" icon="ele-Search" @click="handleQuery(true)" v-auth="'sysJob:pageJobDetail'" :loading="options.loading"> 查询 </el-button>
|
||||
<el-button icon="ele-Refresh" @click="resetQuery" :loading="options.loading"> 重置 </el-button>
|
||||
</el-button-group>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button-group style="margin: 0px 12px">
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
|
||||
<el-card class="full-table" shadow="hover" style="margin-top: 5px">
|
||||
<vxe-grid ref="xGrid" class="xGrid-style" v-bind="options" @sort-change="sortChange">
|
||||
<template #toolbar_buttons>
|
||||
<el-button-group>
|
||||
<el-tooltip content="增加作业">
|
||||
<el-button icon="ele-CirclePlus" @click="openAddJobDetail" v-auth="'sysJob:addJobDetail'"> </el-button>
|
||||
<el-button icon="ele-CirclePlus" @click="handleAdd" v-auth="'sysJob:addJobDetail'"> </el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="启动所有作业">
|
||||
<el-button icon="ele-VideoPlay" @click="startAllJob" />
|
||||
@ -26,7 +40,7 @@
|
||||
<el-button icon="ele-VideoPause" @click="pauseAllJob" />
|
||||
</el-tooltip>
|
||||
</el-button-group>
|
||||
<el-button-group style="margin: 0px 12px 0px 0px">
|
||||
<el-button-group style="margin: 0 12px">
|
||||
<el-tooltip content="强制唤醒作业调度器">
|
||||
<el-button icon="ele-AlarmClock" @click="cancelSleep" />
|
||||
</el-tooltip>
|
||||
@ -36,225 +50,204 @@
|
||||
</el-button-group>
|
||||
<el-button icon="ele-Coin" @click="openJobCluster" plain> 集群控制 </el-button>
|
||||
<el-button icon="ele-Grid" @click="openJobDashboard" plain> 任务看板 </el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-button-group style="padding-left: 12px">
|
||||
<el-button type="primary" icon="ele-Expand" @click="handleExpand"> 全部展开 </el-button>
|
||||
<el-button type="primary" icon="ele-Fold" @click="handleFold"> 全部折叠 </el-button>
|
||||
</el-button-group>
|
||||
</template>
|
||||
<template #toolbar_tools> </template>
|
||||
<template #empty>
|
||||
<el-empty :image-size="200" />
|
||||
</template>
|
||||
<template #row_content="scope">
|
||||
<vxe-table style="margin: 5px" align="center" :data="(scope.row as JobDetailOutput).jobTriggers">
|
||||
<!-- <vxe-column type="checkbox" width="40" fixed="left"></vxe-column> -->
|
||||
<vxe-column type="seq" width="40" fixed="left"></vxe-column>
|
||||
<vxe-column field="triggerId" title="触发器编号" :minWidth="180" showOverflow="tooltip"></vxe-column>
|
||||
<vxe-column field="triggerType" title="类型" :minWidth="120" showOverflow="tooltip"></vxe-column>
|
||||
<!-- <vxe-column field="assemblyName" title="程序集" :minWidth="120" showOverflow="tooltip"></vxe-column> -->
|
||||
<vxe-column field="args" title="参数" :minWidth="120" showOverflow="tooltip"></vxe-column>
|
||||
<vxe-column field="description" title="描述" :minWidth="120" showOverflow="tooltip"></vxe-column>
|
||||
<vxe-column field="status" title="状态" :minWidth="120" showOverflow="tooltip">
|
||||
<template #default="{ row }">
|
||||
<el-tag type="warning" effect="plain" v-if="(row as SysJobTrigger).status == 0"> 积压 </el-tag>
|
||||
<el-tag type="info" effect="plain" v-if="(row as SysJobTrigger).status == 1"> 就绪 </el-tag>
|
||||
<el-tag type="success" effect="plain" v-if="(row as SysJobTrigger).status == 2"> 正在运行 </el-tag>
|
||||
<el-tag type="danger" effect="plain" v-if="(row as SysJobTrigger).status == 3"> 暂停 </el-tag>
|
||||
<el-tag type="danger" effect="plain" v-if="(row as SysJobTrigger).status == 4"> 阻塞 </el-tag>
|
||||
<el-tag type="info" effect="plain" v-if="(row as SysJobTrigger).status == 5"> 由失败进入就绪 </el-tag>
|
||||
<el-tag type="danger" effect="plain" v-if="(row as SysJobTrigger).status == 6"> 归档 </el-tag>
|
||||
<el-tag type="danger" effect="plain" v-if="(row as SysJobTrigger).status == 7"> 崩溃 </el-tag>
|
||||
<el-tag type="danger" effect="plain" v-if="(row as SysJobTrigger).status == 8"> 超限 </el-tag>
|
||||
<el-tag type="danger" effect="plain" v-if="(row as SysJobTrigger).status == 9"> 无触发时间 </el-tag>
|
||||
<el-tag type="danger" effect="plain" v-if="(row as SysJobTrigger).status == 10"> 未启动 </el-tag>
|
||||
<el-tag type="danger" effect="plain" v-if="(row as SysJobTrigger).status == 11"> 未知作业触发器 </el-tag>
|
||||
<el-tag type="danger" effect="plain" v-if="(row as SysJobTrigger).status == 12"> 未知作业处理程序 </el-tag>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="startTime" title="起始时间" :minWidth="100" showOverflow="tooltip"></vxe-column>
|
||||
<vxe-column field="endTime" title="结束时间" :minWidth="100" showOverflow="tooltip"></vxe-column>
|
||||
<vxe-column field="lastRunTime" title="最近运行时间" :minWidth="130" showOverflow="tooltip"></vxe-column>
|
||||
<vxe-column field="nextRunTime" title="下一次运行时间" :minWidth="130" showOverflow="tooltip"></vxe-column>
|
||||
<vxe-column field="numberOfRuns" title="触发次数" :minWidth="70" showOverflow="tooltip"></vxe-column>
|
||||
<vxe-column field="maxNumberOfRuns" title="最大触发次数" :minWidth="90" showOverflow="tooltip"></vxe-column>
|
||||
<vxe-column field="numberOfErrors" title="出错次数" :minWidth="70" showOverflow="tooltip"></vxe-column>
|
||||
<vxe-column field="maxNumberOfErrors" title="最大出错次数" :minWidth="90" showOverflow="tooltip"></vxe-column>
|
||||
<vxe-column field="numRetries" title="重试次数" :minWidth="70" showOverflow="tooltip"></vxe-column>
|
||||
<vxe-column field="retryTimeout" title="重试间隔ms" :minWidth="80" showOverflow="tooltip"></vxe-column>
|
||||
<vxe-column field="startNow" title="是否立即启动" :minWidth="90" showOverflow="tooltip">
|
||||
<template #default="scope">
|
||||
<el-tag v-if="(scope.row as SysJobTrigger).startNow == true"> 是 </el-tag>
|
||||
<el-tag type="info" v-else> 否 </el-tag>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="runOnStart" title="是否启动时执行一次" :minWidth="120" showOverflow="tooltip">
|
||||
<template #default="scope">
|
||||
<el-tag v-if="(scope.row as SysJobTrigger).runOnStart == true"> 是 </el-tag>
|
||||
<el-tag type="info" v-else> 否 </el-tag>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="resetOnlyOnce" title="是否重置触发次数" :minWidth="110" showOverflow="tooltip">
|
||||
<template #default="scope">
|
||||
<el-tag v-if="(scope.row as SysJobTrigger).resetOnlyOnce == true"> 是 </el-tag>
|
||||
<el-tag type="info" v-else> 否 </el-tag>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column title="操作" :minWidth="130" fixed="right">
|
||||
<template #default="scope">
|
||||
<el-tooltip content="启动触发器">
|
||||
<el-button size="small" type="primary" icon="ele-VideoPlay" text @click="startTrigger(scope.row)" />
|
||||
</el-tooltip>
|
||||
<el-tooltip content="暂停触发器">
|
||||
<el-button size="small" type="primary" icon="ele-VideoPause" text @click="pauseTrigger(scope.row)" />
|
||||
</el-tooltip>
|
||||
<el-tooltip content="编辑触发器">
|
||||
<el-button size="small" type="primary" icon="ele-Edit" text @click="openEditJobTrigger(scope.row)"> </el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="删除触发器">
|
||||
<el-button size="small" type="danger" icon="ele-Delete" text @click="delJobTrigger(scope.row)"> </el-button>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
</vxe-column>
|
||||
</vxe-table>
|
||||
</template>
|
||||
<template #row_jobId="{ row }">
|
||||
<div style="display: flex; align-items: center">
|
||||
<el-icon><timer /></el-icon>
|
||||
<span style="margin-left: 5px">{{ (row as JobDetailOutput).jobDetail?.jobId }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<template #row_concurrent="{ row }">
|
||||
<el-tag type="success" v-if="(row as JobDetailOutput).jobDetail?.concurrent == true"> 并行 </el-tag>
|
||||
<el-tag type="warning" v-else> 串行 </el-tag>
|
||||
</template>
|
||||
<template #row_createType="{ row }">
|
||||
<el-tag type="info" v-if="(row as JobDetailOutput).jobDetail?.createType == JobCreateTypeEnum.NUMBER_0"> 内置 </el-tag>
|
||||
<el-tag type="warning" v-if="(row as JobDetailOutput).jobDetail?.createType == JobCreateTypeEnum.NUMBER_1"> 脚本 </el-tag>
|
||||
<el-tag type="success" v-if="(row as JobDetailOutput).jobDetail?.createType == JobCreateTypeEnum.NUMBER_2"> HTTP请求 </el-tag>
|
||||
</template>
|
||||
<template #row_includeAnnotations="{ row }">
|
||||
<el-tag v-if="(row as JobDetailOutput).jobDetail?.includeAnnotations == true"> 是 </el-tag>
|
||||
<el-tag v-else> 否 </el-tag>
|
||||
</template>
|
||||
<template #row_properties="{ row }">
|
||||
<span v-if="(row as JobDetailOutput).jobDetail?.createType != JobCreateTypeEnum.NUMBER_2"> {{ (row as JobDetailOutput).jobDetail?.properties }} </span>
|
||||
<div v-else style="text-align: center">
|
||||
<el-popover placement="left" :width="400" trigger="hover">
|
||||
<template #reference>
|
||||
<el-tag effect="plain" type="info"> 请求参数 </el-tag>
|
||||
</template>
|
||||
<el-descriptions title="Http 请求参数" :column="1" size="small" :border="true">
|
||||
<el-descriptions-item label="请求地址" label-align="right" label-class-name="job-index-descriptions-label-style">
|
||||
{{ getHttpJobMessage((row as JobDetailOutput).jobDetail?.properties).requestUri }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="请求方法" label-align="right" label-class-name="job-index-descriptions-label-style">
|
||||
{{ getHttpMethodDesc(getHttpJobMessage((row as JobDetailOutput).jobDetail?.properties).httpMethod) }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="请求报文体" label-align="right" label-class-name="job-index-descriptions-label-style">
|
||||
{{ getHttpJobMessage((row as JobDetailOutput).jobDetail?.properties).body }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-popover>
|
||||
</div>
|
||||
</template>
|
||||
<template #row_buttons="{ row }">
|
||||
<el-tooltip content="执行记录">
|
||||
<el-button size="small" type="primary" icon="ele-Timer" text @click="openJobTriggerRecord(row)"> </el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="增加触发器">
|
||||
<el-button size="small" type="primary" icon="ele-CirclePlus" text @click="openAddJobTrigger(row)"> </el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="执行作业">
|
||||
<el-button size="small" type="primary" icon="ele-CircleCheck" text @click="runJob(row)" />
|
||||
</el-tooltip>
|
||||
<el-tooltip content="启动作业">
|
||||
<el-button size="small" type="primary" icon="ele-VideoPlay" text @click="startJob(row)" />
|
||||
</el-tooltip>
|
||||
<el-tooltip content="暂停作业">
|
||||
<el-button size="small" type="primary" icon="ele-VideoPause" text @click="pauseJob(row)" />
|
||||
</el-tooltip>
|
||||
<el-tooltip content="取消作业">
|
||||
<el-button size="small" type="primary" icon="ele-CircleClose" text @click="cancelJob(row)" />
|
||||
</el-tooltip>
|
||||
<el-tooltip content="编辑作业">
|
||||
<el-button size="small" type="primary" icon="ele-Edit" text @click="handleEdit(row)" v-auth="'sysJob:updateJobDetail'"> </el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="删除作业">
|
||||
<el-button size="small" type="danger" icon="ele-Delete" text @click="handleDelete(row)" v-auth="'sysJob:deleteJobDetail'"> </el-button>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
<template #pager>
|
||||
<vxe-pager
|
||||
:loading="options.loading"
|
||||
v-model:current-page="state.tableParams.page"
|
||||
v-model:page-size="state.tableParams.pageSize"
|
||||
:total="state.tableParams.total"
|
||||
@page-change="pageChange"
|
||||
/>
|
||||
</template>
|
||||
</vxe-grid>
|
||||
</el-card>
|
||||
|
||||
<el-card class="full-table" shadow="hover" style="margin-top: 5px">
|
||||
<el-table :data="state.jobData" style="width: 100%" v-loading="state.loading" border>
|
||||
<el-table-column type="expand" fixed>
|
||||
<template #default="scope">
|
||||
<el-table style="margin-left: 48px; width: calc(100% - 48px)" :data="(scope.row as JobDetailOutput).jobTriggers" border size="small">
|
||||
<el-table-column type="index" label="序号" width="55" align="center" fixed />
|
||||
<el-table-column prop="triggerId" label="触发器编号" width="180" header-align="center" fixed show-overflow-tooltip />
|
||||
<el-table-column prop="triggerType" label="类型" width="200" header-align="center" show-overflow-tooltip />
|
||||
<!-- <el-table-column prop="assemblyName" label="程序集" show-overflow-tooltip /> -->
|
||||
<el-table-column prop="args" label="参数" header-align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="description" label="描述" width="120" header-align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="status" label="状态" width="120" align="center" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-tag type="warning" effect="plain" v-if="(scope.row as SysJobTrigger).status == 0"> 积压 </el-tag>
|
||||
<el-tag type="" effect="plain" v-if="(scope.row as SysJobTrigger).status == 1"> 就绪 </el-tag>
|
||||
<el-tag type="success" effect="plain" v-if="(scope.row as SysJobTrigger).status == 2"> 正在运行 </el-tag>
|
||||
<el-tag type="danger" effect="plain" v-if="(scope.row as SysJobTrigger).status == 3"> 暂停 </el-tag>
|
||||
<el-tag type="danger" effect="plain" v-if="(scope.row as SysJobTrigger).status == 4"> 阻塞 </el-tag>
|
||||
<el-tag type="" effect="plain" v-if="(scope.row as SysJobTrigger).status == 5"> 由失败进入就绪 </el-tag>
|
||||
<el-tag type="danger" effect="plain" v-if="(scope.row as SysJobTrigger).status == 6"> 归档 </el-tag>
|
||||
<el-tag type="danger" effect="plain" v-if="(scope.row as SysJobTrigger).status == 7"> 崩溃 </el-tag>
|
||||
<el-tag type="danger" effect="plain" v-if="(scope.row as SysJobTrigger).status == 8"> 超限 </el-tag>
|
||||
<el-tag type="danger" effect="plain" v-if="(scope.row as SysJobTrigger).status == 9"> 无触发时间 </el-tag>
|
||||
<el-tag type="danger" effect="plain" v-if="(scope.row as SysJobTrigger).status == 10"> 未启动 </el-tag>
|
||||
<el-tag type="danger" effect="plain" v-if="(scope.row as SysJobTrigger).status == 11"> 未知作业触发器 </el-tag>
|
||||
<el-tag type="danger" effect="plain" v-if="(scope.row as SysJobTrigger).status == 12"> 未知作业处理程序 </el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="startTime" label="起始时间" width="100" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="endTime" label="结束时间" width="100" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="lastRunTime" label="最近运行时间" width="130" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="nextRunTime" label="下一次运行时间" width="130" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="numberOfRuns" label="触发次数" width="100" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="maxNumberOfRuns" label="最大触发次数" width="120" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="numberOfErrors" label="出错次数" width="100" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="maxNumberOfErrors" label="最大出错次数" width="120" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="numRetries" label="重试次数" width="100" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="retryTimeout" label="重试间隔ms" width="100" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="startNow" label="是否立即启动" width="100" align="center" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-tag v-if="(scope.row as SysJobTrigger).startNow == true"> 是 </el-tag>
|
||||
<el-tag type="info" v-else> 否 </el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="runOnStart" label="是否启动时执行一次" width="150" align="center" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-tag v-if="(scope.row as SysJobTrigger).runOnStart == true"> 是 </el-tag>
|
||||
<el-tag type="info" v-else> 否 </el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="resetOnlyOnce" label="是否重置触发次数" width="120" align="center" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-tag v-if="(scope.row as SysJobTrigger).resetOnlyOnce == true"> 是 </el-tag>
|
||||
<el-tag type="info" v-else> 否 </el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="updatedTime" label="更新时间" width="130" align="center" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="140" align="center" show-overflow-tooltip fixed="right">
|
||||
<template #default="scope">
|
||||
<el-tooltip content="启动触发器">
|
||||
<el-button size="small" type="primary" icon="ele-VideoPlay" text @click="startTrigger(scope.row)" />
|
||||
</el-tooltip>
|
||||
<el-tooltip content="暂停触发器">
|
||||
<el-button size="small" type="primary" icon="ele-VideoPause" text @click="pauseTrigger(scope.row)" />
|
||||
</el-tooltip>
|
||||
<el-tooltip content="编辑触发器">
|
||||
<el-button size="small" type="primary" icon="ele-Edit" text @click="openEditJobTrigger(scope.row)"> </el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="删除触发器">
|
||||
<el-button size="small" type="danger" icon="ele-Delete" text @click="delJobTrigger(scope.row)"> </el-button>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-drawer v-model="state.isVisibleDrawer" size="60%">
|
||||
<template #header>
|
||||
<div style="color: #fff">
|
||||
<el-icon size="16" style="margin-right: 3px; display: inline; vertical-align: middle"> <ele-Clock /> </el-icon>
|
||||
<span> 作业触发器运行记录</span>
|
||||
</div>
|
||||
</template>
|
||||
<el-card class="full-table" shadow="hover">
|
||||
<vxe-grid ref="xRecordGrid" class="xGrid-style" v-bind="recordOptions" @sort-change="recordSortChange">
|
||||
<template #toolbar_buttons></template>
|
||||
<template #toolbar_tools> </template>
|
||||
<template #empty>
|
||||
<el-empty :image-size="200" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column type="index" label="序号" width="55" align="center" fixed />
|
||||
<el-table-column prop="jobDetail.jobId" label="作业编号" width="180" header-align="center" fixed>
|
||||
<template #default="scope">
|
||||
<div style="display: flex; align-items: center">
|
||||
<el-icon><timer /></el-icon>
|
||||
<span style="margin-left: 5px">{{ (scope.row as JobDetailOutput).jobDetail?.jobId }}</span>
|
||||
</div>
|
||||
<template #row_status="{ row }">
|
||||
<el-tag type="warning" effect="plain" v-if="(row as SysJobTrigger).status == 0"> 积压 </el-tag>
|
||||
<el-tag type="info" effect="plain" v-if="(row as SysJobTrigger).status == 1"> 就绪 </el-tag>
|
||||
<el-tag type="success" effect="plain" v-if="(row as SysJobTrigger).status == 2"> 正在运行 </el-tag>
|
||||
<el-tag type="danger" effect="plain" v-if="(row as SysJobTrigger).status == 3"> 暂停 </el-tag>
|
||||
<el-tag type="danger" effect="plain" v-if="(row as SysJobTrigger).status == 4"> 阻塞 </el-tag>
|
||||
<el-tag type="info" effect="plain" v-if="(row as SysJobTrigger).status == 5"> 由失败进入就绪 </el-tag>
|
||||
<el-tag type="danger" effect="plain" v-if="(row as SysJobTrigger).status == 6"> 归档 </el-tag>
|
||||
<el-tag type="danger" effect="plain" v-if="(row as SysJobTrigger).status == 7"> 崩溃 </el-tag>
|
||||
<el-tag type="danger" effect="plain" v-if="(row as SysJobTrigger).status == 8"> 超限 </el-tag>
|
||||
<el-tag type="danger" effect="plain" v-if="(row as SysJobTrigger).status == 9"> 无触发时间 </el-tag>
|
||||
<el-tag type="danger" effect="plain" v-if="(row as SysJobTrigger).status == 10"> 未启动 </el-tag>
|
||||
<el-tag type="danger" effect="plain" v-if="(row as SysJobTrigger).status == 11"> 未知作业触发器 </el-tag>
|
||||
<el-tag type="danger" effect="plain" v-if="(row as SysJobTrigger).status == 12"> 未知作业处理程序 </el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="jobDetail.groupName" label="组名称" width="100" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="jobDetail.jobType" label="类型" width="200" header-align="center" show-overflow-tooltip />
|
||||
<!-- <el-table-column prop="jobDetail.assemblyName" label="程序集" show-overflow-tooltip /> -->
|
||||
<el-table-column prop="jobDetail.description" label="描述" header-align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="jobDetail.concurrent" label="执行方式" width="90" align="center" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-tag type="success" v-if="(scope.row as JobDetailOutput).jobDetail?.concurrent == true"> 并行 </el-tag>
|
||||
<el-tag type="warning" v-else> 串行 </el-tag>
|
||||
<template #pager>
|
||||
<vxe-pager
|
||||
:loading="recordOptions.loading"
|
||||
v-model:current-page="state.recordTableParams.page"
|
||||
v-model:page-size="state.recordTableParams.pageSize"
|
||||
:total="state.recordTableParams.total"
|
||||
@page-change="recordPageChange"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="jobDetail.createType" label="作业创建类型" width="110" align="center" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-tag type="info" v-if="(scope.row as JobDetailOutput).jobDetail?.createType == JobCreateTypeEnum.NUMBER_0"> 内置 </el-tag>
|
||||
<el-tag type="warning" v-if="(scope.row as JobDetailOutput).jobDetail?.createType == JobCreateTypeEnum.NUMBER_1"> 脚本 </el-tag>
|
||||
<el-tag type="success" v-if="(scope.row as JobDetailOutput).jobDetail?.createType == JobCreateTypeEnum.NUMBER_2"> HTTP请求 </el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- <el-table-column prop="jobDetail.includeAnnotations" label="扫描特性触发器" align="center" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-tag v-if="(scope.row as JobDetailOutput).jobDetail?.includeAnnotations == true"> 是 </el-tag>
|
||||
<el-tag v-else> 否 </el-tag>
|
||||
</template>
|
||||
</el-table-column> -->
|
||||
<el-table-column prop="jobDetail.updatedTime" label="更新时间" width="130" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="jobDetail.properties" label="额外数据" header-align="center" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<span v-if="(scope.row as JobDetailOutput).jobDetail?.createType != JobCreateTypeEnum.NUMBER_2"> {{ (scope.row as JobDetailOutput).jobDetail?.properties }} </span>
|
||||
<div v-else style="text-align: center">
|
||||
<el-popover placement="left" :width="400" trigger="hover">
|
||||
<template #reference>
|
||||
<el-tag effect="plain" type="info"> 请求参数 </el-tag>
|
||||
</template>
|
||||
<el-descriptions title="Http 请求参数" :column="1" size="small" :border="true">
|
||||
<el-descriptions-item label="请求地址" label-align="right" label-class-name="job-index-descriptions-label-style">
|
||||
{{ getHttpJobMessage((scope.row as JobDetailOutput).jobDetail?.properties).requestUri }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="请求方法" label-align="right" label-class-name="job-index-descriptions-label-style">
|
||||
{{ getHttpMethodDesc(getHttpJobMessage((scope.row as JobDetailOutput).jobDetail?.properties).httpMethod) }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="请求报文体" label-align="right" label-class-name="job-index-descriptions-label-style">
|
||||
{{ getHttpJobMessage((scope.row as JobDetailOutput).jobDetail?.properties).body }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-popover>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="270" fixed="right" align="center" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-tooltip content="执行记录">
|
||||
<el-button size="small" type="primary" icon="ele-Timer" text @click="openJobTriggerRecord(scope.row)"> </el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="增加触发器">
|
||||
<el-button size="small" type="primary" icon="ele-CirclePlus" text @click="openAddJobTrigger(scope.row)"> </el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="执行作业">
|
||||
<el-button size="small" type="primary" icon="ele-CircleCheck" text @click="runJob(scope.row)" />
|
||||
</el-tooltip>
|
||||
<el-tooltip content="启动作业">
|
||||
<el-button size="small" type="primary" icon="ele-VideoPlay" text @click="startJob(scope.row)" />
|
||||
</el-tooltip>
|
||||
<el-tooltip content="暂停作业">
|
||||
<el-button size="small" type="primary" icon="ele-VideoPause" text @click="pauseJob(scope.row)" />
|
||||
</el-tooltip>
|
||||
<el-tooltip content="取消作业">
|
||||
<el-button size="small" type="primary" icon="ele-CircleClose" text @click="cancelJob(scope.row)" />
|
||||
</el-tooltip>
|
||||
<el-tooltip content="编辑作业">
|
||||
<el-button size="small" type="primary" icon="ele-Edit" text @click="openEditJobDetail(scope.row)" v-auth="'sysJob:updateJobDetail'"> </el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="删除作业">
|
||||
<el-button size="small" type="danger" icon="ele-Delete" text @click="delJobDetail(scope.row)" v-auth="'sysJob:deleteJobDetail'"> </el-button>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
v-model:currentPage="state.tableParams.page"
|
||||
v-model:page-size="state.tableParams.pageSize"
|
||||
:total="state.tableParams.total"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
small
|
||||
background
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
/>
|
||||
</el-card>
|
||||
|
||||
<el-drawer v-model="state.isVisibleDrawer" title="作业触发器运行记录" size="45%">
|
||||
<el-card shadow="hover" style="margin: 8px; padding-bottom: 15px">
|
||||
<el-table :data="state.triggerRecordData" style="width: 100%" v-loading="state.loading2" border>
|
||||
<el-table-column type="index" label="序号" width="55" align="center" />
|
||||
<el-table-column prop="jobId" label="作业编号" min-width="120" header-align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="triggerId" label="触发器编号" min-width="120" header-align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="numberOfRuns" label="当前运行次数" min-width="100" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="lastRunTime" label="最近运行时间" min-width="130" header-align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="nextRunTime" label="下一次运行时间" min-width="130" header-align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="status" label="触发器状态" align="center" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-tag type="warning" effect="plain" v-if="(scope.row as SysJobTrigger).status == 0"> 积压 </el-tag>
|
||||
<el-tag type="" effect="plain" v-if="(scope.row as SysJobTrigger).status == 1"> 就绪 </el-tag>
|
||||
<el-tag type="success" effect="plain" v-if="(scope.row as SysJobTrigger).status == 2"> 正在运行 </el-tag>
|
||||
<el-tag type="danger" effect="plain" v-if="(scope.row as SysJobTrigger).status == 3"> 暂停 </el-tag>
|
||||
<el-tag type="danger" effect="plain" v-if="(scope.row as SysJobTrigger).status == 4"> 阻塞 </el-tag>
|
||||
<el-tag type="" effect="plain" v-if="(scope.row as SysJobTrigger).status == 5"> 由失败进入就绪 </el-tag>
|
||||
<el-tag type="danger" effect="plain" v-if="(scope.row as SysJobTrigger).status == 6"> 归档 </el-tag>
|
||||
<el-tag type="danger" effect="plain" v-if="(scope.row as SysJobTrigger).status == 7"> 崩溃 </el-tag>
|
||||
<el-tag type="danger" effect="plain" v-if="(scope.row as SysJobTrigger).status == 8"> 超限 </el-tag>
|
||||
<el-tag type="danger" effect="plain" v-if="(scope.row as SysJobTrigger).status == 9"> 无触发时间 </el-tag>
|
||||
<el-tag type="danger" effect="plain" v-if="(scope.row as SysJobTrigger).status == 10"> 未启动 </el-tag>
|
||||
<el-tag type="danger" effect="plain" v-if="(scope.row as SysJobTrigger).status == 11"> 未知作业触发器 </el-tag>
|
||||
<el-tag type="danger" effect="plain" v-if="(scope.row as SysJobTrigger).status == 12"> 未知作业处理程序 </el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="result" label="执行结果" header-align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="elapsedTime" label="耗时" min-width="80" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="createdTime" label="创建时间" min-width="130" align="center" show-overflow-tooltip />
|
||||
</el-table>
|
||||
<el-pagination
|
||||
v-model:currentPage="state.tableParams2.page"
|
||||
v-model:page-size="state.tableParams2.pageSize"
|
||||
:total="state.tableParams2.total"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
small
|
||||
background
|
||||
@size-change="handleSizeChange2"
|
||||
@current-change="handleCurrentChange2"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
/>
|
||||
</vxe-grid>
|
||||
</el-card>
|
||||
</el-drawer>
|
||||
|
||||
@ -267,35 +260,45 @@
|
||||
<script lang="ts" setup name="sysJob">
|
||||
import { onMounted, reactive, ref } from 'vue';
|
||||
import { ElMessageBox, ElMessage } from 'element-plus';
|
||||
import { auth } from '/@/utils/authFunction';
|
||||
import { VxeGridInstance, VxePagerEvents, VxePagerDefines } from 'vxe-table';
|
||||
import { useVxeTable } from '/@/hooks/vxeTableOptionsHook';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { Timer } from '@element-plus/icons-vue';
|
||||
|
||||
import EditJobDetail from '/@/views/system/job/component/editJobDetail.vue';
|
||||
import EditJobTrigger from '/@/views/system/job/component/editJobTrigger.vue';
|
||||
import JobCluster from '/@/views/system/job/component/jobCluster.vue';
|
||||
|
||||
import { getAPI } from '/@/utils/axios-utils';
|
||||
import { SysJobApi } from '/@/api-services/api';
|
||||
import { JobCreateTypeEnum, JobDetailOutput, SysJobTrigger } from '/@/api-services/models';
|
||||
import { JobCreateTypeEnum, JobDetailOutput, SysJobTrigger, SysJobTriggerRecord } from '/@/api-services/models';
|
||||
|
||||
const xGrid = ref<VxeGridInstance>();
|
||||
const xRecordGrid = ref<VxeGridInstance>();
|
||||
const router = useRouter();
|
||||
const editJobDetailRef = ref<InstanceType<typeof EditJobDetail>>();
|
||||
const editJobTriggerRef = ref<InstanceType<typeof EditJobTrigger>>();
|
||||
const editJobClusterRef = ref<InstanceType<typeof JobCluster>>();
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
jobData: [] as Array<JobDetailOutput>,
|
||||
queryParams: {
|
||||
jobId: undefined,
|
||||
description: undefined,
|
||||
},
|
||||
tableParams: {
|
||||
page: 1,
|
||||
pageSize: 20,
|
||||
pageSize: 50,
|
||||
field: 'id', // 默认的排序字段
|
||||
order: 'aes', // 排序方向
|
||||
descStr: 'desc', // 降序排序的关键字符
|
||||
total: 0 as any,
|
||||
},
|
||||
tableParams2: {
|
||||
recordTableParams: {
|
||||
page: 1,
|
||||
pageSize: 20,
|
||||
pageSize: 50,
|
||||
field: 'id', // 默认的排序字段
|
||||
order: 'desc', // 排序方向
|
||||
descStr: 'desc', // 降序排序的关键字符
|
||||
total: 0 as any,
|
||||
},
|
||||
editJobDetailTitle: '',
|
||||
@ -304,43 +307,91 @@ const state = reactive({
|
||||
isVisibleDrawer: false,
|
||||
triggerRecordData: [] as any,
|
||||
currentJob: {} as any,
|
||||
visible: false,
|
||||
title: '',
|
||||
});
|
||||
|
||||
// 表格参数配置
|
||||
const options = useVxeTable<JobDetailOutput>({
|
||||
id: 'sysJob',
|
||||
name: '作业信息',
|
||||
columns: [
|
||||
// { type: 'checkbox', width: 40 },
|
||||
{ type: 'seq', title: '序号', width: 50, fixed: 'left' },
|
||||
{ type: 'expand', width: 40, slots: { content: 'row_content' } },
|
||||
{ field: 'jobDetail.jobId', title: '作业编号', minWidth: 180, showOverflow: 'tooltip', slots: { default: 'row_jobId' } },
|
||||
{ field: 'jobDetail.groupName', title: '组名称', minWidth: 80, showOverflow: 'tooltip' },
|
||||
{ field: 'jobDetail.jobType', title: '类型', minWidth: 180, showOverflow: 'tooltip' },
|
||||
// { field: 'jobDetail.assemblyName', title: '程序集', minWidth: 100, showOverflow: 'tooltip', sortable: true },
|
||||
{ field: 'jobDetail.description', title: '描述', minWidth: 150, showOverflow: 'tooltip' },
|
||||
{ field: 'jobDetail.concurrent', title: '执行方式', minWidth: 80, showOverflow: 'tooltip', slots: { default: 'row_concurrent' } },
|
||||
{ field: 'jobDetail.createType', title: '作业创建类型', minWidth: 100, showOverflow: 'tooltip', slots: { default: 'row_createType' } },
|
||||
{ field: 'jobDetail.includeAnnotations', title: '扫描特性触发器', minWidth: 120, showOverflow: 'tooltip', slots: { default: 'row_includeAnnotations' } },
|
||||
{ field: 'jobDetail.updatedTime', title: '更新时间', minWidth: 130, showOverflow: 'tooltip' },
|
||||
{ field: 'jobDetail.properties', title: '额外数据', minWidth: 140, showOverflow: 'tooltip', slots: { default: 'row_properties' } },
|
||||
{ title: '操作', minWidth: 200, showOverflow: true, slots: { default: 'row_buttons' } },
|
||||
],
|
||||
enableExport: auth('sysJob:export'),
|
||||
searchCallback: () => handleQuery(),
|
||||
queryAllCallback: () => fetchData({ pageSize: 99999 }),
|
||||
});
|
||||
|
||||
// 页面初始化
|
||||
onMounted(async () => {
|
||||
handleQuery();
|
||||
await handleQuery();
|
||||
});
|
||||
|
||||
// 查询操作
|
||||
const handleQuery = async () => {
|
||||
state.loading = true;
|
||||
let params = Object.assign(state.queryParams, state.tableParams);
|
||||
var res = await getAPI(SysJobApi).apiSysJobPageJobDetailPost(params);
|
||||
state.jobData = res.data.result?.items ?? [];
|
||||
const handleQuery = async (reset = false) => {
|
||||
options.loading = true;
|
||||
if (reset) state.tableParams.page = 1;
|
||||
var res = await fetchData(null);
|
||||
await xGrid.value?.loadData(res.data.result?.items ?? []);
|
||||
state.tableParams.total = res.data.result?.total;
|
||||
state.loading = false;
|
||||
options.loading = false;
|
||||
};
|
||||
|
||||
// 获取数据
|
||||
const fetchData = async (tableParams: any) => {
|
||||
let params = Object.assign(state.queryParams, state.tableParams, tableParams);
|
||||
return getAPI(SysJobApi).apiSysJobPageJobDetailPost(params);
|
||||
};
|
||||
|
||||
// 重置操作
|
||||
const resetQuery = () => {
|
||||
const resetQuery = async () => {
|
||||
state.queryParams.jobId = undefined;
|
||||
state.queryParams.description = undefined;
|
||||
handleQuery();
|
||||
await handleQuery(true);
|
||||
};
|
||||
|
||||
// 改变页码序号或页面容量
|
||||
const pageChange: VxePagerEvents.PageChange = async ({ currentPage, pageSize }: VxePagerDefines.PageChangeEventParams) => {
|
||||
state.tableParams.page = currentPage;
|
||||
state.tableParams.pageSize = pageSize;
|
||||
await handleQuery();
|
||||
};
|
||||
|
||||
// 列排序
|
||||
const sortChange = async (options: any) => {
|
||||
state.tableParams.field = options.field;
|
||||
state.tableParams.order = options.order;
|
||||
await handleQuery();
|
||||
};
|
||||
|
||||
// 打开新增作业页面
|
||||
const openAddJobDetail = () => {
|
||||
const handleAdd = () => {
|
||||
state.editJobDetailTitle = '添加作业';
|
||||
editJobDetailRef.value?.openDialog({ concurrent: true, includeAnnotations: true, groupName: 'default', createType: JobCreateTypeEnum.NUMBER_2 });
|
||||
};
|
||||
|
||||
// 打开编辑作业页面
|
||||
const openEditJobDetail = (row: JobDetailOutput) => {
|
||||
const handleEdit = (row: JobDetailOutput) => {
|
||||
state.editJobDetailTitle = '编辑作业';
|
||||
editJobDetailRef.value?.openDialog(row.jobDetail);
|
||||
};
|
||||
|
||||
// 删除作业
|
||||
const delJobDetail = (row: JobDetailOutput) => {
|
||||
const handleDelete = (row: JobDetailOutput) => {
|
||||
ElMessageBox.confirm(`确定删除作业:【${row.jobDetail?.jobId}】?`, '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
@ -388,18 +439,6 @@ const delJobTrigger = (row: SysJobTrigger) => {
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
// 改变页面容量
|
||||
const handleSizeChange = (val: number) => {
|
||||
state.tableParams.pageSize = val;
|
||||
handleQuery();
|
||||
};
|
||||
|
||||
// 改变页码序号
|
||||
const handleCurrentChange = (val: number) => {
|
||||
state.tableParams.page = val;
|
||||
handleQuery();
|
||||
};
|
||||
|
||||
// 启动所有作业
|
||||
const startAllJob = async () => {
|
||||
await getAPI(SysJobApi).apiSysJobStartAllJobPost();
|
||||
@ -475,10 +514,8 @@ const openJobDashboard = () => {
|
||||
// 根据任务属性获取 HttpJobMessage
|
||||
const getHttpJobMessage = (properties: string | undefined | null): HttpJobMessage => {
|
||||
if (properties === undefined || properties === null || properties === '') return {};
|
||||
|
||||
const propData = JSON.parse(properties);
|
||||
const httpJobMessageNet = JSON.parse(propData['HttpJob']); // 后端大写开头的 HttpJobMessage
|
||||
|
||||
return {
|
||||
requestUri: httpJobMessageNet.RequestUri,
|
||||
httpMethod: JSON.stringify(httpJobMessageNet.HttpMethod),
|
||||
@ -489,40 +526,78 @@ const getHttpJobMessage = (properties: string | undefined | null): HttpJobMessag
|
||||
// 获取请求方法的对应描述
|
||||
const getHttpMethodDesc = (httpMethodStr: string | undefined | null): string => {
|
||||
if (httpMethodStr === undefined || httpMethodStr === null || httpMethodStr === '') return '';
|
||||
|
||||
for (const key in editJobDetailRef.value?.httpMethodDef) {
|
||||
if (editJobDetailRef.value?.httpMethodDef[key] === httpMethodStr) return key;
|
||||
}
|
||||
return '';
|
||||
};
|
||||
|
||||
//全部展开
|
||||
const handleExpand = () => {
|
||||
xGrid.value?.setAllRowExpand(true);
|
||||
};
|
||||
|
||||
//全部折叠
|
||||
const handleFold = () => {
|
||||
xGrid.value?.clearRowExpand();
|
||||
};
|
||||
|
||||
// 打开作业触发器运行记录
|
||||
const openJobTriggerRecord = (row: any) => {
|
||||
const openJobTriggerRecord = async (row: any) => {
|
||||
state.currentJob = row;
|
||||
state.isVisibleDrawer = true;
|
||||
handleQuery2();
|
||||
await handleQueryRecord();
|
||||
};
|
||||
|
||||
// 作业触发器运行记录查询操作
|
||||
const handleQuery2 = async () => {
|
||||
state.loading2 = true;
|
||||
let params = Object.assign({ jobId: state.currentJob.jobDetail.jobId }, state.tableParams2); //state.currentJob.jobTriggers[0].triggerId
|
||||
var res = await getAPI(SysJobApi).apiSysJobPageJobTriggerRecordPost(params);
|
||||
state.triggerRecordData = res.data.result?.items ?? [];
|
||||
state.tableParams2.total = res.data.result?.total;
|
||||
state.loading2 = false;
|
||||
// 表格参数配置-触发器
|
||||
const recordOptions = useVxeTable<SysJobTriggerRecord>({
|
||||
id: 'sysJobRecord',
|
||||
name: '执行记录',
|
||||
columns: [
|
||||
// { type: 'checkbox', width: 40, fixed: 'left' },
|
||||
{ type: 'seq', title: '序号', width: 50, fixed: 'left' },
|
||||
{ field: 'jobId', title: '作业编号', minWidth: 200, showOverflow: 'tooltip' },
|
||||
{ field: 'triggerId', title: '触发器编号', minWidth: 200, showOverflow: 'tooltip' },
|
||||
{ field: 'numberOfRuns', title: '当前运行次数', minWidth: 100, showOverflow: 'tooltip' },
|
||||
{ field: 'lastRunTime', title: '最近运行时间', minWidth: 130, showOverflow: 'tooltip' },
|
||||
{ field: 'nextRunTime', title: '下一次运行时间', minWidth: 130, showOverflow: 'tooltip' },
|
||||
{ field: 'status', title: '触发器状态', minWidth: 110, showOverflow: 'tooltip', slots: { default: 'row_status' } },
|
||||
{ field: 'result', title: '执行结果', minWidth: 200, showOverflow: 'title' },
|
||||
{ field: 'elapsedTime', title: '耗时(ms)', minWidth: 80, showOverflow: 'tooltip' },
|
||||
{ field: 'createdTime', title: '创建时间', minWidth: 130, showOverflow: 'tooltip' },
|
||||
],
|
||||
searchCallback: () => handleQueryRecord(),
|
||||
queryAllCallback: () => fetchRecordData({ pageSize: 99999 }),
|
||||
});
|
||||
|
||||
// 查询操作
|
||||
const handleQueryRecord = async (reset = false) => {
|
||||
recordOptions.loading = true;
|
||||
if (reset) state.recordTableParams.page = 1;
|
||||
var res = await fetchRecordData(null);
|
||||
await xRecordGrid.value?.loadData(res.data.result?.items ?? []);
|
||||
state.recordTableParams.total = res.data.result?.total;
|
||||
recordOptions.loading = false;
|
||||
};
|
||||
|
||||
// 作业触发器运行记录-改变页面容量
|
||||
const handleSizeChange2 = (val: number) => {
|
||||
state.tableParams2.pageSize = val;
|
||||
handleQuery2();
|
||||
// 获取数据
|
||||
const fetchRecordData = async (tableParams: any) => {
|
||||
let params = Object.assign({ jobId: state.currentJob.jobDetail.jobId }, state.recordTableParams, tableParams);
|
||||
return getAPI(SysJobApi).apiSysJobPageJobTriggerRecordPost(params);
|
||||
};
|
||||
|
||||
// 作业触发器运行记录-改变页码序号
|
||||
const handleCurrentChange2 = (val: number) => {
|
||||
state.tableParams2.page = val;
|
||||
handleQuery2();
|
||||
// 改变页码序号或页面容量
|
||||
const recordPageChange: VxePagerEvents.PageChange = async ({ currentPage, pageSize }: VxePagerDefines.PageChangeEventParams) => {
|
||||
state.recordTableParams.page = currentPage;
|
||||
state.recordTableParams.pageSize = pageSize;
|
||||
await handleQueryRecord();
|
||||
};
|
||||
|
||||
// 列排序
|
||||
const recordSortChange = async (options: any) => {
|
||||
state.recordTableParams.field = options.field;
|
||||
state.recordTableParams.order = options.order;
|
||||
await handleQueryRecord();
|
||||
};
|
||||
</script>
|
||||
|
||||
@ -532,3 +607,21 @@ const handleCurrentChange2 = (val: number) => {
|
||||
width: 80px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
:deep(.el-drawer__body) {
|
||||
padding: 5px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
}
|
||||
.full-table {
|
||||
flex: 1;
|
||||
|
||||
:deep(.el-card__body) {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="sys-menu-container">
|
||||
<el-dialog v-model="state.isShowDialog" draggable :close-on-click-modal="false" width="700px">
|
||||
<el-dialog v-model="state.isShowDialog" draggable overflow destroy-on-close width="700px">
|
||||
<template #header>
|
||||
<div style="color: #fff">
|
||||
<el-icon size="16" style="margin-right: 3px; display: inline; vertical-align: middle"> <ele-Edit /> </el-icon>
|
||||
@ -8,7 +8,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<el-form :model="state.ruleForm" ref="ruleFormRef" label-width="auto">
|
||||
<el-row :gutter="35">
|
||||
<el-row :gutter="10">
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
|
||||
<el-form-item label="上级菜单">
|
||||
<el-cascader
|
||||
@ -149,9 +149,9 @@
|
||||
<script lang="ts" setup name="sysEditMenu">
|
||||
import { computed, reactive, ref } from 'vue';
|
||||
import IconSelector from '/@/components/iconSelector/index.vue';
|
||||
import other from '/@/utils/other';
|
||||
|
||||
import { getAPI } from '/@/utils/axios-utils';
|
||||
import other from '/@/utils/other';
|
||||
import { SysMenuApi } from '/@/api-services/api';
|
||||
import { SysMenu, UpdateMenuInput } from '/@/api-services/models';
|
||||
|
||||
|
||||
@ -1,75 +1,89 @@
|
||||
<template>
|
||||
<div class="sys-menu-container">
|
||||
<el-card shadow="hover" :body-style="{ paddingBottom: '0' }">
|
||||
<el-form :model="state.queryParams" ref="queryForm" :inline="true">
|
||||
<el-form-item label="菜单名称">
|
||||
<el-input v-model="state.queryParams.title" placeholder="菜单名称" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="类型">
|
||||
<el-select v-model="state.queryParams.type" placeholder="类型" clearable>
|
||||
<el-option label="目录" :value="1" />
|
||||
<el-option label="菜单" :value="2" />
|
||||
<el-option label="按钮" :value="3" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button-group>
|
||||
<el-button type="primary" icon="ele-Search" @click="handleQuery" v-auth="'sysMenu:list'"> 查询 </el-button>
|
||||
<el-button icon="ele-Refresh" @click="resetQuery"> 重置 </el-button>
|
||||
</el-button-group>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="ele-Plus" @click="openAddMenu" v-auth="'sysMenu:add'"> 新增 </el-button>
|
||||
</el-form-item>
|
||||
<div class="sys-menu-container" v-loading="options.loading">
|
||||
<el-card shadow="hover" :body-style="{ padding: '5px 5px 0 5px', display: 'flex', width: '100%', height: '100%', alignItems: 'start' }">
|
||||
<el-form :model="state.queryParams" ref="queryForm" :show-message="false" :inlineMessage="true" :label-width="'60px'" style="flex: 1 1 0%">
|
||||
<el-row :gutter="10">
|
||||
<el-col class="mb5" :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
|
||||
<el-form-item label="菜单名称" prop="title">
|
||||
<el-input v-model="state.queryParams.title" placeholder="菜单名称" clearable @keyup.enter.native="handleQuery" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col class="mb5" :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
|
||||
<el-form-item label="类型" prop="type">
|
||||
<el-select v-model="state.queryParams.type" placeholder="类型" clearable @clear="state.queryParams.type = undefined">
|
||||
<el-option label="目录" :value="1" />
|
||||
<el-option label="菜单" :value="2" />
|
||||
<el-option label="按钮" :value="3" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
|
||||
<el-divider style="height: calc(100% - 5px); margin: 0 10px" direction="vertical" />
|
||||
|
||||
<el-row>
|
||||
<el-col>
|
||||
<el-button-group>
|
||||
<el-button type="primary" icon="ele-Search" @click="handleQuery" v-auth="'sysMenu:list'" :loading="options.loading"> 查询 </el-button>
|
||||
<el-button icon="ele-Refresh" @click="resetQuery" :loading="options.loading"> 重置 </el-button>
|
||||
</el-button-group>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
|
||||
<el-card class="full-table" shadow="hover" style="margin-top: 5px">
|
||||
<el-table :data="state.menuData" v-loading="state.loading" row-key="id" :tree-props="{ children: 'children', hasChildren: 'hasChildren' }" border>
|
||||
<el-table-column label="菜单名称" header-align="center" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<SvgIcon :name="scope.row.icon" />
|
||||
<span class="ml10">{{ $t(scope.row.title) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="类型" width="70" align="center" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-tag type="warning" v-if="scope.row.type === 1">目录</el-tag>
|
||||
<el-tag v-else-if="scope.row.type === 2">菜单</el-tag>
|
||||
<el-tag type="info" v-else>按钮</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="path" label="路由路径" header-align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="component" label="组件路径" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="permission" label="权限标识" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="orderNo" label="排序" width="70" align="center" show-overflow-tooltip />
|
||||
<el-table-column label="状态" width="80" align="center" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-tag type="success" v-if="scope.row.status === 1">启用</el-tag>
|
||||
<el-tag type="danger" v-else>禁用</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="修改记录" width="100" align="center" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<ModifyRecord :data="scope.row" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="140" fixed="right" align="center" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-button icon="ele-Edit" size="small" text type="primary" @click="openEditMenu(scope.row)" v-auth="'sysMenu:update'"> 编辑 </el-button>
|
||||
<el-button icon="ele-Delete" size="small" text type="danger" @click="delMenu(scope.row)" v-auth="'sysMenu:delete'"> 删除 </el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<vxe-grid ref="xGrid" class="xGrid-style" v-bind="options" :tree-config="{}">
|
||||
<template #toolbar_buttons>
|
||||
<el-button type="primary" icon="ele-Plus" @click="handleAdd" v-auth="'sysMenu:add'"> 新增 </el-button>
|
||||
<el-button-group style="padding-left: 12px">
|
||||
<el-button type="primary" icon="ele-Expand" @click="handleExpand"> 全部展开 </el-button>
|
||||
<el-button type="primary" icon="ele-Fold" @click="handleFold"> 全部折叠 </el-button>
|
||||
</el-button-group>
|
||||
</template>
|
||||
<template #toolbar_tools> </template>
|
||||
<template #empty>
|
||||
<el-empty :image-size="200" />
|
||||
</template>
|
||||
<template #row_title="{ row }">
|
||||
<SvgIcon :name="row.icon" />
|
||||
<span class="ml10">{{ $t(row.title) }}</span>
|
||||
</template>
|
||||
<template #row_type="{ row }">
|
||||
<el-tag type="warning" v-if="row.type === 1">目录</el-tag>
|
||||
<el-tag v-else-if="row.type === 2">菜单</el-tag>
|
||||
<el-tag type="info" v-else>按钮</el-tag>
|
||||
</template>
|
||||
<template #row_status="{ row }">
|
||||
<el-tag v-if="row.status === 1" type="success">启用</el-tag>
|
||||
<el-tag v-else type="danger">禁用</el-tag>
|
||||
</template>
|
||||
<template #row_record="{ row }">
|
||||
<ModifyRecord :data="row" />
|
||||
</template>
|
||||
<template #row_buttons="{ row }">
|
||||
<el-tooltip content="编辑" placement="top">
|
||||
<el-button icon="ele-Edit" text type="primary" v-auth="'sysMenu:update'" @click="handleEdit(row)"> </el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="删除" placement="top">
|
||||
<el-button icon="ele-Delete" text type="danger" v-auth="'sysMenu:delete'" @click="handleDelete(row)"> </el-button>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
</vxe-grid>
|
||||
</el-card>
|
||||
|
||||
<EditMenu ref="editMenuRef" :title="state.editMenuTitle" :menuData="state.menuData" @handleQuery="handleQuery" />
|
||||
<EditMenu ref="editMenuRef" :title="state.title" :menuData="state.menuData" @handleQuery="handleQuery" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="sysMenu">
|
||||
import { onMounted, reactive, ref } from 'vue';
|
||||
import { ElMessageBox, ElMessage } from 'element-plus';
|
||||
import { auth } from '/@/utils/authFunction';
|
||||
import { VxeGridInstance } from 'vxe-table';
|
||||
import { useVxeTable } from '/@/hooks/vxeTableOptionsHook';
|
||||
import SvgIcon from '/@/components/svgIcon/index.vue';
|
||||
|
||||
import EditMenu from '/@/views/system/menu/component/editMenu.vue';
|
||||
import ModifyRecord from '/@/components/table/modifyRecord.vue';
|
||||
|
||||
@ -77,27 +91,60 @@ import { getAPI } from '/@/utils/axios-utils';
|
||||
import { SysMenuApi } from '/@/api-services/api';
|
||||
import { SysMenu } from '/@/api-services/models';
|
||||
|
||||
const xGrid = ref<VxeGridInstance>();
|
||||
const editMenuRef = ref<InstanceType<typeof EditMenu>>();
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
menuData: [] as Array<SysMenu>,
|
||||
queryParams: {
|
||||
title: undefined,
|
||||
type: undefined,
|
||||
},
|
||||
editMenuTitle: '',
|
||||
title: '',
|
||||
});
|
||||
|
||||
// 表格参数配置
|
||||
const options = useVxeTable<SysMenu>(
|
||||
{
|
||||
id: 'sysMenu',
|
||||
name: '菜单信息',
|
||||
columns: [
|
||||
// { type: 'checkbox', width: 40, fixed: 'left' },
|
||||
{ type: 'seq', title: '序号', width: 60, fixed: 'left' },
|
||||
{ field: 'title', title: '菜单名称', minWidth: 180, showOverflow: 'tooltip', treeNode: true, slots: { default: 'row_title' } },
|
||||
{ field: 'type', title: '菜单类型', minWidth: 100, showOverflow: 'tooltip', slots: { default: 'row_type' } },
|
||||
{ field: 'path', title: '路由路径', minWidth: 150, showOverflow: 'tooltip' },
|
||||
{ field: 'component', title: '组件路径', minWidth: 150, showOverflow: 'tooltip' },
|
||||
{ field: 'permission', title: '权限标识', minWidth: 160, showOverflow: 'tooltip' },
|
||||
{ field: 'orderNo', title: '排序', width: 80, showOverflow: 'tooltip' },
|
||||
{ field: 'status', title: '状态', width: 100, showOverflow: 'tooltip', slots: { default: 'row_status' } },
|
||||
{ field: '', title: '修改记录', width: 100, showOverflow: 'tooltip', slots: { default: 'row_record' } },
|
||||
{ title: '操作', fixed: 'right', width: 100, showOverflow: true, slots: { default: 'row_buttons' } },
|
||||
],
|
||||
enableExport: auth('sysMenu:export'),
|
||||
searchCallback: () => handleQuery(),
|
||||
queryAllCallback: () => fetchData({ pageSize: 99999 }),
|
||||
},
|
||||
{ stripe: false, checkboxConfig: { range: false } }
|
||||
);
|
||||
|
||||
// 页面初始化
|
||||
onMounted(async () => {
|
||||
handleQuery();
|
||||
await handleQuery();
|
||||
});
|
||||
|
||||
// 查询操作
|
||||
const handleQuery = async () => {
|
||||
state.loading = true;
|
||||
var res = await getAPI(SysMenuApi).apiSysMenuListGet(state.queryParams.title, state.queryParams.type);
|
||||
options.loading = true;
|
||||
var res = await fetchData(null);
|
||||
xGrid.value?.loadData(res.data.result ?? []);
|
||||
state.menuData = res.data.result ?? [];
|
||||
state.loading = false;
|
||||
options.loading = false;
|
||||
};
|
||||
|
||||
// 获取数据
|
||||
const fetchData = async (tableParams: any) => {
|
||||
let params = Object.assign(state.queryParams, tableParams);
|
||||
return getAPI(SysMenuApi).apiSysMenuListGet(params.title, params.type);
|
||||
};
|
||||
|
||||
// 重置操作
|
||||
@ -108,19 +155,19 @@ const resetQuery = () => {
|
||||
};
|
||||
|
||||
// 打开新增页面
|
||||
const openAddMenu = () => {
|
||||
state.editMenuTitle = '添加菜单';
|
||||
const handleAdd = () => {
|
||||
state.title = '添加菜单';
|
||||
editMenuRef.value?.openDialog({ type: 2, isHide: false, isKeepAlive: true, isAffix: false, isIframe: false, status: 1, orderNo: 100 });
|
||||
};
|
||||
|
||||
// 打开编辑页面
|
||||
const openEditMenu = (row: any) => {
|
||||
state.editMenuTitle = '编辑菜单';
|
||||
const handleEdit = (row: any) => {
|
||||
state.title = '编辑菜单';
|
||||
editMenuRef.value?.openDialog(row);
|
||||
};
|
||||
|
||||
// 删除当前行
|
||||
const delMenu = (row: any) => {
|
||||
const handleDelete = (row: any) => {
|
||||
ElMessageBox.confirm(`确定删除菜单:【${row.title}】?`, '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
@ -128,9 +175,19 @@ const delMenu = (row: any) => {
|
||||
})
|
||||
.then(async () => {
|
||||
await getAPI(SysMenuApi).apiSysMenuDeletePost({ id: row.id });
|
||||
handleQuery();
|
||||
ElMessage.success('删除成功');
|
||||
await handleQuery();
|
||||
})
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
// 全部展开
|
||||
const handleExpand = () => {
|
||||
xGrid.value?.setAllTreeExpand(true);
|
||||
};
|
||||
|
||||
// 全部折叠
|
||||
const handleFold = () => {
|
||||
xGrid.value?.clearTreeExpand();
|
||||
};
|
||||
</script>
|
||||
|
||||
@ -62,11 +62,11 @@ const openDialog = (row: any) => {
|
||||
|
||||
var receiveUser = JSON.parse(JSON.stringify(row));
|
||||
state.ruleForm.receiveUserId = receiveUser.userId;
|
||||
state.ruleForm.receiveUserName = receiveUser.realName;
|
||||
state.ruleForm.receiveUserName = receiveUser.realName;
|
||||
state.ruleForm.connectionId = receiveUser.connectionId;
|
||||
|
||||
|
||||
state.ruleForm.sendUserId = userInfos.value.id;
|
||||
state.ruleForm.sendUserName = userInfos.value.realName;
|
||||
state.ruleForm.sendUserName = userInfos.value.realName;
|
||||
state.ruleForm.sendTime = formatDate(new Date(), 'YYYY-mm-dd HH:MM:SS');
|
||||
state.isShowDialog = true;
|
||||
};
|
||||
|
||||
@ -1,50 +1,65 @@
|
||||
<template>
|
||||
<div class="sys-onlineUser-container">
|
||||
<el-drawer v-model="state.isVisible" title="在线用户列表" size="35%">
|
||||
<el-card shadow="hover" :body-style="{ paddingBottom: '0' }" style="margin: 8px">
|
||||
<el-form :model="state.queryParams" ref="queryForm" :inline="true">
|
||||
<el-form-item label="账号" prop="userName">
|
||||
<el-input placeholder="账号" clearable @keyup.enter="handleQuery" v-model="state.queryParams.userName" />
|
||||
</el-form-item>
|
||||
<el-form-item label="姓名" prop="realName">
|
||||
<el-input placeholder="姓名" clearable @keyup.enter="handleQuery" v-model="state.queryParams.realName" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button-group>
|
||||
<el-button type="primary" icon="ele-Search" @click="handleQuery"> 查询 </el-button>
|
||||
<el-button icon="ele-Refresh" @click="resetQuery"> 重置 </el-button>
|
||||
</el-button-group>
|
||||
</el-form-item>
|
||||
<el-drawer v-model="state.isVisible" size="35%">
|
||||
<template #header>
|
||||
<div style="color: #fff">
|
||||
<el-icon size="16" style="margin-right: 3px; display: inline; vertical-align: middle"> <ele-UserFilled /> </el-icon>
|
||||
<span> 在线用户列表</span>
|
||||
</div>
|
||||
</template>
|
||||
<el-card shadow="hover" :body-style="{ padding: '5px 5px 0 5px', display: 'flex', width: '100%', height: '100%', alignItems: 'start' }">
|
||||
<el-form :model="state.queryParams" ref="queryForm" :show-message="false" :inlineMessage="true" :label-width="'60px'" style="flex: 1 1 0%">
|
||||
<el-row :gutter="10">
|
||||
<el-col class="mb5" :xs="24" :sm="12" :md="8" :lg="8" :xl="6">
|
||||
<el-form-item label="账号" prop="userName">
|
||||
<el-input v-model="state.queryParams.userName" placeholder="账号" clearable @keyup.enter.native="handleQuery(true)" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col class="mb5" :xs="24" :sm="12" :md="8" :lg="8" :xl="6">
|
||||
<el-form-item label="姓名" prop="realName">
|
||||
<el-input v-model="state.queryParams.realName" placeholder="姓名" clearable @keyup.enter.native="handleQuery(true)" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
|
||||
<el-divider style="height: calc(100% - 5px); margin: 0 10px" direction="vertical" />
|
||||
|
||||
<el-row>
|
||||
<el-col>
|
||||
<el-button-group>
|
||||
<el-button type="primary" icon="ele-Search" @click="handleQuery(true)" :loading="options.loading"> 查询 </el-button>
|
||||
<el-button icon="ele-Refresh" @click="resetQuery" :loading="options.loading"> 重置 </el-button>
|
||||
</el-button-group>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
|
||||
<el-card shadow="hover" style="margin: 8px; padding-bottom: 15px">
|
||||
<el-table :data="state.onlineUserList" style="width: 100%" v-loading="state.loading" border>
|
||||
<el-table-column type="index" label="序号" width="55" align="center" />
|
||||
<el-table-column prop="userName" label="账号" header-align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="realName" label="姓名" header-align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="ip" label="IP地址" min-width="100" header-align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="browser" label="浏览器" header-align="center" show-overflow-tooltip />
|
||||
<!-- <el-table-column prop="connectionId" label="连接Id" show-overflow-tooltip></el-table-column> -->
|
||||
<el-table-column prop="time" label="登录时间" min-width="120" header-align="center" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="200" fixed="right" align="center" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-button icon="ele-Position" size="small" text type="primary" v-auth="'sysOnlineUser:forceOffline'" @click="openSendMessage(scope.row)"> 发送消息 </el-button>
|
||||
<el-button icon="ele-CircleCloseFilled" size="small" text type="danger" v-auth="'sysOnlineUser:forceOffline'" @click="forceOffline(scope.row)"> 强制下线 </el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
v-model:currentPage="state.tableParams.page"
|
||||
v-model:page-size="state.tableParams.pageSize"
|
||||
:total="state.tableParams.total"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
small
|
||||
background
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
/>
|
||||
<el-card class="full-table" shadow="hover" style="margin-top: 5px">
|
||||
<vxe-grid ref="xGrid" class="xGrid-style" v-bind="options" @sort-change="sortChange">
|
||||
<template #toolbar_buttons> </template>
|
||||
<template #toolbar_tools> </template>
|
||||
<template #empty>
|
||||
<el-empty :image-size="200" />
|
||||
</template>
|
||||
<template #row_buttons="{ row }">
|
||||
<el-tooltip content="发送消息" placement="top">
|
||||
<el-button icon="ele-Position" text type="primary" @click="openSendMessage(row)"> </el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="强制下线" placement="top">
|
||||
<el-button icon="ele-CircleCloseFilled" text type="danger" v-auth="'sysOnlineUser:forceOffline'" @click="forceOffline(row)"> </el-button>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
<template #pager>
|
||||
<vxe-pager
|
||||
:loading="options.loading"
|
||||
v-model:current-page="state.tableParams.page"
|
||||
v-model:page-size="state.tableParams.pageSize"
|
||||
:total="state.tableParams.total"
|
||||
@page-change="pageChange"
|
||||
/>
|
||||
</template>
|
||||
</vxe-grid>
|
||||
</el-card>
|
||||
</el-drawer>
|
||||
|
||||
@ -56,17 +71,19 @@
|
||||
import { onMounted, reactive, ref } from 'vue';
|
||||
import { ElMessageBox, ElNotification } from 'element-plus';
|
||||
import { throttle } from 'lodash-es';
|
||||
import { signalR } from './signalR';
|
||||
import { VxeGridInstance, VxePagerEvents, VxePagerDefines } from 'vxe-table';
|
||||
import { useVxeTable } from '/@/hooks/vxeTableOptionsHook';
|
||||
|
||||
import SendMessage from '/@/views/system/onlineUser/component/sendMessage.vue';
|
||||
|
||||
import { getAPI, clearAccessTokens } from '/@/utils/axios-utils';
|
||||
import { SysOnlineUserApi, SysAuthApi } from '/@/api-services/api';
|
||||
import { SysOnlineUser } from '/@/api-services/models';
|
||||
|
||||
import { signalR } from './signalR';
|
||||
|
||||
const xGrid = ref<VxeGridInstance>();
|
||||
const sendMessageRef = ref<InstanceType<typeof SendMessage>>();
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
isVisible: false,
|
||||
queryParams: {
|
||||
userName: undefined,
|
||||
@ -74,8 +91,11 @@ const state = reactive({
|
||||
},
|
||||
tableParams: {
|
||||
page: 1,
|
||||
pageSize: 10,
|
||||
total: 1 as any,
|
||||
pageSize: 50,
|
||||
field: 'id', // 默认的排序字段
|
||||
order: 'aes', // 排序方向
|
||||
descStr: 'desc', // 降序排序的关键字符
|
||||
total: 0 as any,
|
||||
},
|
||||
onlineUserList: [] as Array<SysOnlineUser>, // 在线用户列表
|
||||
lastUserState: {
|
||||
@ -84,6 +104,27 @@ const state = reactive({
|
||||
}, // 最后接收的用户变更状态信息
|
||||
});
|
||||
|
||||
// 表格参数配置
|
||||
const options = useVxeTable<SysOnlineUser>({
|
||||
id: 'sysOnlineUser',
|
||||
name: '在线用户',
|
||||
columns: [
|
||||
// { type: 'checkbox', width: 40, fixed: 'left' },
|
||||
{ type: 'seq', title: '序号', width: 50, fixed: 'left' },
|
||||
{ field: 'userName', title: '账号', minWidth: 110, showOverflow: 'tooltip' },
|
||||
{ field: 'realName', title: '姓名', minWidth: 110, showOverflow: 'tooltip' },
|
||||
{ field: 'ip', title: 'IP地址', minWidth: 100, showOverflow: 'tooltip' },
|
||||
{ field: 'browser', title: '浏览器', minWidth: 160, showOverflow: 'tooltip' },
|
||||
// { field: 'connectionId', title: '连接Id', minWidth: 160, showOverflow: 'tooltip', sortable: true },
|
||||
{ field: 'time', title: '登录时间', minWidth: 120, showOverflow: 'tooltip' },
|
||||
{ title: '操作', fixed: 'right', width: 100, showOverflow: true, slots: { default: 'row_buttons' } },
|
||||
],
|
||||
enableExport: true,
|
||||
searchCallback: () => handleQuery(),
|
||||
queryAllCallback: () => fetchData({ pageSize: 99999 }),
|
||||
});
|
||||
|
||||
// 页面初始化
|
||||
onMounted(async () => {
|
||||
// 在线用户列表
|
||||
signalR.off('OnlineUserList');
|
||||
@ -95,7 +136,6 @@ onMounted(async () => {
|
||||
};
|
||||
notificationThrottle();
|
||||
});
|
||||
|
||||
// 强制下线
|
||||
signalR.off('ForceOffline');
|
||||
signalR.on('ForceOffline', async (data: any) => {
|
||||
@ -131,13 +171,19 @@ const openDrawer = () => {
|
||||
};
|
||||
|
||||
// 查询操作
|
||||
const handleQuery = async () => {
|
||||
state.loading = true;
|
||||
let params = Object.assign(state.queryParams, state.tableParams);
|
||||
var res = await getAPI(SysOnlineUserApi).apiSysOnlineUserPagePost(params);
|
||||
state.onlineUserList = res.data.result?.items ?? [];
|
||||
const handleQuery = async (reset = false) => {
|
||||
options.loading = true;
|
||||
if (reset) state.tableParams.page = 1;
|
||||
var res = await fetchData(null);
|
||||
xGrid.value?.loadData(res.data.result?.items ?? []);
|
||||
state.tableParams.total = res.data.result?.total;
|
||||
state.loading = false;
|
||||
options.loading = false;
|
||||
};
|
||||
|
||||
// 获取数据
|
||||
const fetchData = async (tableParams: any) => {
|
||||
let params = Object.assign(state.queryParams, state.tableParams, tableParams);
|
||||
return getAPI(SysOnlineUserApi).apiSysOnlineUserPagePost(params);
|
||||
};
|
||||
|
||||
// 重置操作
|
||||
@ -148,9 +194,9 @@ const resetQuery = () => {
|
||||
};
|
||||
|
||||
// 发送消息
|
||||
const openSendMessage = (row: any)=>{
|
||||
const openSendMessage = (row: any) => {
|
||||
sendMessageRef.value?.openDialog(row);
|
||||
}
|
||||
};
|
||||
|
||||
// 强制下线
|
||||
const forceOffline = async (row: any) => {
|
||||
@ -167,18 +213,38 @@ const forceOffline = async (row: any) => {
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
// 改变页面容量
|
||||
const handleSizeChange = (val: number) => {
|
||||
state.tableParams.pageSize = val;
|
||||
// 改变页码序号或页面容量
|
||||
const pageChange: VxePagerEvents.PageChange = ({ currentPage, pageSize }: VxePagerDefines.PageChangeEventParams) => {
|
||||
state.tableParams.page = currentPage;
|
||||
state.tableParams.pageSize = pageSize;
|
||||
handleQuery();
|
||||
};
|
||||
|
||||
// 改变页码序号
|
||||
const handleCurrentChange = (val: number) => {
|
||||
state.tableParams.page = val;
|
||||
// 列排序
|
||||
const sortChange = (options: any) => {
|
||||
state.tableParams.field = options.field;
|
||||
state.tableParams.order = options.order;
|
||||
handleQuery();
|
||||
};
|
||||
|
||||
// 导出对象
|
||||
defineExpose({ openDrawer });
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
:deep(.el-drawer__body) {
|
||||
padding: 5px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
}
|
||||
.full-table {
|
||||
flex: 1;
|
||||
|
||||
:deep(.el-card__body) {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -20,10 +20,12 @@ connection.serverTimeoutInMilliseconds = 30 * 60 * 1000; // 超时时间30m
|
||||
connection.start().then(() => {
|
||||
console.log('启动连接');
|
||||
});
|
||||
|
||||
// 断开连接
|
||||
connection.onclose(async () => {
|
||||
console.log('断开连接');
|
||||
});
|
||||
|
||||
// 重连中
|
||||
connection.onreconnecting(() => {
|
||||
ElNotification({
|
||||
@ -33,6 +35,7 @@ connection.onreconnecting(() => {
|
||||
position: 'bottom-right',
|
||||
});
|
||||
});
|
||||
|
||||
// 重连成功
|
||||
connection.onreconnected(() => {
|
||||
console.log('重连成功');
|
||||
@ -41,7 +44,7 @@ connection.onreconnected(() => {
|
||||
connection.on('OnlineUserList', () => {});
|
||||
|
||||
// 接收消息
|
||||
connection.on("ReceiveMessage", (message: any)=>{
|
||||
connection.on('ReceiveMessage', (message: any) => {
|
||||
var tmpMsg = `${message.message}<br/>`;
|
||||
tmpMsg += `<p style="color:#808080; font-size:12px">发送人员:${message.sendUserName}<p>`;
|
||||
tmpMsg += `<p style="color:#808080; font-size:12px">发送时间:${message.sendTime}<p>`;
|
||||
@ -52,7 +55,7 @@ connection.on("ReceiveMessage", (message: any)=>{
|
||||
type: 'info',
|
||||
position: 'top-right',
|
||||
dangerouslyUseHTMLString: true,
|
||||
duration: 0
|
||||
duration: 0,
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<el-form :model="state.ruleForm" ref="ruleFormRef" label-width="auto">
|
||||
<el-row :gutter="35">
|
||||
<el-row :gutter="10">
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
|
||||
<el-form-item label="身份标识" prop="accessKey" :rules="[{ required: true, message: '身份标识不能为空', trigger: 'blur' }]">
|
||||
<el-input v-model="state.ruleForm.accessKey" placeholder="身份标识" clearable />
|
||||
@ -69,7 +69,7 @@ const state = reactive({
|
||||
});
|
||||
|
||||
onMounted(async () => {
|
||||
var res = await getAPI(SysTenantApi).apiSysTenantPagePost({ page: 1, pageSize: 10000 });
|
||||
let res = await getAPI(SysTenantApi).apiSysTenantPagePost({ page: 1, pageSize: 10000 });
|
||||
state.tenantData = res.data.result?.items ?? [];
|
||||
});
|
||||
|
||||
@ -78,7 +78,6 @@ const openDialog = (row: any) => {
|
||||
state.ruleForm = JSON.parse(JSON.stringify(row));
|
||||
state.isShowDialog = true;
|
||||
ruleFormRef.value?.resetFields();
|
||||
|
||||
tenantChange(false);
|
||||
};
|
||||
|
||||
|
||||
@ -78,6 +78,7 @@ const openDialog = () => {
|
||||
// 导出对象
|
||||
defineExpose({ openDialog });
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.text-content {
|
||||
h1 {
|
||||
|
||||
@ -1,125 +1,180 @@
|
||||
<template>
|
||||
<div class="sys-open-access-container">
|
||||
<el-card shadow="hover" :body-style="{ paddingBottom: '0' }">
|
||||
<el-form :model="state.queryParams" ref="queryForm" :inline="true">
|
||||
<el-form-item label="身份标识">
|
||||
<el-input v-model="state.queryParams.accessKey" placeholder="身份标识" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button-group>
|
||||
<el-button type="primary" icon="ele-Search" @click="handleQuery" v-auth="'sysOpenAccess:page'"> 查询 </el-button>
|
||||
<el-button icon="ele-Refresh" @click="resetQuery"> 重置 </el-button>
|
||||
</el-button-group>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="ele-Plus" @click="openAddOpenAccess" v-auth="'sysOpenAccess:add'"> 新增 </el-button>
|
||||
<el-button icon="ele-QuestionFilled" @click="openHelp"> 说明 </el-button>
|
||||
</el-form-item>
|
||||
<div class="sys-open-access-container" v-loading="options.loading">
|
||||
<el-card shadow="hover" :body-style="{ padding: '5px 5px 0 5px', display: 'flex', width: '100%', height: '100%', alignItems: 'start' }">
|
||||
<el-form :model="state.queryParams" ref="queryForm" :show-message="false" :inlineMessage="true" :label-width="'60px'" style="flex: 1 1 0%">
|
||||
<el-row :gutter="10">
|
||||
<el-col class="mb5" :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
|
||||
<el-form-item label="身份标识" prop="accessKey">
|
||||
<el-input v-model="state.queryParams.accessKey" placeholder="身份标识" clearable @keyup.enter.native="handleQuery(true)" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
|
||||
<el-divider style="height: calc(100% - 5px); margin: 0 10px" direction="vertical" />
|
||||
|
||||
<el-row>
|
||||
<el-col>
|
||||
<el-button-group>
|
||||
<el-button type="primary" icon="ele-Search" @click="handleQuery(true)" v-auth="'sysOpenAccess:page'" :loading="options.loading"> 查询 </el-button>
|
||||
<el-button icon="ele-Refresh" @click="resetQuery" :loading="options.loading"> 重置 </el-button>
|
||||
</el-button-group>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
|
||||
<el-card class="full-table" shadow="hover" style="margin-top: 5px">
|
||||
<el-table :data="state.openAccessData" style="width: 100%" v-loading="state.loading" border>
|
||||
<el-table-column type="index" label="序号" width="55" align="center" />
|
||||
<el-table-column prop="accessKey" label="身份标识" header-align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="accessSecret" label="密钥" header-align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="bindUserAccount" label="绑定用户账号" header-align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="bindTenantName" label="绑定租户名称" header-align="center" show-overflow-tooltip />
|
||||
<el-table-column label="修改记录" width="100" align="center" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<ModifyRecord :data="scope.row" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="200" fixed="right" align="center" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-button icon="ele-Edit" size="small" text type="primary" @click="openEditOpenAccess(scope.row)" v-auth="'sysOpenAccess:update'" :disabled="scope.row.status === 1"> 编辑 </el-button>
|
||||
<el-button icon="ele-Delete" size="small" text type="danger" @click="delOpenAccess(scope.row)" v-auth="'sysOpenAccess:delete'" :disabled="scope.row.status === 1"> 删除 </el-button>
|
||||
<el-button size="small" text @click="openGenerateSign(scope.row)"> 生成签名 </el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
v-model:currentPage="state.tableParams.page"
|
||||
v-model:page-size="state.tableParams.pageSize"
|
||||
:total="state.tableParams.total"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
small
|
||||
background
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
/>
|
||||
<vxe-grid ref="xGrid" class="xGrid-style" v-bind="options" @sort-change="sortChange">
|
||||
<template #toolbar_buttons>
|
||||
<el-button type="primary" icon="ele-Plus" @click="handleAdd" v-auth="'sysOpenAccess:add'"> 新增 </el-button>
|
||||
<el-button icon="ele-QuestionFilled" @click="openHelp"> 说明 </el-button>
|
||||
</template>
|
||||
<template #toolbar_tools> </template>
|
||||
<template #empty>
|
||||
<el-empty :image-size="200" />
|
||||
</template>
|
||||
<template #row_record="{ row }">
|
||||
<ModifyRecord :data="row" />
|
||||
</template>
|
||||
<template #row_buttons="{ row }">
|
||||
<el-tooltip content="编辑" placement="top">
|
||||
<el-button icon="ele-Edit" size="small" text type="primary" @click="handleEdit(row)" v-auth="'sysOpenAccess:update'" :disabled="row.status === 1" />
|
||||
</el-tooltip>
|
||||
<el-tooltip content="删除" placement="top">
|
||||
<el-button icon="ele-Delete" size="small" text type="danger" @click="handleDelete(row)" v-auth="'sysOpenAccess:delete'" :disabled="row.status === 1" />
|
||||
</el-tooltip>
|
||||
<el-tooltip content="生成签名" placement="top">
|
||||
<el-button icon="ele-EditPen" size="small" text type="warning" @click="handleSign(row)" />
|
||||
</el-tooltip>
|
||||
</template>
|
||||
<template #pager>
|
||||
<vxe-pager
|
||||
:loading="options.loading"
|
||||
v-model:current-page="state.tableParams.page"
|
||||
v-model:page-size="state.tableParams.pageSize"
|
||||
:total="state.tableParams.total"
|
||||
@page-change="pageChange"
|
||||
/>
|
||||
</template>
|
||||
</vxe-grid>
|
||||
</el-card>
|
||||
|
||||
<EditOpenAccess ref="editOpenAccessRef" :title="state.editOpenAccessTitle" @handleQuery="handleQuery" />
|
||||
<HelpView ref="helpViewRef" />
|
||||
<GenerateSign ref="generateSignRef" />
|
||||
<EditOpenAccess ref="editRef" :title="state.title" @handleQuery="handleQuery" />
|
||||
<HelpView ref="helpRef" />
|
||||
<GenerateSign ref="signRef" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="sysOpenAccess">
|
||||
import { onMounted, reactive, ref } from 'vue';
|
||||
import { ElMessageBox, ElMessage } from 'element-plus';
|
||||
import { auth } from '/@/utils/authFunction';
|
||||
import { VxeGridInstance, VxePagerEvents, VxePagerDefines } from 'vxe-table';
|
||||
import { useVxeTable } from '/@/hooks/vxeTableOptionsHook';
|
||||
|
||||
import EditOpenAccess from '/@/views/system/openAccess/component/editOpenAccess.vue';
|
||||
import HelpView from '/@/views/system/openAccess/component/helpView.vue';
|
||||
import ModifyRecord from '/@/components/table/modifyRecord.vue';
|
||||
import GenerateSign from '/@/views/system/openAccess/component/generateSign.vue';
|
||||
import ModifyRecord from '/@/components/table/modifyRecord.vue';
|
||||
|
||||
import { getAPI } from '/@/utils/axios-utils';
|
||||
import { SysOpenAccessApi } from '/@/api-services/api';
|
||||
import { OpenAccessOutput } from '/@/api-services/models';
|
||||
|
||||
const editOpenAccessRef = ref<InstanceType<typeof EditOpenAccess>>();
|
||||
const helpViewRef = ref<InstanceType<typeof HelpView>>();
|
||||
const generateSignRef = ref<InstanceType<typeof GenerateSign>>();
|
||||
const xGrid = ref<VxeGridInstance>();
|
||||
const editRef = ref<InstanceType<typeof EditOpenAccess>>();
|
||||
const helpRef = ref<InstanceType<typeof HelpView>>();
|
||||
const signRef = ref<InstanceType<typeof GenerateSign>>();
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
openAccessData: [] as Array<OpenAccessOutput>,
|
||||
queryParams: {
|
||||
accessKey: undefined,
|
||||
},
|
||||
tableParams: {
|
||||
page: 1,
|
||||
pageSize: 20,
|
||||
pageSize: 50,
|
||||
field: 'id', // 默认的排序字段
|
||||
order: 'aes', // 排序方向
|
||||
descStr: 'desc', // 降序排序的关键字符
|
||||
total: 0 as any,
|
||||
},
|
||||
editOpenAccessTitle: '',
|
||||
title: '',
|
||||
});
|
||||
|
||||
// 表格参数配置
|
||||
const options = useVxeTable<OpenAccessOutput>({
|
||||
id: 'sysOpenAccess',
|
||||
name: '开发接口身份',
|
||||
columns: [
|
||||
// { type: 'checkbox', width: 40, fixed: 'left' },
|
||||
{ type: 'seq', title: '序号', width: 60, fixed: 'left' },
|
||||
{ field: 'accessKey', title: '身份标识', minWidth: 200, showOverflow: 'tooltip' },
|
||||
{ field: 'accessSecret', title: '密钥', minWidth: 200, showOverflow: 'tooltip' },
|
||||
{ field: 'bindUserAccount', title: '绑定用户账号', minWidth: 200, showOverflow: 'tooltip' },
|
||||
{ field: 'bindTenantName', title: '绑定租户名称', minWidth: 200, showOverflow: 'tooltip' },
|
||||
{ field: '', title: '修改记录', width: 100, showOverflow: 'tooltip', slots: { default: 'row_record' } },
|
||||
{ title: '操作', fixed: 'right', minWidth: 100, showOverflow: true, slots: { default: 'row_buttons' } },
|
||||
],
|
||||
enableExport: auth('sysOpenAccess:export'),
|
||||
searchCallback: () => handleQuery(),
|
||||
queryAllCallback: () => fetchData({ pageSize: 99999 }),
|
||||
});
|
||||
|
||||
// 页面初始化
|
||||
onMounted(async () => {
|
||||
handleQuery();
|
||||
await handleQuery();
|
||||
});
|
||||
|
||||
// 查询操作
|
||||
const handleQuery = async () => {
|
||||
state.loading = true;
|
||||
let params = Object.assign(state.queryParams, state.tableParams);
|
||||
var res = await getAPI(SysOpenAccessApi).apiSysOpenAccessPagePost(params);
|
||||
state.openAccessData = res.data.result?.items ?? [];
|
||||
const handleQuery = async (reset = false) => {
|
||||
options.loading = true;
|
||||
if (reset) state.tableParams.page = 1;
|
||||
var res = await fetchData(null);
|
||||
xGrid.value?.loadData(res.data.result?.items ?? []);
|
||||
state.tableParams.total = res.data.result?.total;
|
||||
state.loading = false;
|
||||
options.loading = false;
|
||||
};
|
||||
|
||||
// 获取数据
|
||||
const fetchData = async (tableParams: any) => {
|
||||
let params = Object.assign(state.queryParams, state.tableParams, tableParams);
|
||||
return getAPI(SysOpenAccessApi).apiSysOpenAccessPagePost(params);
|
||||
};
|
||||
|
||||
// 重置操作
|
||||
const resetQuery = () => {
|
||||
state.queryParams.accessKey = undefined;
|
||||
handleQuery(true);
|
||||
};
|
||||
|
||||
// 改变页码序号或页面容量
|
||||
const pageChange: VxePagerEvents.PageChange = ({ currentPage, pageSize }: VxePagerDefines.PageChangeEventParams) => {
|
||||
state.tableParams.page = currentPage;
|
||||
state.tableParams.pageSize = pageSize;
|
||||
handleQuery();
|
||||
};
|
||||
|
||||
// 列排序
|
||||
const sortChange = (options: any) => {
|
||||
state.tableParams.field = options.field;
|
||||
state.tableParams.order = options.order;
|
||||
handleQuery();
|
||||
};
|
||||
|
||||
// 打开新增页面
|
||||
const openAddOpenAccess = () => {
|
||||
state.editOpenAccessTitle = '添加开放接口身份';
|
||||
editOpenAccessRef.value?.openDialog({ type: 1 });
|
||||
const handleAdd = () => {
|
||||
state.title = '添加开放接口身份';
|
||||
editRef.value?.openDialog({ type: 1 });
|
||||
};
|
||||
|
||||
// 打开编辑页面
|
||||
const openEditOpenAccess = (row: any) => {
|
||||
state.editOpenAccessTitle = '编辑开放接口身份';
|
||||
editOpenAccessRef.value?.openDialog(row);
|
||||
const handleEdit = (row: any) => {
|
||||
state.title = '编辑开放接口身份';
|
||||
editRef.value?.openDialog(row);
|
||||
};
|
||||
|
||||
// 删除
|
||||
const delOpenAccess = (row: any) => {
|
||||
const handleDelete = (row: any) => {
|
||||
ElMessageBox.confirm(`确定删除开放接口身份:【${row.accessKey}】?`, '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
@ -133,25 +188,13 @@ const delOpenAccess = (row: any) => {
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
// 改变页面容量
|
||||
const handleSizeChange = (val: number) => {
|
||||
state.tableParams.pageSize = val;
|
||||
handleQuery();
|
||||
};
|
||||
|
||||
// 改变页码序号
|
||||
const handleCurrentChange = (val: number) => {
|
||||
state.tableParams.page = val;
|
||||
handleQuery();
|
||||
};
|
||||
|
||||
// 打开说明页面
|
||||
const openHelp = () => {
|
||||
helpViewRef.value?.openDialog();
|
||||
helpRef.value?.openDialog();
|
||||
};
|
||||
|
||||
// 打开生成签名
|
||||
const openGenerateSign = (row: any) => {
|
||||
generateSignRef.value?.openDialog(row);
|
||||
const handleSign = (row: any) => {
|
||||
signRef.value?.openDialog(row);
|
||||
};
|
||||
</script>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="sys-plugin-container">
|
||||
<el-dialog v-model="state.isShowDialog" draggable :close-on-click-modal="false" width="900px">
|
||||
<el-dialog v-model="state.isShowDialog" draggable overflow destroy-on-close width="900px">
|
||||
<template #header>
|
||||
<div style="color: #fff">
|
||||
<el-icon size="16" style="margin-right: 3px; display: inline; vertical-align: middle"> <ele-Edit /> </el-icon>
|
||||
@ -10,7 +10,7 @@
|
||||
<el-tabs v-model="state.selectedTabName">
|
||||
<el-tab-pane label="插件信息">
|
||||
<el-form :model="state.ruleForm" ref="ruleFormRef" label-width="auto" style="height: 500px">
|
||||
<el-row :gutter="35">
|
||||
<el-row :gutter="10">
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
|
||||
<el-form-item label="功能名称" prop="name" :rules="[{ required: true, message: '功能名称不能为空', trigger: 'blur' }]">
|
||||
<el-input v-model="state.ruleForm.name" placeholder="功能名称" clearable />
|
||||
@ -112,7 +112,7 @@ const openDialog = (row: any) => {
|
||||
state.isShowDialog = true;
|
||||
ruleFormRef.value?.resetFields();
|
||||
|
||||
// 延迟拿值防止取不到
|
||||
// 延迟取值防止取不到
|
||||
setTimeout(() => {
|
||||
if (monacoEditor == null) initMonacoEditor();
|
||||
}, 1);
|
||||
|
||||
@ -1,66 +1,75 @@
|
||||
<template>
|
||||
<div class="sys-plugin-container">
|
||||
<el-card shadow="hover" :body-style="{ paddingBottom: '0' }">
|
||||
<el-form :model="state.queryParams" ref="queryForm" :inline="true">
|
||||
<el-form-item label="功能名称">
|
||||
<el-input v-model="state.queryParams.name" placeholder="功能名称" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button-group>
|
||||
<el-button type="primary" icon="ele-Search" @click="handleQuery" v-auth="'sysPlugin:page'"> 查询 </el-button>
|
||||
<el-button icon="ele-Refresh" @click="resetQuery"> 重置 </el-button>
|
||||
</el-button-group>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="ele-Plus" @click="openAddPlugin" v-auth="'sysPlugin:add'"> 新增 </el-button>
|
||||
</el-form-item>
|
||||
<div class="sys-plugin-container" v-loading="options.loading">
|
||||
<el-card shadow="hover" :body-style="{ padding: '5px 5px 0 5px', display: 'flex', width: '100%', height: '100%', alignItems: 'start' }">
|
||||
<el-form :model="state.queryParams" ref="queryForm" :show-message="false" :inlineMessage="true" :label-width="'60px'" style="flex: 1 1 0%">
|
||||
<el-row :gutter="10">
|
||||
<el-col class="mb5" :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
|
||||
<el-form-item label="功能名称" pro="name">
|
||||
<el-input v-model="state.queryParams.name" placeholder="功能名称" clearable @keyup.enter.native="handleQuery(true)" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
|
||||
<el-divider style="height: calc(100% - 5px); margin: 0 10px" direction="vertical" />
|
||||
|
||||
<el-row>
|
||||
<el-col>
|
||||
<el-button-group>
|
||||
<el-button type="primary" icon="ele-Search" @click="handleQuery(true)" v-auth="'sysPlugin:page'" :loading="options.loading"> 查询 </el-button>
|
||||
<el-button icon="ele-Refresh" @click="resetQuery" :loading="options.loading"> 重置 </el-button>
|
||||
</el-button-group>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
|
||||
<el-card class="full-table" shadow="hover" style="margin-top: 5px">
|
||||
<el-table :data="state.pluginData" style="width: 100%" v-loading="state.loading" border>
|
||||
<el-table-column type="index" label="序号" width="55" align="center" fixed />
|
||||
<el-table-column prop="name" label="功能名称" header-align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="assemblyName" label="程序集名称" header-align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="orderNo" label="排序" width="70" align="center" show-overflow-tooltip />
|
||||
<el-table-column label="状态" width="70" align="center" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-tag type="success" v-if="scope.row.status === 1">启用</el-tag>
|
||||
<el-tag type="danger" v-else>禁用</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="修改记录" width="100" align="center" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<ModifyRecord :data="scope.row" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="140" fixed="right" align="center" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-button icon="ele-Edit" size="small" text type="primary" @click="openEditPlugin(scope.row)" v-auth="'sysPlugin:update'"> 编辑 </el-button>
|
||||
<el-button icon="ele-Delete" size="small" text type="danger" @click="delPlugin(scope.row)" v-auth="'sysPlugin:delete'"> 删除 </el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
v-model:currentPage="state.tableParams.page"
|
||||
v-model:page-size="state.tableParams.pageSize"
|
||||
:total="state.tableParams.total"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
small
|
||||
background
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
/>
|
||||
<vxe-grid ref="xGrid" class="xGrid-style" v-bind="options" @sort-change="sortChange">
|
||||
<template #toolbar_buttons>
|
||||
<el-button type="primary" icon="ele-Plus" @click="handleAdd" v-auth="'sysPlugin:add'"> 新增 </el-button>
|
||||
</template>
|
||||
<template #toolbar_tools> </template>
|
||||
<template #empty>
|
||||
<el-empty :image-size="200" />
|
||||
</template>
|
||||
<template #row_status="{ row }">
|
||||
<el-tag v-if="row.status === 1" type="success">启用</el-tag>
|
||||
<el-tag v-else type="danger">禁用</el-tag>
|
||||
</template>
|
||||
<template #row_record="{ row }">
|
||||
<ModifyRecord :data="row" />
|
||||
</template>
|
||||
<template #row_buttons="{ row }">
|
||||
<el-tooltip content="编辑" placement="top">
|
||||
<el-button icon="ele-Edit" text type="primary" v-auth="'sysPlugin:update'" @click="handleEdit(row)"> </el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="删除" placement="top">
|
||||
<el-button icon="ele-Delete" text type="danger" v-auth="'sysPlugin:delete'" @click="handleDelete(row)"> </el-button>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
<template #pager>
|
||||
<vxe-pager
|
||||
:loading="options.loading"
|
||||
v-model:current-page="state.tableParams.page"
|
||||
v-model:page-size="state.tableParams.pageSize"
|
||||
:total="state.tableParams.total"
|
||||
@page-change="pageChange"
|
||||
/>
|
||||
</template>
|
||||
</vxe-grid>
|
||||
</el-card>
|
||||
|
||||
<EditPlugin ref="editPluginRef" :title="state.editPluginTitle" @handleQuery="handleQuery" />
|
||||
<EditPlugin ref="editPluginRef" :title="state.title" @handleQuery="handleQuery" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="sysPlugin">
|
||||
import { onMounted, reactive, ref } from 'vue';
|
||||
import { ElMessageBox, ElMessage } from 'element-plus';
|
||||
import { auth } from '/@/utils/authFunction';
|
||||
import { VxeGridInstance, VxePagerEvents, VxePagerDefines } from 'vxe-table';
|
||||
import { useVxeTable } from '/@/hooks/vxeTableOptionsHook';
|
||||
|
||||
import EditPlugin from '/@/views/system/plugin/component/editPlugin.vue';
|
||||
import ModifyRecord from '/@/components/table/modifyRecord.vue';
|
||||
|
||||
@ -68,55 +77,97 @@ import { getAPI } from '/@/utils/axios-utils';
|
||||
import { SysPluginApi } from '/@/api-services/api';
|
||||
import { SysPlugin } from '/@/api-services/models';
|
||||
|
||||
const xGrid = ref<VxeGridInstance>();
|
||||
const editPluginRef = ref<InstanceType<typeof EditPlugin>>();
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
pluginData: [] as Array<SysPlugin>,
|
||||
queryParams: {
|
||||
name: undefined,
|
||||
},
|
||||
tableParams: {
|
||||
page: 1,
|
||||
pageSize: 20,
|
||||
pageSize: 50,
|
||||
field: 'id', // 默认的排序字段
|
||||
order: 'aes', // 排序方向
|
||||
descStr: 'desc', // 降序排序的关键字符
|
||||
total: 0 as any,
|
||||
},
|
||||
editPluginTitle: '',
|
||||
visible: false,
|
||||
title: '',
|
||||
});
|
||||
//表格参数配置
|
||||
const options = useVxeTable<SysPlugin>({
|
||||
id: 'sysPlugin',
|
||||
name: '插件信息',
|
||||
columns: [
|
||||
// { type: 'checkbox', width: 40, fixed: 'left' },
|
||||
{ type: 'seq', title: '序号', width: 60, fixed: 'left' },
|
||||
{ field: 'name', title: '功能名称', minWidth: 200, showOverflow: 'tooltip' },
|
||||
{ field: 'assemblyName', title: '程序集名称', minWidth: 200, showOverflow: 'tooltip' },
|
||||
{ field: 'orderNo', title: '排序', width: 80, showOverflow: 'tooltip' },
|
||||
{ field: 'status', title: '状态', width: 80, showOverflow: 'tooltip', slots: { default: 'row_status' } },
|
||||
{ field: '', title: '修改记录', width: 100, showOverflow: 'tooltip', slots: { default: 'row_record' } },
|
||||
{ title: '操作', fixed: 'right', width: 100, showOverflow: true, slots: { default: 'row_buttons' } },
|
||||
],
|
||||
enableExport: auth('sysPlugin:export'),
|
||||
searchCallback: () => handleQuery(),
|
||||
queryAllCallback: () => fetchData({ pageSize: 99999 }),
|
||||
});
|
||||
|
||||
// 页面初始化
|
||||
onMounted(async () => {
|
||||
handleQuery();
|
||||
await handleQuery();
|
||||
});
|
||||
|
||||
// 查询操作
|
||||
const handleQuery = async () => {
|
||||
state.loading = true;
|
||||
let params = Object.assign(state.queryParams, state.tableParams);
|
||||
var res = await getAPI(SysPluginApi).apiSysPluginPagePost(params);
|
||||
state.pluginData = res.data.result?.items ?? [];
|
||||
const handleQuery = async (reset = false) => {
|
||||
options.loading = true;
|
||||
if (reset) state.tableParams.page = 1;
|
||||
var res = await fetchData(null);
|
||||
xGrid.value?.loadData(res.data.result?.items ?? []);
|
||||
state.tableParams.total = res.data.result?.total;
|
||||
state.loading = false;
|
||||
options.loading = false;
|
||||
};
|
||||
|
||||
// 获取数据
|
||||
const fetchData = async (tableParams: any) => {
|
||||
let params = Object.assign(state.queryParams, state.tableParams, tableParams);
|
||||
return getAPI(SysPluginApi).apiSysPluginPagePost(params);
|
||||
};
|
||||
|
||||
// 重置操作
|
||||
const resetQuery = () => {
|
||||
state.queryParams.name = undefined;
|
||||
handleQuery(true);
|
||||
};
|
||||
|
||||
// 改变页码序号或页面容量
|
||||
const pageChange: VxePagerEvents.PageChange = ({ currentPage, pageSize }: VxePagerDefines.PageChangeEventParams) => {
|
||||
state.tableParams.page = currentPage;
|
||||
state.tableParams.pageSize = pageSize;
|
||||
handleQuery();
|
||||
};
|
||||
|
||||
// 列排序
|
||||
const sortChange = (options: any) => {
|
||||
state.tableParams.field = options.field;
|
||||
state.tableParams.order = options.order;
|
||||
handleQuery();
|
||||
};
|
||||
|
||||
// 打开新增页面
|
||||
const openAddPlugin = () => {
|
||||
state.editPluginTitle = '添加动态插件';
|
||||
editPluginRef.value?.openDialog({ orderNo: 100, status: 1 });
|
||||
const handleAdd = () => {
|
||||
state.title = '添加动态插件';
|
||||
editPluginRef.value?.openDialog({ status: 1, orderNo: 100 });
|
||||
};
|
||||
|
||||
// 打开编辑页面
|
||||
const openEditPlugin = (row: any) => {
|
||||
state.editPluginTitle = '编辑动态插件';
|
||||
const handleEdit = (row: any) => {
|
||||
state.title = '编辑动态插件';
|
||||
editPluginRef.value?.openDialog(row);
|
||||
};
|
||||
|
||||
// 删除当前行
|
||||
const delPlugin = (row: any) => {
|
||||
// 删除
|
||||
const handleDelete = (row: any) => {
|
||||
ElMessageBox.confirm(`确定删除动态插件:【${row.name}】?`, '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
@ -129,16 +180,4 @@ const delPlugin = (row: any) => {
|
||||
})
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
// 改变页面容量
|
||||
const handleSizeChange = (val: number) => {
|
||||
state.tableParams.pageSize = val;
|
||||
handleQuery();
|
||||
};
|
||||
|
||||
// 改变页码序号
|
||||
const handleCurrentChange = (val: number) => {
|
||||
state.tableParams.page = val;
|
||||
handleQuery();
|
||||
};
|
||||
</script>
|
||||
|
||||
@ -1,14 +1,14 @@
|
||||
<template>
|
||||
<div class="sys-print-container">
|
||||
<div class="printDialog">
|
||||
<el-dialog v-model="state.isShowDialog" draggable :close-on-click-modal="false" fullscreen>
|
||||
<el-dialog v-model="state.isShowDialog" draggable overflow destroy-on-close fullscreen>
|
||||
<template #header>
|
||||
<div style="color: #fff">
|
||||
<el-icon size="16" style="margin-right: 3px; display: inline; vertical-align: middle"> <ele-Edit /> </el-icon>
|
||||
<span> {{ props.title }} </span>
|
||||
</div>
|
||||
</template>
|
||||
<div style="margin: -16px 0px 0px 0px">
|
||||
<div style="margin: 0px 0px 0px 0px">
|
||||
<HiprintDesign ref="hiprintDesignRef" />
|
||||
</div>
|
||||
<template #footer>
|
||||
@ -20,7 +20,7 @@
|
||||
</el-dialog>
|
||||
</div>
|
||||
|
||||
<el-dialog v-model="state.showDialog2" draggable :close-on-click-modal="false" width="600px">
|
||||
<el-dialog v-model="state.showDialog2" draggable overflow destroy-on-close width="600px">
|
||||
<template #header>
|
||||
<div style="color: #fff">
|
||||
<el-icon size="16" style="margin-right: 3px; display: inline; vertical-align: middle"> <ele-Edit /> </el-icon>
|
||||
@ -28,7 +28,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<el-form :model="state.ruleForm" ref="ruleFormRef" label-width="auto">
|
||||
<el-row :gutter="35">
|
||||
<el-row :gutter="10">
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
|
||||
<el-form-item label="模板名称" prop="name" :rules="[{ required: true, message: '模板名称不能为空', trigger: 'blur' }]">
|
||||
<el-input v-model="state.ruleForm.name" placeholder="模板名称" clearable />
|
||||
@ -104,6 +104,7 @@ const state = reactive({
|
||||
showDialog2: false,
|
||||
});
|
||||
|
||||
// 页面初始化
|
||||
onMounted(async () => {});
|
||||
|
||||
// 打开弹窗
|
||||
@ -168,6 +169,7 @@ defineExpose({ openDialog });
|
||||
}
|
||||
.el-dialog__body {
|
||||
max-height: calc(100vh - 80px) !important;
|
||||
height: calc(100vh - 80px) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -70,19 +70,19 @@
|
||||
|
||||
<el-row :gutter="8">
|
||||
<el-col :span="4">
|
||||
<el-card style="height: 100%" shadow="never">
|
||||
<el-card style="height: 100%" shadow="never" :body-style="{ padding: '0px 0 5px 7px' }">
|
||||
<el-row>
|
||||
<el-col :span="24" id="hiprintEpContainer" class="rect-printElement-types hiprintEpContainer"> </el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="14">
|
||||
<el-card shadow="never" class="card-design">
|
||||
<el-card shadow="never" class="card-design" :body-style="{ padding: '18px' }">
|
||||
<div id="hiprint-printTemplate" class="hiprint-printTemplate"></div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="6" class="params_setting_container">
|
||||
<el-card shadow="never">
|
||||
<el-card shadow="never" :body-style="{ padding: '0px' }">
|
||||
<el-row class="hinnn-layout-sider">
|
||||
<div id="PrintElementOptionSetting"></div>
|
||||
</el-row>
|
||||
@ -181,7 +181,6 @@ const changeMode = () => {
|
||||
hiprint.init({
|
||||
providers: [provider.f],
|
||||
});
|
||||
|
||||
// 渲染自定义选项
|
||||
const hiprintEpContainerEl = document.getElementById('hiprintEpContainer');
|
||||
if (hiprintEpContainerEl) {
|
||||
@ -212,7 +211,7 @@ const changeMode = () => {
|
||||
});
|
||||
hiprintTemplate.value.design('#hiprint-printTemplate');
|
||||
// 获取当前放大比例, 当zoom时传true才会有
|
||||
state.scaleValue = hiprintTemplate.value.editingPanel.scale || 1;
|
||||
state.scaleValue = hiprintTemplate.value.editingPanel?.scale ?? 1;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -239,7 +238,7 @@ const changeScale = (currentValue: number, oldValue: number) => {
|
||||
let big = false;
|
||||
currentValue <= oldValue ? (big = false) : (big = true);
|
||||
|
||||
let scaleVal = state.scaleValue;
|
||||
let scaleVal = currentValue;
|
||||
if (big) {
|
||||
if (scaleVal > state.scaleMax) scaleVal = 5;
|
||||
} else {
|
||||
|
||||
@ -1,66 +1,75 @@
|
||||
<template>
|
||||
<div class="sys-print-container">
|
||||
<el-card shadow="hover" :body-style="{ paddingBottom: '0' }">
|
||||
<el-form :model="state.queryParams" ref="queryForm" :inline="true">
|
||||
<el-form-item label="模板名称">
|
||||
<el-input v-model="state.queryParams.name" placeholder="模板名称" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button-group>
|
||||
<el-button type="primary" icon="ele-Search" @click="handleQuery" v-auth="'sysPrint:page'"> 查询 </el-button>
|
||||
<el-button icon="ele-Refresh" @click="resetQuery"> 重置 </el-button>
|
||||
</el-button-group>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="ele-Plus" @click="openAddPrint" v-auth="'sysPrint:add'"> 新增 </el-button>
|
||||
</el-form-item>
|
||||
<div class="sys-print-container" v-loading="options.loading">
|
||||
<el-card shadow="hover" :body-style="{ padding: '5px 5px 0 5px', display: 'flex', width: '100%', height: '100%', alignItems: 'start' }">
|
||||
<el-form :model="state.queryParams" ref="queryForm" :show-message="false" :inlineMessage="true" :label-width="'60px'" style="flex: 1 1 0%">
|
||||
<el-row :gutter="10">
|
||||
<el-col class="mb5" :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
|
||||
<el-form-item label="模板名称" prop="name">
|
||||
<el-input v-model="state.queryParams.name" placeholder="模板名称" clearable @keyup.enter.native="handleQuery(true)" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
|
||||
<el-divider style="height: calc(100% - 5px); margin: 0 10px" direction="vertical" />
|
||||
|
||||
<el-row>
|
||||
<el-col>
|
||||
<el-button-group>
|
||||
<el-button type="primary" icon="ele-Search" @click="handleQuery(true)" v-auth="'sysPrint:page'" :loading="options.loading"> 查询 </el-button>
|
||||
<el-button icon="ele-Refresh" @click="resetQuery" :loading="options.loading"> 重置 </el-button>
|
||||
</el-button-group>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
|
||||
<el-card class="full-table" shadow="hover" style="margin-top: 5px">
|
||||
<el-table :data="state.printData" style="width: 100%" v-loading="state.loading" border>
|
||||
<el-table-column type="index" label="序号" width="55" align="center" fixed />
|
||||
<el-table-column prop="name" label="名称" header-align="center" show-overflow-tooltip />
|
||||
<!-- <el-table-column prop="template" label="模板" show-overflow-tooltip /> -->
|
||||
<el-table-column prop="orderNo" label="排序" align="center" show-overflow-tooltip />
|
||||
<el-table-column label="状态" align="center" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-tag type="success" v-if="scope.row.status === 1">启用</el-tag>
|
||||
<el-tag type="danger" v-else>禁用</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="修改记录" width="100" align="center" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<ModifyRecord :data="scope.row" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="140" fixed="right" align="center" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-button icon="ele-Edit" size="small" text type="primary" @click="openEditPrint(scope.row)" v-auth="'sysPrint:update'"> 编辑 </el-button>
|
||||
<el-button icon="ele-Delete" size="small" text type="danger" @click="delPrint(scope.row)" v-auth="'sysPrint:delete'"> 删除 </el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
v-model:currentPage="state.tableParams.page"
|
||||
v-model:page-size="state.tableParams.pageSize"
|
||||
:total="state.tableParams.total"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
small
|
||||
background
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
/>
|
||||
<vxe-grid ref="xGrid" class="xGrid-style" v-bind="options" @sort-change="sortChange">
|
||||
<template #toolbar_buttons>
|
||||
<el-button type="primary" icon="ele-Plus" @click="handleAdd" v-auth="'sysPrint:add'"> 新增 </el-button>
|
||||
</template>
|
||||
<template #toolbar_tools> </template>
|
||||
<template #empty>
|
||||
<el-empty :image-size="200" />
|
||||
</template>
|
||||
<template #row_status="{ row }">
|
||||
<el-tag v-if="row.status === 1" type="success">启用</el-tag>
|
||||
<el-tag v-else type="danger">禁用</el-tag>
|
||||
</template>
|
||||
<template #row_record="{ row }">
|
||||
<ModifyRecord :data="row" />
|
||||
</template>
|
||||
<template #row_buttons="{ row }">
|
||||
<el-tooltip content="编辑" placement="top">
|
||||
<el-button icon="ele-Edit" text type="primary" v-auth="'sysPrint:update'" @click="handleEdit(row)"> </el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="删除" placement="top">
|
||||
<el-button icon="ele-Delete" text type="danger" v-auth="'sysPrint:delete'" @click="handleDelete(row)"> </el-button>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
<template #pager>
|
||||
<vxe-pager
|
||||
:loading="options.loading"
|
||||
v-model:current-page="state.tableParams.page"
|
||||
v-model:page-size="state.tableParams.pageSize"
|
||||
:total="state.tableParams.total"
|
||||
@page-change="pageChange"
|
||||
/>
|
||||
</template>
|
||||
</vxe-grid>
|
||||
</el-card>
|
||||
|
||||
<EditPrint ref="editPrintRef" :title="state.editPrintTitle" @handleQuery="handleQuery" />
|
||||
<EditPrint ref="editPrintRef" :title="state.title" @handleQuery="handleQuery" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="sysPrint">
|
||||
import { onMounted, reactive, ref } from 'vue';
|
||||
import { ElMessageBox, ElMessage } from 'element-plus';
|
||||
import { auth } from '/@/utils/authFunction';
|
||||
import { VxeGridInstance, VxePagerEvents, VxePagerDefines } from 'vxe-table';
|
||||
import { useVxeTable } from '/@/hooks/vxeTableOptionsHook';
|
||||
|
||||
import EditPrint from '/@/views/system/print/component/editPrint.vue';
|
||||
import ModifyRecord from '/@/components/table/modifyRecord.vue';
|
||||
|
||||
@ -68,55 +77,100 @@ import { getAPI } from '/@/utils/axios-utils';
|
||||
import { SysPrintApi } from '/@/api-services/api';
|
||||
import { SysPrint } from '/@/api-services/models';
|
||||
|
||||
const xGrid = ref<VxeGridInstance>();
|
||||
const editPrintRef = ref<InstanceType<typeof EditPrint>>();
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
printData: [] as Array<SysPrint>,
|
||||
queryParams: {
|
||||
name: undefined,
|
||||
},
|
||||
tableParams: {
|
||||
page: 1,
|
||||
pageSize: 10,
|
||||
pageSize: 50,
|
||||
field: 'id', // 默认的排序字段
|
||||
order: 'aes', // 排序方向
|
||||
descStr: 'desc', // 降序排序的关键字符
|
||||
total: 0 as any,
|
||||
},
|
||||
editPrintTitle: '',
|
||||
visible: false,
|
||||
title: '',
|
||||
});
|
||||
|
||||
// 表格参数配置
|
||||
const options = useVxeTable<SysPrint>({
|
||||
id: 'sysPrint',
|
||||
name: '打印信息',
|
||||
columns: [
|
||||
// { type: 'checkbox', width: 40, fixed: 'left' },
|
||||
{ type: 'seq', title: '序号', width: 60, fixed: 'left' },
|
||||
{ field: 'name', title: '名称', minWidth: 250, showOverflow: 'tooltip' },
|
||||
// { field: 'template', title: '模板', minWidth: 200, showOverflow: 'tooltip', sortable: true },
|
||||
{ field: 'createTime', title: '修改时间', minWidth: 150, showOverflow: 'tooltip' },
|
||||
{ field: 'remark', title: '备注', minWidth: 250, showOverflow: 'tooltip' },
|
||||
{ field: 'orderNo', title: '排序', width: 80, showOverflow: 'tooltip' },
|
||||
{ field: 'status', title: '状态', width: 100, showOverflow: 'tooltip', slots: { default: 'row_status' } },
|
||||
{ field: '', title: '修改记录', width: 100, showOverflow: 'tooltip', slots: { default: 'row_record' } },
|
||||
{ title: '操作', fixed: 'right', width: 100, showOverflow: true, slots: { default: 'row_buttons' } },
|
||||
],
|
||||
enableExport: auth('sysPrint:export'),
|
||||
searchCallback: () => handleQuery(),
|
||||
queryAllCallback: () => fetchData({ pageSize: 99999 }),
|
||||
});
|
||||
|
||||
// 页面初始化
|
||||
onMounted(async () => {
|
||||
handleQuery();
|
||||
await handleQuery();
|
||||
});
|
||||
|
||||
// 查询操作
|
||||
const handleQuery = async () => {
|
||||
state.loading = true;
|
||||
let params = Object.assign(state.queryParams, state.tableParams);
|
||||
var res = await getAPI(SysPrintApi).apiSysPrintPagePost(params);
|
||||
state.printData = res.data.result?.items ?? [];
|
||||
const handleQuery = async (reset = false) => {
|
||||
options.loading = true;
|
||||
if (reset) state.tableParams.page = 1;
|
||||
var res = await fetchData(null);
|
||||
xGrid.value?.loadData(res.data.result?.items ?? []);
|
||||
state.tableParams.total = res.data.result?.total;
|
||||
state.loading = false;
|
||||
options.loading = false;
|
||||
};
|
||||
|
||||
// 获取数据
|
||||
const fetchData = async (tableParams: any) => {
|
||||
let params = Object.assign(state.queryParams, state.tableParams, tableParams);
|
||||
return getAPI(SysPrintApi).apiSysPrintPagePost(params);
|
||||
};
|
||||
|
||||
// 重置操作
|
||||
const resetQuery = () => {
|
||||
state.queryParams.name = undefined;
|
||||
handleQuery(true);
|
||||
};
|
||||
|
||||
// 改变页码序号或页面容量
|
||||
const pageChange: VxePagerEvents.PageChange = ({ currentPage, pageSize }: VxePagerDefines.PageChangeEventParams) => {
|
||||
state.tableParams.page = currentPage;
|
||||
state.tableParams.pageSize = pageSize;
|
||||
handleQuery();
|
||||
};
|
||||
|
||||
// 列排序
|
||||
const sortChange = (options: any) => {
|
||||
state.tableParams.field = options.field;
|
||||
state.tableParams.order = options.order;
|
||||
handleQuery();
|
||||
};
|
||||
|
||||
// 打开新增页面
|
||||
const openAddPrint = () => {
|
||||
state.editPrintTitle = '添加打印模板';
|
||||
const handleAdd = () => {
|
||||
state.title = '添加打印模板';
|
||||
editPrintRef.value?.openDialog({});
|
||||
};
|
||||
|
||||
// 打开编辑页面
|
||||
const openEditPrint = (row: any) => {
|
||||
state.editPrintTitle = '编辑打印模板';
|
||||
const handleEdit = (row: any) => {
|
||||
state.title = '编辑打印模板';
|
||||
editPrintRef.value?.openDialog(row);
|
||||
};
|
||||
|
||||
// 删除当前行
|
||||
const delPrint = (row: any) => {
|
||||
// 删除
|
||||
const handleDelete = (row: any) => {
|
||||
ElMessageBox.confirm(`确定删除打印模板:【${row.name}】?`, '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
@ -129,16 +183,4 @@ const delPrint = (row: any) => {
|
||||
})
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
// 改变页面容量
|
||||
const handleSizeChange = (val: number) => {
|
||||
state.tableParams.pageSize = val;
|
||||
handleQuery();
|
||||
};
|
||||
|
||||
// 改变页码序号
|
||||
const handleCurrentChange = (val: number) => {
|
||||
state.tableParams.page = val;
|
||||
handleQuery();
|
||||
};
|
||||
</script>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="sys-region-container">
|
||||
<el-dialog v-model="state.isShowDialog" draggable :close-on-click-modal="false" width="700px">
|
||||
<el-dialog v-model="state.isShowDialog" draggable overflow destroy-on-close width="700px">
|
||||
<template #header>
|
||||
<div style="color: #fff">
|
||||
<el-icon size="16" style="margin-right: 3px; display: inline; vertical-align: middle"> <ele-Edit /> </el-icon>
|
||||
@ -8,7 +8,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<el-form :model="state.ruleForm" ref="ruleFormRef" label-width="auto">
|
||||
<el-row :gutter="35">
|
||||
<el-row :gutter="10">
|
||||
<!-- <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
|
||||
<el-form-item label="上级名称">
|
||||
<el-cascader
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
<template>
|
||||
<el-card class="box-card" shadow="hover" style="height: 100%" body-style="height:100%; overflow:auto">
|
||||
<el-card class="box-card" shadow="hover" body-style="height:100%; overflow:auto;padding:5px;">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<div class="tree-h-flex">
|
||||
<div class="tree-h-left">
|
||||
<el-input :prefix-icon="Search" v-model="filterText" placeholder="行政区域名称" />
|
||||
<el-input :prefix-icon="Search" v-model="filterText" clearable placeholder="行政区域名称" />
|
||||
</div>
|
||||
<div class="tree-h-right">
|
||||
<el-dropdown @command="handleCommand">
|
||||
@ -27,20 +27,22 @@
|
||||
</div>
|
||||
</template>
|
||||
<div style="margin-bottom: 45px" v-loading="state.loading">
|
||||
<el-tree
|
||||
ref="treeRef"
|
||||
class="filter-tree"
|
||||
:data="state.regionData"
|
||||
node-key="id"
|
||||
:props="{ children: 'children', label: 'name' }"
|
||||
:filter-node-method="filterNode"
|
||||
@node-click="nodeClick"
|
||||
highlight-current
|
||||
check-strictly
|
||||
accordion
|
||||
lazy
|
||||
:load="loadNode"
|
||||
/>
|
||||
<el-scrollbar>
|
||||
<el-tree
|
||||
ref="treeRef"
|
||||
class="filter-tree"
|
||||
:data="state.regionData"
|
||||
node-key="id"
|
||||
:props="{ children: 'children', label: 'name' }"
|
||||
:filter-node-method="filterNode"
|
||||
@node-click="nodeClick"
|
||||
highlight-current
|
||||
check-strictly
|
||||
accordion
|
||||
lazy
|
||||
:load="loadNode"
|
||||
/>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
</el-card>
|
||||
</template>
|
||||
@ -49,6 +51,7 @@
|
||||
import { onMounted, reactive, ref, watch } from 'vue';
|
||||
import type { ElTree } from 'element-plus';
|
||||
import { Search, MoreFilled } from '@element-plus/icons-vue';
|
||||
import { TreeKey } from 'element-plus/es/components/tree/src/tree.type';
|
||||
|
||||
import { getAPI } from '/@/utils/axios-utils';
|
||||
import { SysRegionApi } from '/@/api-services/api';
|
||||
@ -62,14 +65,14 @@ const state = reactive({
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
initTreeData();
|
||||
fetchTreeData();
|
||||
});
|
||||
|
||||
watch(filterText, (val) => {
|
||||
treeRef.value!.filter(val);
|
||||
});
|
||||
|
||||
const initTreeData = async () => {
|
||||
const fetchTreeData = async () => {
|
||||
state.loading = true;
|
||||
var res = await getAPI(SysRegionApi).apiSysRegionListGet(0);
|
||||
state.regionData = res.data.result ?? [];
|
||||
@ -106,8 +109,9 @@ const handleCommand = async (command: string | number | object) => {
|
||||
treeRef.value!.store._getAllNodes()[i].expanded = false;
|
||||
}
|
||||
} else if ('refresh' == command) {
|
||||
initTreeData();
|
||||
fetchTreeData();
|
||||
} else if ('rootNode' == command) {
|
||||
treeRef.value?.setCurrentKey();
|
||||
emits('node-click', { id: 0, name: '' });
|
||||
}
|
||||
};
|
||||
@ -118,11 +122,22 @@ const nodeClick = (node: any) => {
|
||||
emits('node-click', { id: node.id, name: node.name });
|
||||
};
|
||||
|
||||
// 设置当前选中节点
|
||||
const setCurrentKey = (key?: TreeKey | undefined, shouldAutoExpandParent?: boolean | undefined) => {
|
||||
treeRef.value?.setCurrentKey(key, shouldAutoExpandParent);
|
||||
};
|
||||
|
||||
// 导出对象
|
||||
defineExpose({ initTreeData, getCheckedKeys });
|
||||
defineExpose({ fetchTreeData, getCheckedKeys, setCurrentKey });
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.box-card {
|
||||
flex: 1;
|
||||
> :deep(.el-card__header) {
|
||||
padding: 5px;
|
||||
}
|
||||
}
|
||||
.tree-h-flex {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
@ -1,68 +1,86 @@
|
||||
<template>
|
||||
<div class="sys-region-container">
|
||||
<el-row :gutter="8" style="width: 100%; flex: 1">
|
||||
<el-col :span="6" :xs="24">
|
||||
<RegionTree ref="regionTreeRef" @node-click="nodeClick" />
|
||||
<div class="sys-region-container" v-loading="options.loading">
|
||||
<el-row :gutter="5" style="width: 100%; height: 100%">
|
||||
<el-col :span="6" :xs="24" style="display: flex; height: 100%">
|
||||
<RegionTree ref="regionTreeRef" @node-click="handleNodeChange" />
|
||||
</el-col>
|
||||
|
||||
<el-col :span="18" :xs="24" style="display: flex; flex-direction: column">
|
||||
<el-card shadow="hover" :body-style="{ paddingBottom: '0' }">
|
||||
<el-form :model="state.queryParams" ref="queryForm" :inline="true">
|
||||
<el-form-item label="行政名称">
|
||||
<el-input v-model="state.queryParams.name" placeholder="行政名称" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="行政代码">
|
||||
<el-input v-model="state.queryParams.code" placeholder="行政代码" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button-group>
|
||||
<el-button type="primary" icon="ele-Search" @click="handleQuery" v-auth="'sysRegion:page'"> 查询 </el-button>
|
||||
<el-button icon="ele-Refresh" @click="resetQuery"> 重置 </el-button>
|
||||
</el-button-group>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="ele-Plus" @click="openAddRegion" v-auth="'sysRegion:add'"> 新增 </el-button>
|
||||
<el-button type="danger" icon="ele-Lightning" @click="handlSync" v-auth="'sysRegion:sync'"> 同步统计局 </el-button>
|
||||
</el-form-item>
|
||||
<el-col :span="18" :xs="24" style="display: flex; flex-direction: column; height: 100%">
|
||||
<el-card shadow="hover" :body-style="{ padding: '5px 5px 0 5px', display: 'flex', width: '100%', height: '100%', alignItems: 'start' }">
|
||||
<el-form :model="state.queryParams" ref="queryForm" :show-message="false" :inlineMessage="true" :label-width="'60px'" style="flex: 1 1 0%">
|
||||
<el-row :gutter="10">
|
||||
<el-col class="mb5" :xs="24" :sm="12" :md="8" :lg="8" :xl="6">
|
||||
<el-form-item label="行政名称" prop="name">
|
||||
<el-input v-model="state.queryParams.name" placeholder="行政名称" clearable @keyup.enter.native="handleQuery(true)" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col class="mb5" :xs="24" :sm="12" :md="8" :lg="8" :xl="6">
|
||||
<el-form-item label="行政代码" prop="code">
|
||||
<el-input v-model="state.queryParams.code" placeholder="行政代码" clearable @keyup.enter.native="handleQuery(true)" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
|
||||
<el-divider style="height: calc(100% - 5px); margin: 0 10px" direction="vertical" />
|
||||
|
||||
<el-row>
|
||||
<el-col>
|
||||
<el-button-group>
|
||||
<el-button type="primary" icon="ele-Search" @click="handleQuery(true)" v-auth="'sysRegion:page'" :loading="options.loading"> 查询 </el-button>
|
||||
<el-button icon="ele-Refresh" @click="resetQuery" :loading="options.loading"> 重置 </el-button>
|
||||
</el-button-group>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
|
||||
<el-card class="full-table" shadow="hover" style="margin-top: 5px">
|
||||
<el-table :data="state.regionData" style="width: 100%" v-loading="state.loading" row-key="id" default-expand-all :tree-props="{ children: 'children', hasChildren: 'hasChildren' }" border>
|
||||
<el-table-column prop="name" label="行政名称" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="code" label="行政代码" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="cityCode" label="区号" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="orderNo" label="排序" width="70" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="remark" label="备注" header-align="center" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="140" fixed="right" align="center" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-button icon="ele-Edit" size="small" text type="primary" @click="openEditRegion(scope.row)" v-auth="'sysRegion:update'"> 编辑 </el-button>
|
||||
<el-button icon="ele-Delete" size="small" text type="danger" @click="delRegion(scope.row)" v-auth="'sysRegion:delete'"> 删除 </el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
v-model:currentPage="state.tableParams.page"
|
||||
v-model:page-size="state.tableParams.pageSize"
|
||||
:total="state.tableParams.total"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
small
|
||||
background
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
/>
|
||||
<el-card class="full-table" shadow="hover" style="margin-top: 5px; flex: 1">
|
||||
<vxe-grid ref="xGrid" class="xGrid-style" v-bind="options" :tree-config="{ transform: true, parentField: 'pid' }" @sort-change="sortChange">
|
||||
<template #toolbar_buttons>
|
||||
<el-button type="primary" icon="ele-Plus" @click="handleAdd" v-auth="'sysRegion:add'"> 新增 </el-button>
|
||||
<el-button type="danger" icon="ele-Lightning" @click="handlSync" v-auth="'sysRegion:add'"> 同步统计局 </el-button>
|
||||
<el-button-group style="padding-left: 12px">
|
||||
<el-button type="primary" icon="ele-Expand" @click="handleExpand"> 全部展开 </el-button>
|
||||
<el-button type="primary" icon="ele-Fold" @click="handleFold"> 全部折叠 </el-button>
|
||||
</el-button-group>
|
||||
</template>
|
||||
<template #toolbar_tools> </template>
|
||||
<template #empty>
|
||||
<el-empty :image-size="200" />
|
||||
</template>
|
||||
<template #row_buttons="{ row }">
|
||||
<el-tooltip content="编辑" placement="top">
|
||||
<el-button icon="ele-Edit" text type="primary" v-auth="'sysRegion:update'" @click="handleEdit(row)"> </el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="删除" placement="top">
|
||||
<el-button icon="ele-Delete" text type="danger" v-auth="'sysRegion:delete'" @click="handleDelete(row)"> </el-button>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
<template #pager>
|
||||
<vxe-pager
|
||||
:loading="options.loading"
|
||||
v-model:current-page="state.tableParams.page"
|
||||
v-model:page-size="state.tableParams.pageSize"
|
||||
:total="state.tableParams.total"
|
||||
@page-change="pageChange"
|
||||
/>
|
||||
</template>
|
||||
</vxe-grid>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<EditRegion ref="editRegionRef" :title="state.editRegionTitle" @handleQuery="handleQuery" />
|
||||
<EditRegion ref="editRegionRef" :title="state.title" @handleQuery="handleQuery" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="sysRegion">
|
||||
import { onMounted, reactive, ref } from 'vue';
|
||||
import { nextTick, onMounted, reactive, ref } from 'vue';
|
||||
import { ElMessageBox, ElMessage, ElNotification } from 'element-plus';
|
||||
import { auth } from '/@/utils/authFunction';
|
||||
import { VxeGridInstance, VxePagerEvents, VxePagerDefines } from 'vxe-table';
|
||||
import { useVxeTable } from '/@/hooks/vxeTableOptionsHook';
|
||||
|
||||
import RegionTree from '/@/views/system/region/component/regionTree.vue';
|
||||
import EditRegion from '/@/views/system/region/component/editRegion.vue';
|
||||
|
||||
@ -70,11 +88,10 @@ import { getAPI } from '/@/utils/axios-utils';
|
||||
import { SysRegionApi } from '/@/api-services/api';
|
||||
import { SysRegion } from '/@/api-services/models';
|
||||
|
||||
const xGrid = ref<VxeGridInstance>();
|
||||
const editRegionRef = ref<InstanceType<typeof EditRegion>>();
|
||||
const regionTreeRef = ref<InstanceType<typeof RegionTree>>();
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
regionData: [] as Array<SysRegion>, // 列表数据
|
||||
queryParams: {
|
||||
id: -1,
|
||||
pid: undefined,
|
||||
@ -83,24 +100,61 @@ const state = reactive({
|
||||
},
|
||||
tableParams: {
|
||||
page: 1,
|
||||
pageSize: 20,
|
||||
pageSize: 50,
|
||||
field: 'id', // 默认的排序字段
|
||||
order: 'aes', // 排序方向
|
||||
descStr: 'desc', // 降序排序的关键字符
|
||||
total: 0 as any,
|
||||
},
|
||||
editRegionTitle: '',
|
||||
visible: false,
|
||||
title: '',
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
handleQuery();
|
||||
// 表格参数配置
|
||||
const options = useVxeTable<SysRegion>({
|
||||
id: 'sysRegion',
|
||||
name: '区域信息',
|
||||
columns: [
|
||||
// { type: 'checkbox', width: 40, fixed: 'left' },
|
||||
{ type: 'seq', title: '序号', width: 100, fixed: 'left' },
|
||||
{ field: 'name', title: '行政名称', minWidth: 280, showOverflow: 'tooltip', treeNode: true },
|
||||
{ field: 'code', title: '行政代码', minWidth: 120, showOverflow: 'tooltip' },
|
||||
{ field: 'cityCode', title: '区号', minWidth: 100, showOverflow: 'tooltip' },
|
||||
{ field: 'orderNo', title: '排序', minWidth: 80, showOverflow: 'tooltip' },
|
||||
{ field: 'createTime', title: '修改时间', minWidth: 150, showOverflow: 'tooltip' },
|
||||
{ field: 'remark', title: '备注', minWidth: 300, showOverflow: 'tooltip' },
|
||||
{ title: '操作', fixed: 'right', width: 100, showOverflow: true, slots: { default: 'row_buttons' } },
|
||||
],
|
||||
enableExport: auth('sysRegion:export'),
|
||||
searchCallback: () => handleQuery(),
|
||||
queryAllCallback: () => fetchData({ pageSize: 99999 }),
|
||||
});
|
||||
|
||||
// 页面初始化
|
||||
onMounted(async () => {
|
||||
await handleQuery();
|
||||
// 展开表格所有数据,数据量大时请勿开启
|
||||
nextTick(() => {
|
||||
setTimeout(() => {
|
||||
xGrid.value?.setAllTreeExpand(true);
|
||||
}, 1000);
|
||||
});
|
||||
});
|
||||
|
||||
// 查询操作
|
||||
const handleQuery = async () => {
|
||||
state.loading = true;
|
||||
let params = Object.assign(state.queryParams, state.tableParams);
|
||||
var res = await getAPI(SysRegionApi).apiSysRegionPagePost(params);
|
||||
state.regionData = res.data.result?.items ?? [];
|
||||
const handleQuery = async (reset = false) => {
|
||||
options.loading = true;
|
||||
if (reset) state.tableParams.page = 1;
|
||||
var res = await fetchData(null);
|
||||
xGrid.value?.loadData(res.data.result?.items ?? []);
|
||||
state.tableParams.total = res.data.result?.total;
|
||||
state.loading = false;
|
||||
options.loading = false;
|
||||
};
|
||||
|
||||
// 获取数据
|
||||
const fetchData = async (tableParams: any) => {
|
||||
let params = Object.assign(state.queryParams, state.tableParams, tableParams);
|
||||
return getAPI(SysRegionApi).apiSysRegionPagePost(params);
|
||||
};
|
||||
|
||||
// 重置操作
|
||||
@ -109,23 +163,37 @@ const resetQuery = () => {
|
||||
state.queryParams.pid = undefined;
|
||||
state.queryParams.name = undefined;
|
||||
state.queryParams.code = undefined;
|
||||
handleQuery(true);
|
||||
};
|
||||
|
||||
// 改变页码序号或页面容量
|
||||
const pageChange: VxePagerEvents.PageChange = ({ currentPage, pageSize }: VxePagerDefines.PageChangeEventParams) => {
|
||||
state.tableParams.page = currentPage;
|
||||
state.tableParams.pageSize = pageSize;
|
||||
handleQuery();
|
||||
};
|
||||
|
||||
// 列排序
|
||||
const sortChange = (options: any) => {
|
||||
state.tableParams.field = options.field;
|
||||
state.tableParams.order = options.order;
|
||||
handleQuery();
|
||||
};
|
||||
|
||||
// 打开新增页面
|
||||
const openAddRegion = () => {
|
||||
state.editRegionTitle = '添加行政区域';
|
||||
const handleAdd = () => {
|
||||
state.title = '添加行政区域';
|
||||
editRegionRef.value?.openDialog({ orderNo: 100 });
|
||||
};
|
||||
|
||||
// 打开编辑页面
|
||||
const openEditRegion = (row: any) => {
|
||||
state.editRegionTitle = '编辑行政区域';
|
||||
const handleEdit = (row: any) => {
|
||||
state.title = '编辑行政区域';
|
||||
editRegionRef.value?.openDialog(row);
|
||||
};
|
||||
|
||||
// 删除
|
||||
const delRegion = (row: any) => {
|
||||
const handleDelete = (row: any) => {
|
||||
ElMessageBox.confirm(`确定删除行政区域:【${row.name}】?`, '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
@ -135,14 +203,14 @@ const delRegion = (row: any) => {
|
||||
await getAPI(SysRegionApi).apiSysRegionDeletePost({ id: row.id });
|
||||
handleQuery();
|
||||
// 编辑删除后更新机构数据
|
||||
regionTreeRef.value?.initTreeData();
|
||||
regionTreeRef.value?.fetchTreeData();
|
||||
ElMessage.success('删除成功');
|
||||
})
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
// 树组件点击
|
||||
const nodeClick = async (node: any) => {
|
||||
const handleNodeChange = async (node: any) => {
|
||||
state.queryParams.pid = node.id;
|
||||
state.queryParams.name = undefined;
|
||||
state.queryParams.code = undefined;
|
||||
@ -168,15 +236,13 @@ const handlSync = async () => {
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
// 改变页面容量
|
||||
const handleSizeChange = (val: number) => {
|
||||
state.tableParams.pageSize = val;
|
||||
handleQuery();
|
||||
// 全部展开
|
||||
const handleExpand = () => {
|
||||
xGrid.value?.setAllTreeExpand(true);
|
||||
};
|
||||
|
||||
// 改变页码序号
|
||||
const handleCurrentChange = (val: number) => {
|
||||
state.tableParams.page = val;
|
||||
handleQuery();
|
||||
// 全部折叠
|
||||
const handleFold = () => {
|
||||
xGrid.value?.clearTreeExpand();
|
||||
};
|
||||
</script>
|
||||
|
||||
@ -1,6 +1,12 @@
|
||||
<template>
|
||||
<div class="sys-baseApi-container">
|
||||
<el-drawer v-model="state.isVisible" :title="state.drawerTitle" size="30%">
|
||||
<el-drawer v-model="state.isVisible" size="30%">
|
||||
<template #header>
|
||||
<div style="color: #fff">
|
||||
<el-icon size="16" style="margin-right: 3px; display: inline; vertical-align: middle"> <ele-Link /> </el-icon>
|
||||
<span>设置基础接口资源【免鉴权授权】</span>
|
||||
</div>
|
||||
</template>
|
||||
<el-card class="tree-card" shadow="hover" style="height: calc(100vh - 110px)" body-style="height:100%; overflow:auto">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
@ -69,7 +75,6 @@ const state = reactive({
|
||||
allApiData: [] as any,
|
||||
ownApiList: [] as any,
|
||||
selectRow: [] as any,
|
||||
drawerTitle: '',
|
||||
selectedTabName: 0,
|
||||
});
|
||||
|
||||
@ -98,7 +103,6 @@ const initTreeData = async () => {
|
||||
// 打开页面
|
||||
const openDrawer = async () => {
|
||||
state.selectedTabName = 0;
|
||||
state.drawerTitle = '设置基础接口资源【免鉴权授权】';
|
||||
state.isVisible = true;
|
||||
state.loading = false;
|
||||
|
||||
|
||||
@ -1,6 +1,12 @@
|
||||
<template>
|
||||
<div class="sys-grantApi-container">
|
||||
<el-drawer v-model="state.isVisible" :title="state.drawerTitle" size="30%">
|
||||
<el-drawer v-model="state.isVisible" size="30%">
|
||||
<template #header>
|
||||
<div style="color: #fff">
|
||||
<el-icon size="16" style="margin-right: 3px; display: inline; vertical-align: middle"> <ele-Link /> </el-icon>
|
||||
<span>{{ state.drawerTitle }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<el-card class="tree-card" shadow="hover" style="height: calc(100vh - 110px)" body-style="height:100%; overflow:auto">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
|
||||
@ -153,7 +153,7 @@ const options = useVxeTable<TenantOutput>({
|
||||
{ field: 'name', title: '租户名称', minWidth: 160, showOverflow: 'tooltip' },
|
||||
{ field: 'adminAccount', title: '租管账号', minWidth: 120, showOverflow: 'tooltip' },
|
||||
{ field: 'phone', title: '电话', minWidth: 120, showOverflow: 'tooltip' },
|
||||
{ field: 'host', title: '主机', minWidth: 150, showOverflow: 'tooltip' },
|
||||
{ field: 'host', title: '主机', showOverflow: 'tooltip' },
|
||||
{ field: 'email', title: '邮箱', minWidth: 150, showOverflow: 'tooltip' },
|
||||
{ field: 'tenantType', title: '租户类型', minWidth: 100, showOverflow: 'tooltip', slots: { default: 'row_tenantType' } },
|
||||
{ field: 'status', title: '状态', minWidth: 100, slots: { default: 'row_status' } },
|
||||
|
||||
Loading…
Reference in New Issue
Block a user