Browse Source

Merge branch 'dev' into localized-static-cache

pull/1305/head
yx lin 8 months ago
committed by GitHub
parent
commit
6ed0e4a0f3
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 2
      .github/workflows/release.yml
  2. 7
      Directory.Packages.props
  3. 6
      apps/vben5/.husky/commit-msg
  4. 3
      apps/vben5/.husky/post-merge
  5. 7
      apps/vben5/.husky/pre-commit
  6. 20
      apps/vben5/.lintstagedrc.mjs
  7. 3
      apps/vben5/apps/app-antd/package.json
  8. 8
      apps/vben5/apps/app-antd/src/adapter/component/index.ts
  9. 15
      apps/vben5/apps/app-antd/src/locales/index.ts
  10. 8
      apps/vben5/apps/app-antd/src/preferences.ts
  11. 262
      apps/vben5/apps/app-antd/src/views/dashboard/workspace/index.vue
  12. 3
      apps/vben5/packages/@abp/identity/src/components/roles/RoleTable.vue
  13. 5
      apps/vben5/packages/@abp/platform/package.json
  14. 1
      apps/vben5/packages/@abp/platform/src/api/index.ts
  15. 62
      apps/vben5/packages/@abp/platform/src/api/useMyFavoriteMenusApi.ts
  16. 2
      apps/vben5/packages/@abp/platform/src/components/index.ts
  17. 45
      apps/vben5/packages/@abp/platform/src/components/workbench/components/WorkbenchHeader.vue
  18. 124
      apps/vben5/packages/@abp/platform/src/components/workbench/components/WorkbenchQuickNav.vue
  19. 137
      apps/vben5/packages/@abp/platform/src/components/workbench/components/WorkbenchQuickNavModal.vue
  20. 64
      apps/vben5/packages/@abp/platform/src/components/workbench/components/WorkbenchTodo.vue
  21. 65
      apps/vben5/packages/@abp/platform/src/components/workbench/components/WorkbenchTrends.vue
  22. 218
      apps/vben5/packages/@abp/platform/src/components/workbench/index.vue
  23. 10
      apps/vben5/packages/@abp/platform/src/components/workbench/types.ts
  24. 1
      apps/vben5/packages/@abp/platform/src/index.ts
  25. 20
      apps/vben5/packages/@abp/platform/src/locales/index.ts
  26. 37
      apps/vben5/packages/@abp/platform/src/locales/langs/en-US/workbench.json
  27. 37
      apps/vben5/packages/@abp/platform/src/locales/langs/zh-CN/workbench.json
  28. 34
      apps/vben5/packages/@abp/platform/src/types/favorites.ts
  29. 1
      apps/vben5/packages/@abp/platform/src/types/index.ts
  30. 6
      apps/vben5/packages/@abp/settings/src/components/settings/SettingForm.vue
  31. 1
      apps/vben5/packages/@abp/tasks/src/components/job-infos/JobInfoDrawer.vue
  32. 2
      apps/vben5/packages/@abp/ui/src/components/vxe-table/use-vxe-grid.ts
  33. 2
      apps/vben5/packages/@abp/ui/src/components/vxe-table/use-vxe-grid.vue
  34. 2
      apps/vben5/packages/effects/plugins/src/vxe-table/use-vxe-grid.vue
  35. 5
      apps/vben5/pnpm-workspace.yaml
  36. 3
      aspnet-core/framework/auditing/LINGYUN.Abp.AspNetCore.Auditing/FodyWeavers.xml
  37. 20
      aspnet-core/framework/auditing/LINGYUN.Abp.AspNetCore.Auditing/LINGYUN.Abp.AspNetCore.Auditing.csproj
  38. 19
      aspnet-core/framework/auditing/LINGYUN.Abp.AspNetCore.Auditing/LINGYUN/Abp/AspNetCore/Auditing/AbpAspNetCoreAuditingHeaderOptions.cs
  39. 17
      aspnet-core/framework/auditing/LINGYUN.Abp.AspNetCore.Auditing/LINGYUN/Abp/AspNetCore/Auditing/AbpAspNetCoreAuditingModule.cs
  40. 51
      aspnet-core/framework/auditing/LINGYUN.Abp.AspNetCore.Auditing/LINGYUN/Abp/AspNetCore/Auditing/AspNetCoreRecordHeaderAuditLogContributor.cs
  41. 19
      aspnet-core/framework/auditing/LINGYUN.Abp.AspNetCore.Auditing/README.md
  42. 2
      aspnet-core/framework/common/LINGYUN.Abp.IP2Region/LINGYUN/Abp/IP2Region/AbpIP2RegionModule.cs
  43. 2
      aspnet-core/framework/common/LINGYUN.Abp.IP2Region/LINGYUN/Abp/IP2Region/IP2RegionIPLocationResolveContributor.cs
  44. 196
      aspnet-core/framework/dynamic-queryable/LINGYUN.Linq.Dynamic.Queryable/System/Linq/Expressions/ObjectQueryableExtensions.cs
  45. 6
      aspnet-core/modules/account/LINGYUN.Abp.Account.Application/LINGYUN/Abp/Account/MyProfileAppService.cs
  46. 2
      aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain/LINGYUN/Abp/Identity/AbpIdentityDomainModule.cs
  47. 71
      aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain/LINGYUN/Abp/Identity/Session/IdentitySessionCacheItemSynchronizer.cs
  48. 28
      aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain/LINGYUN/Abp/Identity/Session/IdentitySessionCleanupBackgroundWorker.cs
  49. 1
      aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/LocalizationTextStoreCache.cs
  50. 19
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application.Contracts/LINGYUN/Abp/OssManagement/IFileAppService.cs
  51. 14
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application.Contracts/LINGYUN/Abp/OssManagement/IPrivateFileAppService.cs
  52. 18
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application.Contracts/LINGYUN/Abp/OssManagement/IPublicFileAppService.cs
  53. 2
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN/Abp/OssManagement/FileAppServiceBase.cs
  54. 4
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi.Client/ClientProxies/LINGYUN/Abp/OssManagement/PrivateFilesClientProxy.Generated.cs
  55. 4
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi.Client/ClientProxies/LINGYUN/Abp/OssManagement/PublicFilesClientProxy.Generated.cs
  56. 182
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi.Client/ClientProxies/oss-management-generate-proxy.json
  57. 2
      aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.Templating/LINGYUN.Abp.Notifications.Templating.csproj
  58. 5
      aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Domain/LINGYUN/Abp/TaskManagement/BackgroundJobInfo.cs
  59. 3
      aspnet-core/services/.gitignore
  60. 6
      aspnet-core/services/LY.MicroService.Applications.Single/package.json
  61. 31
      aspnet-core/services/LY.MicroService.AuthServer/AuthServerModule.Configure.cs
  62. 3
      aspnet-core/services/LY.MicroService.AuthServer/AuthServerModule.cs
  63. 4
      aspnet-core/services/LY.MicroService.AuthServer/appsettings.json
  64. 6
      aspnet-core/services/LY.MicroService.AuthServer/package.json
  65. 2
      aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/bootstrap/css/bootstrap.css
  66. 2
      aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/bootstrap/css/bootstrap.css.map
  67. 2
      aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/bootstrap/css/bootstrap.min.css
  68. 2
      aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/bootstrap/css/bootstrap.min.css.map
  69. 2
      aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/bootstrap/css/bootstrap.rtl.css
  70. 2
      aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/bootstrap/css/bootstrap.rtl.css.map
  71. 2
      aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/bootstrap/css/bootstrap.rtl.min.css
  72. 2
      aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/bootstrap/css/bootstrap.rtl.min.css.map
  73. 6
      aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/bootstrap/js/bootstrap.bundle.js
  74. 2
      aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/bootstrap/js/bootstrap.bundle.js.map
  75. 4
      aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/bootstrap/js/bootstrap.bundle.min.js
  76. 2
      aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/bootstrap/js/bootstrap.bundle.min.js.map
  77. 13
      aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/datatables.net-bs5/css/dataTables.bootstrap5.css
  78. 4
      aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/datatables.net/js/dataTables.min.js
  79. 226
      aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/luxon/luxon.js
  80. 2
      aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/luxon/luxon.js.map
  81. 2
      aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/luxon/luxon.min.js
  82. 2
      aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/luxon/luxon.min.js.map
  83. BIN
      aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/moment/locale/de-ch.js
  84. 91
      aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/moment/locale/en-au.js
  85. 35
      aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/sweetalert2/sweetalert2.all.js
  86. 6
      aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/sweetalert2/sweetalert2.all.min.js
  87. 104
      aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/sweetalert2/sweetalert2.css
  88. 35
      aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/sweetalert2/sweetalert2.esm.all.js
  89. 6
      aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/sweetalert2/sweetalert2.esm.all.min.js
  90. 33
      aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/sweetalert2/sweetalert2.esm.js
  91. 4
      aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/sweetalert2/sweetalert2.esm.min.js
  92. 33
      aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/sweetalert2/sweetalert2.js
  93. 2
      aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/sweetalert2/sweetalert2.min.css
  94. 4
      aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/sweetalert2/sweetalert2.min.js
  95. 6
      aspnet-core/services/LY.MicroService.IdentityServer/package.json
  96. 1879
      aspnet-core/services/LY.MicroService.IdentityServer/wwwroot/libs/jquery/jquery.js
  97. 4
      aspnet-core/services/LY.MicroService.IdentityServer/wwwroot/libs/select2/js/i18n/nb.js
  98. BIN
      aspnet-core/services/LY.MicroService.IdentityServer/wwwroot/libs/timeago/locales/jquery.timeago.rs.js
  99. BIN
      aspnet-core/services/LY.MicroService.IdentityServer/wwwroot/libs/timeago/locales/jquery.timeago.sk.js
  100. 31
      aspnet-core/services/LY.MicroService.IdentityServer/wwwroot/libs/timeago/locales/jquery.timeago.th.js

2
.github/workflows/release.yml

@ -14,4 +14,4 @@ jobs:
with:
repo_token: "${{ secrets.GITHUB_TOKEN }}"
prerelease: false
automatic_release_tag: "9.2.1"
automatic_release_tag: "9.2.3"

7
Directory.Packages.props

@ -3,8 +3,8 @@
<DotNetCoreCAPPackageVersion>8.3.5</DotNetCoreCAPPackageVersion>
<ElsaPackageVersion>2.15.2</ElsaPackageVersion>
<ElsaNextPackageVersion>3.3.5</ElsaNextPackageVersion>
<VoloAbpPackageVersion>9.2.1</VoloAbpPackageVersion>
<LINGYUNAbpPackageVersion>9.2.1</LINGYUNAbpPackageVersion>
<VoloAbpPackageVersion>9.2.3</VoloAbpPackageVersion>
<LINGYUNAbpPackageVersion>9.2.3</LINGYUNAbpPackageVersion>
<MicrosoftExtensionsPackageVersion>9.0.4</MicrosoftExtensionsPackageVersion>
<MicrosoftAspNetCorePackageVersion>9.0.4</MicrosoftAspNetCorePackageVersion>
<MicrosoftEntityFrameworkCorePackageVersion>9.0.4</MicrosoftEntityFrameworkCorePackageVersion>
@ -12,7 +12,7 @@
</PropertyGroup>
<!-- Abp Framework -->
<ItemGroup>
<PackageVersion Include="Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonXLite" Version="4.2.1" />
<PackageVersion Include="Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonXLite" Version="4.2.3" />
<PackageVersion Include="Volo.Abp.Core" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Account.Application" Version="$(VoloAbpPackageVersion)" />
<PackageVersion Include="Volo.Abp.Account.Application.Contracts" Version="$(VoloAbpPackageVersion)" />
@ -309,6 +309,7 @@
<PackageVersion Include="OpenTelemetry.Instrumentation.Http" Version="1.12.0" />
<PackageVersion Include="OpenTelemetry.Instrumentation.EntityFrameworkCore" Version="1.12.0-beta.2" />
<PackageVersion Include="OpenTelemetry.Instrumentation.Runtime" Version="1.12.0" />
<PackageVersion Include="OpenTelemetry.Instrumentation.SqlClient" Version="1.12.0-beta.1" />
<PackageVersion Include="Polly" Version="8.5.2" />
<PackageVersion Include="QRCoder" Version="1.5.1" />
<PackageVersion Include="Quartz.Serialization.Json" Version="3.14.0" />

6
apps/vben5/.husky/commit-msg

@ -1,6 +0,0 @@
echo Start running commit-msg hook...
# Check whether the git commit information is standardized
pnpm exec commitlint --edit "$1"
echo Run commit-msg hook done.

3
apps/vben5/.husky/post-merge

@ -1,3 +0,0 @@
# 每次 git pull 之后, 安装依赖
pnpm install

7
apps/vben5/.husky/pre-commit

@ -1,7 +0,0 @@
# update `.vscode/vben-admin.code-workspace` file
pnpm vsh code-workspace --auto-commit
# Format and submit code according to lintstagedrc.js configuration
pnpm exec lint-staged
echo Run pre-commit hook done.

20
apps/vben5/.lintstagedrc.mjs

@ -1,20 +0,0 @@
export default {
'*.md': ['prettier --cache --ignore-unknown --write'],
'*.vue': [
'prettier --write',
'eslint --cache --fix',
'stylelint --fix --allow-empty-input',
],
'*.{js,jsx,ts,tsx}': [
'prettier --cache --ignore-unknown --write',
'eslint --cache --fix',
],
'*.{scss,less,styl,html,vue,css}': [
'prettier --cache --ignore-unknown --write',
'stylelint --fix --allow-empty-input',
],
'package.json': ['prettier --cache --write'],
'{!(package)*.json,*.code-snippets,.!(browserslist)*rc}': [
'prettier --cache --write--parser json',
],
};

3
apps/vben5/apps/app-antd/package.json

@ -66,6 +66,7 @@
"dayjs": "catalog:",
"pinia": "catalog:",
"vue": "catalog:",
"vue-router": "catalog:"
"vue-router": "catalog:",
"vue3-colorpicker": "catalog:"
}
}

8
apps/vben5/apps/app-antd/src/adapter/component/index.ts

@ -31,6 +31,12 @@ const Button = defineAsyncComponent(() => import('ant-design-vue/es/button'));
const Checkbox = defineAsyncComponent(
() => import('ant-design-vue/es/checkbox'),
);
const ColorPicker = defineAsyncComponent(() =>
import('vue3-colorpicker').then((res) => {
import('vue3-colorpicker/style.css');
return res.ColorPicker;
}),
);
const CheckboxGroup = defineAsyncComponent(() =>
import('ant-design-vue/es/checkbox').then((res) => res.CheckboxGroup),
);
@ -117,6 +123,7 @@ export type ComponentType =
| 'AutoComplete'
| 'Checkbox'
| 'CheckboxGroup'
| 'ColorPicker'
| 'DatePicker'
| 'DefaultButton'
| 'Divider'
@ -182,6 +189,7 @@ async function initComponentAdapter() {
AutoComplete,
Checkbox,
CheckboxGroup,
ColorPicker,
DatePicker,
// 自定义默认按钮
DefaultButton: (props, { attrs, slots }) => {

15
apps/vben5/apps/app-antd/src/locales/index.ts

@ -15,6 +15,7 @@ import { preferences } from '@vben/preferences';
import { useAbpStore } from '@abp/core';
import { useLocalizationsApi } from '@abp/localization';
import { loadPaltformMessages } from '@abp/platform';
import antdEnLocale from 'ant-design-vue/es/locale/en_US';
import antdDefaultLocale from 'ant-design-vue/es/locale/zh_CN';
import dayjs from 'dayjs';
@ -34,13 +35,17 @@ const localesMap = loadLocalesMapFromDir(
* @param lang
*/
async function loadMessages(lang: SupportedLanguagesType) {
const [appLocaleMessages, _, abpLocales] = await Promise.all([
localesMap[lang]?.(),
loadThirdPartyMessage(lang),
loadAbpLocale(lang),
]);
const [appLocaleMessages, platformLocales, _, abpLocales] = await Promise.all(
[
localesMap[lang]?.(),
loadPaltformMessages(lang),
loadThirdPartyMessage(lang),
loadAbpLocale(lang),
],
);
return {
...appLocaleMessages?.default,
...platformLocales?.default,
...abpLocales,
};
}

8
apps/vben5/apps/app-antd/src/preferences.ts

@ -9,7 +9,15 @@ export const overridesPreferences = defineOverridesPreferences({
// overrides
app: {
accessMode: 'backend',
defaultHomePath: '/workspace',
enableRefreshToken: true,
name: import.meta.env.VITE_APP_TITLE,
},
theme: {
mode: 'auto',
radius: '0.25',
},
widget: {
notification: false,
},
});

262
apps/vben5/apps/app-antd/src/views/dashboard/workspace/index.vue

@ -1,266 +1,32 @@
<script lang="ts" setup>
import type {
WorkbenchProjectItem,
WorkbenchQuickNavItem,
WorkbenchTodoItem,
WorkbenchTrendItem,
} from '@vben/common-ui';
<script setup lang="ts">
import type { FavoriteMenu } from '@abp/platform';
import { ref } from 'vue';
import { useRouter } from 'vue-router';
import {
AnalysisChartCard,
WorkbenchHeader,
WorkbenchProject,
WorkbenchQuickNav,
WorkbenchTodo,
WorkbenchTrends,
} from '@vben/common-ui';
import { preferences } from '@vben/preferences';
import { useUserStore } from '@vben/stores';
import { openWindow } from '@vben/utils';
import AnalyticsVisitsSource from '../analytics/analytics-visits-source.vue';
const userStore = useUserStore();
//
// url navTo
// url: /dashboard/workspace
const projectItems: WorkbenchProjectItem[] = [
{
color: '',
content: '不要等待机会,而要创造机会。',
date: '2021-04-01',
group: '开源组',
icon: 'carbon:logo-github',
title: 'Github',
url: 'https://github.com',
},
{
color: '#3fb27f',
content: '现在的你决定将来的你。',
date: '2021-04-01',
group: '算法组',
icon: 'ion:logo-vue',
title: 'Vue',
url: 'https://vuejs.org',
},
{
color: '#e18525',
content: '没有什么才能比努力更重要。',
date: '2021-04-01',
group: '上班摸鱼',
icon: 'ion:logo-html5',
title: 'Html5',
url: 'https://developer.mozilla.org/zh-CN/docs/Web/HTML',
},
{
color: '#bf0c2c',
content: '热情和欲望可以突破一切难关。',
date: '2021-04-01',
group: 'UI',
icon: 'ion:logo-angular',
title: 'Angular',
url: 'https://angular.io',
},
{
color: '#00d8ff',
content: '健康的身体是实现目标的基石。',
date: '2021-04-01',
group: '技术牛',
icon: 'bx:bxl-react',
title: 'React',
url: 'https://reactjs.org',
},
{
color: '#EBD94E',
content: '路是走出来的,而不是空想出来的。',
date: '2021-04-01',
group: '架构组',
icon: 'ion:logo-javascript',
title: 'Js',
url: 'https://developer.mozilla.org/zh-CN/docs/Web/JavaScript',
},
];
// url 使 http
const quickNavItems: WorkbenchQuickNavItem[] = [
{
color: '#1fdaca',
icon: 'ion:home-outline',
title: '首页',
url: '/',
},
{
color: '#bf0c2c',
icon: 'ion:grid-outline',
title: '仪表盘',
url: '/dashboard',
},
{
color: '#e18525',
icon: 'ion:layers-outline',
title: '组件',
url: '/demos/features/icons',
},
{
color: '#3fb27f',
icon: 'ion:settings-outline',
title: '系统管理',
url: '/demos/features/login-expired', // URL
},
{
color: '#4daf1bc9',
icon: 'ion:key-outline',
title: '权限管理',
url: '/demos/access/page-control',
},
{
color: '#00d8ff',
icon: 'ion:bar-chart-outline',
title: '图表',
url: '/analytics',
},
];
const todoItems = ref<WorkbenchTodoItem[]>([
{
completed: false,
content: `审查最近提交到Git仓库的前端代码,确保代码质量和规范。`,
date: '2024-07-30 11:00:00',
title: '审查前端代码提交',
},
{
completed: true,
content: `检查并优化系统性能,降低CPU使用率。`,
date: '2024-07-30 11:00:00',
title: '系统性能优化',
},
{
completed: false,
content: `进行系统安全检查,确保没有安全漏洞或未授权的访问。 `,
date: '2024-07-30 11:00:00',
title: '安全检查',
},
{
completed: false,
content: `更新项目中的所有npm依赖包,确保使用最新版本。`,
date: '2024-07-30 11:00:00',
title: '更新项目依赖',
},
{
completed: false,
content: `修复用户报告的页面UI显示问题,确保在不同浏览器中显示一致。 `,
date: '2024-07-30 11:00:00',
title: '修复UI显示问题',
},
]);
const trendItems: WorkbenchTrendItem[] = [
{
avatar: 'svg:avatar-1',
content: `在 <a>开源组</a> 创建了项目 <a>Vue</a>`,
date: '刚刚',
title: '威廉',
},
{
avatar: 'svg:avatar-2',
content: `关注了 <a>威廉</a> `,
date: '1个小时前',
title: '艾文',
},
{
avatar: 'svg:avatar-3',
content: `发布了 <a>个人动态</a> `,
date: '1天前',
title: '克里斯',
},
{
avatar: 'svg:avatar-4',
content: `发表文章 <a>如何编写一个Vite插件</a> `,
date: '2天前',
title: 'Vben',
},
{
avatar: 'svg:avatar-1',
content: `回复了 <a>杰克</a> 的问题 <a>如何进行项目优化?</a>`,
date: '3天前',
title: '皮特',
},
{
avatar: 'svg:avatar-2',
content: `关闭了问题 <a>如何运行项目</a> `,
date: '1周前',
title: '杰克',
},
{
avatar: 'svg:avatar-3',
content: `发布了 <a>个人动态</a> `,
date: '1周前',
title: '威廉',
},
{
avatar: 'svg:avatar-4',
content: `推送了代码到 <a>Github</a>`,
date: '2021-04-01 20:00',
title: '威廉',
},
{
avatar: 'svg:avatar-4',
content: `发表文章 <a>如何编写使用 Admin Vben</a> `,
date: '2021-03-01 20:00',
title: 'Vben',
},
];
import { Workbench } from '@abp/platform';
const router = useRouter();
//
// This is a sample method, adjust according to the actual project requirements
function navTo(nav: WorkbenchProjectItem | WorkbenchQuickNavItem) {
if (nav.url?.startsWith('http')) {
openWindow(nav.url);
function navTo(menu: FavoriteMenu) {
if (menu.path?.startsWith('http')) {
openWindow(menu.path);
return;
}
if (nav.url?.startsWith('/')) {
router.push(nav.url).catch((error) => {
if (menu.path?.startsWith('/')) {
router.push(menu.path).catch((error) => {
console.error('Navigation failed:', error);
});
} else {
console.warn(`Unknown URL for navigation item: ${nav.title} -> ${nav.url}`);
console.warn(
`Unknown URL for navigation item: ${menu.displayName} -> ${menu.path}`,
);
}
}
</script>
<template>
<div class="p-5">
<WorkbenchHeader
:avatar="userStore.userInfo?.avatar || preferences.app.defaultAvatar"
>
<template #title>
早安, {{ userStore.userInfo?.realName }}, 开始您一天的工作吧
</template>
<template #description> 今日晴20 - 32 </template>
</WorkbenchHeader>
<div class="mt-5 flex flex-col lg:flex-row">
<div class="mr-4 w-full lg:w-3/5">
<WorkbenchProject :items="projectItems" title="项目" @click="navTo" />
<WorkbenchTrends :items="trendItems" class="mt-5" title="最新动态" />
</div>
<div class="w-full lg:w-2/5">
<WorkbenchQuickNav
:items="quickNavItems"
class="mt-5 lg:mt-0"
title="快捷导航"
@click="navTo"
/>
<WorkbenchTodo :items="todoItems" class="mt-5" title="待办事项" />
<AnalysisChartCard class="mt-5" title="访问来源">
<AnalyticsVisitsSource />
</AnalysisChartCard>
</div>
</div>
</div>
<Workbench @nav-to="navTo" />
</template>
<style scoped></style>

3
apps/vben5/packages/@abp/identity/src/components/roles/RoleTable.vue

@ -37,6 +37,7 @@ const MenuOutlined = createIconifyIcon('heroicons-outline:menu-alt-3');
const ClaimOutlined = createIconifyIcon('la:id-card-solid');
const PermissionsOutlined = createIconifyIcon('icon-park-outline:permissions');
const AuditLogIcon = createIconifyIcon('fluent-mdl2:compliance-audit');
const ProtectedIcon = createIconifyIcon('mdi:protected-outline');
const RoleModal = defineAsyncComponent(() => import('./RoleModal.vue'));
const ClaimModal = defineAsyncComponent(() => import('./RoleClaimModal.vue'));
@ -290,7 +291,7 @@ function onPermissionChange(_name: string, key: string) {
>
{{ $t('AbpAuditLogging.EntitiesChanged') }}
</MenuItem>
<MenuItem key="entity-rules">
<MenuItem key="entity-rules" :icon="h(ProtectedIcon)">
{{ '数据权限' }}
</MenuItem>
</Menu>

5
apps/vben5/packages/@abp/platform/package.json

@ -22,19 +22,24 @@
"dependencies": {
"@abp/components": "workspace:*",
"@abp/core": "workspace:*",
"@abp/notifications": "workspace:*",
"@abp/request": "workspace:*",
"@abp/ui": "workspace:*",
"@ant-design/icons-vue": "catalog:",
"@vben-core/shadcn-ui": "workspace:*",
"@vben/access": "workspace:*",
"@vben/common-ui": "workspace:*",
"@vben/hooks": "workspace:*",
"@vben/icons": "workspace:*",
"@vben/layouts": "workspace:*",
"@vben/locales": "workspace:*",
"@vben/preferences": "workspace:*",
"@vben/stores": "workspace:*",
"@vben/types": "workspace:*",
"ant-design-vue": "catalog:",
"lodash.clonedeep": "catalog:",
"vue": "catalog:*",
"vue3-colorpicker": "catalog:",
"vxe-table": "catalog:"
},
"devDependencies": {

1
apps/vben5/packages/@abp/platform/src/api/index.ts

@ -2,6 +2,7 @@ export { useDataDictionariesApi } from './useDataDictionariesApi';
export { useEmailMessagesApi } from './useEmailMessagesApi';
export { useLayoutsApi } from './useLayoutsApi';
export { useMenusApi } from './useMenusApi';
export { useMyFavoriteMenusApi } from './useMyFavoriteMenusApi';
export { useMyMenusApi } from './useMyMenusApi';
export { useRoleMenusApi } from './useRoleMenusApi';
export { useSmsMessagesApi } from './useSmsMessagesApi';

62
apps/vben5/packages/@abp/platform/src/api/useMyFavoriteMenusApi.ts

@ -0,0 +1,62 @@
import type { ListResultDto } from '@abp/core';
import type {
UserFavoriteMenuCreateDto,
UserFavoriteMenuDto,
} from '../types/favorites';
import { useRequest } from '@abp/request';
export function useMyFavoriteMenusApi() {
const { cancel, request } = useRequest();
/**
*
* @param input
* @returns
*/
function createApi(
input: UserFavoriteMenuCreateDto,
): Promise<UserFavoriteMenuDto> {
return request<UserFavoriteMenuDto>(
`/api/platform/menus/favorites/my-favorite-menus`,
{
data: input,
method: 'POST',
},
);
}
/**
*
* @param id Id
*/
function deleteApi(id: string): Promise<void> {
return request(`/api/platform/menus/favorites/my-favorite-menus/${id}`, {
method: 'DELETE',
});
}
/**
*
* @param framework ui框架
* @returns
*/
function getListApi(
framework?: string,
): Promise<ListResultDto<UserFavoriteMenuDto>> {
return request<ListResultDto<UserFavoriteMenuDto>>(
`/api/platform/menus/favorites/my-favorite-menus?framework=${framework}`,
{
method: 'GET',
},
);
}
return {
cancel,
createApi,
deleteApi,
getListApi,
};
}

2
apps/vben5/packages/@abp/platform/src/components/index.ts

@ -4,3 +4,5 @@ export { default as MenuAllotModal } from './menus/MenuAllotModal.vue';
export { default as MenuTable } from './menus/MenuTable.vue';
export { default as EmailMessageTable } from './messages/email/EmailMessageTable.vue';
export { default as SmsMessageTable } from './messages/sms/SmsMessageTable.vue';
export { default as Workbench } from './workbench/index.vue';
export * from './workbench/types';

45
apps/vben5/packages/@abp/platform/src/components/workbench/components/WorkbenchHeader.vue

@ -0,0 +1,45 @@
<script lang="ts" setup>
import { VbenAvatar } from '@vben-core/shadcn-ui';
interface Props {
avatar?: string;
notifierCount?: number;
text?: string;
}
defineOptions({
name: 'WorkbenchHeader',
});
withDefaults(defineProps<Props>(), {
avatar: '',
text: '',
notifierCount: 0,
});
</script>
<template>
<div class="card-box p-4 py-6 lg:flex">
<VbenAvatar :alt="text" :src="avatar" class="size-20" />
<div
v-if="$slots.title || $slots.description"
class="flex flex-col justify-center md:ml-6 md:mt-0"
>
<h1 v-if="$slots.title" class="text-md font-semibold md:text-xl">
<slot name="title"></slot>
</h1>
<span v-if="$slots.description" class="text-foreground/80 mt-1">
<slot name="description"></slot>
</span>
</div>
<div class="mt-4 flex flex-1 justify-end md:mt-0">
<div class="flex flex-col justify-center text-right">
<span class="text-foreground/80">
{{ $t('workbench.header.notifier.title') }}
</span>
<a class="text-2xl">{{
$t('workbench.header.notifier.count', [notifierCount])
}}</a>
</div>
</div>
</div>
</template>

124
apps/vben5/packages/@abp/platform/src/components/workbench/components/WorkbenchQuickNav.vue

@ -0,0 +1,124 @@
<script setup lang="ts">
import type { FavoriteMenu } from '../types';
import { computed, h } from 'vue';
import { $t } from '@vben/locales';
import {
Card,
CardContent,
CardHeader,
CardTitle,
VbenIcon,
} from '@vben-core/shadcn-ui';
import { DeleteOutlined } from '@ant-design/icons-vue';
import { Dropdown, Menu, Modal } from 'ant-design-vue';
interface Props {
items?: FavoriteMenu[];
title: string;
}
defineOptions({
name: 'WorkbenchQuickNav',
});
const props = withDefaults(defineProps<Props>(), {
items: () => [],
});
const emits = defineEmits<{
(event: 'click', menu: FavoriteMenu): void;
(event: 'delete', menu: FavoriteMenu): void;
(event: 'add'): void;
}>();
const MenuItem = Menu.Item;
const getFavoriteMenus = computed(() => {
const addMenu: FavoriteMenu = {
id: 'addMenu',
displayName: $t('workbench.content.favoriteMenu.create'),
icon: 'ion:add-outline',
color: '#00bfff',
isDefault: true,
};
return [...props.items, addMenu];
});
function onClick(menu: FavoriteMenu) {
if (menu.id === 'addMenu') {
emits('add');
return;
}
emits('click', menu);
}
function onMenuClick(key: string, menu: FavoriteMenu) {
switch (key) {
case 'delete': {
Modal.confirm({
centered: true,
iconType: 'warning',
title: $t('AbpUi.AreYouSure'),
content: $t('AbpUi.ItemWillBeDeletedMessage'),
okCancel: true,
onOk: () => {
emits('delete', menu);
},
});
}
}
}
</script>
<template>
<Card>
<CardHeader class="py-4">
<CardTitle class="text-lg">{{ title }}</CardTitle>
</CardHeader>
<CardContent class="flex flex-wrap p-0">
<template
v-for="(item, index) in getFavoriteMenus"
:key="item.displayName"
>
<Dropdown :trigger="['contextmenu']">
<div
:class="{
'border-r-0': index % 3 === 2,
'border-b-0': index < 3,
'pb-4': index > 2,
'rounded-bl-xl': index === items.length - 3,
'rounded-br-xl': index === items.length - 1,
}"
class="flex-col-center border-border group w-1/3 cursor-pointer border-r border-t py-8 hover:shadow-xl"
@click="onClick(item)"
>
<VbenIcon
:color="item.color"
:icon="item.icon"
class="size-7 transition-all duration-300 group-hover:scale-125"
/>
<span class="text-md mt-2 truncate">{{ item.displayName }}</span>
</div>
<template #overlay>
<Menu
v-if="!item.isDefault"
@click="
({ key: menuKey }) => onMenuClick(menuKey.toString(), item)
"
>
<MenuItem key="delete" :icon="h(DeleteOutlined)">
{{ $t('workbench.content.favoriteMenu.delete') }}
</MenuItem>
</Menu>
</template>
</Dropdown>
</template>
</CardContent>
</Card>
</template>
<style scoped></style>

137
apps/vben5/packages/@abp/platform/src/components/workbench/components/WorkbenchQuickNavModal.vue

@ -0,0 +1,137 @@
<script setup lang="ts">
import type { MenuDto, UserFavoriteMenuDto } from '../../../types';
import { defineAsyncComponent, ref } from 'vue';
import { useVbenForm, useVbenModal } from '@vben/common-ui';
import { useAppConfig } from '@vben/hooks';
import { IconifyIcon } from '@vben/icons';
import { $t } from '@vben/locales';
import { listToTree } from '@abp/core';
import { message, TreeSelect } from 'ant-design-vue';
import { useMyFavoriteMenusApi } from '../../../api/useMyFavoriteMenusApi';
import { useMyMenusApi } from '../../../api/useMyMenusApi';
const emits = defineEmits<{
(event: 'change', data: UserFavoriteMenuDto): void;
}>();
const ColorPicker = defineAsyncComponent(() =>
import('vue3-colorpicker').then((res) => {
import('vue3-colorpicker/style.css');
return res.ColorPicker;
}),
);
const availableMenus = ref<MenuDto[]>([]);
const { getAllApi } = useMyMenusApi();
const { createApi } = useMyFavoriteMenusApi();
const { uiFramework } = useAppConfig(import.meta.env, import.meta.env.PROD);
const [Form, formApi] = useVbenForm({
schema: [
{
label: $t('workbench.content.favoriteMenu.select'),
fieldName: 'menuId',
component: 'TreeSelect',
rules: 'selectRequired',
},
{
label: $t('workbench.content.favoriteMenu.color'),
fieldName: 'color',
component: 'ColorPicker',
defaultValue: '#000000',
modelPropName: 'pureColor',
},
{
label: $t('workbench.content.favoriteMenu.alias'),
fieldName: 'aliasName',
component: 'Input',
},
{
label: $t('workbench.content.favoriteMenu.icon'),
fieldName: 'icon',
component: 'IconPicker',
},
],
showDefaultActions: false,
handleSubmit: onSubmit,
commonConfig: {
colon: true,
componentProps: {
class: 'w-full',
},
},
});
const [Modal, modalApi] = useVbenModal({
async onConfirm() {
await formApi.validateAndSubmitForm();
},
async onOpenChange(isOpen) {
if (isOpen) {
await onInitMenus();
}
},
});
async function onInitMenus() {
const { items } = await getAllApi({
framework: uiFramework,
});
const menus = listToTree<MenuDto>(items, { id: 'id', pid: 'parentId' });
availableMenus.value = menus;
}
async function onSubmit(values: Record<string, any>) {
try {
modalApi.setState({ submitting: true });
const menuDto = await createApi({
framework: uiFramework,
menuId: values.menuId,
color: values.color,
icon: values.icon,
aliasName: values.aliasName,
});
message.success($t('AbpUi.SavedSuccessfully'));
emits('change', menuDto);
modalApi.close();
} finally {
modalApi.setState({ submitting: false });
}
}
</script>
<template>
<Modal :title="$t('workbench.content.favoriteMenu.manage')">
<Form>
<template #color="slotProps">
<div class="flex flex-row items-center">
<ColorPicker v-bind="slotProps" format="hex" />
<span>({{ slotProps.value }})</span>
</div>
</template>
<template #menuId="slotProps">
<TreeSelect
allow-clear
class="w-full"
tree-icon
v-bind="slotProps"
:field-names="{ label: 'displayName', value: 'id' }"
:tree-data="availableMenus"
>
<template #title="item">
<div class="flex flex-row items-center gap-1">
<IconifyIcon v-if="item.meta?.icon" :icon="item.meta.icon" />
<span>{{ item.displayName }}</span>
</div>
</template>
</TreeSelect>
</template>
</Form>
</Modal>
</template>
<style scoped></style>

64
apps/vben5/packages/@abp/platform/src/components/workbench/components/WorkbenchTodo.vue

@ -0,0 +1,64 @@
<script setup lang="ts">
import type { WorkbenchTodoItem } from '@vben/common-ui';
import {
Card,
CardContent,
CardHeader,
CardTitle,
VbenCheckbox,
} from '@vben-core/shadcn-ui';
interface Props {
items?: WorkbenchTodoItem[];
title: string;
}
defineOptions({
name: 'WorkbenchTodo',
});
withDefaults(defineProps<Props>(), {
items: () => [],
});
</script>
<template>
<Card>
<CardHeader class="py-4">
<CardTitle class="text-lg">{{ title }}</CardTitle>
</CardHeader>
<slot v-if="items.length === 0" name="empty"></slot>
<CardContent v-else class="flex flex-wrap p-5 pt-0">
<ul class="divide-border w-full divide-y" role="list">
<li
v-for="item in items"
:key="item.title"
:class="{
'select-none line-through opacity-60': item.completed,
}"
class="flex cursor-pointer justify-between gap-x-6 py-5"
>
<div class="flex min-w-0 items-center gap-x-4">
<VbenCheckbox v-model:checked="item.completed" name="completed" />
<div class="min-w-0 flex-auto">
<p class="text-foreground text-sm font-semibold leading-6">
{{ item.title }}
</p>
<!-- eslint-disable vue/no-v-html -->
<p
class="text-foreground/80 *:text-primary mt-1 truncate text-xs leading-5"
v-html="item.content"
></p>
</div>
</div>
<div class="hidden h-full shrink-0 sm:flex sm:flex-col sm:items-end">
<span class="text-foreground/80 mt-6 text-xs leading-6">
{{ item.date }}
</span>
</div>
</li>
</ul>
</CardContent>
</Card>
</template>

65
apps/vben5/packages/@abp/platform/src/components/workbench/components/WorkbenchTrends.vue

@ -0,0 +1,65 @@
<script setup lang="ts">
import type { WorkbenchTrendItem } from '@vben/common-ui';
import {
Card,
CardContent,
CardHeader,
CardTitle,
VbenIcon,
} from '@vben-core/shadcn-ui';
interface Props {
items?: WorkbenchTrendItem[];
title: string;
}
defineOptions({
name: 'WorkbenchTrends',
});
withDefaults(defineProps<Props>(), {
items: () => [],
});
</script>
<template>
<Card>
<CardHeader class="py-4">
<CardTitle class="text-lg">{{ title }}</CardTitle>
</CardHeader>
<slot v-if="items.length === 0" name="empty"></slot>
<CardContent v-else class="flex flex-wrap p-5 pt-0">
<ul class="divide-border w-full divide-y" role="list">
<li
v-for="item in items"
:key="item.title"
class="flex justify-between gap-x-6 py-5"
>
<div class="flex min-w-0 items-center gap-x-4">
<VbenIcon
:icon="item.avatar"
alt=""
class="size-10 flex-none rounded-full"
/>
<div class="min-w-0 flex-auto">
<p class="text-foreground text-sm font-semibold leading-6">
{{ item.title }}
</p>
<!-- eslint-disable vue/no-v-html -->
<p
class="text-foreground/80 *:text-primary mt-1 truncate text-xs leading-5"
v-html="item.content"
></p>
</div>
</div>
<div class="hidden h-full shrink-0 sm:flex sm:flex-col sm:items-end">
<span class="text-foreground/80 mt-6 text-xs leading-6">
{{ item.date }}
</span>
</div>
</li>
</ul>
</CardContent>
</Card>
</template>

218
apps/vben5/packages/@abp/platform/src/components/workbench/index.vue

@ -0,0 +1,218 @@
<script setup lang="ts">
import type { WorkbenchTodoItem, WorkbenchTrendItem } from '@vben/common-ui';
import type { FavoriteMenu } from './types';
import { computed, defineAsyncComponent, onMounted, ref } from 'vue';
import { useVbenModal } from '@vben/common-ui';
import { useAppConfig } from '@vben/hooks';
import { $t } from '@vben/locales';
import { preferences } from '@vben/preferences';
import { useUserStore } from '@vben/stores';
import { formatToDateTime } from '@abp/core';
import {
NotificationReadState,
useMyNotifilersApi,
useNotificationSerializer,
} from '@abp/notifications';
import { Empty, message } from 'ant-design-vue';
import { useMyFavoriteMenusApi } from '../../api/useMyFavoriteMenusApi';
import WorkbenchHeader from './components/WorkbenchHeader.vue';
import WorkbenchQuickNav from './components/WorkbenchQuickNav.vue';
import WorkbenchTodo from './components/WorkbenchTodo.vue';
import WorkbenchTrends from './components/WorkbenchTrends.vue';
defineEmits<{
(event: 'navTo', menu: FavoriteMenu): void;
}>();
const userStore = useUserStore();
const { getMyNotifilersApi } = useMyNotifilersApi();
const { getListApi: getFavoriteMenusApi, deleteApi: deleteFavoriteMenuApi } =
useMyFavoriteMenusApi();
const { deserialize } = useNotificationSerializer();
const { uiFramework } = useAppConfig(import.meta.env, import.meta.env.PROD);
const defaultMenus: FavoriteMenu[] = [
{
id: '1',
color: '#1fdaca',
icon: 'ion:home-outline',
displayName: $t('workbench.content.favoriteMenu.home'),
path: '/',
isDefault: true,
},
{
id: '2',
color: '#bf0c2c',
icon: 'ion:grid-outline',
displayName: $t('workbench.content.favoriteMenu.dashboard'),
path: '/',
isDefault: true,
},
{
id: '3',
color: '#00d8ff',
icon: 'ant-design:notification-outlined',
displayName: $t('workbench.content.favoriteMenu.notifiers'),
path: '/manage/notifications/my-notifilers',
isDefault: true,
},
{
id: '4',
color: '#4daf1bc9',
icon: 'tdesign:user-setting',
displayName: $t('workbench.content.favoriteMenu.settings'),
path: '/account/my-settings',
isDefault: true,
},
{
id: '5',
color: '#3fb27f',
icon: 'hugeicons:profile-02',
displayName: $t('workbench.content.favoriteMenu.profile'),
path: '/account/profile',
isDefault: true,
},
];
const unReadNotifilerCount = ref(0);
const unReadNotifilers = ref<WorkbenchTrendItem[]>([]);
const favoriteMenus = ref<FavoriteMenu[]>([]);
const todoList = ref<WorkbenchTodoItem[]>([]);
const getFavoriteMenus = computed(() => {
return [...defaultMenus, ...favoriteMenus.value];
});
const getWelcomeTitle = computed(() => {
const now = new Date();
const hour = now.getHours();
if (hour < 12) {
return $t('workbench.header.welcome.morning', [
userStore.userInfo?.realName,
]);
}
if (hour < 14) {
return $t('workbench.header.welcome.atoon', [userStore.userInfo?.realName]);
}
if (hour < 17) {
return $t('workbench.header.welcome.afternoon', [
userStore.userInfo?.realName,
]);
}
if (hour < 24) {
return $t('workbench.header.welcome.evening', [
userStore.userInfo?.realName,
]);
}
return '';
});
const [WorkbenchQuickNavModal, quickNavModalApi] = useVbenModal({
connectedComponent: defineAsyncComponent(
() => import('./components/WorkbenchQuickNavModal.vue'),
),
});
async function onInit() {
await Promise.all([
onInitFavoriteMenus(),
onInitNotifiers(),
onInitTodoList(),
]);
}
async function onInitFavoriteMenus() {
const { items } = await getFavoriteMenusApi(uiFramework);
favoriteMenus.value = items.map((item) => {
return {
...item,
id: item.menuId,
isDefault: false,
};
});
}
async function onInitNotifiers() {
const { items, totalCount } = await getMyNotifilersApi({
maxResultCount: 10,
readState: NotificationReadState.UnRead,
});
unReadNotifilers.value = items.map((item) => {
const notifier = deserialize(item);
return {
avatar: '',
date: formatToDateTime(item.creationTime),
title: notifier.title,
content: notifier.message,
};
});
unReadNotifilerCount.value = totalCount;
}
async function onInitTodoList() {
// TODO:
todoList.value = [];
}
function onCreatingFavoriteMenu() {
quickNavModalApi.open();
}
async function onDeleteFavoriteMenu(menu: FavoriteMenu) {
await deleteFavoriteMenuApi(menu.id);
await onInitFavoriteMenus();
message.success($t('AbpUi.SuccessfullyDeleted'));
}
onMounted(onInit);
</script>
<template>
<div class="p-5">
<WorkbenchHeader
:avatar="userStore.userInfo?.avatar || preferences.app.defaultAvatar"
:text="userStore.userInfo?.realName"
:notifier-count="unReadNotifilerCount"
>
<template #title>
{{ getWelcomeTitle }}
</template>
<template #description> 今日晴20 - 32 </template>
</WorkbenchHeader>
<div class="mt-5 flex flex-col lg:flex-row">
<div class="mr-4 w-full lg:w-3/5">
<WorkbenchQuickNav
:items="getFavoriteMenus"
class="mt-5 lg:mt-0"
:title="$t('workbench.content.favoriteMenu.title')"
@add="onCreatingFavoriteMenu"
@delete="onDeleteFavoriteMenu"
@click="(menu: FavoriteMenu) => $emit('navTo', menu)"
/>
<WorkbenchTodo
:items="todoList"
class="mt-5"
:title="$t('workbench.content.todo.title')"
>
<template #empty>
<Empty />
</template>
</WorkbenchTodo>
</div>
<div class="w-full lg:w-2/5">
<WorkbenchTrends
:items="unReadNotifilers"
:title="$t('workbench.content.trends.title')"
>
<template #empty>
<Empty />
</template>
</WorkbenchTrends>
</div>
</div>
<WorkbenchQuickNavModal @change="onInitFavoriteMenus" />
</div>
</template>
<style scoped></style>

10
apps/vben5/packages/@abp/platform/src/components/workbench/types.ts

@ -0,0 +1,10 @@
interface FavoriteMenu {
color?: string;
displayName: string;
icon?: string;
id: string;
isDefault: boolean;
path?: string;
}
export type { FavoriteMenu };

1
apps/vben5/packages/@abp/platform/src/index.ts

@ -1,4 +1,5 @@
export * from './api';
export * from './components';
export * from './hooks';
export * from './locales';
export * from './types';

20
apps/vben5/packages/@abp/platform/src/locales/index.ts

@ -0,0 +1,20 @@
import type { SupportedLanguagesType } from '@vben/locales';
import { loadLocalesMapFromDir } from '@vben/locales';
const modules = import.meta.glob('./langs/**/*.json');
const localesMap = loadLocalesMapFromDir(
/\.\/langs\/([^/]+)\/(.*)\.json$/,
modules,
);
/**
*
* @param lang
* @returns
*/
export async function loadPaltformMessages(lang: SupportedLanguagesType) {
const locales = localesMap[lang]?.();
return locales;
}

37
apps/vben5/packages/@abp/platform/src/locales/langs/en-US/workbench.json

@ -0,0 +1,37 @@
{
"header": {
"welcome": {
"atoon": "Good afternoon, {0}, pay attention to rest oh~",
"afternoon": "Good afternoon, {0}, relax in time, can improve work efficiency~",
"evening": "Good evening, {0}. Still at work? The off work~",
"morning": "Good morning, {0}. Begin your day~"
},
"notifier": {
"title": "Notifier",
"count": "({0})"
}
},
"content": {
"favoriteMenu": {
"title": "Favorite Menus",
"home": "Home",
"dashboard": "Dashboard",
"profile": "Personal Profile",
"settings": "Personal Settings",
"notifiers": "Notifiers",
"manage": "Manage menu",
"create": "New menu",
"delete": "Delete Menu",
"select": "Select Menu",
"color": "Select Color",
"alias": "Alias Name",
"icon": "Icon"
},
"trends": {
"title": "Latest News"
},
"todo": {
"title": "Todo List"
}
}
}

37
apps/vben5/packages/@abp/platform/src/locales/langs/zh-CN/workbench.json

@ -0,0 +1,37 @@
{
"header": {
"welcome": {
"atoon": "中午好, {0}, 注意休息哦~",
"afternoon": "下午好, {0}, 适时放松,可以提高工作效率~",
"evening": "晚上好, {0}, 还在工作么?该下班了~",
"morning": "早安, {0}, 开始您一天的工作吧~"
},
"notifier": {
"title": "通知",
"count": "({0})"
}
},
"content": {
"favoriteMenu": {
"title": "常用",
"home": "首页",
"dashboard": "仪表盘",
"profile": "个人中心",
"settings": "个人设置",
"notifiers": "通知消息",
"manage": "管理菜单",
"create": "添加菜单",
"delete": "删除菜单",
"select": "选择菜单",
"color": "选择颜色",
"alias": "自定义别名",
"icon": "自定义图标"
},
"trends": {
"title": "最新消息"
},
"todo": {
"title": "待办事项"
}
}
}

34
apps/vben5/packages/@abp/platform/src/types/favorites.ts

@ -0,0 +1,34 @@
import type { AuditedEntityDto, IHasConcurrencyStamp } from '@abp/core';
interface UserFavoriteMenuDto extends AuditedEntityDto<string> {
aliasName?: string;
color?: string;
displayName: string;
framework: string;
icon?: string;
menuId: string;
name: string;
path?: string;
userId: string;
}
interface UserFavoriteMenuCreateOrUpdateDto {
aliasName?: string;
color?: string;
icon?: string;
menuId: string;
}
interface UserFavoriteMenuCreateDto extends UserFavoriteMenuCreateOrUpdateDto {
framework: string;
}
interface UserFavoriteMenuUpdateDto
extends IHasConcurrencyStamp,
UserFavoriteMenuCreateOrUpdateDto {}
export type {
UserFavoriteMenuCreateDto,
UserFavoriteMenuDto,
UserFavoriteMenuUpdateDto,
};

1
apps/vben5/packages/@abp/platform/src/types/index.ts

@ -1,4 +1,5 @@
export * from './dataDictionaries';
export * from './favorites';
export * from './layouts';
export * from './menus';
export * from './messages';

6
apps/vben5/packages/@abp/settings/src/components/settings/SettingForm.vue

@ -71,7 +71,7 @@ async function onSubmit() {
const input = toValue(settingsUpdateInput);
await props.submitApi(input);
emits('change', input);
message.success($t('AbpSettingManagement.SuccessfullySaved'));
message.success($t('AbpSettingManagement.SavedSuccessfully'));
} finally {
submiting.value = false;
}
@ -142,8 +142,8 @@ onMounted(onGet);
v-if="detail.slot"
:change="
detail.valueType === ValueType.Boolean
? onCheckChange(detail)
: onValueChange(detail)
? onCheckChange
: onValueChange
"
:detail="detail"
:name="detail.slot"

1
apps/vben5/packages/@abp/tasks/src/components/job-infos/JobInfoDrawer.vue

@ -94,6 +94,7 @@ const [Drawer, drawerApi] = useVbenDrawer({
if (isOpen) {
try {
formModel.value = {
args: {},
beginTime: formatToDate(new Date()),
isEnabled: true,
jobType: JobType.Once,

2
apps/vben5/packages/@abp/ui/src/components/vxe-table/use-vxe-grid.ts

@ -24,8 +24,8 @@ export function useVbenVxeGrid(options: VxeGridProps) {
return () => h(VxeGrid, { ...props, ...attrs, api: extendedApi }, slots);
},
{
inheritAttrs: false,
name: 'VbenVxeGrid',
inheritAttrs: false,
},
);
// Add reactivity support

2
apps/vben5/packages/@abp/ui/src/components/vxe-table/use-vxe-grid.vue

@ -249,7 +249,7 @@ async function init() {
const enableProxyConfig = options.value.proxyConfig?.enabled;
if (enableProxyConfig && autoLoad) {
props.api.grid.commitProxy?.(
'_init',
'initial',
formOptions.value ? ((await formApi.getValues()) ?? {}) : {},
);
// props.api.reload(formApi.form?.values ?? {});

2
apps/vben5/packages/effects/plugins/src/vxe-table/use-vxe-grid.vue

@ -300,7 +300,7 @@ async function init() {
const enableProxyConfig = options.value.proxyConfig?.enabled;
if (enableProxyConfig && autoLoad) {
props.api.grid.commitProxy?.(
'_init',
'initial',
formOptions.value ? ((await formApi.getValues()) ?? {}) : {},
);
// props.api.reload(formApi.form?.values ?? {});

5
apps/vben5/pnpm-workspace.yaml

@ -205,8 +205,9 @@ catalog:
vue-simple-uploader: ^1.0.3
vue-tippy: ^6.7.0
vue-tsc: 2.2.10
vxe-pc-ui: ^4.5.35
vxe-table: ^4.13.16
vue3-colorpicker: ^2.3.0
vxe-pc-ui: ^4.7.12
vxe-table: ^4.14.4
watermark-js-plus: ^1.6.0
zod: ^3.24.3
zod-defaults: ^0.1.3

3
aspnet-core/framework/auditing/LINGYUN.Abp.AspNetCore.Auditing/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

20
aspnet-core/framework/auditing/LINGYUN.Abp.AspNetCore.Auditing/LINGYUN.Abp.AspNetCore.Auditing.csproj

@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\..\configureawait.props" />
<Import Project="..\..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<AssemblyName>LINGYUN.Abp.AspNetCore.Auditing</AssemblyName>
<PackageId>LINGYUN.Abp.AspNetCore.Auditing</PackageId>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.AspNetCore" />
</ItemGroup>
</Project>

19
aspnet-core/framework/auditing/LINGYUN.Abp.AspNetCore.Auditing/LINGYUN/Abp/AspNetCore/Auditing/AbpAspNetCoreAuditingHeaderOptions.cs

@ -0,0 +1,19 @@
using System.Collections.Generic;
namespace LINGYUN.Abp.AspNetCore.Auditing;
public class AbpAspNetCoreAuditingHeaderOptions
{
/// <summary>
/// 是否在审计日志中记录Http请求头,默认: true
/// </summary>
public bool IsEnabled { get; set; }
/// <summary>
/// 要记录的Http请求头
/// </summary>
public IList<string> HttpHeaders { get; }
public AbpAspNetCoreAuditingHeaderOptions()
{
IsEnabled = true;
HttpHeaders = new List<string>();
}
}

17
aspnet-core/framework/auditing/LINGYUN.Abp.AspNetCore.Auditing/LINGYUN/Abp/AspNetCore/Auditing/AbpAspNetCoreAuditingModule.cs

@ -0,0 +1,17 @@
using Volo.Abp.AspNetCore;
using Volo.Abp.Auditing;
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.AspNetCore.Auditing;
[DependsOn(typeof(AbpAspNetCoreModule))]
public class AbpAspNetCoreAuditingModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpAuditingOptions>(options =>
{
options.Contributors.Add(new AspNetCoreRecordHeaderAuditLogContributor());
});
}
}

51
aspnet-core/framework/auditing/LINGYUN.Abp.AspNetCore.Auditing/LINGYUN/Abp/AspNetCore/Auditing/AspNetCoreRecordHeaderAuditLogContributor.cs

@ -0,0 +1,51 @@
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using System.Collections.Generic;
using System.Collections.Immutable;
using Volo.Abp.Auditing;
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.AspNetCore.Auditing;
public class AspNetCoreRecordHeaderAuditLogContributor : AuditLogContributor, ITransientDependency
{
private const string HttpHeaderRecordKey = "HttpHeaders";
public AspNetCoreRecordHeaderAuditLogContributor()
{
}
public override void PreContribute(AuditLogContributionContext context)
{
var options = context.ServiceProvider.GetRequiredService<IOptions<AbpAspNetCoreAuditingHeaderOptions>>();
if (!options.Value.IsEnabled)
{
return;
}
var httpContext = context.ServiceProvider.GetRequiredService<IHttpContextAccessor>().HttpContext;
if (httpContext == null)
{
return;
}
if (context.AuditInfo.HasProperty(HttpHeaderRecordKey))
{
return;
}
var headerRcords = new Dictionary<string, string>();
var httpHeaders = httpContext.Request.Headers.ToImmutableDictionary();
foreach (var headerKey in options.Value.HttpHeaders)
{
if (httpHeaders.TryGetValue(headerKey, out var headers))
{
headerRcords[headerKey] = headers.JoinAsString(";");
}
}
context.AuditInfo.SetProperty(HttpHeaderRecordKey, headerRcords);
}
}

19
aspnet-core/framework/auditing/LINGYUN.Abp.AspNetCore.Auditing/README.md

@ -0,0 +1,19 @@
# LINGYUN.Abp.AspNetCore.Auditing
审计日期扩展模块, 用于在审计日志中加入特定的Http请求头记录
## 模块引用
```csharp
[DependsOn(typeof(AbpAspNetCoreAuditingModule))]
public class YouProjectModule : AbpModule
{
// other
}
```
## 配置项
* AbpAspNetCoreAuditingHeaderOptions.IsEnabled 是否在审计日志中记录Http请求头,默认: true
* AbpAspNetCoreAuditingHeaderOptions.HttpHeaders 需要在审计日志中记录的Http请求头列表

2
aspnet-core/framework/common/LINGYUN.Abp.IP2Region/LINGYUN/Abp/IP2Region/AbpIP2RegionModule.cs

@ -29,7 +29,7 @@ public class AbpIP2RegionModule : AbpModule
Configure<AbpIPLocationResolveOptions>(options =>
{
options.IPLocationResolvers.Add(new IP2RegionIPLocationResolveContributorBase());
options.IPLocationResolvers.Add(new IP2RegionIPLocationResolveContributor());
});
}
}

2
aspnet-core/framework/common/LINGYUN.Abp.IP2Region/LINGYUN/Abp/IP2Region/IP2RegionIPLocationResolveContributorBase.cs → aspnet-core/framework/common/LINGYUN.Abp.IP2Region/LINGYUN/Abp/IP2Region/IP2RegionIPLocationResolveContributor.cs

@ -5,7 +5,7 @@ using System;
using System.Threading.Tasks;
namespace LINGYUN.Abp.IP2Region;
public class IP2RegionIPLocationResolveContributorBase : IPLocationResolveContributorBase
public class IP2RegionIPLocationResolveContributor : IPLocationResolveContributorBase
{
public const string ContributorName = "IP2Region";
public override string Name => ContributorName;

196
aspnet-core/framework/dynamic-queryable/LINGYUN.Linq.Dynamic.Queryable/System/Linq/Expressions/ObjectQueryableExtensions.cs

@ -41,38 +41,30 @@ public static class ObjectQueryableExtensions
// For example(MySql):
// ...Other (Field <> Value)
exp = Expression.NotEqual(
leftParamter,
Expression.Convert(Expression.Constant(paramter.Value), propertyType));
leftParamter,
GetValue(paramter, propertyType));
break;
case DynamicComparison.LessThan:
// For example(MySql):
// ...Other (Field < Value)
exp = Expression.LessThan(
leftParamter,
Expression.Convert(Expression.Constant(paramter.Value), propertyType));
exp = BuildLessThanExpression(paramter, leftParamter, propertyType);
break;
case DynamicComparison.LessThanOrEqual:
// For example(MySql):
// ...Other (Field <= Value)
exp = Expression.LessThanOrEqual(
leftParamter,
Expression.Convert(Expression.Constant(paramter.Value), propertyType));
exp = BuildLessThanOrEqualExpression(paramter, leftParamter, propertyType);
break;
case DynamicComparison.GreaterThan:
// For example(MySql):
// ...Other (Field > Value)
exp = Expression.GreaterThan(
leftParamter,
Expression.Convert(Expression.Constant(paramter.Value), propertyType));
exp = BuildGreaterThanExpression(paramter, leftParamter, propertyType);
break;
case DynamicComparison.GreaterThanOrEqual:
// For example(MySql):
// ...Other (Field >= Value)
exp = Expression.GreaterThanOrEqual(
leftParamter,
Expression.Convert(Expression.Constant(paramter.Value), propertyType));
exp = BuildGreaterThanOrEqualExpression(paramter, leftParamter, propertyType);
break;
case DynamicComparison.StartsWith:
// For example(MySql):
@ -80,7 +72,7 @@ public static class ObjectQueryableExtensions
exp = Expression.Call(
leftParamter,
typeof(string).GetMethod(nameof(String.StartsWith), new[] { typeof(string) }),
Expression.Convert(Expression.Constant(paramter.Value), propertyType));
GetValue(paramter, propertyType));
// TODO: 单元测试通过
// For example(MySql):
@ -106,7 +98,7 @@ public static class ObjectQueryableExtensions
Expression.Call(
leftParamter,
typeof(string).GetMethod(nameof(String.StartsWith), new[] { typeof(string) }),
Expression.Convert(Expression.Constant(paramter.Value), propertyType)));
GetValue(paramter, propertyType)));
// TODO: 单元测试通过
// For example(MySql):
@ -129,7 +121,7 @@ public static class ObjectQueryableExtensions
exp = Expression.Call(
leftParamter,
typeof(string).GetMethod(nameof(String.EndsWith), new[] { typeof(string) }),
Expression.Convert(Expression.Constant(paramter.Value), propertyType));
GetValue(paramter, propertyType));
// TODO: 单元测试通过
// For example(MySql):
@ -153,7 +145,7 @@ public static class ObjectQueryableExtensions
Expression.Call(
leftParamter,
typeof(string).GetMethod(nameof(String.EndsWith), new[] { typeof(string) }),
Expression.Convert(Expression.Constant(paramter.Value), propertyType)));
GetValue(paramter, propertyType)));
// TODO: 单元测试通过
// For example(MySql):
@ -176,7 +168,7 @@ public static class ObjectQueryableExtensions
exp = Expression.Call(
leftParamter,
typeof(string).GetMethod(nameof(String.Contains), new[] { typeof(string) }),
Expression.Convert(Expression.Constant(paramter.Value), propertyType));
GetValue(paramter, propertyType));
// TODO: 单元测试通过
// For example(MySql):
@ -200,7 +192,7 @@ public static class ObjectQueryableExtensions
Expression.Call(
leftParamter,
typeof(string).GetMethod(nameof(String.Contains), new[] { typeof(string) }),
Expression.Convert(Expression.Constant(paramter.Value), propertyType)));
GetValue(paramter, propertyType)));
// TODO: 单元测试通过
// For example(MySql):
// ...Other ((Field IS NULL) OR (Field NOT LIKE '%Value%'))
@ -223,16 +215,14 @@ public static class ObjectQueryableExtensions
// 非空字段设定为比对默认值
exp = Expression.Equal(leftParamter,
Expression.Convert(
Expression.Constant(GetDefaultValue(propertyType)), propertyType));
Expression.Constant(GetDefaultValue(propertyType)));
break;
case DynamicComparison.NotNull:
// For example(MySql):
// ...Other (Field IS NOT NULL)
exp = Expression.NotEqual(leftParamter,
Expression.Convert(
Expression.Constant(GetDefaultValue(propertyType)), propertyType));
Expression.Constant(GetDefaultValue(propertyType)));
break;
default:
case DynamicComparison.Equal:
@ -240,8 +230,8 @@ public static class ObjectQueryableExtensions
// ...Other (Field = Value)
exp = Expression.Equal(
leftParamter,
Expression.Convert(Expression.Constant(paramter.Value), propertyType));
leftParamter,
GetValue(paramter, propertyType));
break;
}
expressions.Push(exp);
@ -267,6 +257,160 @@ public static class ObjectQueryableExtensions
return Expression.Lambda<T>(expressions.Pop(), condition.Parameters.ToArray());
}
private static Expression BuildLessThanExpression(DynamicParamter paramter, MemberExpression member, Type propertyType)
{
if (propertyType == typeof(string))
{
// 字符串比较: Field < Value
return Expression.LessThan(
Expression.Call(
member,
typeof(string).GetMethod("CompareTo", new[] { typeof(string) }),
Expression.Constant(Convert.ToString(paramter.Value))),
Expression.Constant(0));
}
if (propertyType.IsNullableType())
{
// 可空类型比较: Field < Value
var underlyingType = Nullable.GetUnderlyingType(propertyType);
var hasValue = Expression.Property(member, "HasValue");
var value = Expression.Property(member, "Value");
return Expression.AndAlso(
hasValue,
Expression.LessThan(
value,
GetValue(paramter, underlyingType)));
}
else
{
// 数值比较: Field < Value
return Expression.LessThan(
member,
GetValue(paramter, propertyType));
}
}
private static Expression BuildLessThanOrEqualExpression(DynamicParamter paramter, MemberExpression member, Type propertyType)
{
if (propertyType == typeof(string))
{
// 字符串比较: Field <= Value
return Expression.LessThanOrEqual(
Expression.Call(
member,
typeof(string).GetMethod("CompareTo", new[] { typeof(string) }),
Expression.Constant(Convert.ToString(paramter.Value))),
Expression.Constant(0));
}
if (propertyType.IsNullableType())
{
// 可空类型比较: Field <= Value
var underlyingType = Nullable.GetUnderlyingType(propertyType);
var hasValue = Expression.Property(member, "HasValue");
var value = Expression.Property(member, "Value");
return Expression.AndAlso(
hasValue,
Expression.LessThanOrEqual(
value,
GetValue(paramter, underlyingType)));
}
else
{
// 数值比较: Field <= Value
return Expression.LessThanOrEqual(
member,
GetValue(paramter, propertyType));
}
}
private static Expression BuildGreaterThanExpression(DynamicParamter paramter, MemberExpression member, Type propertyType)
{
if (propertyType == typeof(string))
{
// 字符串比较: Field > Value
return Expression.GreaterThan(
Expression.Call(
member,
typeof(string).GetMethod("CompareTo", new[] { typeof(string) }),
Expression.Constant(Convert.ToString(paramter.Value))),
Expression.Constant(0));
}
if (propertyType.IsNullableType())
{
// 可空类型比较: Field > Value
var underlyingType = Nullable.GetUnderlyingType(propertyType);
var hasValue = Expression.Property(member, "HasValue");
var value = Expression.Property(member, "Value");
return Expression.AndAlso(
hasValue,
Expression.GreaterThan(
value,
GetValue(paramter, underlyingType)));
}
else
{
// 数值比较: Field > Value
return Expression.GreaterThan(
member,
GetValue(paramter, propertyType));
}
}
private static Expression BuildGreaterThanOrEqualExpression(DynamicParamter paramter, MemberExpression member, Type propertyType)
{
if (propertyType == typeof(string))
{
// 字符串比较: Field >= Value
return Expression.GreaterThanOrEqual(
Expression.Call(
member,
typeof(string).GetMethod("CompareTo", new[] { typeof(string) }),
Expression.Constant(Convert.ToString(paramter.Value))),
Expression.Constant(0));
}
if (propertyType.IsNullableType())
{
// 可空类型比较: Field >= Value
var underlyingType = Nullable.GetUnderlyingType(propertyType);
var hasValue = Expression.Property(member, "HasValue");
var value = Expression.Property(member, "Value");
return Expression.AndAlso(
hasValue,
Expression.GreaterThanOrEqual(
value,
GetValue(paramter, underlyingType)));
}
else
{
// 数值比较: Field >= Value
return Expression.GreaterThanOrEqual(
member,
GetValue(paramter, propertyType));
}
}
private static ConstantExpression GetValue(DynamicParamter paramter, Type propertyType)
{
object typedValue;
if (propertyType.IsNullableType())
{
propertyType = Nullable.GetUnderlyingType(propertyType);
}
typedValue = Convert.ChangeType(paramter.Value, propertyType);
return Expression.Constant(typedValue, propertyType);
}
private static object GetDefaultValue(Type type)
{
// TODO: 非空字段此处返回默认值

6
aspnet-core/modules/account/LINGYUN.Abp.Account.Application/LINGYUN/Abp/Account/MyProfileAppService.cs

@ -75,12 +75,12 @@ public class MyProfileAppService : AccountApplicationServiceBase, IMyProfileAppS
public async virtual Task<PagedResultDto<IdentitySessionDto>> GetSessionsAsync(GetMySessionsInput input)
{
var user = await GetCurrentUserAsync();
var userId = CurrentUser.GetId();
var totalCount = await IdentitySessionRepository.GetCountAsync(
user.Id, input.Device, input.ClientId);
userId, input.Device, input.ClientId);
var identitySessions = await IdentitySessionRepository.GetListAsync(
input.Sorting, input.MaxResultCount, input.SkipCount,
user.Id, input.Device, input.ClientId);
userId, input.Device, input.ClientId);
return new PagedResultDto<IdentitySessionDto>(totalCount,
identitySessions.Select(session => new IdentitySessionDto

2
aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain/LINGYUN/Abp/Identity/AbpIdentityDomainModule.cs

@ -5,6 +5,7 @@ using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.AutoMapper;
using Volo.Abp.BackgroundWorkers;
using Volo.Abp.DistributedLocking;
using Volo.Abp.Domain.Entities.Events.Distributed;
using Volo.Abp.Identity;
using Volo.Abp.Modularity;
@ -14,6 +15,7 @@ namespace LINGYUN.Abp.Identity;
[DependsOn(
typeof(AbpIdentityDomainSharedModule),
typeof(AbpDistributedLockingAbstractionsModule),
typeof(Volo.Abp.Identity.AbpIdentityDomainModule))]
public class AbpIdentityDomainModule : AbpModule
{

71
aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain/LINGYUN/Abp/Identity/Session/IdentitySessionCacheItemSynchronizer.cs

@ -4,6 +4,7 @@ using Microsoft.Extensions.Logging.Abstractions;
using System;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.DistributedLocking;
using Volo.Abp.Domain.Entities.Events;
using Volo.Abp.Domain.Entities.Events.Distributed;
using Volo.Abp.EventBus;
@ -22,15 +23,18 @@ public class IdentitySessionCacheItemSynchronizer :
{
public ILogger<IdentitySessionCacheItemSynchronizer> Logger { protected get; set; }
protected ISettingProvider SettingProvider { get; }
protected IAbpDistributedLock DistributedLock { get; }
protected IIdentitySessionCache IdentitySessionCache { get; }
protected IIdentitySessionStore IdentitySessionStore { get; }
public IdentitySessionCacheItemSynchronizer(
ISettingProvider settingProvider,
IAbpDistributedLock distributedLock,
IIdentitySessionCache identitySessionCache,
IIdentitySessionStore identitySessionStore)
{
SettingProvider = settingProvider;
DistributedLock = distributedLock;
IdentitySessionCache = identitySessionCache;
IdentitySessionStore = identitySessionStore;
@ -45,34 +49,71 @@ public class IdentitySessionCacheItemSynchronizer :
[UnitOfWork]
public async virtual Task HandleEventAsync(EntityCreatedEto<IdentitySessionEto> eventData)
{
await RefreshSessionCache(eventData.Entity);
await CheckConcurrentLoginStrategy(eventData.Entity);
var lockKey = $"{nameof(IdentitySessionCacheItemSynchronizer)}_{nameof(EntityCreatedEto<IdentitySessionEto>)}";
await using (var handle = await DistributedLock.TryAcquireAsync(lockKey))
{
Logger.LogInformation($"Lock is acquired for {lockKey}");
if (handle == null)
{
Logger.LogInformation($"Handle is null because of the locking for : {lockKey}");
return;
}
await RefreshSessionCache(eventData.Entity);
await CheckConcurrentLoginStrategy(eventData.Entity);
}
}
[UnitOfWork]
public async virtual Task HandleEventAsync(IdentitySessionChangeAccessedEvent eventData)
{
var idetitySession = await IdentitySessionStore.FindAsync(eventData.SessionId);
if (idetitySession != null)
var lockKey = $"{nameof(IdentitySessionCacheItemSynchronizer)}_{nameof(IdentitySessionChangeAccessedEvent)}";
await using (var handle = await DistributedLock.TryAcquireAsync(lockKey))
{
if (!eventData.IpAddresses.IsNullOrWhiteSpace())
Logger.LogInformation($"Lock is acquired for {lockKey}");
if (handle == null)
{
idetitySession.SetIpAddresses(eventData.IpAddresses.Split(","));
Logger.LogInformation($"Handle is null because of the locking for : {lockKey}");
return;
}
idetitySession.UpdateLastAccessedTime(eventData.LastAccessed);
await IdentitySessionStore.UpdateAsync(idetitySession);
}
else
{
// 数据库中不存在会话, 清理缓存, 后续请求会话失效
await IdentitySessionCache.RemoveAsync(eventData.SessionId);
var idetitySession = await IdentitySessionStore.FindAsync(eventData.SessionId);
if (idetitySession != null)
{
if (!eventData.IpAddresses.IsNullOrWhiteSpace())
{
idetitySession.SetIpAddresses(eventData.IpAddresses.Split(","));
}
idetitySession.UpdateLastAccessedTime(eventData.LastAccessed);
await IdentitySessionStore.UpdateAsync(idetitySession);
}
else
{
// 数据库中不存在会话, 清理缓存, 后续请求会话失效
await IdentitySessionCache.RemoveAsync(eventData.SessionId);
}
}
}
public async virtual Task HandleEventAsync(EntityDeletedEventData<IdentityUser> eventData)
{
// 用户被删除, 移除所有会话
await IdentitySessionStore.RevokeAllAsync(eventData.Entity.Id);
var lockKey = $"{nameof(IdentitySessionCacheItemSynchronizer)}_{nameof(EntityDeletedEventData<IdentityUser>)}";
await using (var handle = await DistributedLock.TryAcquireAsync(lockKey))
{
Logger.LogInformation($"Lock is acquired for {lockKey}");
if (handle == null)
{
Logger.LogInformation($"Handle is null because of the locking for : {lockKey}");
return;
}
// 用户被删除, 移除所有会话
await IdentitySessionStore.RevokeAllAsync(eventData.Entity.Id);
}
}
protected async virtual Task RefreshSessionCache(IdentitySessionEto session)

28
aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain/LINGYUN/Abp/Identity/Session/IdentitySessionCleanupBackgroundWorker.cs

@ -1,20 +1,25 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System.Threading.Tasks;
using Volo.Abp.BackgroundWorkers;
using Volo.Abp.DistributedLocking;
using Volo.Abp.Threading;
namespace LINGYUN.Abp.Identity.Session;
public class IdentitySessionCleanupBackgroundWorker : AsyncPeriodicBackgroundWorkerBase
{
protected IAbpDistributedLock DistributedLock { get; }
protected IdentitySessionCleanupOptions Options { get; }
public IdentitySessionCleanupBackgroundWorker(
AbpAsyncTimer timer,
IServiceScopeFactory serviceScopeFactory,
IOptions<IdentitySessionCleanupOptions> options)
IOptions<IdentitySessionCleanupOptions> options,
IAbpDistributedLock distributedLock)
: base(timer, serviceScopeFactory)
{
DistributedLock = distributedLock;
Options = options.Value;
timer.Period = Options.CleanupPeriod;
}
@ -26,9 +31,22 @@ public class IdentitySessionCleanupBackgroundWorker : AsyncPeriodicBackgroundWor
return;
}
await workerContext
.ServiceProvider
.GetRequiredService<IdentitySessionCleanupService>()
.CleanAsync();
await using (var handle = await DistributedLock.TryAcquireAsync(nameof(IdentitySessionCleanupBackgroundWorker)))
{
Logger.LogInformation($"Lock is acquired for {nameof(IdentitySessionCleanupBackgroundWorker)}");
if (handle != null)
{
await workerContext
.ServiceProvider
.GetRequiredService<IdentitySessionCleanupService>()
.CleanAsync();
Logger.LogInformation($"Lock is released for {nameof(IdentitySessionCleanupBackgroundWorker)}");
return;
}
Logger.LogInformation($"Handle is null because of the locking for : {nameof(IdentitySessionCleanupBackgroundWorker)}");
}
}
}

1
aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/LocalizationTextStoreCache.cs

@ -76,6 +76,7 @@ public class LocalizationTextStoreCache : ILocalizationTextStoreCache, ISingleto
protected async virtual Task<LocalizationTextCacheItem> GetCacheItemAsync(LocalizationResourceBase resource, string cultureName)
{
// 异步本地化函数不受影响
var cacheKey = LocalizationTextCacheItem.CalculateCacheKey(resource.ResourceName, cultureName);
var cacheItem = await LocalizationTextCache.GetAsync(cacheKey);
if (cacheItem != null)

19
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application.Contracts/LINGYUN/Abp/OssManagement/IFileAppService.cs

@ -1,19 +0,0 @@
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Content;
namespace LINGYUN.Abp.OssManagement;
public interface IFileAppService : IApplicationService
{
Task<OssObjectDto> UploadAsync(UploadFileInput input);
Task<IRemoteStreamContent> GetAsync(GetPublicFileInput input);
Task<ListResultDto<OssObjectDto>> GetListAsync(GetFilesInput input);
Task UploadChunkAsync(UploadFileChunkInput input);
Task DeleteAsync(GetPublicFileInput input);
}

14
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application.Contracts/LINGYUN/Abp/OssManagement/IPrivateFileAppService.cs

@ -1,10 +1,22 @@
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Content;
namespace LINGYUN.Abp.OssManagement;
public interface IPrivateFileAppService : IFileAppService
public interface IPrivateFileAppService : IApplicationService
{
Task<OssObjectDto> UploadAsync(UploadFileInput input);
Task<IRemoteStreamContent> GetAsync(GetPublicFileInput input);
Task<ListResultDto<OssObjectDto>> GetListAsync(GetFilesInput input);
Task UploadChunkAsync(UploadFileChunkInput input);
Task DeleteAsync(GetPublicFileInput input);
Task<FileShareDto> ShareAsync(FileShareInput input);
Task<ListResultDto<MyFileShareDto>> GetShareListAsync();

18
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application.Contracts/LINGYUN/Abp/OssManagement/IPublicFileAppService.cs

@ -1,5 +1,19 @@
namespace LINGYUN.Abp.OssManagement;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Content;
public interface IPublicFileAppService : IFileAppService
namespace LINGYUN.Abp.OssManagement;
public interface IPublicFileAppService : IApplicationService
{
Task<OssObjectDto> UploadAsync(UploadFileInput input);
Task<IRemoteStreamContent> GetAsync(GetPublicFileInput input);
Task<ListResultDto<OssObjectDto>> GetListAsync(GetFilesInput input);
Task UploadChunkAsync(UploadFileChunkInput input);
Task DeleteAsync(GetPublicFileInput input);
}

2
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN/Abp/OssManagement/FileAppServiceBase.cs

@ -14,7 +14,7 @@ using Volo.Abp.Validation;
namespace LINGYUN.Abp.OssManagement;
public abstract class FileAppServiceBase : OssManagementApplicationServiceBase, IFileAppService
public abstract class FileAppServiceBase : OssManagementApplicationServiceBase
{
protected IFileUploader FileUploader { get; }
protected IFileValidater FileValidater { get; }

4
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi.Client/ClientProxies/LINGYUN/Abp/OssManagement/PrivateFilesClientProxy.Generated.cs

@ -15,8 +15,8 @@ using Volo.Abp.Http.Modeling;
namespace LINGYUN.Abp.OssManagement;
[Dependency(ReplaceServices = true)]
[ExposeServices(typeof(IFileAppService), typeof(PrivateFilesClientProxy))]
public partial class PrivateFilesClientProxy : ClientProxyBase<IFileAppService>, IFileAppService
[ExposeServices(typeof(IPrivateFileAppService), typeof(PrivateFilesClientProxy))]
public partial class PrivateFilesClientProxy : ClientProxyBase<IPrivateFileAppService>, IPrivateFileAppService
{
public virtual async Task<OssObjectDto> UploadAsync(UploadFileInput input)
{

4
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi.Client/ClientProxies/LINGYUN/Abp/OssManagement/PublicFilesClientProxy.Generated.cs

@ -15,8 +15,8 @@ using Volo.Abp.Http.Modeling;
namespace LINGYUN.Abp.OssManagement;
[Dependency(ReplaceServices = true)]
[ExposeServices(typeof(IFileAppService), typeof(PublicFilesClientProxy))]
public partial class PublicFilesClientProxy : ClientProxyBase<IFileAppService>, IFileAppService
[ExposeServices(typeof(IPublicFileAppService), typeof(PublicFilesClientProxy))]
public partial class PublicFilesClientProxy : ClientProxyBase<IPublicFileAppService>, IPublicFileAppService
{
public virtual async Task<OssObjectDto> UploadAsync(UploadFileInput input)
{

182
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi.Client/ClientProxies/oss-management-generate-proxy.json

@ -1694,97 +1694,6 @@
}
}
]
},
{
"type": "LINGYUN.Abp.OssManagement.IFileAppService",
"name": "IFileAppService",
"methods": [
{
"name": "UploadAsync",
"parametersOnMethod": [
{
"name": "input",
"typeAsString": "LINGYUN.Abp.OssManagement.UploadFileInput, LINGYUN.Abp.OssManagement.Application.Contracts",
"type": "LINGYUN.Abp.OssManagement.UploadFileInput",
"typeSimple": "LINGYUN.Abp.OssManagement.UploadFileInput",
"isOptional": false,
"defaultValue": null
}
],
"returnValue": {
"type": "LINGYUN.Abp.OssManagement.OssObjectDto",
"typeSimple": "LINGYUN.Abp.OssManagement.OssObjectDto"
}
},
{
"name": "GetAsync",
"parametersOnMethod": [
{
"name": "input",
"typeAsString": "LINGYUN.Abp.OssManagement.GetPublicFileInput, LINGYUN.Abp.OssManagement.Application.Contracts",
"type": "LINGYUN.Abp.OssManagement.GetPublicFileInput",
"typeSimple": "LINGYUN.Abp.OssManagement.GetPublicFileInput",
"isOptional": false,
"defaultValue": null
}
],
"returnValue": {
"type": "Volo.Abp.Content.IRemoteStreamContent",
"typeSimple": "Volo.Abp.Content.IRemoteStreamContent"
}
},
{
"name": "GetListAsync",
"parametersOnMethod": [
{
"name": "input",
"typeAsString": "LINGYUN.Abp.OssManagement.GetFilesInput, LINGYUN.Abp.OssManagement.Application.Contracts",
"type": "LINGYUN.Abp.OssManagement.GetFilesInput",
"typeSimple": "LINGYUN.Abp.OssManagement.GetFilesInput",
"isOptional": false,
"defaultValue": null
}
],
"returnValue": {
"type": "Volo.Abp.Application.Dtos.ListResultDto<LINGYUN.Abp.OssManagement.OssObjectDto>",
"typeSimple": "Volo.Abp.Application.Dtos.ListResultDto<LINGYUN.Abp.OssManagement.OssObjectDto>"
}
},
{
"name": "UploadChunkAsync",
"parametersOnMethod": [
{
"name": "input",
"typeAsString": "LINGYUN.Abp.OssManagement.UploadFileChunkInput, LINGYUN.Abp.OssManagement.Application.Contracts",
"type": "LINGYUN.Abp.OssManagement.UploadFileChunkInput",
"typeSimple": "LINGYUN.Abp.OssManagement.UploadFileChunkInput",
"isOptional": false,
"defaultValue": null
}
],
"returnValue": {
"type": "System.Void",
"typeSimple": "System.Void"
}
},
{
"name": "DeleteAsync",
"parametersOnMethod": [
{
"name": "input",
"typeAsString": "LINGYUN.Abp.OssManagement.GetPublicFileInput, LINGYUN.Abp.OssManagement.Application.Contracts",
"type": "LINGYUN.Abp.OssManagement.GetPublicFileInput",
"typeSimple": "LINGYUN.Abp.OssManagement.GetPublicFileInput",
"isOptional": false,
"defaultValue": null
}
],
"returnValue": {
"type": "System.Void",
"typeSimple": "System.Void"
}
}
]
}
],
"actions": {
@ -2317,97 +2226,6 @@
}
}
]
},
{
"type": "LINGYUN.Abp.OssManagement.IFileAppService",
"name": "IFileAppService",
"methods": [
{
"name": "UploadAsync",
"parametersOnMethod": [
{
"name": "input",
"typeAsString": "LINGYUN.Abp.OssManagement.UploadFileInput, LINGYUN.Abp.OssManagement.Application.Contracts",
"type": "LINGYUN.Abp.OssManagement.UploadFileInput",
"typeSimple": "LINGYUN.Abp.OssManagement.UploadFileInput",
"isOptional": false,
"defaultValue": null
}
],
"returnValue": {
"type": "LINGYUN.Abp.OssManagement.OssObjectDto",
"typeSimple": "LINGYUN.Abp.OssManagement.OssObjectDto"
}
},
{
"name": "GetAsync",
"parametersOnMethod": [
{
"name": "input",
"typeAsString": "LINGYUN.Abp.OssManagement.GetPublicFileInput, LINGYUN.Abp.OssManagement.Application.Contracts",
"type": "LINGYUN.Abp.OssManagement.GetPublicFileInput",
"typeSimple": "LINGYUN.Abp.OssManagement.GetPublicFileInput",
"isOptional": false,
"defaultValue": null
}
],
"returnValue": {
"type": "Volo.Abp.Content.IRemoteStreamContent",
"typeSimple": "Volo.Abp.Content.IRemoteStreamContent"
}
},
{
"name": "GetListAsync",
"parametersOnMethod": [
{
"name": "input",
"typeAsString": "LINGYUN.Abp.OssManagement.GetFilesInput, LINGYUN.Abp.OssManagement.Application.Contracts",
"type": "LINGYUN.Abp.OssManagement.GetFilesInput",
"typeSimple": "LINGYUN.Abp.OssManagement.GetFilesInput",
"isOptional": false,
"defaultValue": null
}
],
"returnValue": {
"type": "Volo.Abp.Application.Dtos.ListResultDto<LINGYUN.Abp.OssManagement.OssObjectDto>",
"typeSimple": "Volo.Abp.Application.Dtos.ListResultDto<LINGYUN.Abp.OssManagement.OssObjectDto>"
}
},
{
"name": "UploadChunkAsync",
"parametersOnMethod": [
{
"name": "input",
"typeAsString": "LINGYUN.Abp.OssManagement.UploadFileChunkInput, LINGYUN.Abp.OssManagement.Application.Contracts",
"type": "LINGYUN.Abp.OssManagement.UploadFileChunkInput",
"typeSimple": "LINGYUN.Abp.OssManagement.UploadFileChunkInput",
"isOptional": false,
"defaultValue": null
}
],
"returnValue": {
"type": "System.Void",
"typeSimple": "System.Void"
}
},
{
"name": "DeleteAsync",
"parametersOnMethod": [
{
"name": "input",
"typeAsString": "LINGYUN.Abp.OssManagement.GetPublicFileInput, LINGYUN.Abp.OssManagement.Application.Contracts",
"type": "LINGYUN.Abp.OssManagement.GetPublicFileInput",
"typeSimple": "LINGYUN.Abp.OssManagement.GetPublicFileInput",
"isOptional": false,
"defaultValue": null
}
],
"returnValue": {
"type": "System.Void",
"typeSimple": "System.Void"
}
}
]
}
],
"actions": {

2
aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.Templating/LINGYUN.Abp.Notifications.Templating.csproj

@ -4,7 +4,7 @@
<Import Project="..\..\..\..\common.props" />
<PropertyGroup>
<TargetFrameworks>netstandard2.0;netstandard2.1;net8.0</TargetFrameworks>
<TargetFrameworks>netstandard2.0;netstandard2.1;net8.0;net9.0</TargetFrameworks>
<AssemblyName>LINGYUN.Abp.Notifications.Templating</AssemblyName>
<PackageId>LINGYUN.Abp.Notifications.Templating</PackageId>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>

5
aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Domain/LINGYUN/Abp/TaskManagement/BackgroundJobInfo.cs

@ -146,7 +146,10 @@ public class BackgroundJobInfo : AuditedAggregateRoot<string>, IMultiTenant
// TODO: 是否需要将参数挪到另一个实体?
// 任务参数的建议是尽量最小化, 仅存储关键信息
Args = new ExtraPropertyDictionary();
Args.AddIfNotContains(args);
if (args != null)
{
Args.AddIfNotContains(args);
}
}
public void SetPeriodJob(string cron)

3
aspnet-core/services/.gitignore

@ -1,3 +1,4 @@
Modules
file-blob-storing
blobs
blobs
yarn.lock

6
aspnet-core/services/LY.MicroService.Applications.Single/package.json

@ -1,9 +1,9 @@
{
"version": "9.2.0",
"version": "9.2.3",
"name": "my-app-single",
"private": true,
"dependencies": {
"@abp/aspnetcore.mvc.ui.theme.leptonxlite": "4.2.0",
"@abp/qrcode": "9.2.0"
"@abp/aspnetcore.mvc.ui.theme.leptonxlite": "4.2.3",
"@abp/qrcode": "9.2.3"
}
}

31
aspnet-core/services/LY.MicroService.AuthServer/AuthServerModule.Configure.cs

@ -29,6 +29,8 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.IdentityModel.Logging;
using Microsoft.IdentityModel.Tokens;
using OpenIddict.Server;
using OpenIddict.Server.AspNetCore;
using OpenIddict.Validation.AspNetCore;
using StackExchange.Redis;
using System;
@ -111,7 +113,7 @@ public partial class AuthServerModule
});
}
private void PreConfigureAuth()
private void PreConfigureAuthServer()
{
PreConfigure<OpenIddictBuilder>(builder =>
{
@ -139,7 +141,7 @@ public partial class AuthServerModule
PreConfigure<OpenIddictServerBuilder>(builder =>
{
builder.AddProductionEncryptionAndSigningCertificate("openiddict.pfx", "e1c48393-0c43-11f0-9582-4aecacda42db");
builder.AddProductionEncryptionAndSigningCertificate(configuration["App:SslFile"], configuration["App:SslPassword"]);
});
}
@ -367,6 +369,31 @@ public partial class AuthServerModule
}
});
}
private void ConfigureAuthServer(IConfiguration configuration)
{
Configure<OpenIddictServerAspNetCoreBuilder>(builder =>
{
builder.DisableTransportSecurityRequirement();
});
Configure<OpenIddictServerAspNetCoreOptions>(options =>
{
options.DisableTransportSecurityRequirement = true;
});
Configure<OpenIddictServerOptions>(options =>
{
var lifetime = configuration.GetSection("OpenIddict:Lifetime");
options.AuthorizationCodeLifetime = lifetime.GetValue("AuthorizationCode", options.AuthorizationCodeLifetime);
options.AccessTokenLifetime = lifetime.GetValue("AccessToken", options.AccessTokenLifetime);
options.DeviceCodeLifetime = lifetime.GetValue("DeviceCode", options.DeviceCodeLifetime);
options.IdentityTokenLifetime = lifetime.GetValue("IdentityToken", options.IdentityTokenLifetime);
options.RefreshTokenLifetime = lifetime.GetValue("RefreshToken", options.RefreshTokenLifetime);
options.RefreshTokenReuseLeeway = lifetime.GetValue("RefreshTokenReuseLeeway", options.RefreshTokenReuseLeeway);
options.UserCodeLifetime = lifetime.GetValue("UserCode", options.UserCodeLifetime);
});
}
private void ConfigureSecurity(IServiceCollection services, IConfiguration configuration, bool isDevelopment = false)
{
services.ForwardIdentityAuthenticationForBearer(OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme);

3
aspnet-core/services/LY.MicroService.AuthServer/AuthServerModule.cs

@ -84,10 +84,10 @@ public partial class AuthServerModule : AbpModule
var configuration = context.Services.GetConfiguration();
var hostingEnvironment = context.Services.GetHostingEnvironment();
PreConfigureAuth();
PreConfigureWrapper();
PreConfigureFeature();
PreForwardedHeaders();
PreConfigureAuthServer();
PreConfigureApp(configuration);
PreConfigureCAP(configuration);
PreConfigureCertificate(configuration, hostingEnvironment);
@ -110,6 +110,7 @@ public partial class AuthServerModule : AbpModule
ConfigureUrls(configuration);
ConfigureTiming(configuration);
ConfigureAuditing(configuration);
ConfigureAuthServer(configuration);
ConfigureMultiTenancy(configuration);
ConfigureJsonSerializer(configuration);
ConfigureMvc(context.Services, configuration);

4
aspnet-core/services/LY.MicroService.AuthServer/appsettings.json

@ -2,7 +2,9 @@
"App": {
"Branding": {
"AppName": "Auth Server"
}
},
"SslFile": "openiddict.pfx",
"SslPassword": "e1c48393-0c43-11f0-9582-4aecacda42db"
},
"Clock": {
"Kind": "Local"

6
aspnet-core/services/LY.MicroService.AuthServer/package.json

@ -1,9 +1,9 @@
{
"version": "9.2.0",
"version": "9.2.3",
"name": "my-app-authserver",
"private": true,
"dependencies": {
"@abp/aspnetcore.mvc.ui.theme.leptonxlite": "4.2.0",
"@abp/qrcode": "9.2.0"
"@abp/aspnetcore.mvc.ui.theme.leptonxlite": "4.2.3",
"@abp/qrcode": "9.2.3"
}
}

2
aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/bootstrap/css/bootstrap.css

@ -1,6 +1,6 @@
@charset "UTF-8";
/*!
* Bootstrap v5.3.6 (https://getbootstrap.com/)
* Bootstrap v5.3.7 (https://getbootstrap.com/)
* Copyright 2011-2025 The Bootstrap Authors
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/

2
aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/bootstrap/css/bootstrap.css.map

File diff suppressed because one or more lines are too long

2
aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/bootstrap/css/bootstrap.min.css

File diff suppressed because one or more lines are too long

2
aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/bootstrap/css/bootstrap.min.css.map

File diff suppressed because one or more lines are too long

2
aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/bootstrap/css/bootstrap.rtl.css

@ -1,6 +1,6 @@
@charset "UTF-8";
/*!
* Bootstrap v5.3.6 (https://getbootstrap.com/)
* Bootstrap v5.3.7 (https://getbootstrap.com/)
* Copyright 2011-2025 The Bootstrap Authors
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/

2
aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/bootstrap/css/bootstrap.rtl.css.map

File diff suppressed because one or more lines are too long

2
aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/bootstrap/css/bootstrap.rtl.min.css

File diff suppressed because one or more lines are too long

2
aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/bootstrap/css/bootstrap.rtl.min.css.map

File diff suppressed because one or more lines are too long

6
aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/bootstrap/js/bootstrap.bundle.js

@ -1,5 +1,5 @@
/*!
* Bootstrap v5.3.6 (https://getbootstrap.com/)
* Bootstrap v5.3.7 (https://getbootstrap.com/)
* Copyright 2011-2025 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
@ -647,7 +647,7 @@
* Constants
*/
const VERSION = '5.3.6';
const VERSION = '5.3.7';
/**
* Class definition
@ -4805,7 +4805,6 @@
*
* Shout-out to Angular https://github.com/angular/angular/blob/15.2.8/packages/core/src/sanitization/url_sanitizer.ts#L38
*/
// eslint-disable-next-line unicorn/better-regex
const SAFE_URL_PATTERN = /^(?!javascript:)(?:[a-z0-9+.-]+:|[^&:/?#]*(?:[/?#]|$))/i;
const allowedAttribute = (attribute, allowedAttributeList) => {
const attributeName = attribute.nodeName.toLowerCase();
@ -5349,6 +5348,7 @@
if (trigger === 'click') {
EventHandler.on(this._element, this.constructor.eventName(EVENT_CLICK$1), this._config.selector, event => {
const context = this._initializeOnDelegatedTarget(event);
context._activeTrigger[TRIGGER_CLICK] = !(context._isShown() && context._activeTrigger[TRIGGER_CLICK]);
context.toggle();
});
} else if (trigger !== TRIGGER_MANUAL) {

2
aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/bootstrap/js/bootstrap.bundle.js.map

File diff suppressed because one or more lines are too long

4
aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/bootstrap/js/bootstrap.bundle.min.js

File diff suppressed because one or more lines are too long

2
aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/bootstrap/js/bootstrap.bundle.min.js.map

File diff suppressed because one or more lines are too long

13
aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/datatables.net-bs5/css/dataTables.bootstrap5.css

@ -5,17 +5,18 @@
--dt-row-stripe: 0, 0, 0;
--dt-row-hover: 0, 0, 0;
--dt-column-ordering: 0, 0, 0;
--dt-header-align-items: center;
--dt-html-background: white;
}
:root.dark {
--dt-html-background: rgb(33, 37, 41);
}
table.dataTable td.dt-control {
table.dataTable tbody td.dt-control {
text-align: center;
cursor: pointer;
}
table.dataTable td.dt-control:before {
table.dataTable tbody td.dt-control:before {
display: inline-block;
box-sizing: border-box;
content: "";
@ -24,7 +25,7 @@ table.dataTable td.dt-control:before {
border-bottom: 5px solid transparent;
border-right: 0px solid transparent;
}
table.dataTable tr.dt-hasChild td.dt-control:before {
table.dataTable tbody tr.dt-hasChild td.dt-control:before {
border-top: 10px solid rgba(0, 0, 0, 0.5);
border-left: 5px solid transparent;
border-bottom: 0px solid transparent;
@ -151,7 +152,7 @@ table.dataTable tfoot > tr > td div.dt-column-header,
table.dataTable tfoot > tr > td div.dt-column-footer {
display: flex;
justify-content: space-between;
align-items: center;
align-items: var(--dt-header-align-items);
gap: 4px;
}
table.dataTable thead > tr > th div.dt-column-header span.dt-column-title,
@ -409,6 +410,10 @@ table.dataTable tbody td.dt-body-nowrap {
white-space: nowrap;
}
:root {
--dt-header-align-items: flex-end;
}
/*! Bootstrap 5 integration for DataTables
*
* ©2020 SpryMedia Ltd, all rights reserved.

4
aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/datatables.net/js/dataTables.min.js

File diff suppressed because one or more lines are too long

226
aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/luxon/luxon.js

@ -1270,6 +1270,11 @@ var luxon = (function (exports) {
format = false;
}
return listStuff(this, length, months, function () {
// Workaround for "ja" locale: formatToParts does not label all parts of the month
// as "month" and for this locale there is no difference between "format" and "non-format".
// As such, just use format() instead of formatToParts() and take the whole string
var monthSpecialCase = _this2.intl === "ja" || _this2.intl.startsWith("ja-");
format &= !monthSpecialCase;
var intl = format ? {
month: length,
day: "numeric"
@ -1278,9 +1283,12 @@ var luxon = (function (exports) {
},
formatStr = format ? "format" : "standalone";
if (!_this2.monthsCache[formatStr][length]) {
_this2.monthsCache[formatStr][length] = mapMonths(function (dt) {
var mapper = !monthSpecialCase ? function (dt) {
return _this2.extract(dt, intl, "month");
});
} : function (dt) {
return _this2.dtFormatter(dt, intl).format();
};
_this2.monthsCache[formatStr][length] = mapMonths(mapper);
}
return _this2.monthsCache[formatStr][length];
});
@ -2311,13 +2319,25 @@ var luxon = (function (exports) {
return Math.floor(f);
}
}
function roundTo(number, digits, towardZero) {
if (towardZero === void 0) {
towardZero = false;
function roundTo(number, digits, rounding) {
if (rounding === void 0) {
rounding = "round";
}
var factor = Math.pow(10, digits);
switch (rounding) {
case "expand":
return number > 0 ? Math.ceil(number * factor) / factor : Math.floor(number * factor) / factor;
case "trunc":
return Math.trunc(number * factor) / factor;
case "round":
return Math.round(number * factor) / factor;
case "floor":
return Math.floor(number * factor) / factor;
case "ceil":
return Math.ceil(number * factor) / factor;
default:
throw new RangeError("Value rounding " + rounding + " is out of range");
}
var factor = Math.pow(10, digits),
rounder = towardZero ? Math.trunc : Math.round;
return rounder(number * factor) / factor;
}
// DATE BASICS
@ -2419,7 +2439,7 @@ var luxon = (function (exports) {
function asNumber(value) {
var numericValue = Number(value);
if (typeof value === "boolean" || value === "" || Number.isNaN(numericValue)) throw new InvalidArgumentError("Invalid unit value " + value);
if (typeof value === "boolean" || value === "" || !Number.isFinite(numericValue)) throw new InvalidArgumentError("Invalid unit value " + value);
return numericValue;
}
function normalizeObject(obj, normalizer) {
@ -2622,10 +2642,11 @@ var luxon = (function (exports) {
for (var i = 0; i < fmt.length; i++) {
var c = fmt.charAt(i);
if (c === "'") {
if (currentFull.length > 0) {
// turn '' into a literal signal quote instead of just skipping the empty literal
if (currentFull.length > 0 || bracketed) {
splits.push({
literal: bracketed || /^\s+$/.test(currentFull),
val: currentFull
val: currentFull === "" ? "'" : currentFull
});
}
current = null;
@ -2689,10 +2710,13 @@ var luxon = (function (exports) {
_proto.resolvedOptions = function resolvedOptions(dt, opts) {
return this.dtFormatter(dt, opts).resolvedOptions();
};
_proto.num = function num(n, p) {
_proto.num = function num(n, p, signDisplay) {
if (p === void 0) {
p = 0;
}
if (signDisplay === void 0) {
signDisplay = undefined;
}
// we get some perf out of doing this here, annoyingly
if (this.opts.forceSimple) {
return padStart(n, p);
@ -2701,6 +2725,9 @@ var luxon = (function (exports) {
if (p > 0) {
opts.padTo = p;
}
if (signDisplay) {
opts.signDisplay = signDisplay;
}
return this.loc.numberFormatter(opts).format(n);
};
_proto.formatDateTimeFromString = function formatDateTimeFromString(dt, fmt) {
@ -2969,33 +2996,44 @@ var luxon = (function (exports) {
};
_proto.formatDurationFromString = function formatDurationFromString(dur, fmt) {
var _this2 = this;
var invertLargest = this.opts.signMode === "negativeLargestOnly" ? -1 : 1;
var tokenToField = function tokenToField(token) {
switch (token[0]) {
case "S":
return "millisecond";
return "milliseconds";
case "s":
return "second";
return "seconds";
case "m":
return "minute";
return "minutes";
case "h":
return "hour";
return "hours";
case "d":
return "day";
return "days";
case "w":
return "week";
return "weeks";
case "M":
return "month";
return "months";
case "y":
return "year";
return "years";
default:
return null;
}
},
tokenToString = function tokenToString(lildur) {
tokenToString = function tokenToString(lildur, info) {
return function (token) {
var mapped = tokenToField(token);
if (mapped) {
return _this2.num(lildur.get(mapped), token.length);
var inversionFactor = info.isNegativeDuration && mapped !== info.largestUnit ? invertLargest : 1;
var signDisplay;
if (_this2.opts.signMode === "negativeLargestOnly" && mapped !== info.largestUnit) {
signDisplay = "never";
} else if (_this2.opts.signMode === "all") {
signDisplay = "always";
} else {
// "auto" and "negative" are the same, but "auto" has better support
signDisplay = "auto";
}
return _this2.num(lildur.get(mapped) * inversionFactor, token.length, signDisplay);
} else {
return token;
}
@ -3009,8 +3047,14 @@ var luxon = (function (exports) {
}, []),
collapsed = dur.shiftTo.apply(dur, realTokens.map(tokenToField).filter(function (t) {
return t;
}));
return stringifyTokens(tokens, tokenToString(collapsed));
})),
durationInfo = {
isNegativeDuration: collapsed < 0,
// this relies on "collapsed" being based on "shiftTo", which builds up the object
// in order
largestUnit: Object.keys(collapsed.values)[0]
};
return stringifyTokens(tokens, tokenToString(collapsed, durationInfo));
};
return Formatter;
}();
@ -3085,11 +3129,11 @@ var luxon = (function (exports) {
}
// ISO and SQL parsing
var offsetRegex = /(?:(Z)|([+-]\d\d)(?::?(\d\d))?)/;
var offsetRegex = /(?:([Zz])|([+-]\d\d)(?::?(\d\d))?)/;
var isoExtendedZone = "(?:" + offsetRegex.source + "?(?:\\[(" + ianaRegex.source + ")\\])?)?";
var isoTimeBaseRegex = /(\d\d)(?::?(\d\d)(?::?(\d\d)(?:[.,](\d{1,30}))?)?)?/;
var isoTimeRegex = RegExp("" + isoTimeBaseRegex.source + isoExtendedZone);
var isoTimeExtensionRegex = RegExp("(?:T" + isoTimeRegex.source + ")?");
var isoTimeExtensionRegex = RegExp("(?:[Tt]" + isoTimeRegex.source + ")?");
var isoYmdRegex = /([+-]\d{6}|\d{4})(?:-?(\d\d)(?:-?(\d\d))?)?/;
var isoWeekRegex = /(\d{4})-?W(\d\d)(?:-?(\d))?/;
var isoOrdinalRegex = /(\d{4})-?(\d{3})/;
@ -3730,9 +3774,13 @@ var luxon = (function (exports) {
* @param {string} fmt - the format string
* @param {Object} opts - options
* @param {boolean} [opts.floor=true] - floor numerical values
* @param {'negative'|'all'|'negativeLargestOnly'} [opts.signMode=negative] - How to handle signs
* @example Duration.fromObject({ years: 1, days: 6, seconds: 2 }).toFormat("y d s") //=> "1 6 2"
* @example Duration.fromObject({ years: 1, days: 6, seconds: 2 }).toFormat("yy dd sss") //=> "01 06 002"
* @example Duration.fromObject({ years: 1, days: 6, seconds: 2 }).toFormat("M S") //=> "12 518402000"
* @example Duration.fromObject({ days: 6, seconds: 2 }).toFormat("d s", { signMode: "all" }) //=> "+6 +2"
* @example Duration.fromObject({ days: -6, seconds: -2 }).toFormat("d s", { signMode: "all" }) //=> "-6 -2"
* @example Duration.fromObject({ days: -6, seconds: -2 }).toFormat("d s", { signMode: "negativeLargestOnly" }) //=> "-6 2"
* @return {string}
*/
_proto.toFormat = function toFormat(fmt, opts) {
@ -3752,12 +3800,14 @@ var luxon = (function (exports) {
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat#options
* @param {Object} opts - Formatting options. Accepts the same keys as the options parameter of the native `Intl.NumberFormat` constructor, as well as `listStyle`.
* @param {string} [opts.listStyle='narrow'] - How to format the merged list. Corresponds to the `style` property of the options parameter of the native `Intl.ListFormat` constructor.
* @param {boolean} [opts.showZeros=true] - Show all units previously used by the duration even if they are zero
* @example
* ```js
* var dur = Duration.fromObject({ days: 1, hours: 5, minutes: 6 })
* dur.toHuman() //=> '1 day, 5 hours, 6 minutes'
* dur.toHuman({ listStyle: "long" }) //=> '1 day, 5 hours, and 6 minutes'
* dur.toHuman({ unitDisplay: "short" }) //=> '1 day, 5 hr, 6 min'
* var dur = Duration.fromObject({ months: 1, weeks: 0, hours: 5, minutes: 6 })
* dur.toHuman() //=> '1 month, 0 weeks, 5 hours, 6 minutes'
* dur.toHuman({ listStyle: "long" }) //=> '1 month, 0 weeks, 5 hours, and 6 minutes'
* dur.toHuman({ unitDisplay: "short" }) //=> '1 mth, 0 wks, 5 hr, 6 min'
* dur.toHuman({ showZeros: false }) //=> '1 month, 5 hours, 6 minutes'
* ```
*/;
_proto.toHuman = function toHuman(opts) {
@ -3766,9 +3816,10 @@ var luxon = (function (exports) {
opts = {};
}
if (!this.isValid) return INVALID$2;
var showZeros = opts.showZeros !== false;
var l = orderedUnits$1.map(function (unit) {
var val = _this.values[unit];
if (isUndefined(val)) {
if (isUndefined(val) || val === 0 && !showZeros) {
return null;
}
return _this.loc.numberFormatter(_extends({
@ -4145,6 +4196,19 @@ var luxon = (function (exports) {
}, true);
}
/**
* Removes all units with values equal to 0 from this Duration.
* @example Duration.fromObject({ years: 2, days: 0, hours: 0, minutes: 0 }).removeZeros().toObject() //=> { years: 2 }
* @return {Duration}
*/;
_proto.removeZeros = function removeZeros() {
if (!this.isValid) return this;
var vals = removeZeroes(this.values);
return clone$1(this, {
values: vals
}, true);
}
/**
* Get the years.
* @type {number}
@ -4960,7 +5024,8 @@ var luxon = (function (exports) {
}
/**
* Returns the end of the Interval
* Returns the end of the Interval. This is the first instant which is not part of the interval
* (Interval is half-open).
* @type {DateTime}
*/
}, {
@ -6045,39 +6110,55 @@ var luxon = (function (exports) {
forceSimple: true
}).formatDateTimeFromString(dt, format) : null;
}
function _toISODate(o, extended) {
function _toISODate(o, extended, precision) {
var longFormat = o.c.year > 9999 || o.c.year < 0;
var c = "";
if (longFormat && o.c.year >= 0) c += "+";
c += padStart(o.c.year, longFormat ? 6 : 4);
if (precision === "year") return c;
if (extended) {
c += "-";
c += padStart(o.c.month);
if (precision === "month") return c;
c += "-";
c += padStart(o.c.day);
} else {
c += padStart(o.c.month);
c += padStart(o.c.day);
if (precision === "month") return c;
}
c += padStart(o.c.day);
return c;
}
function _toISOTime(o, extended, suppressSeconds, suppressMilliseconds, includeOffset, extendedZone) {
var c = padStart(o.c.hour);
if (extended) {
c += ":";
c += padStart(o.c.minute);
if (o.c.millisecond !== 0 || o.c.second !== 0 || !suppressSeconds) {
c += ":";
}
} else {
c += padStart(o.c.minute);
}
if (o.c.millisecond !== 0 || o.c.second !== 0 || !suppressSeconds) {
c += padStart(o.c.second);
if (o.c.millisecond !== 0 || !suppressMilliseconds) {
c += ".";
c += padStart(o.c.millisecond, 3);
}
function _toISOTime(o, extended, suppressSeconds, suppressMilliseconds, includeOffset, extendedZone, precision) {
var showSeconds = !suppressSeconds || o.c.millisecond !== 0 || o.c.second !== 0,
c = "";
switch (precision) {
case "day":
case "month":
case "year":
break;
default:
c += padStart(o.c.hour);
if (precision === "hour") break;
if (extended) {
c += ":";
c += padStart(o.c.minute);
if (precision === "minute") break;
if (showSeconds) {
c += ":";
c += padStart(o.c.second);
}
} else {
c += padStart(o.c.minute);
if (precision === "minute") break;
if (showSeconds) {
c += padStart(o.c.second);
}
}
if (precision === "second") break;
if (showSeconds && (!suppressMilliseconds || o.c.millisecond !== 0)) {
c += ".";
c += padStart(o.c.millisecond, 3);
}
}
if (includeOffset) {
if (o.isOffsetFixed && o.offset === 0 && !extendedZone) {
@ -6258,8 +6339,9 @@ var luxon = (function (exports) {
}
function diffRelative(start, end, opts) {
var round = isUndefined(opts.round) ? true : opts.round,
rounding = isUndefined(opts.rounding) ? "trunc" : opts.rounding,
format = function format(c, unit) {
c = roundTo(c, round || opts.calendary ? 0 : 2, true);
c = roundTo(c, round || opts.calendary ? 0 : 2, opts.calendary ? "round" : rounding);
var formatter = end.loc.clone(opts).relFormatter(opts);
return formatter.format(c, unit);
},
@ -7359,10 +7441,13 @@ var luxon = (function (exports) {
* @param {boolean} [opts.includeOffset=true] - include the offset, such as 'Z' or '-04:00'
* @param {boolean} [opts.extendedZone=false] - add the time zone format extension
* @param {string} [opts.format='extended'] - choose between the basic and extended format
* @param {string} [opts.precision='milliseconds'] - truncate output to desired presicion: 'years', 'months', 'days', 'hours', 'minutes', 'seconds' or 'milliseconds'. When precision and suppressSeconds or suppressMilliseconds are used together, precision sets the maximum unit shown in the output, however seconds or milliseconds will still be suppressed if they are 0.
* @example DateTime.utc(1983, 5, 25).toISO() //=> '1982-05-25T00:00:00.000Z'
* @example DateTime.now().toISO() //=> '2017-04-22T20:47:05.335-04:00'
* @example DateTime.now().toISO({ includeOffset: false }) //=> '2017-04-22T20:47:05.335'
* @example DateTime.now().toISO({ format: 'basic' }) //=> '20170422T204705.335-0400'
* @example DateTime.now().toISO({ precision: 'day' }) //=> '2017-04-22Z'
* @example DateTime.now().toISO({ precision: 'minute' }) //=> '2017-04-22T20:47Z'
* @return {string|null}
*/;
_proto.toISO = function toISO(_temp4) {
@ -7376,14 +7461,17 @@ var luxon = (function (exports) {
_ref5$includeOffset = _ref5.includeOffset,
includeOffset = _ref5$includeOffset === void 0 ? true : _ref5$includeOffset,
_ref5$extendedZone = _ref5.extendedZone,
extendedZone = _ref5$extendedZone === void 0 ? false : _ref5$extendedZone;
extendedZone = _ref5$extendedZone === void 0 ? false : _ref5$extendedZone,
_ref5$precision = _ref5.precision,
precision = _ref5$precision === void 0 ? "milliseconds" : _ref5$precision;
if (!this.isValid) {
return null;
}
precision = normalizeUnit(precision);
var ext = format === "extended";
var c = _toISODate(this, ext);
c += "T";
c += _toISOTime(this, ext, suppressSeconds, suppressMilliseconds, includeOffset, extendedZone);
var c = _toISODate(this, ext, precision);
if (orderedUnits.indexOf(precision) >= 3) c += "T";
c += _toISOTime(this, ext, suppressSeconds, suppressMilliseconds, includeOffset, extendedZone, precision);
return c;
}
@ -7391,18 +7479,22 @@ var luxon = (function (exports) {
* Returns an ISO 8601-compliant string representation of this DateTime's date component
* @param {Object} opts - options
* @param {string} [opts.format='extended'] - choose between the basic and extended format
* @param {string} [opts.precision='day'] - truncate output to desired precision: 'years', 'months', or 'days'.
* @example DateTime.utc(1982, 5, 25).toISODate() //=> '1982-05-25'
* @example DateTime.utc(1982, 5, 25).toISODate({ format: 'basic' }) //=> '19820525'
* @example DateTime.utc(1982, 5, 25).toISODate({ precision: 'month' }) //=> '1982-05'
* @return {string|null}
*/;
_proto.toISODate = function toISODate(_temp5) {
var _ref6 = _temp5 === void 0 ? {} : _temp5,
_ref6$format = _ref6.format,
format = _ref6$format === void 0 ? "extended" : _ref6$format;
format = _ref6$format === void 0 ? "extended" : _ref6$format,
_ref6$precision = _ref6.precision,
precision = _ref6$precision === void 0 ? "day" : _ref6$precision;
if (!this.isValid) {
return null;
}
return _toISODate(this, format === "extended");
return _toISODate(this, format === "extended", normalizeUnit(precision));
}
/**
@ -7423,10 +7515,12 @@ var luxon = (function (exports) {
* @param {boolean} [opts.extendedZone=true] - add the time zone format extension
* @param {boolean} [opts.includePrefix=false] - include the `T` prefix
* @param {string} [opts.format='extended'] - choose between the basic and extended format
* @param {string} [opts.precision='milliseconds'] - truncate output to desired presicion: 'hours', 'minutes', 'seconds' or 'milliseconds'. When precision and suppressSeconds or suppressMilliseconds are used together, precision sets the maximum unit shown in the output, however seconds or milliseconds will still be suppressed if they are 0.
* @example DateTime.utc().set({ hour: 7, minute: 34 }).toISOTime() //=> '07:34:19.361Z'
* @example DateTime.utc().set({ hour: 7, minute: 34, seconds: 0, milliseconds: 0 }).toISOTime({ suppressSeconds: true }) //=> '07:34Z'
* @example DateTime.utc().set({ hour: 7, minute: 34 }).toISOTime({ format: 'basic' }) //=> '073419.361Z'
* @example DateTime.utc().set({ hour: 7, minute: 34 }).toISOTime({ includePrefix: true }) //=> 'T07:34:19.361Z'
* @example DateTime.utc().set({ hour: 7, minute: 34, second: 56 }).toISOTime({ precision: 'minute' }) //=> '07:34Z'
* @return {string}
*/;
_proto.toISOTime = function toISOTime(_temp6) {
@ -7442,12 +7536,15 @@ var luxon = (function (exports) {
_ref7$extendedZone = _ref7.extendedZone,
extendedZone = _ref7$extendedZone === void 0 ? false : _ref7$extendedZone,
_ref7$format = _ref7.format,
format = _ref7$format === void 0 ? "extended" : _ref7$format;
format = _ref7$format === void 0 ? "extended" : _ref7$format,
_ref7$precision = _ref7.precision,
precision = _ref7$precision === void 0 ? "milliseconds" : _ref7$precision;
if (!this.isValid) {
return null;
}
var c = includePrefix ? "T" : "";
return c + _toISOTime(this, format === "extended", suppressSeconds, suppressMilliseconds, includeOffset, extendedZone);
precision = normalizeUnit(precision);
var c = includePrefix && orderedUnits.indexOf(precision) >= 3 ? "T" : "";
return c + _toISOTime(this, format === "extended", suppressSeconds, suppressMilliseconds, includeOffset, extendedZone, precision);
}
/**
@ -7736,12 +7833,13 @@ var luxon = (function (exports) {
/**
* Returns a string representation of a this time relative to now, such as "in two days". Can only internationalize if your
* platform supports Intl.RelativeTimeFormat. Rounds down by default.
* platform supports Intl.RelativeTimeFormat. Rounds towards zero by default.
* @param {Object} options - options that affect the output
* @param {DateTime} [options.base=DateTime.now()] - the DateTime to use as the basis to which this time is compared. Defaults to now.
* @param {string} [options.style="long"] - the style of units, must be "long", "short", or "narrow"
* @param {string|string[]} options.unit - use a specific unit or array of units; if omitted, or an array, the method will pick the best unit. Use an array or one of "years", "quarters", "months", "weeks", "days", "hours", "minutes", or "seconds"
* @param {boolean} [options.round=true] - whether to round the numbers in the output.
* @param {string} [options.rounding="trunc"] - rounding method to use when rounding the numbers in the output. Can be "trunc" (toward zero), "expand" (away from zero), "round", "floor", or "ceil".
* @param {number} [options.padding=0] - padding in milliseconds. This allows you to round up the result if it fits inside the threshold. Don't use in combination with {round: false} because the decimal output will include the padding.
* @param {string} options.locale - override the locale of this DateTime
* @param {string} options.numberingSystem - override the numberingSystem of this DateTime. The Intl system may choose not to honor this
@ -8624,7 +8722,7 @@ var luxon = (function (exports) {
}
}
var VERSION = "3.6.1";
var VERSION = "3.7.1";
exports.DateTime = DateTime;
exports.Duration = Duration;

2
aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/luxon/luxon.js.map

File diff suppressed because one or more lines are too long

2
aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/luxon/luxon.min.js

File diff suppressed because one or more lines are too long

2
aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/luxon/luxon.min.js.map

File diff suppressed because one or more lines are too long

BIN
aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/moment/locale/de-ch.js

Binary file not shown.

91
aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/moment/locale/en-au.js

@ -1,12 +1,79 @@
:"2025-07-05 11:31:41 [DBG] [Microsoft.AspNetCore.Server.Kestrel.Connections] [1] [135] - Connection id \"0HNDQQATBSFQF\" completed keep alive response.\n","stream":"stderr","time":"2025-07-05T03:31:41.530579165Z"}
{"log":"2025-07-05 11:31:41 [INF] [Microsoft.AspNetCore.Hosting.Diagnostics] [1] [135] - Request finished HTTP/1.1 GET http://localhost/healthz - 500 0 null 3.1038ms\n","stream":"stderr","time":"2025-07-05T03:31:41.530631619Z"}
{"log":"2025-07-05 11:31:41 [DBG] [Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets] [1] [95] - Connection id \"0HNDQQATBSFQF\" received FIN.\n","stream":"stderr","time":"2025-07-05T03:31:41.530770288Z"}
{"log":"2025-07-05 11:31:41 [DBG] [Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets] [1] [95] - Connection id \"0HNDQQATBSFQF\" sending FIN because: \"The Socket transport's send loop completed gracefully.\"\n","stream":"stderr","time":"2025-07-05T03:31:41.5309084Z"}
{"log":"2025-07-05 11:31:41 [DBG] [Microsoft.AspNetCore.Server.Kestrel.Connections] [1] [95] - Connection id \"0HNDQQATBSFQF\" disconnecting.\n","stream":"stderr","time":"2025-07-05T03:31:41.530921423Z"}
{"log":"2025-07-05 11:31:41 [DBG] [Microsoft.AspNetCore.Server.Kestrel.Connections] [1] [135] - Connection id \"0HNDQQATBSFQF\" stopped.\n","stream":"stderr","time":"2025-07-05T03:31:41.531023048Z"}
{"log":"2025-07-05 11:31:51 [DBG] [Microsoft.AspNetCore.Server.Kestrel.Connections] [1] [100] - Connection id \"0HNDQQATBSFQG\" accepted.\n","stream":"stderr","time":"2025-07-05T03:31:51.593587844Z"}
{"log":"2025-07-05 11:31:51 [DBG] [Microsoft.AspNetCore.Server.Kestrel.Connections] [1] [135] - Connection id \"0HNDQQATBSFQG\" started.\n","stream":"stderr","time":"2025-07-05T03:31:51.593608909Z"}
{"log":"2025-07-05 11:31:51 [INF] [Microsoft.AspNetCore.Hosting.Diagnostics] [1] [135] - Request starting HTTP/1.1 HEAD http://localhost/healthz - null null\n","stream":"stderr","time":"2025-07-05T03:31:51.593735211Z"}
{"log":"2025-07-05 11:31:51 [DBG] [Microsoft.AspNetCore.Localization.RequestLocalizationMiddleware] [1] [135] - AbpCultureMapRequestCultureProvider returned the following unsupported cultures '[]'.\n","stream":"stderr","time":"2025-07-05T03:31:51.594228126Z"}
{"log":"2025-07-05 11:31:51 [DBG] [Microsoft.AspNetCore.Localization.RequestLocalizationMiddleware] [1] [135] - AbpCultureMapRequestCultureProvider returned the following unsupported UI Cultures '[]'.\n","stream":"stderr","time":"2025-07-05T03:31:51.594231565Z"}
{"log":"2025-07-05 11:31:51 [DBG] [Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware] [1] [135] - The request path /healthz does not match a supported file type\n","stream":"st
//! moment.js locale configuration
//! locale : English (Australia) [en-au]
//! author : Jared Morse : https://github.com/jarcoal
;(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined'
&& typeof require === 'function' ? factory(require('../moment')) :
typeof define === 'function' && define.amd ? define(['../moment'], factory) :
factory(global.moment)
}(this, (function (moment) { 'use strict';
//! moment.js locale configuration
var enAu = moment.defineLocale('en-au', {
months: 'January_February_March_April_May_June_July_August_September_October_November_December'.split(
'_'
),
monthsShort: 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'),
weekdays: 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split(
'_'
),
weekdaysShort: 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'),
weekdaysMin: 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'),
longDateFormat: {
LT: 'h:mm A',
LTS: 'h:mm:ss A',
L: 'DD/MM/YYYY',
LL: 'D MMMM YYYY',
LLL: 'D MMMM YYYY h:mm A',
LLLL: 'dddd, D MMMM YYYY h:mm A',
},
calendar: {
sameDay: '[Today at] LT',
nextDay: '[Tomorrow at] LT',
nextWeek: 'dddd [at] LT',
lastDay: '[Yesterday at] LT',
lastWeek: '[Last] dddd [at] LT',
sameElse: 'L',
},
relativeTime: {
future: 'in %s',
past: '%s ago',
s: 'a few seconds',
ss: '%d seconds',
m: 'a minute',
mm: '%d minutes',
h: 'an hour',
hh: '%d hours',
d: 'a day',
dd: '%d days',
M: 'a month',
MM: '%d months',
y: 'a year',
yy: '%d years',
},
dayOfMonthOrdinalParse: /\d{1,2}(st|nd|rd|th)/,
ordinal: function (number) {
var b = number % 10,
output =
~~((number % 100) / 10) === 1
? 'th'
: b === 1
? 'st'
: b === 2
? 'nd'
: b === 3
? 'rd'
: 'th';
return number + output;
},
week: {
dow: 0, // Sunday is the first day of the week.
doy: 4, // The week that contains Jan 4th is the first week of the year.
},
});
return enAu;
})));

35
aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/sweetalert2/sweetalert2.all.js

File diff suppressed because one or more lines are too long

6
aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/sweetalert2/sweetalert2.all.min.js

File diff suppressed because one or more lines are too long

104
aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/sweetalert2/sweetalert2.css

@ -9,41 +9,56 @@
--swal2-border-radius: 0.3125rem;
--swal2-background: white;
--swal2-color: #545454;
--swal2-footer-border-color: #eee;
--swal2-show-animation: swal2-show 0.3s;
--swal2-hide-animation: swal2-hide 0.15s forwards;
--swal2-icon-zoom: 1;
--swal2-icon-animations: true;
--swal2-title-padding: 0.8em 1em 0;
--swal2-html-container-padding: 1em 1.6em 0.3em;
--swal2-input-border: 1px solid #d9d9d9;
--swal2-input-border-radius: 0.1875em;
--swal2-input-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.06), 0 0 0 3px transparent;
--swal2-input-background: transparent;
--swal2-input-transition: border-color 0.1s, box-shadow 0.1s;
--swal2-input-transition: border-color 0.2s, box-shadow 0.2s;
--swal2-input-hover-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.06), 0 0 0 3px transparent;
--swal2-input-focus-border: 1px solid #b4dbed;
--swal2-input-focus-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.06), 0 0 0 3px $swal2-outline-color;
--swal2-progress-step-background: #add8e6;
--swal2-validation-message-background: #f0f0f0;
--swal2-validation-message-color: #666;
--swal2-footer-border-color: #eee;
--swal2-footer-background: transparent;
--swal2-footer-color: inherit;
--swal2-close-button-position: initial;
--swal2-close-button-inset: auto;
--swal2-close-button-font-size: 2.5em;
--swal2-close-button-color: #ccc;
--swal2-close-button-transition: color 0.1s, box-shadow 0.1s;
--swal2-close-button-transition: color 0.2s, box-shadow 0.2s;
--swal2-close-button-outline: initial;
--swal2-close-button-box-shadow: inset 0 0 0 3px transparent;
--swal2-close-button-focus-box-shadow: inset var(--swal2-outline);
--swal2-close-button-hover-transform: none;
--swal2-button-darken-hover: rgba(0, 0, 0, 0.1);
--swal2-button-darken-active: rgba(0, 0, 0, 0.2);
--swal2-button-transition: box-shadow 0.1s;
--swal2-confirm-button-border: 0;
--swal2-actions-justify-content: center;
--swal2-actions-width: auto;
--swal2-actions-margin: 1.25em auto 0;
--swal2-actions-padding: 0;
--swal2-actions-border-radius: 0;
--swal2-actions-background: transparent;
--swal2-action-button-transition: background-color 0.2s, box-shadow 0.2s;
--swal2-action-button-hover: black 10%;
--swal2-action-button-active: black 10%;
--swal2-confirm-button-box-shadow: none;
--swal2-confirm-button-border-radius: 0.25em;
--swal2-confirm-button-background-color: #7066e0;
--swal2-deny-button-border: 0;
--swal2-confirm-button-color: #fff;
--swal2-deny-button-box-shadow: none;
--swal2-deny-button-border-radius: 0.25em;
--swal2-deny-button-background-color: #dc3741;
--swal2-cancel-button-border: 0;
--swal2-deny-button-color: #fff;
--swal2-cancel-button-box-shadow: none;
--swal2-cancel-button-border-radius: 0.25em;
--swal2-cancel-button-background-color: #6e7881;
--swal2-cancel-button-color: #fff;
--swal2-toast-show-animation: swal2-toast-show 0.5s;
--swal2-toast-hide-animation: swal2-toast-hide 0.1s forwards;
--swal2-toast-border: none;
@ -287,19 +302,12 @@ div:where(.swal2-container) div:where(.swal2-actions) {
box-sizing: border-box;
flex-wrap: wrap;
align-items: center;
justify-content: center;
width: auto;
margin: 1.25em auto 0;
padding: 0;
}
div:where(.swal2-container) div:where(.swal2-actions):not(.swal2-loading) .swal2-styled[disabled] {
opacity: 0.4;
}
div:where(.swal2-container) div:where(.swal2-actions):not(.swal2-loading) .swal2-styled:hover {
background-image: linear-gradient(var(--swal2-button-darken-hover), var(--swal2-button-darken-hover));
}
div:where(.swal2-container) div:where(.swal2-actions):not(.swal2-loading) .swal2-styled:active {
background-image: linear-gradient(var(--swal2-button-darken-active), var(--swal2-button-darken-active));
justify-content: var(--swal2-actions-justify-content);
width: var(--swal2-actions-width);
margin: var(--swal2-actions-margin);
padding: var(--swal2-actions-padding);
border-radius: var(--swal2-actions-border-radius);
background: var(--swal2-actions-background);
}
div:where(.swal2-container) div:where(.swal2-loader) {
display: none;
@ -317,7 +325,8 @@ div:where(.swal2-container) div:where(.swal2-loader) {
div:where(.swal2-container) button:where(.swal2-styled) {
margin: 0.3125em;
padding: 0.625em 1.1em;
transition: var(--swal2-button-transition);
transition: var(--swal2-action-button-transition);
border: none;
box-shadow: 0 0 0 3px transparent;
font-weight: 500;
}
@ -325,32 +334,53 @@ div:where(.swal2-container) button:where(.swal2-styled):not([disabled]) {
cursor: pointer;
}
div:where(.swal2-container) button:where(.swal2-styled):where(.swal2-confirm) {
border: var(--swal2-confirm-button-border);
border-radius: var(--swal2-confirm-button-border-radius);
background: initial;
background-color: var(--swal2-confirm-button-background-color);
color: #fff;
box-shadow: var(--swal2-confirm-button-box-shadow);
color: var(--swal2-confirm-button-color);
font-size: 1em;
}
div:where(.swal2-container) button:where(.swal2-styled):where(.swal2-confirm):hover {
background-color: color-mix(in srgb, var(--swal2-confirm-button-background-color), var(--swal2-action-button-hover));
}
div:where(.swal2-container) button:where(.swal2-styled):where(.swal2-confirm):active {
background-color: color-mix(in srgb, var(--swal2-confirm-button-background-color), var(--swal2-action-button-active));
}
div:where(.swal2-container) button:where(.swal2-styled):where(.swal2-deny) {
border: var(--swal2-deny-button-border);
border-radius: var(--swal2-deny-button-border-radius);
background: initial;
background-color: var(--swal2-deny-button-background-color);
color: #fff;
box-shadow: var(--swal2-deny-button-box-shadow);
color: var(--swal2-deny-button-color);
font-size: 1em;
}
div:where(.swal2-container) button:where(.swal2-styled):where(.swal2-deny):hover {
background-color: color-mix(in srgb, var(--swal2-deny-button-background-color), var(--swal2-action-button-hover));
}
div:where(.swal2-container) button:where(.swal2-styled):where(.swal2-deny):active {
background-color: color-mix(in srgb, var(--swal2-deny-button-background-color), var(--swal2-action-button-active));
}
div:where(.swal2-container) button:where(.swal2-styled):where(.swal2-cancel) {
border: var(--swal2-cancel-button-border);
border-radius: var(--swal2-cancel-button-border-radius);
background: initial;
background-color: var(--swal2-cancel-button-background-color);
color: #fff;
box-shadow: var(--swal2-cancel-button-box-shadow);
color: var(--swal2-cancel-button-color);
font-size: 1em;
}
div:where(.swal2-container) button:where(.swal2-styled):where(.swal2-cancel):hover {
background-color: color-mix(in srgb, var(--swal2-cancel-button-background-color), var(--swal2-action-button-hover));
}
div:where(.swal2-container) button:where(.swal2-styled):where(.swal2-cancel):active {
background-color: color-mix(in srgb, var(--swal2-cancel-button-background-color), var(--swal2-action-button-active));
}
div:where(.swal2-container) button:where(.swal2-styled):focus-visible {
outline: none;
box-shadow: var(--swal2-action-button-outline);
box-shadow: var(--swal2-action-button-focus-box-shadow);
}
div:where(.swal2-container) button:where(.swal2-styled)[disabled]:not(.swal2-loading) {
opacity: 0.4;
}
div:where(.swal2-container) button:where(.swal2-styled)::-moz-focus-inner {
border: 0;
@ -359,7 +389,8 @@ div:where(.swal2-container) div:where(.swal2-footer) {
margin: 1em 0 0;
padding: 1em 1em 0;
border-top: 1px solid var(--swal2-footer-border-color);
color: inherit;
background: var(--swal2-footer-background);
color: var(--swal2-footer-color);
font-size: 1em;
text-align: center;
cursor: initial;
@ -449,7 +480,7 @@ div:where(.swal2-container) textarea:where(.swal2-textarea) {
box-sizing: border-box;
width: auto;
transition: var(--swal2-input-transition);
border: 1px solid #d9d9d9;
border: var(--swal2-input-border);
border-radius: var(--swal2-input-border-radius);
background: var(--swal2-input-background);
box-shadow: var(--swal2-input-box-shadow);
@ -462,12 +493,17 @@ div:where(.swal2-container) textarea:where(.swal2-textarea).swal2-inputerror {
border-color: #f27474 !important;
box-shadow: 0 0 2px #f27474 !important;
}
div:where(.swal2-container) input:where(.swal2-input):hover,
div:where(.swal2-container) input:where(.swal2-file):hover,
div:where(.swal2-container) textarea:where(.swal2-textarea):hover {
box-shadow: var(--swal2-input-hover-box-shadow);
}
div:where(.swal2-container) input:where(.swal2-input):focus,
div:where(.swal2-container) input:where(.swal2-file):focus,
div:where(.swal2-container) textarea:where(.swal2-textarea):focus {
border: 1px solid #b4dbed;
border: var(--swal2-input-focus-border);
outline: none;
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.06), 0 0 0 3px rgba(100, 150, 200, 0.5);
box-shadow: var(--swal2-input-focus-box-shadow);
}
div:where(.swal2-container) input:where(.swal2-input)::placeholder,
div:where(.swal2-container) input:where(.swal2-file)::placeholder,

35
aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/sweetalert2/sweetalert2.esm.all.js

File diff suppressed because one or more lines are too long

6
aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/sweetalert2/sweetalert2.esm.all.min.js

File diff suppressed because one or more lines are too long

33
aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/sweetalert2/sweetalert2.esm.js

@ -1,5 +1,5 @@
/*!
* sweetalert2 v11.21.1
* sweetalert2 v11.22.2
* Released under the MIT License.
*/
function _assertClassBrand(e, t, n) {
@ -982,8 +982,12 @@ function handleButtonsStyling(confirmButton, denyButton, cancelButton, params) {
*/
function applyOutlineColor(button) {
const buttonStyle = window.getComputedStyle(button);
if (buttonStyle.getPropertyValue('--swal2-action-button-focus-box-shadow')) {
// If the button already has a custom outline color, no need to change it
return;
}
const outlineColor = buttonStyle.backgroundColor.replace(/rgba?\((\d+), (\d+), (\d+).*/, 'rgba($1, $2, $3, 0.5)');
button.style.setProperty('--swal2-action-button-outline', buttonStyle.getPropertyValue('--swal2-outline').replace(/ rgba\(.*/, ` ${outlineColor}`));
button.style.setProperty('--swal2-action-button-focus-box-shadow', buttonStyle.getPropertyValue('--swal2-outline').replace(/ rgba\(.*/, ` ${outlineColor}`));
}
/**
@ -1507,11 +1511,18 @@ const adjustSuccessIconBackgroundColor = () => {
successIconParts[i].style.backgroundColor = popupBackgroundColor;
}
};
const successIconHtml = `
<div class="swal2-success-circular-line-left"></div>
/**
*
* @param {SweetAlertOptions} params
* @returns {string}
*/
const successIconHtml = params => `
${params.animation ? '<div class="swal2-success-circular-line-left"></div>' : ''}
<span class="swal2-success-line-tip"></span> <span class="swal2-success-line-long"></span>
<div class="swal2-success-ring"></div> <div class="swal2-success-fix"></div>
<div class="swal2-success-circular-line-right"></div>
<div class="swal2-success-ring"></div>
${params.animation ? '<div class="swal2-success-fix"></div>' : ''}
${params.animation ? '<div class="swal2-success-circular-line-right"></div>' : ''}
`;
const errorIconHtml = `
<span class="swal2-x-mark">
@ -1533,7 +1544,7 @@ const setContent = (icon, params) => {
if (params.iconHtml) {
newContent = iconContent(params.iconHtml);
} else if (params.icon === 'success') {
newContent = successIconHtml;
newContent = successIconHtml(params);
oldContent = oldContent.replace(/ style=".*?"/g, ''); // undo adjustSuccessIconBackgroundColor()
} else if (params.icon === 'error') {
newContent = errorIconHtml;
@ -2100,8 +2111,8 @@ const handleArrows = key => {
* @param {Function} dismissWith
*/
const handleEsc = (event, innerParams, dismissWith) => {
event.preventDefault();
if (callIfFunction(innerParams.allowEscapeKey)) {
event.preventDefault();
dismissWith(DismissReason.esc);
}
};
@ -3242,8 +3253,8 @@ const showWarningsForParams = params => {
if (params.backdrop === false && params.allowOutsideClick) {
warn('"allowOutsideClick" parameter requires `backdrop` parameter to be set to `true`');
}
if (params.theme && !['light', 'dark', 'auto', 'minimal', 'borderless', 'embed-iframe'].includes(params.theme)) {
warn(`Invalid theme "${params.theme}". Expected "light", "dark", "auto", "minimal", "borderless", or "embed-iframe"`);
if (params.theme && !['light', 'dark', 'auto', 'minimal', 'borderless', 'embed-iframe', 'bulma', 'bulma-light', 'bulma-dark'].includes(params.theme)) {
warn(`Invalid theme "${params.theme}"`);
}
for (const param in params) {
checkIfParamIsValid(param);
@ -4611,7 +4622,7 @@ Object.keys(instanceMethods).forEach(key => {
};
});
SweetAlert.DismissReason = DismissReason;
SweetAlert.version = '11.21.1';
SweetAlert.version = '11.22.2';
const Swal = SweetAlert;
// @ts-ignore

4
aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/sweetalert2/sweetalert2.esm.min.js

File diff suppressed because one or more lines are too long

33
aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/sweetalert2/sweetalert2.js

@ -1,5 +1,5 @@
/*!
* sweetalert2 v11.21.1
* sweetalert2 v11.22.2
* Released under the MIT License.
*/
(function (global, factory) {
@ -988,8 +988,12 @@
*/
function applyOutlineColor(button) {
const buttonStyle = window.getComputedStyle(button);
if (buttonStyle.getPropertyValue('--swal2-action-button-focus-box-shadow')) {
// If the button already has a custom outline color, no need to change it
return;
}
const outlineColor = buttonStyle.backgroundColor.replace(/rgba?\((\d+), (\d+), (\d+).*/, 'rgba($1, $2, $3, 0.5)');
button.style.setProperty('--swal2-action-button-outline', buttonStyle.getPropertyValue('--swal2-outline').replace(/ rgba\(.*/, ` ${outlineColor}`));
button.style.setProperty('--swal2-action-button-focus-box-shadow', buttonStyle.getPropertyValue('--swal2-outline').replace(/ rgba\(.*/, ` ${outlineColor}`));
}
/**
@ -1513,11 +1517,18 @@
successIconParts[i].style.backgroundColor = popupBackgroundColor;
}
};
const successIconHtml = `
<div class="swal2-success-circular-line-left"></div>
/**
*
* @param {SweetAlertOptions} params
* @returns {string}
*/
const successIconHtml = params => `
${params.animation ? '<div class="swal2-success-circular-line-left"></div>' : ''}
<span class="swal2-success-line-tip"></span> <span class="swal2-success-line-long"></span>
<div class="swal2-success-ring"></div> <div class="swal2-success-fix"></div>
<div class="swal2-success-circular-line-right"></div>
<div class="swal2-success-ring"></div>
${params.animation ? '<div class="swal2-success-fix"></div>' : ''}
${params.animation ? '<div class="swal2-success-circular-line-right"></div>' : ''}
`;
const errorIconHtml = `
<span class="swal2-x-mark">
@ -1539,7 +1550,7 @@
if (params.iconHtml) {
newContent = iconContent(params.iconHtml);
} else if (params.icon === 'success') {
newContent = successIconHtml;
newContent = successIconHtml(params);
oldContent = oldContent.replace(/ style=".*?"/g, ''); // undo adjustSuccessIconBackgroundColor()
} else if (params.icon === 'error') {
newContent = errorIconHtml;
@ -2106,8 +2117,8 @@
* @param {Function} dismissWith
*/
const handleEsc = (event, innerParams, dismissWith) => {
event.preventDefault();
if (callIfFunction(innerParams.allowEscapeKey)) {
event.preventDefault();
dismissWith(DismissReason.esc);
}
};
@ -3248,8 +3259,8 @@
if (params.backdrop === false && params.allowOutsideClick) {
warn('"allowOutsideClick" parameter requires `backdrop` parameter to be set to `true`');
}
if (params.theme && !['light', 'dark', 'auto', 'minimal', 'borderless', 'embed-iframe'].includes(params.theme)) {
warn(`Invalid theme "${params.theme}". Expected "light", "dark", "auto", "minimal", "borderless", or "embed-iframe"`);
if (params.theme && !['light', 'dark', 'auto', 'minimal', 'borderless', 'embed-iframe', 'bulma', 'bulma-light', 'bulma-dark'].includes(params.theme)) {
warn(`Invalid theme "${params.theme}"`);
}
for (const param in params) {
checkIfParamIsValid(param);
@ -4617,7 +4628,7 @@
};
});
SweetAlert.DismissReason = DismissReason;
SweetAlert.version = '11.21.1';
SweetAlert.version = '11.22.2';
const Swal = SweetAlert;
// @ts-ignore

2
aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/sweetalert2/sweetalert2.min.css

File diff suppressed because one or more lines are too long

4
aspnet-core/services/LY.MicroService.AuthServer/wwwroot/libs/sweetalert2/sweetalert2.min.js

File diff suppressed because one or more lines are too long

6
aspnet-core/services/LY.MicroService.IdentityServer/package.json

@ -1,9 +1,9 @@
{
"version": "9.2.0",
"version": "9.2.3",
"name": "my-app-identityserver",
"private": true,
"dependencies": {
"@abp/aspnetcore.mvc.ui.theme.leptonxlite": "4.2.0",
"@abp/qrcode": "~9.2.0"
"@abp/aspnetcore.mvc.ui.theme.leptonxlite": "4.2.3",
"@abp/qrcode": "~9.2.3"
}
}

1879
aspnet-core/services/LY.MicroService.IdentityServer/wwwroot/libs/jquery/jquery.js

File diff suppressed because it is too large

4
aspnet-core/services/LY.MicroService.IdentityServer/wwwroot/libs/select2/js/i18n/nb.js

@ -1 +1,3 @@
","ebx_topicSuggestionExplanationTitle":"Kay rimanata sutichay huk runakunata imayna kasqanman, runakunaman, churayninkunaman yaykunankupaq.","ebx_repeatedWordsExplanationTitle":"Kay simiqa kutipasqam","ebx_showBeta":"Beta kaypi {0}","ebx_googleDocs":"Google Docs","ebx_indicatorTooltip":"Qillqachaqta kichay utaq clicta ruway alliq ñitinapi aswan akllaykuna qawanapaq","ebx_indicatorTooltipActive":"Editorpi llanpan yacharichiyta qaway utaq clicta ruway alliq ñitinapi aswan akllaykuna qawanapaq","contextAccessibilityLabelForSpelling":"Mana allin qillqasqa, {0}, {1}","contextAccessibilityLabelForRepeatedWord":"Kutipasqa simi, {0}, {1}","contextAccessibilityLabelForGrammar":"Allin rimana pantay, {0}, {1}","contextAccessibilityLabelForRefinement":"Refinamiento rikchay, {0
/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */
!function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/nb",[],function(){return{errorLoading:function(){return"Kunne ikke hente resultater."},inputTooLong:function(e){return"Vennligst fjern "+(e.input.length-e.maximum)+" tegn"},inputTooShort:function(e){return"Vennligst skriv inn "+(e.minimum-e.input.length)+" tegn til"},loadingMore:function(){return"Laster flere resultater…"},maximumSelected:function(e){return"Du kan velge maks "+e.maximum+" elementer"},noResults:function(){return"Ingen treff"},searching:function(){return"Søker…"},removeAllItems:function(){return"Fjern alle elementer"}}}),e.define,e.require}();

BIN
aspnet-core/services/LY.MicroService.IdentityServer/wwwroot/libs/timeago/locales/jquery.timeago.rs.js

Binary file not shown.

BIN
aspnet-core/services/LY.MicroService.IdentityServer/wwwroot/libs/timeago/locales/jquery.timeago.sk.js

Binary file not shown.

31
aspnet-core/services/LY.MicroService.IdentityServer/wwwroot/libs/timeago/locales/jquery.timeago.th.js

@ -1 +1,30 @@
olour to ${color} on table ${tableName}",TableBodyRangeFormatSetFontColorLabel:"Set the font colour to ${color} on table ${tableName} body",TableHeaderRowRangeFormatSetFontColorLabel:"Set the font colour to ${color} on table ${tableName} header row",TableTotalRowRangeFormatSetFontColorLabel:"Set the font colour to ${color} on table ${tableName} total row",TableGeneralRangeFormatSetFontColorLabel:"Set the font colour to ${color} on sub-range of table ${tableName}",TableRowsRangeFormatSetFontColorLabel:"Set the font colour to ${color} on ${count} row(s) in table ${tableName}",TableRowByIndexRangeFormatSetFontColorLabel:"Set the font colour to ${color} on row at index ${rowIndex} in table ${tableName}",TableColumnsRangeFormatSetFontColorLabel:"Set the font colour to ${color} on ${count} column(s) in table ${tableName}",TableColumnByNameRangeFormatSetFontColorLabel:"Set the font colour to ${color} on column '${columnName}' in table ${tableName}",TableColumnByIndexRangeFormatSetFontColorLabel:"Set the font colour to ${color}
(function (factory) {
if (typeof define === 'function' && define.amd) {
define(['jquery'], factory);
} else if (typeof module === 'object' && typeof module.exports === 'object') {
factory(require('jquery'));
} else {
factory(jQuery);
}
}(function (jQuery) {
// Thai
jQuery.timeago.settings.strings = {
prefixAgo: null,
prefixFromNow: null,
suffixAgo: "ที่แล้ว",
suffixFromNow: "จากตอนนี้",
seconds: "น้อยกว่าหนึ่งนาที",
minute: "ประมาณหนึ่งนาที",
minutes: "%d นาที",
hour: "ประมาณหนึ่งชั่วโมง",
hours: "ประมาณ %d ชั่วโมง",
day: "หนึ่งวัน",
days: "%d วัน",
month: "ประมาณหนึ่งเดือน",
months: "%d เดือน",
year: "ประมาณหนึ่งปี",
years: "%d ปี",
wordSeparator: "",
numbers: []
};
}));

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save