diff --git a/Admin.NET/Admin.NET.Core/Admin.NET.Core.csproj b/Admin.NET/Admin.NET.Core/Admin.NET.Core.csproj
index 40a42f83..9bb9cd9e 100644
--- a/Admin.NET/Admin.NET.Core/Admin.NET.Core.csproj
+++ b/Admin.NET/Admin.NET.Core/Admin.NET.Core.csproj
@@ -17,17 +17,17 @@
-
-
-
-
+
+
+
+
-
+
@@ -37,7 +37,7 @@
-
+
@@ -56,9 +56,9 @@
-
-
-
+
+
+
diff --git a/Admin.NET/Admin.NET.Core/Entity/SysWechatRefund.cs b/Admin.NET/Admin.NET.Core/Entity/SysWechatRefund.cs
index 94b33c53..d4ef92a3 100644
--- a/Admin.NET/Admin.NET.Core/Entity/SysWechatRefund.cs
+++ b/Admin.NET/Admin.NET.Core/Entity/SysWechatRefund.cs
@@ -63,7 +63,7 @@ public class SysWechatRefund : EntityBase
/// 退款资金来源, 可不传,默认使用未结算资金退款(仅对老资金流商户适用)
///
[SugarColumn(ColumnDescription = "退款资金来源", Length = 32)]
- public string FundsAccount { get; set; }
+ public string? FundsAccount { get; set; }
///
/// 关联的商户订单号
diff --git a/Admin.NET/Admin.NET.Core/Service/Cache/SysCacheService.cs b/Admin.NET/Admin.NET.Core/Service/Cache/SysCacheService.cs
index 89d79784..6ddead17 100644
--- a/Admin.NET/Admin.NET.Core/Service/Cache/SysCacheService.cs
+++ b/Admin.NET/Admin.NET.Core/Service/Cache/SysCacheService.cs
@@ -62,6 +62,17 @@ public class SysCacheService : IDynamicApiController, ISingleton
return _cacheProvider.Cache.Set($"{_cacheOptions.Prefix}{key}", value, expire);
}
+ ///
+ /// 获取缓存的剩余生存时间
+ ///
+ ///
+ ///
+ [NonAction]
+ public TimeSpan GetExpire(string key)
+ {
+ return _cacheProvider.Cache.GetExpire(key);
+ }
+
///
/// 获取缓存
///
diff --git a/Admin.NET/Admin.NET.Core/Service/CodeGen/SysCodeGenService.cs b/Admin.NET/Admin.NET.Core/Service/CodeGen/SysCodeGenService.cs
index 3cc5e5ae..822df72c 100644
--- a/Admin.NET/Admin.NET.Core/Service/CodeGen/SysCodeGenService.cs
+++ b/Admin.NET/Admin.NET.Core/Service/CodeGen/SysCodeGenService.cs
@@ -42,6 +42,7 @@ public class SysCodeGenService : IDynamicApiController, ITransient
return await _db.Queryable()
.WhereIF(!string.IsNullOrWhiteSpace(input.TableName), u => u.TableName.Contains(input.TableName.Trim()))
.WhereIF(!string.IsNullOrWhiteSpace(input.BusName), u => u.BusName.Contains(input.BusName.Trim()))
+ .OrderBy(u => u.Id, OrderByType.Desc)
.ToPagedListAsync(input.Page, input.PageSize);
}
diff --git a/Admin.NET/Admin.NET.Core/Service/Config/SysConfigService.cs b/Admin.NET/Admin.NET.Core/Service/Config/SysConfigService.cs
index c6640026..3a0b1b12 100644
--- a/Admin.NET/Admin.NET.Core/Service/Config/SysConfigService.cs
+++ b/Admin.NET/Admin.NET.Core/Service/Config/SysConfigService.cs
@@ -14,12 +14,15 @@ public class SysConfigService : IDynamicApiController, ITransient
{
private readonly SysCacheService _sysCacheService;
private readonly SqlSugarRepository _sysConfigRep;
+ private readonly UserManager _userManager;
public SysConfigService(SysCacheService sysCacheService,
- SqlSugarRepository sysConfigRep)
+ SqlSugarRepository sysConfigRep,
+ UserManager userManager)
{
_sysCacheService = sysCacheService;
_sysConfigRep = sysConfigRep;
+ _userManager = userManager;
}
///
@@ -31,7 +34,7 @@ public class SysConfigService : IDynamicApiController, ITransient
public async Task> Page(PageConfigInput input)
{
return await _sysConfigRep.AsQueryable()
- .Where(u => u.GroupCode != "WebConfig") // 不显示 WebConfig 分组
+ .WhereIF(!_userManager.SuperAdmin, u => u.GroupCode != "WebConfig") // 若非超管,不显示 WebConfig 分组
.WhereIF(!string.IsNullOrWhiteSpace(input.Name?.Trim()), u => u.Name.Contains(input.Name))
.WhereIF(!string.IsNullOrWhiteSpace(input.Code?.Trim()), u => u.Code.Contains(input.Code))
.WhereIF(!string.IsNullOrWhiteSpace(input.GroupCode?.Trim()), u => u.GroupCode.Equals(input.GroupCode))
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 ce4bbe98..de62f3c7 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
@@ -20,7 +20,7 @@
-
+
@if(Model.QueryWhetherList.Count > 0){
@@ -156,7 +156,7 @@
@:
} else if(@column.EffectType == "DatePicker") {
@:
- @:{{ formatDate(new Date(row.@(@column.LowerPropertyName)), 'YYYY-mm-dd') }}
+ @:{{ formatDate(new Date(row.@(@column.LowerPropertyName)), 'YYYY-mm-dd HH:MM:SS') }}
@:
}
}
@@ -227,19 +227,19 @@ import ModifyRecord from '/@@/components/table/modifyRecord.vue';
@if (@Model.IsApiService) {
// 接口函数
-import { getAPI } from '/@@/utils/axios-utils';
+@:import { getAPI } from '/@@/utils/axios-utils';
// 接口
-import { @(@Model.ClassName)Api } from '/@@/api-services/api';
+@:import { @(@Model.ClassName)Api } from '/@@/api-services/api';
// 模型
-import { @(@Model.ClassName), @(@Model.ClassName)Input, @(@Model.ClassName)Output } from '/@@/api-services/models';
+@:import { @(@Model.ClassName), @(@Model.ClassName)Input, @(@Model.ClassName)Output } from '/@@/api-services/models';
} else {
-@:import { page@(@Model.ClassName), delete@(@Model.ClassName) } from '/@@/api/@(@Model.PagePath)/@(@Model.LowerEntityName)';
+@:import { page@(@Model.ClassName), delete@(@Model.ClassName) } from '/@@/api/@(@Model.PagePath)/@(@Model.LowerClassName)';
foreach (var column in Model.QueryWhetherList){
if(@column.EffectType == "fk"){
- @:import { get@(@column.FkEntityName)@(@column.PropertyName)Dropdown } from '/@@/api/@(@Model.PagePath)/@(@Model.LowerEntityName)';
+ @:import { get@(@column.FkEntityName)@(@column.PropertyName)Dropdown } from '/@@/api/@(@Model.PagePath)/@(@Model.LowerClassName)';
}
}
}
diff --git a/Web/package.json b/Web/package.json
index efcffd08..15fca79c 100644
--- a/Web/package.json
+++ b/Web/package.json
@@ -2,7 +2,7 @@
"name": "admin.net.pro",
"type": "module",
"version": "2.4.33",
- "lastBuildTime": "2024.07.09",
+ "lastBuildTime": "2024.07.10",
"description": "Admin.NET 站在巨人肩膀上的 .NET 通用权限开发框架",
"author": "zuohuaijun",
"license": "MIT",
@@ -16,7 +16,7 @@
"@element-plus/icons-vue": "^2.3.1",
"@logicflow/core": "^1.2.27",
"@logicflow/extension": "^1.2.27",
- "@microsoft/signalr": "^8.0.0",
+ "@microsoft/signalr": "^8.0.7",
"@vue-office/docx": "^1.6.2",
"@vue-office/excel": "^1.7.8",
"@vue-office/pdf": "^2.0.2",
@@ -49,10 +49,10 @@
"print-js": "^1.6.0",
"push.js": "^1.0.12",
"qrcodejs2-fixes": "^0.0.2",
- "qs": "^6.12.2",
+ "qs": "^6.12.3",
"relation-graph": "^2.2.2",
"screenfull": "^6.0.2",
- "sm-crypto-v2": "^1.9.0",
+ "sm-crypto-v2": "^1.9.1",
"sortablejs": "^1.15.2",
"splitpanes": "^3.1.5",
"vcrontab-3": "^3.3.22",
@@ -68,8 +68,8 @@
"vue-signature-pad": "^3.0.2",
"vue3-tree-org": "^4.2.2",
"vuedraggable": "4.0.3",
- "vxe-pc-ui": "^4.0.51",
- "vxe-table": "^4.7.45",
+ "vxe-pc-ui": "^4.0.58",
+ "vxe-table": "^4.7.47",
"vxe-table-plugin-element": "^4.0.4",
"vxe-table-plugin-export-xlsx": "^4.0.5",
"xe-utils": "^3.5.28",
@@ -93,8 +93,8 @@
"less": "^4.2.0",
"prettier": "^3.3.2",
"rollup-plugin-visualizer": "^5.12.0",
- "sass": "^1.77.6",
- "terser": "^5.31.1",
+ "sass": "^1.77.7",
+ "terser": "^5.31.2",
"typescript": "^5.5.3",
"vite": "^5.3.3",
"vite-plugin-cdn-import": "^1.0.1",
diff --git a/Web/src/hooks/setupVXETableHook.ts b/Web/src/hooks/setupVXETableHook.ts
index 8c699285..332873da 100644
--- a/Web/src/hooks/setupVXETableHook.ts
+++ b/Web/src/hooks/setupVXETableHook.ts
@@ -8,10 +8,10 @@ import 'vxe-table-plugin-element/dist/style.css';
// Vxe UI 组件库
import VxeUI, { VxeComponentSizeType } from 'vxe-pc-ui';
import ExcelJS from 'exceljs';
-import { Local } from '../utils/storage';
+import { useThemeConfig } from '/@/stores/themeConfig';
+const vxeSize: VxeComponentSizeType = useThemeConfig().themeConfig.globalComponentSize == 'small' ? 'mini' : useThemeConfig().themeConfig.globalComponentSize == 'default' ? 'small' : 'medium';
export const setupVXETable = (app: App) => {
- let vxeSize = getVxeTableSize();
// 加载插件
VxeUITable.use(VXETablePluginElement);
VxeUITable.use(VXETablePluginExportXLSX, { ExcelJS: ExcelJS });
@@ -109,18 +109,3 @@ export const setupVXETable = (app: App) => {
// app.config.globalProperties.$XSaveFile = VxeUI.saveFile
// app.config.globalProperties.$XReadFile = VxeUI.readFile
};
-
-// 从全局主题里面获取组件大小模式
-function getVxeTableSize() {
- let vxeSize: VxeComponentSizeType = 'mini';
-
- let themeConfig = Local.get('themeConfig');
- if (themeConfig == null || themeConfig == undefined) return vxeSize;
-
- let size = themeConfig.globalComponentSize;
- if (size == 'large') vxeSize = 'medium';
- else if (size == 'default') vxeSize = 'small';
- else if (size == 'small') vxeSize = 'mini';
-
- return vxeSize;
-}
diff --git a/Web/src/hooks/useVxeTableOptionsHook.ts b/Web/src/hooks/useVxeTableOptionsHook.ts
new file mode 100644
index 00000000..e8f0b0f7
--- /dev/null
+++ b/Web/src/hooks/useVxeTableOptionsHook.ts
@@ -0,0 +1,84 @@
+import { dayjs } from 'element-plus';
+import { reactive } from 'vue';
+import { VxeGridProps, VxeGridPropTypes, VxeComponentSizeType } from 'vxe-table';
+import { useThemeConfig } from '/@/stores/themeConfig';
+import { merge } from 'lodash-es';
+
+const vxeSize: VxeComponentSizeType = useThemeConfig().themeConfig.globalComponentSize == 'small' ? 'mini' : useThemeConfig().themeConfig.globalComponentSize == 'default' ? 'small' : 'medium';
+
+/**
+ * @param {String} id 表格唯一标识,为空时自动随机产生;
+ * @param {String} id name:表格名称,与导出文件名有关;
+ * @param {VxeGridPropTypes.Columns} columns 列配置;
+ */
+interface iVxeOption {
+ id?: string;
+ name?: string;
+ columns: VxeGridPropTypes.Columns;
+}
+
+/**
+ * Vxe表格参数化Hook
+ * @param {iVxeOption} opt 参数
+ * @param {VxeGridProps} extras 要覆盖的参数
+ * @returns
+ */
+export const useVxeTable = (opt: iVxeOption, extras?: VxeGridProps) => {
+ // 默认参数
+ opt = Object.assign({ enableExport: true, remoteExport: false }, opt);
+ // 创建tableId,表格id固定才可以记录调整列宽,再次刷新仍有效。
+ opt.id = opt.id ? opt.id : String(new Date().getTime());
+ // console.log(opt);
+ const options = reactive({
+ id: opt.id,
+ height: 'auto',
+ autoResize: true,
+ size: vxeSize,
+ loading: false,
+ align: 'center', // 自动监听父元素的变化去重新计算表格(对于父元素可能存在动态变化、显示隐藏的容器中、列宽异常等场景中的可能会用到)
+ // data: [] as Array,
+ columns: opt.columns,
+ toolbarConfig: {
+ size: vxeSize,
+ slots: { buttons: 'toolbar_buttons', tools: 'toolbar_tools' },
+ refresh: {
+ code: 'query',
+ },
+ export: true,
+ print: true,
+ zoom: true,
+ custom: true,
+ },
+ checkboxConfig: { range: true },
+ sortConfig: { trigger: 'cell', remote: true },
+ exportConfig: {
+ remote: false, // 设置使用服务端导出
+ filename: `${opt.name}导出_${dayjs().format('YYMMDDHHmmss')}`,
+ },
+ pagerConfig: {
+ enabled: true,
+ size: vxeSize,
+ pageSize: 20,
+ }, // 分页
+ printConfig: { sheetName: '' },
+ proxyConfig: {
+ enabled: true,
+ autoLoad: false,
+ sort: true,
+ props: {
+ list: 'data.result', // 不分页时
+ result: 'data.result.items', // 分页时
+ total: 'data.result.total',
+ message: 'data.message',
+ },
+ },
+ customConfig: {
+ storage: {
+ // 是否启用 localStorage 本地保存,会将列操作状态保留在本地(需要有 id)
+ visible: true, // 启用显示/隐藏列状态
+ resizable: true, // 启用列宽状态
+ },
+ },
+ });
+ return extras ? merge(options, extras) : options;
+};
diff --git a/Web/src/theme/element.scss b/Web/src/theme/element.scss
index 83daf5b7..47524694 100644
--- a/Web/src/theme/element.scss
+++ b/Web/src/theme/element.scss
@@ -376,13 +376,13 @@
/* Table 表格 element plus 2.2.0 版本
------------------------------- */
.el-table {
+ // 表头背景色
+ --el-table-header-bg-color: var(--next-bg-main-color);
+
.el-button.is-text {
padding: 0;
}
- // 表头背景色
- --el-table-header-bg-color: var(--next-bg-main-color);
-
// 表头字体颜色
thead {
color: var(--el-text-color-regular);
diff --git a/Web/src/theme/vxeTable.scss b/Web/src/theme/vxeTable.scss
index 2482ce3b..a1be7244 100644
--- a/Web/src/theme/vxeTable.scss
+++ b/Web/src/theme/vxeTable.scss
@@ -36,10 +36,11 @@
.vxe-cell {
padding-left: 5px !important;
padding-right: 5px !important;
+ user-select: text !important;
+
.el-button {
padding: 0 !important;
}
- user-select: text !important;
}
.vxe-pager.size--mini {
diff --git a/Web/src/views/login/component/account.vue b/Web/src/views/login/component/account.vue
index 1407af75..a22804a5 100644
--- a/Web/src/views/login/component/account.vue
+++ b/Web/src/views/login/component/account.vue
@@ -283,6 +283,8 @@ defineExpose({ saveTokenAndInitRoutes });