diff --git a/Admin.NET/Admin.NET.Core/Admin.NET.Core.csproj b/Admin.NET/Admin.NET.Core/Admin.NET.Core.csproj index 583bdf82..5f5d9587 100644 --- a/Admin.NET/Admin.NET.Core/Admin.NET.Core.csproj +++ b/Admin.NET/Admin.NET.Core/Admin.NET.Core.csproj @@ -17,7 +17,7 @@ - + @@ -33,11 +33,11 @@ - + - + diff --git a/Admin.NET/Admin.NET.Core/Job/EnumToDictJob.cs b/Admin.NET/Admin.NET.Core/Job/EnumToDictJob.cs index c113b1bb..95848948 100644 --- a/Admin.NET/Admin.NET.Core/Job/EnumToDictJob.cs +++ b/Admin.NET/Admin.NET.Core/Job/EnumToDictJob.cs @@ -1,4 +1,4 @@ -// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 // // 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 // @@ -59,6 +59,7 @@ public class EnumToDictJob : IJob dictData.Value = enumData.Value.ToString(); dictData.Code = enumData.Name; dictData.OrderNo = enumData.Value + 10; + dictData.Name = enumData.Describe; uSysDictData.Add(dictData); } }); diff --git a/Admin.NET/Admin.NET.Core/SeedData/SysMenuSeedData.cs b/Admin.NET/Admin.NET.Core/SeedData/SysMenuSeedData.cs index 1ee40f4d..d2eb934d 100644 --- a/Admin.NET/Admin.NET.Core/SeedData/SysMenuSeedData.cs +++ b/Admin.NET/Admin.NET.Core/SeedData/SysMenuSeedData.cs @@ -192,6 +192,8 @@ public class SysMenuSeedData : ISqlSugarEntitySeedData new SysMenu{ Id=1310000000711, Pid=1310000000701, Title="后台教程", Path="/doc/furion", Name="sysFurion", Component="layout/routerView/link", IsIframe=false, IsKeepAlive=false, OutLink="https://furion.baiqian.ltd/", Icon="ele-Promotion", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 }, new SysMenu{ Id=1310000000712, Pid=1310000000701, Title="前端教程", Path="/doc/element", Name="sysElement", Component="layout/routerView/link", IsIframe=false, IsKeepAlive=false, OutLink="https://element-plus.gitee.io/zh-CN/", Icon="ele-Position", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=110 }, new SysMenu{ Id=1310000000713, Pid=1310000000701, Title="SqlSugar", Path="/doc/SqlSugar", Name="sysSqlSugar", Component="layout/routerView/link", IsIframe=false, IsKeepAlive=false, OutLink="https://www.donet5.com/Home/Doc", Icon="ele-Coin", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=120 }, + + new SysMenu{ Id=1310000000801, Pid=0, Title="关于项目", Path="/about", Name="about", Component="/about/index", Icon="ele-InfoFilled", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2023-03-12 00:00:00"), OrderNo=15000 }, }; } } \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Service/Config/Dto/ConfigInput.cs b/Admin.NET/Admin.NET.Core/Service/Config/Dto/ConfigInput.cs index 1fdc16b4..d5c0b3ec 100644 --- a/Admin.NET/Admin.NET.Core/Service/Config/Dto/ConfigInput.cs +++ b/Admin.NET/Admin.NET.Core/Service/Config/Dto/ConfigInput.cs @@ -38,4 +38,20 @@ public class UpdateConfigInput : AddConfigInput public class DeleteConfigInput : BaseIdInput { +} + +/// +/// 批量配置参数输入 +/// +public class BatchConfigInput +{ + /// + /// 编码 + /// + public string Code { get; set; } + + /// + /// 属性值 + /// + public string Value { get; set; } } \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Service/Config/SysConfigService.cs b/Admin.NET/Admin.NET.Core/Service/Config/SysConfigService.cs index 820bb2f8..6c0fafac 100644 --- a/Admin.NET/Admin.NET.Core/Service/Config/SysConfigService.cs +++ b/Admin.NET/Admin.NET.Core/Service/Config/SysConfigService.cs @@ -44,9 +44,11 @@ public class SysConfigService : IDynamicApiController, ITransient /// /// [DisplayName("获取参数配置列表")] - public async Task> GetList() + public async Task> List(PageConfigInput input) { - return await _sysConfigRep.GetListAsync(); + return await _sysConfigRep.AsQueryable() + .WhereIF(!string.IsNullOrWhiteSpace(input.GroupCode?.Trim()), u => u.GroupCode.Equals(input.GroupCode)) + .ToListAsync(); } /// @@ -147,7 +149,7 @@ public class SysConfigService : IDynamicApiController, ITransient var value = _sysCacheService.Get($"{CacheConst.KeyConfig}{code}"); if (string.IsNullOrEmpty(value)) { - var config = await _sysConfigRep.GetFirstAsync(u => u.Code == code); + var config = await _sysConfigRep.CopyNew().GetFirstAsync(u => u.Code == code); value = config != null ? config.Value : default; _sysCacheService.Set($"{CacheConst.KeyConfig}{code}", value); } @@ -210,6 +212,22 @@ public class SysConfigService : IDynamicApiController, ITransient return refreshTokenExpire == 0 ? 40 : refreshTokenExpire; } + /// + /// 批量更新参数配置值 + /// + /// + /// + [ApiDescriptionSettings(Name = "BatchUpdate"), HttpPost] + [DisplayName("批量更新参数配置值")] + public async Task BatchUpdateConfig(List input) + { + foreach (var Config in input) + { + await _sysConfigRep.AsUpdateable().SetColumns(u => u.Value == Config.Value).Where(u => u.Code == Config.Code).ExecuteCommandAsync(); + _sysCacheService.Remove($"{CacheConst.KeyConfig}{Config.Code}"); + } + } + /// /// 获取系统信息 🔖 /// diff --git a/Admin.NET/Admin.NET.Core/Service/Job/DbJobPersistence.cs b/Admin.NET/Admin.NET.Core/Service/Job/DbJobPersistence.cs index 83fdd7f9..3dbcc2ed 100644 --- a/Admin.NET/Admin.NET.Core/Service/Job/DbJobPersistence.cs +++ b/Admin.NET/Admin.NET.Core/Service/Job/DbJobPersistence.cs @@ -1,4 +1,4 @@ -// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 // // 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 // @@ -27,7 +27,7 @@ public class DbJobPersistence : IJobPersistence public async Task> PreloadAsync(CancellationToken stoppingToken) { using var scope = _serviceScopeFactory.CreateScope(); - var db = scope.ServiceProvider.GetRequiredService(); + var db = scope.ServiceProvider.GetRequiredService().CopyNew(); var dynamicJobCompiler = scope.ServiceProvider.GetRequiredService(); // 获取所有定义的作业 @@ -132,7 +132,7 @@ public class DbJobPersistence : IJobPersistence { using (var scope = _serviceScopeFactory.CreateScope()) { - var db = scope.ServiceProvider.GetRequiredService(); + var db = scope.ServiceProvider.GetRequiredService().CopyNew(); var jobDetail = context.JobDetail.Adapt(); switch (context.Behavior) @@ -160,7 +160,7 @@ public class DbJobPersistence : IJobPersistence { using (var scope = _serviceScopeFactory.CreateScope()) { - var db = scope.ServiceProvider.GetRequiredService(); + var db = scope.ServiceProvider.GetRequiredService().CopyNew(); var jobTrigger = context.Trigger.Adapt(); switch (context.Behavior) @@ -188,7 +188,7 @@ public class DbJobPersistence : IJobPersistence { using (var scope = _serviceScopeFactory.CreateScope()) { - var db = scope.ServiceProvider.GetRequiredService(); + var db = scope.ServiceProvider.GetRequiredService().CopyNew(); var jobTriggerRecord = timeline.Adapt(); await db.Insertable(jobTriggerRecord).ExecuteCommandAsync(); diff --git a/Admin.NET/Admin.NET.Core/Service/Message/SysSmsService.cs b/Admin.NET/Admin.NET.Core/Service/Message/SysSmsService.cs index 466c962d..83dfadaf 100644 --- a/Admin.NET/Admin.NET.Core/Service/Message/SysSmsService.cs +++ b/Admin.NET/Admin.NET.Core/Service/Message/SysSmsService.cs @@ -1,4 +1,4 @@ -// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 // // 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 // @@ -73,7 +73,7 @@ public class SysSmsService : IDynamicApiController, ITransient TemplateParam = templateParam.ToString(), // 模板中的变量替换JSON串 OutId = YitIdHelper.NextId().ToString() }; - var sendSmsResponse = client.SendSms(sendSmsRequest); + var sendSmsResponse = await client.SendSmsAsync(sendSmsRequest); if (sendSmsResponse.Body.Code == "OK" && sendSmsResponse.Body.Message == "OK") { // var bizId = sendSmsResponse.Body.BizId; @@ -87,6 +87,43 @@ public class SysSmsService : IDynamicApiController, ITransient await Task.CompletedTask; } + /// + /// 发送短信模板 + /// + /// + /// + /// + [AllowAnonymous] + [DisplayName("发送短信模板")] + public async Task AliyunSendSmsTemplate([Required] string phoneNumber, [Required] dynamic templateParam) + { + if (!phoneNumber.TryValidate(ValidationTypes.PhoneNumber).IsValid) + throw Oops.Oh("请正确填写手机号码"); + + if (string.IsNullOrWhiteSpace(templateParam.ToString())) + throw Oops.Oh("短信内容不能为空"); + + var client = CreateAliyunClient(); + var sendSmsRequest = new SendSmsRequest + { + PhoneNumbers = phoneNumber, // 待发送手机号, 多个以逗号分隔 + SignName = _smsOptions.Aliyun.SignName, // 短信签名 + TemplateCode = _smsOptions.Aliyun.TemplateCode, // 短信模板 + TemplateParam = templateParam.ToString(), // 模板中的变量替换JSON串 + OutId = YitIdHelper.NextId().ToString() + }; + var sendSmsResponse = await client.SendSmsAsync(sendSmsRequest); + if (sendSmsResponse.Body.Code == "OK" && sendSmsResponse.Body.Message == "OK") + { + } + else + { + throw Oops.Oh($"短信发送失败:{sendSmsResponse.Body.Code}-{sendSmsResponse.Body.Message}"); + } + + await Task.CompletedTask; + } + /// /// 腾讯云发送短信 📨 /// diff --git a/Admin.NET/Admin.NET.Web.Entry/wwwroot/Template/Service.cs.vm b/Admin.NET/Admin.NET.Web.Entry/wwwroot/Template/Service.cs.vm index a42bda89..6b81ee0c 100644 --- a/Admin.NET/Admin.NET.Web.Entry/wwwroot/Template/Service.cs.vm +++ b/Admin.NET/Admin.NET.Web.Entry/wwwroot/Template/Service.cs.vm @@ -1,3 +1,9 @@ +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + using Admin.NET.Core.Service; using @(@Model.NameSpace).Entity; using Microsoft.AspNetCore.Http; diff --git a/Admin.NET/Admin.NET.Web.Entry/wwwroot/Template/editDialog.vue.vm b/Admin.NET/Admin.NET.Web.Entry/wwwroot/Template/editDialog.vue.vm index 2fe982e8..e26550fc 100644 --- a/Admin.NET/Admin.NET.Web.Entry/wwwroot/Template/editDialog.vue.vm +++ b/Admin.NET/Admin.NET.Web.Entry/wwwroot/Template/editDialog.vue.vm @@ -135,7 +135,7 @@ @: @: @: - @: + @: @: @: @@ -172,14 +172,23 @@ import type { FormRules } from "element-plus"; @if(@Model.TableField.Any(x=>x.EffectType == "ConstSelector")){ @:import { getConstType } from "/@@/utils/constHelper"; - } +} +@if(@Model.TableField.Any(x=>x.EffectType == "Select")){ + @:import { getDictDataItem as di, getDictDataList as dl } from '/@@/utils/dict-utils'; +} +@if(@Model.TableField.Any(x=>x.EffectType == "EnumSelector")){ + @:import { getDictLabelByVal as dv } from '/@@/utils/dict-utils'; +} +@if(@Model.TableField.Any(x=>x.EffectType == "DatePicker")){ + @:import { formatDate } from '/@@/utils/formatTime'; +} @if(@Model.TableField.Any(x=>x.EffectType == "Upload")){ @:import { Plus } from "@@element-plus/icons-vue"; @:import { UploadRequestOptions } from "element-plus"; @:import {@string.Join(",",Model.TableField.Where(x=>x.EffectType == "Upload").Select(x=>"upload"+x.PropertyName).ToList())} from '/@@/api/@(@Model.PagePath)/@(@Model.LowerClassName)'; } import { add@(@Model.ClassName), update@(@Model.ClassName), detail@(@Model.ClassName) } from "/@@/api/@(@Model.PagePath)/@(@Model.LowerClassName)"; - @foreach (var column in Model.TableField){ +@foreach (var column in Model.TableField){ if(@column.EffectType == "ApiTreeSelect" && !definedObjects.ContainsKey("import__@(@column.FkEntityName)Tree")){ @{definedObjects.Add("import__@(@column.FkEntityName)Tree", 1);} @:import { get@(@column.FkEntityName)Tree } from '/@@/api/@(@Model.PagePath)/@(@Model.LowerClassName)'; @@ -187,17 +196,12 @@ if(@column.EffectType == "fk" && @column.WhetherAddUpdate == "Y"){ @:import { get@(@column.FkEntityName)@(@column.PropertyName)Dropdown } from '/@@/api/@(@Model.PagePath)/@(@Model.LowerClassName)'; } - } - @if(@Model.TableField.Any(x=>x.EffectType == "EnumSelector")){ +} +@if(@Model.TableField.Any(x=>x.EffectType == "EnumSelector")){ @:import { getAPI } from '/@@/utils/axios-utils'; @:import { SysEnumApi } from '/@@/api-services/api'; - } +} - @foreach (var column in Model.TableField){ - if(@column.EffectType == "EnumSelector"){ - @:const getEnum@(@column.PropertyName)Data = ref([]); - } - } //父级传递来的参数 var props = defineProps({ title: { @@ -220,7 +224,12 @@ @:@column.LowerPropertyName: [{required: true, message: '请选择@(@column.ColumnComment)!', trigger: 'change',},], } } - } +} + }); + + // 页面加载时 + onMounted(() => { + }); // 打开弹窗 @@ -312,16 +321,6 @@ } } - - // 页面加载时 - onMounted(async () => { - @foreach (var column in Model.TableField){ - if(@column.EffectType == "EnumSelector"){ - @:getEnum@(@column.PropertyName)Data.value = (await getAPI(SysEnumApi).apiSysEnumEnumDataListGet('@(@column.DictTypeCode)')).data.result ?? []; - } - } - }); - //将属性或者函数暴露给父组件 defineExpose({ openDialog }); diff --git a/Admin.NET/Admin.NET.Web.Entry/wwwroot/Template/index.vue.vm b/Admin.NET/Admin.NET.Web.Entry/wwwroot/Template/index.vue.vm index a9b55298..18139233 100644 --- a/Admin.NET/Admin.NET.Web.Entry/wwwroot/Template/index.vue.vm +++ b/Admin.NET/Admin.NET.Web.Entry/wwwroot/Template/index.vue.vm @@ -47,7 +47,7 @@ }else if(@column.EffectType == "fk"){ @: @: - @: + @: @: @: @@ -63,7 +63,7 @@ }else if(@column.EffectType == "EnumSelector"){ @: @: - @: + @: @: @: @@ -165,7 +165,7 @@ else if(@column.EffectType == "EnumSelector"){ @: @: @: } @@ -215,11 +215,19 @@ import { ref } from "vue"; import { ElMessageBox, ElMessage } from "element-plus"; import { auth } from '/@@/utils/authFunction'; + @if(@Model.TableField.Any(x=>x.EffectType == "ConstSelector")){ @:import { codeToName, getConstType } from "/@@/utils/constHelper"; } - import { getDictDataItem as di, getDictDataList as dl } from '/@@/utils/dict-utils'; - import { formatDate } from '/@@/utils/formatTime'; + @if(@Model.TableField.Any(x=>x.EffectType == "Select")){ + @:import { getDictDataItem as di, getDictDataList as dl } from '/@@/utils/dict-utils'; + } + @if(@Model.TableField.Any(x=>x.EffectType == "EnumSelector")){ + @:import { getDictLabelByVal as dv } from '/@@/utils/dict-utils'; + } + @if(@Model.TableField.Any(x=>x.EffectType == "DatePicker")){ + @:import { formatDate } from '/@@/utils/formatTime'; + } @if(@Model.PrintType == "custom"){ @:// 推荐设置操作 width 为 200 @@ -242,15 +250,6 @@ @:import commonFunction from '/@@/utils/commonFunction'; } - @foreach (var column in Model.QueryWhetherList){ - if(@column.EffectType == "EnumSelector"){ - @:const getEnum@(@column.PropertyName)Data_Index = ref([]); - } - } - - @if(@Model.QueryWhetherList.Any(x=>x.EffectType == "EnumSelector")){ - @:const { getEnumDesc } = commonFunction(); - } @if(haveLikeCdt){ @:const showAdvanceQueryUI = ref(false); }else { @@ -274,7 +273,6 @@ const changeAdvanceQueryUI = () => { showAdvanceQueryUI.value = !showAdvanceQueryUI.value; } - // 查询操作 const handleQuery = async () => { @@ -283,11 +281,6 @@ tableData.value = res.data.result?.items ?? []; tableParams.value.total = res.data.result?.total; loading.value = false; - @foreach (var column in Model.QueryWhetherList){ - if(@column.EffectType == "EnumSelector"){ - @:getEnum@(@column.PropertyName)Data_Index.value = (await getAPI(SysEnumApi).apiSysEnumEnumDataListGet('@(@column.DictTypeCode)')).data.result ?? []; - } - } }; // 列排序 diff --git a/Admin.NET/Admin.NET.Web.Entry/wwwroot/Upload/logo.png b/Admin.NET/Admin.NET.Web.Entry/wwwroot/Upload/logo.png new file mode 100644 index 00000000..5de6838f Binary files /dev/null and b/Admin.NET/Admin.NET.Web.Entry/wwwroot/Upload/logo.png differ diff --git a/Admin.NET/Plugins/Admin.NET.Plugin.ReZero/Admin.NET.Plugin.ReZero.csproj b/Admin.NET/Plugins/Admin.NET.Plugin.ReZero/Admin.NET.Plugin.ReZero.csproj index 2037c4c0..7054a940 100644 --- a/Admin.NET/Plugins/Admin.NET.Plugin.ReZero/Admin.NET.Plugin.ReZero.csproj +++ b/Admin.NET/Plugins/Admin.NET.Plugin.ReZero/Admin.NET.Plugin.ReZero.csproj @@ -24,7 +24,7 @@ - + diff --git a/Web/.prettierrc.js b/Web/.prettierrc.cjs similarity index 100% rename from Web/.prettierrc.js rename to Web/.prettierrc.cjs diff --git a/Web/package.json b/Web/package.json index ecce033e..8e32c211 100644 --- a/Web/package.json +++ b/Web/package.json @@ -2,6 +2,7 @@ "name": "admin.net.pro", "type": "module", "version": "2.4.33", + "lastBuildTime": "2024.6.16", "description": "Admin.NET 站在巨人肩膀上的 .NET 通用权限开发框架", "author": "zuohuaijun", "license": "MIT", @@ -19,7 +20,7 @@ "@vue-office/docx": "^1.6.2", "@vue-office/excel": "^1.7.8", "@vue-office/pdf": "^2.0.2", - "@vueuse/core": "^10.10.0", + "@vueuse/core": "^10.11.0", "@wangeditor/editor": "^5.1.23", "@wangeditor/editor-for-vue": "^5.1.12", "animate.css": "^4.1.1", @@ -52,14 +53,14 @@ "splitpanes": "^3.1.5", "vcrontab-3": "^3.3.22", "vform3-builds": "^3.0.10", - "vue": "^3.4.27", + "vue": "^3.4.29", "vue-clipboard3": "^2.0.0", "vue-demi": "^0.14.8", "vue-grid-layout": "3.0.0-beta1", "vue-i18n": "^9.13.1", "vue-json-pretty": "^2.4.0", "vue-plugin-hiprint": "0.0.57-beta20", - "vue-router": "^4.3.2", + "vue-router": "^4.3.3", "vue-signature-pad": "^3.0.2", "vue3-tree-org": "^4.2.2", "vuedraggable": "4.0.3", @@ -71,21 +72,21 @@ "@types/node": "^20.14.2", "@types/nprogress": "^0.2.3", "@types/sortablejs": "^1.15.8", - "@typescript-eslint/eslint-plugin": "^7.12.0", - "@typescript-eslint/parser": "^7.12.0", + "@typescript-eslint/eslint-plugin": "^7.13.0", + "@typescript-eslint/parser": "^7.13.0", "@vitejs/plugin-vue": "^5.0.5", "@vitejs/plugin-vue-jsx": "^4.0.0", - "@vue/compiler-sfc": "^3.4.27", - "code-inspector-plugin": "^0.14.1", - "eslint": "^9.4.0", + "@vue/compiler-sfc": "^3.4.29", + "code-inspector-plugin": "^0.14.2", + "eslint": "^9.5.0", "eslint-plugin-vue": "^9.26.0", "less": "^4.2.0", - "prettier": "^3.3.1", + "prettier": "^3.3.2", "rollup-plugin-visualizer": "^5.12.0", - "sass": "^1.77.4", + "sass": "^1.77.5", "terser": "^5.31.1", "typescript": "^5.4.5", - "vite": "^5.2.13", + "vite": "^5.3.1", "vite-plugin-cdn-import": "^1.0.1", "vite-plugin-compression2": "^1.1.1", "vite-plugin-vue-setup-extend": "^0.4.0", diff --git a/Web/src/api-services/apis/sys-config-api.ts b/Web/src/api-services/apis/sys-config-api.ts index c1604a0d..5bee5bff 100644 --- a/Web/src/api-services/apis/sys-config-api.ts +++ b/Web/src/api-services/apis/sys-config-api.ts @@ -23,6 +23,7 @@ import { AdminResultListSysConfig } from '../models'; import { AdminResultObject } from '../models'; import { AdminResultSqlSugarPagedListSysConfig } from '../models'; import { AdminResultSysConfig } from '../models'; +import { BatchConfigInput } from '../models'; import { DeleteConfigInput } from '../models'; import { InfoSaveInput } from '../models'; import { PageConfigInput } from '../models'; @@ -129,6 +130,54 @@ export const SysConfigApiAxiosParamCreator = function (configuration?: Configura options: localVarRequestOptions, }; }, + /** + * + * @summary 批量更新参数配置值 + * @param {Array} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + apiSysConfigBatchUpdatePost: async (body?: Array, options: AxiosRequestConfig = {}): Promise => { + const localVarPath = `/api/sysConfig/batchUpdate`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, 'https://example.com'); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication Bearer required + // http bearer authentication required + if (configuration && configuration.accessToken) { + const accessToken = typeof configuration.accessToken === 'function' + ? await configuration.accessToken() + : await configuration.accessToken; + localVarHeaderParameter["Authorization"] = "Bearer " + accessToken; + } + + localVarHeaderParameter['Content-Type'] = 'application/json-patch+json'; + + const query = new URLSearchParams(localVarUrlObj.search); + for (const key in localVarQueryParameter) { + query.set(key, localVarQueryParameter[key]); + } + for (const key in options.params) { + query.set(key, options.params[key]); + } + localVarUrlObj.search = (new URLSearchParams(query)).toString(); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json'; + localVarRequestOptions.data = needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || ""); + + return { + url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash, + options: localVarRequestOptions, + }; + }, /** * * @summary 删除参数配置 🔖 @@ -275,10 +324,11 @@ export const SysConfigApiAxiosParamCreator = function (configuration?: Configura /** * * @summary 获取参数配置列表 🔖 + * @param {PageConfigInput} [body] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - apiSysConfigListGet: async (options: AxiosRequestConfig = {}): Promise => { + apiSysConfigListPost: async (body?: PageConfigInput, options: AxiosRequestConfig = {}): Promise => { const localVarPath = `/api/sysConfig/list`; // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, 'https://example.com'); @@ -286,7 +336,7 @@ export const SysConfigApiAxiosParamCreator = function (configuration?: Configura if (configuration) { baseOptions = configuration.baseOptions; } - const localVarRequestOptions :AxiosRequestConfig = { method: 'GET', ...baseOptions, ...options}; + const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options}; const localVarHeaderParameter = {} as any; const localVarQueryParameter = {} as any; @@ -299,6 +349,8 @@ export const SysConfigApiAxiosParamCreator = function (configuration?: Configura localVarHeaderParameter["Authorization"] = "Bearer " + accessToken; } + localVarHeaderParameter['Content-Type'] = 'application/json-patch+json'; + const query = new URLSearchParams(localVarUrlObj.search); for (const key in localVarQueryParameter) { query.set(key, localVarQueryParameter[key]); @@ -309,6 +361,8 @@ export const SysConfigApiAxiosParamCreator = function (configuration?: Configura localVarUrlObj.search = (new URLSearchParams(query)).toString(); let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json'; + localVarRequestOptions.data = needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || ""); return { url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash, @@ -539,6 +593,20 @@ export const SysConfigApiFp = function(configuration?: Configuration) { return axios.request(axiosRequestArgs); }; }, + /** + * + * @summary 批量更新参数配置值 + * @param {Array} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysConfigBatchUpdatePost(body?: Array, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise>> { + const localVarAxiosArgs = await SysConfigApiAxiosParamCreator(configuration).apiSysConfigBatchUpdatePost(body, options); + return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => { + const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url}; + return axios.request(axiosRequestArgs); + }; + }, /** * * @summary 删除参数配置 🔖 @@ -583,11 +651,12 @@ export const SysConfigApiFp = function(configuration?: Configuration) { /** * * @summary 获取参数配置列表 🔖 + * @param {PageConfigInput} [body] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async apiSysConfigListGet(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise>> { - const localVarAxiosArgs = await SysConfigApiAxiosParamCreator(configuration).apiSysConfigListGet(options); + async apiSysConfigListPost(body?: PageConfigInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise>> { + const localVarAxiosArgs = await SysConfigApiAxiosParamCreator(configuration).apiSysConfigListPost(body, options); return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => { const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url}; return axios.request(axiosRequestArgs); @@ -677,6 +746,16 @@ export const SysConfigApiFactory = function (configuration?: Configuration, base async apiSysConfigBatchDeletePost(body?: Array, options?: AxiosRequestConfig): Promise> { return SysConfigApiFp(configuration).apiSysConfigBatchDeletePost(body, options).then((request) => request(axios, basePath)); }, + /** + * + * @summary 批量更新参数配置值 + * @param {Array} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysConfigBatchUpdatePost(body?: Array, options?: AxiosRequestConfig): Promise> { + return SysConfigApiFp(configuration).apiSysConfigBatchUpdatePost(body, options).then((request) => request(axios, basePath)); + }, /** * * @summary 删除参数配置 🔖 @@ -709,11 +788,12 @@ export const SysConfigApiFactory = function (configuration?: Configuration, base /** * * @summary 获取参数配置列表 🔖 + * @param {PageConfigInput} [body] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async apiSysConfigListGet(options?: AxiosRequestConfig): Promise> { - return SysConfigApiFp(configuration).apiSysConfigListGet(options).then((request) => request(axios, basePath)); + async apiSysConfigListPost(body?: PageConfigInput, options?: AxiosRequestConfig): Promise> { + return SysConfigApiFp(configuration).apiSysConfigListPost(body, options).then((request) => request(axios, basePath)); }, /** * @@ -786,6 +866,17 @@ export class SysConfigApi extends BaseAPI { public async apiSysConfigBatchDeletePost(body?: Array, options?: AxiosRequestConfig) : Promise> { return SysConfigApiFp(this.configuration).apiSysConfigBatchDeletePost(body, options).then((request) => request(this.axios, this.basePath)); } + /** + * + * @summary 批量更新参数配置值 + * @param {Array} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof SysConfigApi + */ + public async apiSysConfigBatchUpdatePost(body?: Array, options?: AxiosRequestConfig) : Promise> { + return SysConfigApiFp(this.configuration).apiSysConfigBatchUpdatePost(body, options).then((request) => request(this.axios, this.basePath)); + } /** * * @summary 删除参数配置 🔖 @@ -821,12 +912,13 @@ export class SysConfigApi extends BaseAPI { /** * * @summary 获取参数配置列表 🔖 + * @param {PageConfigInput} [body] * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof SysConfigApi */ - public async apiSysConfigListGet(options?: AxiosRequestConfig) : Promise> { - return SysConfigApiFp(this.configuration).apiSysConfigListGet(options).then((request) => request(this.axios, this.basePath)); + public async apiSysConfigListPost(body?: PageConfigInput, options?: AxiosRequestConfig) : Promise> { + return SysConfigApiFp(this.configuration).apiSysConfigListPost(body, options).then((request) => request(this.axios, this.basePath)); } /** * diff --git a/Web/src/api-services/apis/sys-sms-api.ts b/Web/src/api-services/apis/sys-sms-api.ts index d09dc347..59366fd1 100644 --- a/Web/src/api-services/apis/sys-sms-api.ts +++ b/Web/src/api-services/apis/sys-sms-api.ts @@ -72,6 +72,64 @@ export const SysSmsApiAxiosParamCreator = function (configuration?: Configuratio options: localVarRequestOptions, }; }, + /** + * + * @summary 发送短信模板 + * @param {any} body + * @param {string} phoneNumber + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + apiSysSmsAliyunSendSmsTemplatePhoneNumberPost: async (body: any, phoneNumber: string, options: AxiosRequestConfig = {}): Promise => { + // verify required parameter 'body' is not null or undefined + if (body === null || body === undefined) { + throw new RequiredError('body','Required parameter body was null or undefined when calling apiSysSmsAliyunSendSmsTemplatePhoneNumberPost.'); + } + // verify required parameter 'phoneNumber' is not null or undefined + if (phoneNumber === null || phoneNumber === undefined) { + throw new RequiredError('phoneNumber','Required parameter phoneNumber was null or undefined when calling apiSysSmsAliyunSendSmsTemplatePhoneNumberPost.'); + } + const localVarPath = `/api/sysSms/aliyunSendSmsTemplate/{phoneNumber}` + .replace(`{${"phoneNumber"}}`, encodeURIComponent(String(phoneNumber))); + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, 'https://example.com'); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication Bearer required + // http bearer authentication required + if (configuration && configuration.accessToken) { + const accessToken = typeof configuration.accessToken === 'function' + ? await configuration.accessToken() + : await configuration.accessToken; + localVarHeaderParameter["Authorization"] = "Bearer " + accessToken; + } + + localVarHeaderParameter['Content-Type'] = 'application/json-patch+json'; + + const query = new URLSearchParams(localVarUrlObj.search); + for (const key in localVarQueryParameter) { + query.set(key, localVarQueryParameter[key]); + } + for (const key in options.params) { + query.set(key, options.params[key]); + } + localVarUrlObj.search = (new URLSearchParams(query)).toString(); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json'; + localVarRequestOptions.data = needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || ""); + + return { + url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash, + options: localVarRequestOptions, + }; + }, /** * * @summary 发送短信 📨 @@ -193,6 +251,21 @@ export const SysSmsApiFp = function(configuration?: Configuration) { return axios.request(axiosRequestArgs); }; }, + /** + * + * @summary 发送短信模板 + * @param {any} body + * @param {string} phoneNumber + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysSmsAliyunSendSmsTemplatePhoneNumberPost(body: any, phoneNumber: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise>> { + const localVarAxiosArgs = await SysSmsApiAxiosParamCreator(configuration).apiSysSmsAliyunSendSmsTemplatePhoneNumberPost(body, phoneNumber, options); + return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => { + const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url}; + return axios.request(axiosRequestArgs); + }; + }, /** * * @summary 发送短信 📨 @@ -240,6 +313,17 @@ export const SysSmsApiFactory = function (configuration?: Configuration, basePat async apiSysSmsAliyunSendSmsPhoneNumberPost(phoneNumber: string, options?: AxiosRequestConfig): Promise> { return SysSmsApiFp(configuration).apiSysSmsAliyunSendSmsPhoneNumberPost(phoneNumber, options).then((request) => request(axios, basePath)); }, + /** + * + * @summary 发送短信模板 + * @param {any} body + * @param {string} phoneNumber + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysSmsAliyunSendSmsTemplatePhoneNumberPost(body: any, phoneNumber: string, options?: AxiosRequestConfig): Promise> { + return SysSmsApiFp(configuration).apiSysSmsAliyunSendSmsTemplatePhoneNumberPost(body, phoneNumber, options).then((request) => request(axios, basePath)); + }, /** * * @summary 发送短信 📨 @@ -281,6 +365,18 @@ export class SysSmsApi extends BaseAPI { public async apiSysSmsAliyunSendSmsPhoneNumberPost(phoneNumber: string, options?: AxiosRequestConfig) : Promise> { return SysSmsApiFp(this.configuration).apiSysSmsAliyunSendSmsPhoneNumberPost(phoneNumber, options).then((request) => request(this.axios, this.basePath)); } + /** + * + * @summary 发送短信模板 + * @param {any} body + * @param {string} phoneNumber + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof SysSmsApi + */ + public async apiSysSmsAliyunSendSmsTemplatePhoneNumberPost(body: any, phoneNumber: string, options?: AxiosRequestConfig) : Promise> { + return SysSmsApiFp(this.configuration).apiSysSmsAliyunSendSmsTemplatePhoneNumberPost(body, phoneNumber, options).then((request) => request(this.axios, this.basePath)); + } /** * * @summary 发送短信 📨 diff --git a/Web/src/api-services/models/batch-config-input.ts b/Web/src/api-services/models/batch-config-input.ts new file mode 100644 index 00000000..452146bf --- /dev/null +++ b/Web/src/api-services/models/batch-config-input.ts @@ -0,0 +1,38 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Admin.NET 通用权限开发平台 + * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。
👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + * + * OpenAPI spec version: 1.0.0 + * + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + + /** + * 批量配置参数输入 + * + * @export + * @interface BatchConfigInput + */ +export interface BatchConfigInput { + + /** + * 编码 + * + * @type {string} + * @memberof BatchConfigInput + */ + code?: string | null; + + /** + * 属性值 + * + * @type {string} + * @memberof BatchConfigInput + */ + value?: string | null; +} diff --git a/Web/src/api-services/models/index.ts b/Web/src/api-services/models/index.ts index d1648432..94172478 100644 --- a/Web/src/api-services/models/index.ts +++ b/Web/src/api-services/models/index.ts @@ -102,6 +102,7 @@ export * from './api-info'; export * from './api-output'; export * from './assembly'; export * from './base-proc-input'; +export * from './batch-config-input'; export * from './calendar'; export * from './calendar-algorithm-type'; export * from './calendar-week-rule'; diff --git a/Web/src/views/about/index.vue b/Web/src/views/about/index.vue new file mode 100644 index 00000000..f3864372 --- /dev/null +++ b/Web/src/views/about/index.vue @@ -0,0 +1,120 @@ + + + + + diff --git a/Web/src/views/system/database/component/addTable.vue b/Web/src/views/system/database/component/addTable.vue index 3372d95f..19a98263 100644 --- a/Web/src/views/system/database/component/addTable.vue +++ b/Web/src/views/system/database/component/addTable.vue @@ -300,6 +300,13 @@ function handleColDown(record: EditRecordRow, index: number) { } function ChangeExForArray(index1: number, index2: number, array: Array) { + let maxIndex = state.tableData.length - 1; //最大索引 + if (index2 > maxIndex) { + index2 = 0; + } + if (index2 < 0) { + index2 = maxIndex; + } let temp = array[index1]; array[index1] = array[index2]; array[index2] = temp; diff --git a/Web/src/views/system/database/index.vue b/Web/src/views/system/database/index.vue index e8510c00..e469454a 100644 --- a/Web/src/views/system/database/index.vue +++ b/Web/src/views/system/database/index.vue @@ -15,7 +15,7 @@ 增加表 - 编辑表 + 编辑表 删除表 可视化 diff --git a/Web/src/views/system/log/exlog/index.vue b/Web/src/views/system/log/exlog/index.vue index 2fbe777d..cf5d3bc1 100644 --- a/Web/src/views/system/log/exlog/index.vue +++ b/Web/src/views/system/log/exlog/index.vue @@ -16,7 +16,7 @@ 清空 - 导出 + 导出 diff --git a/Web/src/views/system/org/index.vue b/Web/src/views/system/org/index.vue index 51630b22..879dfaa3 100644 --- a/Web/src/views/system/org/index.vue +++ b/Web/src/views/system/org/index.vue @@ -107,10 +107,14 @@ const handleQuery = async (updateTree: boolean = false) => { // 是否更新左侧机构列表树 if (updateTree == true) { orgTreeRef.value?.initTreeData(); + // 更新编辑页面机构列表树 + var res = await getAPI(SysOrgApi).apiSysOrgListGet(0); + state.orgTreeData = res.data.result ?? []; } // 若无选择节点并且查询条件为空时,更新编辑页面机构列表树 - if (state.queryParams.id == 0 && state.queryParams.name == undefined && state.queryParams.code == undefined && state.queryParams.type == undefined) state.orgTreeData = state.orgData; + if (state.queryParams.id == 0 && state.queryParams.name == undefined && state.queryParams.code == undefined && state.queryParams.type == undefined && updateTree == false) + state.orgTreeData = state.orgData; }; // 重置操作 diff --git a/Web/vite.config.ts b/Web/vite.config.ts index 055aede4..3266a0d4 100644 --- a/Web/vite.config.ts +++ b/Web/vite.config.ts @@ -31,6 +31,7 @@ const viteConfig = defineConfig((mode: ConfigEnv) => { vue(), vueJsx(), webUpdateNotice({ + versionType: 'build_timestamp', notificationConfig: { placement: 'topLeft', },