😎同步升级

This commit is contained in:
zuohuaijun 2024-06-16 02:40:42 +08:00
parent 43a7248bb8
commit 062bacd0ec
24 changed files with 511 additions and 79 deletions

View File

@ -17,7 +17,7 @@
<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.1" />
<PackageReference Include="Elastic.Clients.Elasticsearch" Version="8.14.2" />
<PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.4" />
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.4" />
<PackageReference Include="Furion.Pure" Version="4.9.4" />
@ -33,11 +33,11 @@
<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.4.0" />
<PackageReference Include="SKIT.FlurlHttpClient.Wechat.TenpayV3" Version="3.5.0" />
<PackageReference Include="SqlSugarCore" Version="5.1.4.158" />
<PackageReference Include="SSH.NET" Version="2024.0.0" />
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.4.0" />
<PackageReference Include="TencentCloudSDK.Sms" Version="3.0.1023" />
<PackageReference Include="TencentCloudSDK.Sms" Version="3.0.1026" />
<PackageReference Include="UAParser" Version="3.1.47" />
<PackageReference Include="Yitter.IdGenerator" Version="1.0.14" />
</ItemGroup>

View File

@ -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);
}
});

View File

@ -192,6 +192,8 @@ public class SysMenuSeedData : ISqlSugarEntitySeedData<SysMenu>
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 },
};
}
}

View File

@ -39,3 +39,19 @@ public class UpdateConfigInput : AddConfigInput
public class DeleteConfigInput : BaseIdInput
{
}
/// <summary>
/// 批量配置参数输入
/// </summary>
public class BatchConfigInput
{
/// <summary>
/// 编码
/// </summary>
public string Code { get; set; }
/// <summary>
/// 属性值
/// </summary>
public string Value { get; set; }
}

View File

@ -44,9 +44,11 @@ public class SysConfigService : IDynamicApiController, ITransient
/// </summary>
/// <returns></returns>
[DisplayName("获取参数配置列表")]
public async Task<List<SysConfig>> GetList()
public async Task<List<SysConfig>> List(PageConfigInput input)
{
return await _sysConfigRep.GetListAsync();
return await _sysConfigRep.AsQueryable()
.WhereIF(!string.IsNullOrWhiteSpace(input.GroupCode?.Trim()), u => u.GroupCode.Equals(input.GroupCode))
.ToListAsync();
}
/// <summary>
@ -147,7 +149,7 @@ public class SysConfigService : IDynamicApiController, ITransient
var value = _sysCacheService.Get<string>($"{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;
}
/// <summary>
/// 批量更新参数配置值
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[ApiDescriptionSettings(Name = "BatchUpdate"), HttpPost]
[DisplayName("批量更新参数配置值")]
public async Task BatchUpdateConfig(List<BatchConfigInput> 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}");
}
}
/// <summary>
/// 获取系统信息 🔖
/// </summary>

View File

@ -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<IEnumerable<SchedulerBuilder>> PreloadAsync(CancellationToken stoppingToken)
{
using var scope = _serviceScopeFactory.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<ISqlSugarClient>();
var db = scope.ServiceProvider.GetRequiredService<ISqlSugarClient>().CopyNew();
var dynamicJobCompiler = scope.ServiceProvider.GetRequiredService<DynamicJobCompiler>();
// 获取所有定义的作业
@ -132,7 +132,7 @@ public class DbJobPersistence : IJobPersistence
{
using (var scope = _serviceScopeFactory.CreateScope())
{
var db = scope.ServiceProvider.GetRequiredService<ISqlSugarClient>();
var db = scope.ServiceProvider.GetRequiredService<ISqlSugarClient>().CopyNew();
var jobDetail = context.JobDetail.Adapt<SysJobDetail>();
switch (context.Behavior)
@ -160,7 +160,7 @@ public class DbJobPersistence : IJobPersistence
{
using (var scope = _serviceScopeFactory.CreateScope())
{
var db = scope.ServiceProvider.GetRequiredService<ISqlSugarClient>();
var db = scope.ServiceProvider.GetRequiredService<ISqlSugarClient>().CopyNew();
var jobTrigger = context.Trigger.Adapt<SysJobTrigger>();
switch (context.Behavior)
@ -188,7 +188,7 @@ public class DbJobPersistence : IJobPersistence
{
using (var scope = _serviceScopeFactory.CreateScope())
{
var db = scope.ServiceProvider.GetRequiredService<ISqlSugarClient>();
var db = scope.ServiceProvider.GetRequiredService<ISqlSugarClient>().CopyNew();
var jobTriggerRecord = timeline.Adapt<SysJobTriggerRecord>();
await db.Insertable(jobTriggerRecord).ExecuteCommandAsync();

View File

@ -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;
}
/// <summary>
/// 发送短信模板
/// </summary>
/// <param name="phoneNumber"></param>
/// <param name="templateParam"></param>
/// <returns></returns>
[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;
}
/// <summary>
/// 腾讯云发送短信 📨
/// </summary>

View File

@ -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;

View File

@ -135,7 +135,7 @@
@:<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
@:<el-form-item label="@column.ColumnComment" prop="@(@column.LowerPropertyName)">
@:<el-select clearable v-model="ruleForm.@(@column.LowerPropertyName)" placeholder="请选择@(@column.ColumnComment)">
@:<el-option v-for="(item,index) in getEnum@(@column.PropertyName)Data" :key="index" :value="item.value" :label="`[${item.value}] ${item.describe}`"></el-option>
@:<el-option v-for="(item,index) in dl('@(@column.PropertyName)Enum')" :key="index" :value="@(@column.NetType == "string?" ? "item.value" : "Number(item.value)")" :label="`${item.name} (${item.code}) [${item.value}]`"></el-option>
@:
</el-select>
@:
@ -173,6 +173,15 @@
@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";
@ -193,11 +202,6 @@
@:import { SysEnumApi } from '/@@/api-services/api';
}
@foreach (var column in Model.TableField){
if(@column.EffectType == "EnumSelector"){
@:const getEnum@(@column.PropertyName)Data = ref<any>([]);
}
}
//父级传递来的参数
var props = defineProps({
title: {
@ -223,6 +227,11 @@
}
});
// 页面加载时
onMounted(() => {
});
// 打开弹窗
const openDialog = async (row: any) => {
// ruleForm.value = JSON.parse(JSON.stringify(row));
@ -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 });
</script>

View File

@ -63,7 +63,7 @@
}else if(@column.EffectType == "EnumSelector"){
@:<el-form-item label="@column.ColumnComment">
@:<el-select clearable="" v-model="queryParams.@(@column.LowerPropertyName)" placeholder="请选择@(@column.ColumnComment)">
@:<el-option v-for="(item,index) in getEnum@(@column.PropertyName)Data_Index" :key="index" :value="item.value" :label="`[${item.value}] ${item.describe}`" />
@:<el-option v-for="(item,index) in dl('@(@column.PropertyName)Enum')" :key="index" :value="item.value" :label="`${item.name} (${item.code}) [${item.value}] `" />
@:
</el-select>
@:
@ -165,7 +165,7 @@
else if(@column.EffectType == "EnumSelector"){
@:<el-table-column prop="@column.LowerPropertyName" label="@column.ColumnComment" @(column.WhetherSortable == "Y" ? "sortable='custom'" : "") show-overflow-tooltip="" >
@:<template #default="scope">
@:<el-tag>{{ getEnumDesc(scope.row.@column.LowerPropertyName, getEnum@(@column.PropertyName)Data_Index)}}</el-tag>
@:<el-tag :type="dv('@(@column.PropertyName)Enum', scope.row.@(@column.LowerPropertyName))?.tagType"> {{dv('@(@column.PropertyName)Enum', scope.row.@column.LowerPropertyName)?.name}}</el-tag>
@:</template>
@:</el-table-column>
}
@ -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<any>([]);
}
}
@if(@Model.QueryWhetherList.Any(x=>x.EffectType == "EnumSelector")){
@:const { getEnumDesc } = commonFunction();
}
@if(haveLikeCdt){
@:const showAdvanceQueryUI = ref(false);
}else {
@ -275,7 +274,6 @@
showAdvanceQueryUI.value = !showAdvanceQueryUI.value;
}
// 查询操作
const handleQuery = async () => {
loading.value = true;
@ -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 ?? [];
}
}
};
// 列排序

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -24,7 +24,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Rezero.Api" Version="1.6.10" />
<PackageReference Include="Rezero.Api" Version="1.6.18" />
</ItemGroup>
<ItemGroup>

View File

@ -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",

View File

@ -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<BatchConfigInput>} [body]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
apiSysConfigBatchUpdatePost: async (body?: Array<BatchConfigInput>, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
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<RequestArgs> => {
apiSysConfigListPost: async (body?: PageConfigInput, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
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<BatchConfigInput>} [body]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async apiSysConfigBatchUpdatePost(body?: Array<BatchConfigInput>, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<void>>> {
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<AxiosResponse<AdminResultListSysConfig>>> {
const localVarAxiosArgs = await SysConfigApiAxiosParamCreator(configuration).apiSysConfigListGet(options);
async apiSysConfigListPost(body?: PageConfigInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultListSysConfig>>> {
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<number>, options?: AxiosRequestConfig): Promise<AxiosResponse<void>> {
return SysConfigApiFp(configuration).apiSysConfigBatchDeletePost(body, options).then((request) => request(axios, basePath));
},
/**
*
* @summary
* @param {Array<BatchConfigInput>} [body]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async apiSysConfigBatchUpdatePost(body?: Array<BatchConfigInput>, options?: AxiosRequestConfig): Promise<AxiosResponse<void>> {
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<AxiosResponse<AdminResultListSysConfig>> {
return SysConfigApiFp(configuration).apiSysConfigListGet(options).then((request) => request(axios, basePath));
async apiSysConfigListPost(body?: PageConfigInput, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultListSysConfig>> {
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<number>, options?: AxiosRequestConfig) : Promise<AxiosResponse<void>> {
return SysConfigApiFp(this.configuration).apiSysConfigBatchDeletePost(body, options).then((request) => request(this.axios, this.basePath));
}
/**
*
* @summary
* @param {Array<BatchConfigInput>} [body]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof SysConfigApi
*/
public async apiSysConfigBatchUpdatePost(body?: Array<BatchConfigInput>, options?: AxiosRequestConfig) : Promise<AxiosResponse<void>> {
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<AxiosResponse<AdminResultListSysConfig>> {
return SysConfigApiFp(this.configuration).apiSysConfigListGet(options).then((request) => request(this.axios, this.basePath));
public async apiSysConfigListPost(body?: PageConfigInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultListSysConfig>> {
return SysConfigApiFp(this.configuration).apiSysConfigListPost(body, options).then((request) => request(this.axios, this.basePath));
}
/**
*

View File

@ -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<RequestArgs> => {
// 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<AxiosResponse<void>>> {
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<AxiosResponse<void>> {
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<AxiosResponse<void>> {
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<AxiosResponse<void>> {
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<AxiosResponse<void>> {
return SysSmsApiFp(this.configuration).apiSysSmsAliyunSendSmsTemplatePhoneNumberPost(body, phoneNumber, options).then((request) => request(this.axios, this.basePath));
}
/**
*
* @summary 📨

View File

@ -0,0 +1,38 @@
/* tslint:disable */
/* eslint-disable */
/**
* Admin.NET
* .NET <br/><u><b><font color='FF0000'> 👮</font></b></u>
*
* 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;
}

View File

@ -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';

View File

@ -0,0 +1,120 @@
<template>
<div class="el-card box">
<div class="card mb10">
<h4 class="title">
<el-icon size="16" style="margin-right: 3px; display: inline; vertical-align: middle"> <ele-Postcard /> </el-icon>(About)
</h4>
<span class="text">
基于 .NET6 (Furion/SqlSugar) 实现的通用权限开发框架前端采用
Vue3+Element-plus+Vite5整合众多优秀技术和框架模块插件式开发集成多租户缓存数据校验鉴权事件总线动态API通讯远程请求任务调度打印等众多黑科技代码结构简单清晰注释详尽易于上手与二次开发即便是复杂业务逻辑也能迅速实现真正实现开箱即用
</span>
</div>
<div class="card mb10">
<h4 class="title">
<el-icon size="16" style="margin-right: 3px; display: inline; vertical-align: middle"> <ele-Warning /> </el-icon>(Information)
</h4>
<el-descriptions :column="2" border>
<el-descriptions-item label="名称及作者">
<el-tag>{{ name }}</el-tag> <el-tag type="info">{{ author }}</el-tag>
</el-descriptions-item>
<el-descriptions-item label="框架描述">
<el-tag>{{ description }}</el-tag>
</el-descriptions-item>
<el-descriptions-item label="版本号">
<el-tag>{{ version }}</el-tag> <el-tag type="success">{{ license }}</el-tag>
</el-descriptions-item>
<el-descriptions-item label="发布时间">
<el-tag>{{ lastBuildTime }}</el-tag>
</el-descriptions-item>
<el-descriptions-item label="Gitee">
<el-link type="primary" href="https://gitee.com/zuohuaijun/Admin.NET" target="_blank"> Gitee </el-link>
</el-descriptions-item>
<el-descriptions-item label="Github">
<el-link type="primary" href="https://github.com/zuohuaijun/Admin.NET.git" target="_blank"> Github </el-link>
</el-descriptions-item>
<el-descriptions-item label="文档地址">
<el-link type="primary" href="http://101.43.53.74:5050/" target="_blank"> 文档地址 </el-link>
</el-descriptions-item>
<el-descriptions-item label="预览地址">
<el-link type="primary" href="http://101.43.53.74:5005/dist/index.html" target="_blank"> 预览地址 </el-link>
</el-descriptions-item>
</el-descriptions>
</div>
<div class="card mb10">
<h4 class="title">
<el-icon size="16" style="margin-right: 3px; display: inline; vertical-align: middle"> <ele-SetUp /> </el-icon>(Dependencies)
</h4>
<el-descriptions :column="3" border>
<el-descriptions-item v-for="(value, key) in dependencies" :key="key" width="400px" :label="key">
<el-tag type="success" effect="plain">
{{ value }}
</el-tag>
</el-descriptions-item>
</el-descriptions>
</div>
<div class="card">
<h4 class="title">
<el-icon size="16" style="margin-right: 3px; display: inline; vertical-align: middle"> <ele-SetUp /> </el-icon>(devDependencies)
</h4>
<el-descriptions :column="3" border>
<el-descriptions-item v-for="(value, key) in devDependencies" :key="key" width="400px" :label="key">
<el-tag type="danger" effect="plain">
{{ value }}
</el-tag>
</el-descriptions-item>
</el-descriptions>
</div>
<div class="card">
<h4 class="title">
<el-icon size="16" style="margin-right: 3px; display: inline; vertical-align: middle"> <ele-SetUp /> </el-icon>(Keywords)
</h4>
<el-descriptions :column="4" border>
<el-descriptions-item v-for="(value, key) in keywords" :key="value" width="400px" :label="key + 1">
<el-text type="primary">
{{ value }}
</el-text>
</el-descriptions-item>
</el-descriptions>
</div>
</div>
</template>
<script setup lang="ts" name="about">
import PackageJson from '/package.json';
const { dependencies, devDependencies, keywords, version, lastBuildTime, author, description, license, name } = PackageJson;
</script>
<style lang="scss" scoped>
.box {
overflow-y: auto;
}
el-descriptions-item {
width: 50%;
}
.card {
padding: 10px;
.title {
margin: 5px 5px 10px;
font-size: 17px;
font-weight: bold;
color: var(--el-text-color-primary);
}
.text {
text-indent: 50px;
font-size: 15px;
line-height: 30px;
padding: 10px 20px;
color: var(--el-text-color-regular);
.el-link {
font-size: 15px;
}
}
}
</style>

View File

@ -300,6 +300,13 @@ function handleColDown(record: EditRecordRow, index: number) {
}
function ChangeExForArray(index1: number, index2: number, array: Array<EditRecordRow>) {
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;

View File

@ -15,7 +15,7 @@
<el-form-item>
<el-button-group>
<el-button icon="ele-Plus" type="primary" @click="openAddTable"> 增加表 </el-button>
<el-button icon="ele-Edit" @click="openEditTable" disabled> 编辑表 </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>

View File

@ -16,7 +16,7 @@
</el-form-item>
<el-form-item>
<el-button icon="ele-DeleteFilled" type="danger" @click="clearLog" v-auth="'sysExlog:clear'"> 清空 </el-button>
<el-button icon="ele-FolderOpened" @click="exportLog" v-auth="'sysOplog:export'"> 导出 </el-button>
<el-button icon="ele-FolderOpened" @click="exportLog" v-auth="'sysExlog:export'"> 导出 </el-button>
</el-form-item>
</el-form>
</el-card>

View File

@ -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;
};
//

View File

@ -31,6 +31,7 @@ const viteConfig = defineConfig((mode: ConfigEnv) => {
vue(),
vueJsx(),
webUpdateNotice({
versionType: 'build_timestamp',
notificationConfig: {
placement: 'topLeft',
},