diff --git a/apps/vben5/apps/app-antd/package.json b/apps/vben5/apps/app-antd/package.json
index b4fc532a3..efbe91733 100644
--- a/apps/vben5/apps/app-antd/package.json
+++ b/apps/vben5/apps/app-antd/package.json
@@ -46,6 +46,7 @@
"@abp/text-templating": "workspace:*",
"@abp/ui": "workspace:*",
"@abp/webhooks": "workspace:*",
+ "@abp/wechat": "workspace:*",
"@vben-core/shadcn-ui": "workspace:*",
"@vben/access": "workspace:*",
"@vben/common-ui": "workspace:*",
diff --git a/apps/vben5/apps/app-antd/src/locales/langs/en-US/abp.json b/apps/vben5/apps/app-antd/src/locales/langs/en-US/abp.json
index 277f4585d..49dced4c6 100644
--- a/apps/vben5/apps/app-antd/src/locales/langs/en-US/abp.json
+++ b/apps/vben5/apps/app-antd/src/locales/langs/en-US/abp.json
@@ -142,5 +142,9 @@
"title": "Object storage",
"containers": "Containers",
"objects": "Files"
+ },
+ "wechat": {
+ "title": "WeChat",
+ "settings": "Settings"
}
}
diff --git a/apps/vben5/apps/app-antd/src/locales/langs/zh-CN/abp.json b/apps/vben5/apps/app-antd/src/locales/langs/zh-CN/abp.json
index 0665783bc..16bb7ec01 100644
--- a/apps/vben5/apps/app-antd/src/locales/langs/zh-CN/abp.json
+++ b/apps/vben5/apps/app-antd/src/locales/langs/zh-CN/abp.json
@@ -142,5 +142,9 @@
"title": "对象存储",
"containers": "容器管理",
"objects": "文件管理"
+ },
+ "wechat": {
+ "title": "微信集成",
+ "settings": "微信设置"
}
}
diff --git a/apps/vben5/apps/app-antd/src/views/account/my-settings/index.vue b/apps/vben5/apps/app-antd/src/views/account/my-settings/index.vue
index 29ccab460..5dda522cc 100644
--- a/apps/vben5/apps/app-antd/src/views/account/my-settings/index.vue
+++ b/apps/vben5/apps/app-antd/src/views/account/my-settings/index.vue
@@ -1,15 +1,98 @@
-
+
+
diff --git a/apps/vben5/packages/@abp/account/src/api/index.ts b/apps/vben5/packages/@abp/account/src/api/index.ts
index 9f94ff5ed..3810e2eb2 100644
--- a/apps/vben5/packages/@abp/account/src/api/index.ts
+++ b/apps/vben5/packages/@abp/account/src/api/index.ts
@@ -1,4 +1,5 @@
export { useAccountApi } from './useAccountApi';
+export { useExternalLoginsApi } from './useExternalLoginsApi';
export { useMySessionApi } from './useMySessionApi';
export { useProfileApi } from './useProfileApi';
export { useScanQrCodeApi } from './useScanQrCodeApi';
diff --git a/apps/vben5/packages/@abp/account/src/api/useExternalLoginsApi.ts b/apps/vben5/packages/@abp/account/src/api/useExternalLoginsApi.ts
new file mode 100644
index 000000000..ff2b0122f
--- /dev/null
+++ b/apps/vben5/packages/@abp/account/src/api/useExternalLoginsApi.ts
@@ -0,0 +1,58 @@
+import type {
+ ExternalLoginResultDto,
+ RemoveExternalLoginInput,
+ WorkWeixinLoginBindInput,
+} from '../types/external-logins';
+
+import { useRequest } from '@abp/request';
+
+export function useExternalLoginsApi() {
+ const { cancel, request } = useRequest();
+
+ /**
+ * 绑定企业微信
+ * @param input 绑定参数
+ * @returns { Promise }
+ */
+ async function bindWorkWeixinApi(
+ input: WorkWeixinLoginBindInput,
+ ): Promise {
+ return await request(`/api/account/oauth/work-weixin/bind`, {
+ method: 'POST',
+ data: input,
+ });
+ }
+
+ /**
+ * 获取外部登录提供者列表
+ * @returns 外部登录提供者列表
+ */
+ async function getExternalLoginsApi(): Promise {
+ return await request(
+ `/api/account/external-logins`,
+ {
+ method: 'GET',
+ },
+ );
+ }
+
+ /**
+ * 移除外部登录提供者
+ * @returns { Promise }
+ */
+ async function removeExternalLoginApi(
+ input: RemoveExternalLoginInput,
+ ): Promise {
+ return await request(`/api/account/external-logins/remove`, {
+ method: 'DELETE',
+ params: input,
+ });
+ }
+
+ return {
+ cancel,
+ bindWorkWeixinApi,
+ getExternalLoginsApi,
+ removeExternalLoginApi,
+ };
+}
diff --git a/apps/vben5/packages/@abp/account/src/components/MySetting.vue b/apps/vben5/packages/@abp/account/src/components/MySetting.vue
index 9266f6f8c..848cf6630 100644
--- a/apps/vben5/packages/@abp/account/src/components/MySetting.vue
+++ b/apps/vben5/packages/@abp/account/src/components/MySetting.vue
@@ -1,4 +1,5 @@
-
+
+
+
+
+
+
+
+
+
diff --git a/apps/vben5/packages/@abp/account/src/components/components/SecuritySettings.vue b/apps/vben5/packages/@abp/account/src/components/components/SecuritySettings.vue
index 65ac3940b..ce65c2368 100644
--- a/apps/vben5/packages/@abp/account/src/components/components/SecuritySettings.vue
+++ b/apps/vben5/packages/@abp/account/src/components/components/SecuritySettings.vue
@@ -86,13 +86,8 @@ onMounted(onGet);
-
- {{
- $t('abp.account.settings.security.password')
- }}
-
-
+ :title="$t('abp.account.settings.security.password')"
+ />
diff --git a/apps/vben5/packages/@abp/account/src/types/bind.ts b/apps/vben5/packages/@abp/account/src/types/bind.ts
new file mode 100644
index 000000000..b85215d3d
--- /dev/null
+++ b/apps/vben5/packages/@abp/account/src/types/bind.ts
@@ -0,0 +1,17 @@
+import type { ButtonType } from 'ant-design-vue/lib/button';
+
+interface BindButton {
+ click: () => Promise | void;
+ title: string;
+ type?: ButtonType;
+}
+
+interface BindItem {
+ buttons?: BindButton[];
+ description?: string;
+ enable?: boolean;
+ slot?: string;
+ title: string;
+}
+
+export type { BindItem };
diff --git a/apps/vben5/packages/@abp/account/src/types/external-logins.ts b/apps/vben5/packages/@abp/account/src/types/external-logins.ts
new file mode 100644
index 000000000..2d8ce8587
--- /dev/null
+++ b/apps/vben5/packages/@abp/account/src/types/external-logins.ts
@@ -0,0 +1,32 @@
+interface UserLoginInfoDto {
+ loginProvider: string;
+ providerDisplayName: string;
+ providerKey: string;
+}
+
+interface ExternalLoginInfoDto {
+ displayName: string;
+ name: string;
+}
+
+interface WorkWeixinLoginBindInput {
+ code: string;
+}
+
+interface ExternalLoginResultDto {
+ externalLogins: ExternalLoginInfoDto[];
+ userLogins: UserLoginInfoDto[];
+}
+
+interface RemoveExternalLoginInput {
+ loginProvider: string;
+ providerKey: string;
+}
+
+export type {
+ ExternalLoginInfoDto,
+ ExternalLoginResultDto,
+ RemoveExternalLoginInput,
+ UserLoginInfoDto,
+ WorkWeixinLoginBindInput,
+};
diff --git a/apps/vben5/packages/@abp/account/src/types/index.ts b/apps/vben5/packages/@abp/account/src/types/index.ts
index 1dd5f3324..0f182a66b 100644
--- a/apps/vben5/packages/@abp/account/src/types/index.ts
+++ b/apps/vben5/packages/@abp/account/src/types/index.ts
@@ -1,4 +1,6 @@
export * from './account';
+export * from './bind';
+export * from './external-logins';
export * from './profile';
export * from './token';
export * from './user';
diff --git a/apps/vben5/packages/@abp/core/src/utils/index.ts b/apps/vben5/packages/@abp/core/src/utils/index.ts
index 4c7bf48a5..3c3ccf781 100644
--- a/apps/vben5/packages/@abp/core/src/utils/index.ts
+++ b/apps/vben5/packages/@abp/core/src/utils/index.ts
@@ -5,3 +5,4 @@ export * from './mitt';
export * from './regex';
export * from './string';
export * from './tree';
+export * from './uuid';
diff --git a/apps/vben5/packages/@abp/core/src/utils/uuid.ts b/apps/vben5/packages/@abp/core/src/utils/uuid.ts
new file mode 100644
index 000000000..81c49a09d
--- /dev/null
+++ b/apps/vben5/packages/@abp/core/src/utils/uuid.ts
@@ -0,0 +1,42 @@
+const hexList: string[] = [];
+for (let i = 0; i <= 15; i++) {
+ hexList[i] = i.toString(16);
+}
+
+export function buildUUID(): string {
+ let uuid = '';
+ for (let i = 1; i <= 36; i++) {
+ switch (i) {
+ case 9:
+ case 14:
+ case 19:
+ case 24: {
+ uuid += '-';
+
+ break;
+ }
+ case 15: {
+ uuid += 4;
+
+ break;
+ }
+ case 20: {
+ uuid += hexList[(Math.random() * 4) | 8];
+
+ break;
+ }
+ default: {
+ uuid += hexList[Math.trunc(Math.random() * 16)];
+ }
+ }
+ }
+ return uuid.replaceAll('-', '');
+}
+
+let unique = 0;
+export function buildShortUUID(prefix = ''): string {
+ const time = Date.now();
+ const random = Math.floor(Math.random() * 1_000_000_000);
+ unique++;
+ return `${prefix}_${random}${unique}${String(time)}`;
+}
diff --git a/apps/vben5/packages/@abp/settings/src/components/index.ts b/apps/vben5/packages/@abp/settings/src/components/index.ts
index aaa211b75..53dbe96f7 100644
--- a/apps/vben5/packages/@abp/settings/src/components/index.ts
+++ b/apps/vben5/packages/@abp/settings/src/components/index.ts
@@ -1,3 +1,4 @@
export { default as SettingDefinitionTable } from './definitions/SettingDefinitionTable.vue';
+export { default as SettingForm } from './settings/SettingForm.vue';
export { default as SystemSetting } from './settings/SystemSetting.vue';
export { default as UserSetting } from './settings/UserSetting.vue';
diff --git a/apps/vben5/packages/@abp/wechat/package.json b/apps/vben5/packages/@abp/wechat/package.json
new file mode 100644
index 000000000..28d20c24a
--- /dev/null
+++ b/apps/vben5/packages/@abp/wechat/package.json
@@ -0,0 +1,40 @@
+{
+ "name": "@abp/wechat",
+ "version": "9.2.0",
+ "homepage": "https://github.com/colinin/abp-next-admin",
+ "bugs": "https://github.com/colinin/abp-next-admin/issues",
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/colinin/abp-next-admin.git",
+ "directory": "packages/@abp/wechat"
+ },
+ "license": "MIT",
+ "type": "module",
+ "sideEffects": [
+ "**/*.css"
+ ],
+ "exports": {
+ ".": {
+ "types": "./src/index.ts",
+ "default": "./src/index.ts"
+ }
+ },
+ "dependencies": {
+ "@abp/core": "workspace:*",
+ "@abp/features": "workspace:*",
+ "@abp/request": "workspace:*",
+ "@abp/settings": "workspace:*",
+ "@abp/ui": "workspace:*",
+ "@ant-design/icons-vue": "catalog:",
+ "@vben/access": "workspace:*",
+ "@vben/common-ui": "workspace:*",
+ "@vben/hooks": "workspace:*",
+ "@vben/icons": "workspace:*",
+ "@vben/layouts": "workspace:*",
+ "@vben/locales": "workspace:*",
+ "@wecom/jssdk": "catalog:",
+ "ant-design-vue": "catalog:",
+ "dayjs": "catalog:",
+ "vue": "catalog:*"
+ }
+}
diff --git a/apps/vben5/packages/@abp/wechat/src/api/index.ts b/apps/vben5/packages/@abp/wechat/src/api/index.ts
new file mode 100644
index 000000000..745447658
--- /dev/null
+++ b/apps/vben5/packages/@abp/wechat/src/api/index.ts
@@ -0,0 +1,2 @@
+export { userWorkWeixinJsSdkApi } from './userWorkWeixinJsSdkApi';
+export { useWechatSettingsApi } from './useWechatSettingsApi';
diff --git a/apps/vben5/packages/@abp/wechat/src/api/useWechatSettingsApi.ts b/apps/vben5/packages/@abp/wechat/src/api/useWechatSettingsApi.ts
new file mode 100644
index 000000000..9f9aa2a19
--- /dev/null
+++ b/apps/vben5/packages/@abp/wechat/src/api/useWechatSettingsApi.ts
@@ -0,0 +1,40 @@
+import type { ListResultDto } from '@abp/core';
+import type { SettingGroup } from '@abp/settings';
+
+import { useRequest } from '@abp/request';
+
+export function useWechatSettingsApi() {
+ const { cancel, request } = useRequest();
+
+ /**
+ * 获取全局设置
+ * @returns 设置数据传输对象列表
+ */
+ function getGlobalSettingsApi(): Promise> {
+ return request>(
+ `/api/wechat/setting-management/by-global`,
+ {
+ method: 'GET',
+ },
+ );
+ }
+
+ /**
+ * 获取租户设置
+ * @returns 设置数据传输对象列表
+ */
+ function getTenantSettingsApi(): Promise> {
+ return request>(
+ `/api/wechat/setting-management/by-current-tenant`,
+ {
+ method: 'GET',
+ },
+ );
+ }
+
+ return {
+ cancel,
+ getGlobalSettingsApi,
+ getTenantSettingsApi,
+ };
+}
diff --git a/apps/vben5/packages/@abp/wechat/src/api/userWorkWeixinJsSdkApi.ts b/apps/vben5/packages/@abp/wechat/src/api/userWorkWeixinJsSdkApi.ts
new file mode 100644
index 000000000..804fa7105
--- /dev/null
+++ b/apps/vben5/packages/@abp/wechat/src/api/userWorkWeixinJsSdkApi.ts
@@ -0,0 +1,22 @@
+import type { AgentConfigDto } from '../types/js-sdk';
+
+import { useRequest } from '@abp/request';
+
+export function userWorkWeixinJsSdkApi() {
+ const { cancel, request } = useRequest();
+
+ /**
+ * 获取企业微信应用配置
+ * @returns 企业微信应用配置Dto
+ */
+ function getAgentConfigApi(): Promise {
+ return request(`/api/wechat/work/jssdk/agent-config`, {
+ method: 'GET',
+ });
+ }
+
+ return {
+ cancel,
+ getAgentConfigApi,
+ };
+}
diff --git a/apps/vben5/packages/@abp/wechat/src/components/bind-user/index.vue b/apps/vben5/packages/@abp/wechat/src/components/bind-user/index.vue
new file mode 100644
index 000000000..e752a0700
--- /dev/null
+++ b/apps/vben5/packages/@abp/wechat/src/components/bind-user/index.vue
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
diff --git a/apps/vben5/packages/@abp/wechat/src/components/index.ts b/apps/vben5/packages/@abp/wechat/src/components/index.ts
new file mode 100644
index 000000000..8e84134b5
--- /dev/null
+++ b/apps/vben5/packages/@abp/wechat/src/components/index.ts
@@ -0,0 +1,2 @@
+export { default as WechatWorkUserBinder } from './bind-user/index.vue';
+export { default as WechatSettings } from './settings/index.vue';
diff --git a/apps/vben5/packages/@abp/wechat/src/components/settings/index.vue b/apps/vben5/packages/@abp/wechat/src/components/settings/index.vue
new file mode 100644
index 000000000..e1f3e30a6
--- /dev/null
+++ b/apps/vben5/packages/@abp/wechat/src/components/settings/index.vue
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
diff --git a/apps/vben5/packages/@abp/wechat/src/index.ts b/apps/vben5/packages/@abp/wechat/src/index.ts
new file mode 100644
index 000000000..0ef464305
--- /dev/null
+++ b/apps/vben5/packages/@abp/wechat/src/index.ts
@@ -0,0 +1,2 @@
+export * from './api';
+export * from './components';
diff --git a/apps/vben5/packages/@abp/wechat/src/types/js-sdk.ts b/apps/vben5/packages/@abp/wechat/src/types/js-sdk.ts
new file mode 100644
index 000000000..44031b6b5
--- /dev/null
+++ b/apps/vben5/packages/@abp/wechat/src/types/js-sdk.ts
@@ -0,0 +1,6 @@
+interface AgentConfigDto {
+ agentId: string;
+ corpId: string;
+}
+
+export type { AgentConfigDto };
diff --git a/apps/vben5/packages/@abp/wechat/tsconfig.json b/apps/vben5/packages/@abp/wechat/tsconfig.json
new file mode 100644
index 000000000..ce1a891fb
--- /dev/null
+++ b/apps/vben5/packages/@abp/wechat/tsconfig.json
@@ -0,0 +1,6 @@
+{
+ "$schema": "https://json.schemastore.org/tsconfig",
+ "extends": "@vben/tsconfig/web.json",
+ "include": ["src"],
+ "exclude": ["node_modules"]
+}
diff --git a/apps/vben5/pnpm-workspace.yaml b/apps/vben5/pnpm-workspace.yaml
index b599ab73f..517e67b0e 100644
--- a/apps/vben5/pnpm-workspace.yaml
+++ b/apps/vben5/pnpm-workspace.yaml
@@ -73,6 +73,7 @@ catalog:
'@vueuse/core': ^13.1.0
'@vueuse/integrations': ^13.1.0
'@vueuse/motion': ^3.0.3
+ '@wecom/jssdk': ^2.3.1
ant-design-vue: ^4.2.6
archiver: ^7.0.1
autoprefixer: ^10.4.21