Compare commits
37 Commits
1.2.2-back
...
1.2.3-back
Author | SHA1 | Date | |
---|---|---|---|
![]() |
b97c83fdf3 | ||
![]() |
bb5ad57d9c | ||
![]() |
a8f20a2baa | ||
![]() |
0e7b76d5ed | ||
![]() |
877cc06eff | ||
![]() |
ba6785931d | ||
![]() |
731c9be4f1 | ||
![]() |
e546c21ad6 | ||
![]() |
22ff5bddae | ||
![]() |
b2c66c07b4 | ||
![]() |
cd110433c1 | ||
![]() |
3f0d30897f | ||
![]() |
66c1d390b9 | ||
![]() |
6c942418b4 | ||
![]() |
db955071d7 | ||
![]() |
17e82fb766 | ||
![]() |
03ceb2aac5 | ||
![]() |
f3e455c8d3 | ||
![]() |
39888cebaa | ||
![]() |
efb69fc75f | ||
![]() |
711a179c69 | ||
![]() |
3133f8f8b9 | ||
![]() |
f0a43912d1 | ||
![]() |
949004c67f | ||
![]() |
feb6229383 | ||
![]() |
614d998daf | ||
![]() |
9e4f886197 | ||
![]() |
18f2b84093 | ||
![]() |
25616baa1d | ||
![]() |
b92ac5c36d | ||
![]() |
504070f3eb | ||
![]() |
7032f79069 | ||
![]() |
a0b5aaa4dd | ||
![]() |
7230b94b16 | ||
![]() |
cca456aa82 | ||
![]() |
5310bddc1c | ||
![]() |
2e064604c1 |
18
.github/CODEOWNERS
vendored
18
.github/CODEOWNERS
vendored
@@ -1,14 +1,14 @@
|
||||
# default onwer
|
||||
* anncwb@126.com vince292007@gmail.com netfan@foxmail.com
|
||||
* anncwb@126.com vince292007@gmail.com netfan@foxmail.com jinmao88@qq.com
|
||||
|
||||
# vben core onwer
|
||||
/.github/ anncwb@126.com vince292007@gmail.com netfan@foxmail.com
|
||||
/.vscode/ anncwb@126.com vince292007@gmail.com netfan@foxmail.com
|
||||
/packages/ anncwb@126.com vince292007@gmail.com netfan@foxmail.com
|
||||
/packages/@core/ anncwb@126.com vince292007@gmail.com netfan@foxmail.com
|
||||
/internal/ anncwb@126.com vince292007@gmail.com netfan@foxmail.com
|
||||
/scripts/ anncwb@126.com vince292007@gmail.com netfan@foxmail.com
|
||||
/.github/ anncwb@126.com vince292007@gmail.com netfan@foxmail.com jinmao88@qq.com
|
||||
/.vscode/ anncwb@126.com vince292007@gmail.com netfan@foxmail.com jinmao88@qq.com
|
||||
/packages/ anncwb@126.com vince292007@gmail.com netfan@foxmail.com jinmao88@qq.com
|
||||
/packages/@core/ anncwb@126.com vince292007@gmail.com netfan@foxmail.com jinmao88@qq.com
|
||||
/internal/ anncwb@126.com vince292007@gmail.com netfan@foxmail.com jinmao88@qq.com
|
||||
/scripts/ anncwb@126.com vince292007@gmail.com netfan@foxmail.com jinmao88@qq.com
|
||||
|
||||
# vben team onwer
|
||||
apps/ anncwb@126.com vince292007@gmail.com netfan@foxmail.com @vbenjs/team-v5
|
||||
docs/ anncwb@126.com vince292007@gmail.com netfan@foxmail.com @vbenjs/team-v5
|
||||
apps/ anncwb@126.com vince292007@gmail.com netfan@foxmail.com @vbenjs/team-v5 jinmao88@qq.com
|
||||
docs/ anncwb@126.com vince292007@gmail.com netfan@foxmail.com @vbenjs/team-v5 jinmao88@qq.com
|
||||
|
18
CHANGELOG.md
18
CHANGELOG.md
@@ -1,3 +1,21 @@
|
||||
# 1.2.3
|
||||
|
||||
**BUG FIX**
|
||||
|
||||
- `withDefaultPlaceholder`中将`placeholder`修改为computed, 解决后续使用`updateSchema`无法正常更新显示placeholder(响应式问题)
|
||||
|
||||
- 流程定义 修改accept类型 解决无法拖拽上传
|
||||
|
||||
**FEATURES**
|
||||
|
||||
- 增加`环境变量`打包配置demo -> build:antd:test
|
||||
- 角色管理 勾选权限组件添加对错误用法的校验提示
|
||||
|
||||
**REFACTOR**
|
||||
|
||||
- OAuth内部逻辑重构 增加新的默认OAuth登录方式
|
||||
- 重构部分setup组件为setup语法糖形式
|
||||
|
||||
# 1.2.2
|
||||
|
||||
**FEATURES**
|
||||
|
@@ -6,25 +6,19 @@
|
||||
|
||||
v5版本采用分仓(包)目录结构, 具体开发路径为: `根目录/apps/web-antd`
|
||||
|
||||
目前对应后端版本: **分布式5.3.0/微服务2.2.2**
|
||||
目前对应后端版本: **分布式5.3.1/微服务2.3.0**
|
||||
|
||||
V1.1.0版本已支持离线图标
|
||||
|
||||
V1.2.0版本对接warmflow工作流
|
||||
|
||||
`微服务最新版暂不支持warmflow工作流`
|
||||
|
||||
`微服务最新版暂不支持warmflow工作流`
|
||||
|
||||
`微服务最新版暂不支持warmflow工作流`
|
||||
|
||||
## 简介
|
||||
|
||||
基于 [vben5 & ant-design-vue](https://github.com/vbenjs/vue-vben-admin) 的 RuoYi-Vue-Plus 前端项目
|
||||
|
||||
| 组件/框架 | 版本 |
|
||||
| :------------- | :----- |
|
||||
| vben | 5.5.3 |
|
||||
| vben | 5.5.4 |
|
||||
| ant-design-vue | 4.2.6 |
|
||||
| vue | 3.5.13 |
|
||||
|
||||
|
@@ -15,7 +15,7 @@ VITE_INJECT_APP_LOADING=true
|
||||
# 打包后是否生成dist.zip
|
||||
VITE_ARCHIVER=true
|
||||
|
||||
# 后台请求路径 具体在vite.config.mts配置代理
|
||||
# 后端接口地址
|
||||
VITE_GLOB_API_URL=/prod-api
|
||||
|
||||
# 全局加密开关(即开启了加解密功能才会生效 不是全部接口加密 需要和后端对应)
|
||||
|
35
apps/web-antd/.env.test
Normal file
35
apps/web-antd/.env.test
Normal file
@@ -0,0 +1,35 @@
|
||||
# 该文件是为了给一个增加环境变量打包的例子
|
||||
# 对应在根目录package.json -> build:antd:test 命令
|
||||
|
||||
VITE_BASE=/
|
||||
|
||||
# 是否开启压缩,可以设置为 none, brotli, gzip
|
||||
VITE_COMPRESS=gzip
|
||||
|
||||
# 是否开启 PWA
|
||||
VITE_PWA=false
|
||||
|
||||
# vue-router 的模式
|
||||
VITE_ROUTER_HISTORY=history
|
||||
|
||||
# 是否注入全局loading
|
||||
VITE_INJECT_APP_LOADING=true
|
||||
|
||||
# 打包后是否生成dist.zip
|
||||
VITE_ARCHIVER=true
|
||||
|
||||
# 后端接口地址
|
||||
VITE_GLOB_API_URL=/test-api
|
||||
|
||||
# 全局加密开关(即开启了加解密功能才会生效 不是全部接口加密 需要和后端对应)
|
||||
VITE_GLOB_ENABLE_ENCRYPT=true
|
||||
# RSA公钥 请求加密使用 注意这两个是两对RSA公私钥 请求加密-后端解密是一对 响应解密-后端加密是一对
|
||||
VITE_GLOB_RSA_PUBLIC_KEY=MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdHnzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ==
|
||||
# RSA私钥 响应解密使用 注意这两个是两对RSA公私钥 请求加密-后端解密是一对 响应解密-后端加密是一对
|
||||
VITE_GLOB_RSA_PRIVATE_KEY=MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAmc3CuPiGL/LcIIm7zryCEIbl1SPzBkr75E2VMtxegyZ1lYRD+7TZGAPkvIsBcaMs6Nsy0L78n2qh+lIZMpLH8wIDAQABAkEAk82Mhz0tlv6IVCyIcw/s3f0E+WLmtPFyR9/WtV3Y5aaejUkU60JpX4m5xNR2VaqOLTZAYjW8Wy0aXr3zYIhhQQIhAMfqR9oFdYw1J9SsNc+CrhugAvKTi0+BF6VoL6psWhvbAiEAxPPNTmrkmrXwdm/pQQu3UOQmc2vCZ5tiKpW10CgJi8kCIFGkL6utxw93Ncj4exE/gPLvKcT+1Emnoox+O9kRXss5AiAMtYLJDaLEzPrAWcZeeSgSIzbL+ecokmFKSDDcRske6QIgSMkHedwND1olF8vlKsJUGK3BcdtM8w4Xq7BpSBwsloE=
|
||||
# 客户端id
|
||||
VITE_GLOB_APP_CLIENT_ID=e5cd7e4891bf95d1d19206ce24a7b32e
|
||||
|
||||
# 开启SSE
|
||||
VITE_GLOB_SSE_ENABLE=true
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben/web-antd",
|
||||
"version": "1.2.2",
|
||||
"version": "1.2.3",
|
||||
"homepage": "https://vben.pro",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
@@ -16,7 +16,7 @@
|
||||
},
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "pnpm vite build --mode production",
|
||||
"build": "pnpm vite build",
|
||||
"build:analyze": "pnpm vite build --mode analyze",
|
||||
"dev": "pnpm vite --mode development",
|
||||
"preview": "vite preview",
|
||||
|
@@ -8,7 +8,7 @@ import type { Component } from 'vue';
|
||||
import type { BaseFormComponentType } from '@vben/common-ui';
|
||||
import type { Recordable } from '@vben/types';
|
||||
|
||||
import { defineComponent, getCurrentInstance, h, ref } from 'vue';
|
||||
import { computed, defineComponent, getCurrentInstance, h, ref } from 'vue';
|
||||
|
||||
import { ApiComponent, globalShareState, IconPicker } from '@vben/common-ui';
|
||||
import { $t } from '@vben/locales';
|
||||
@@ -49,10 +49,16 @@ const withDefaultPlaceholder = <T extends Component>(
|
||||
inheritAttrs: false,
|
||||
name: component.name,
|
||||
setup: (props: any, { attrs, expose, slots }) => {
|
||||
const placeholder =
|
||||
props?.placeholder ||
|
||||
attrs?.placeholder ||
|
||||
$t(`ui.placeholder.${type}`);
|
||||
/**
|
||||
* 需要使用computed 否则后续updateSchema更新的placeholder无法显示(响应式问题)
|
||||
*/
|
||||
const placeholder = computed(
|
||||
() =>
|
||||
props?.placeholder ||
|
||||
attrs?.placeholder ||
|
||||
$t(`ui.placeholder.${type}`),
|
||||
);
|
||||
|
||||
// 透传组件暴露的方法
|
||||
const innerRef = ref();
|
||||
const publicApi: Recordable<any> = {};
|
||||
@@ -66,7 +72,11 @@ const withDefaultPlaceholder = <T extends Component>(
|
||||
}
|
||||
});
|
||||
return () =>
|
||||
h(component, { ...props, ...attrs, placeholder, ref: innerRef }, slots);
|
||||
h(
|
||||
component,
|
||||
{ ...props, ...attrs, placeholder: placeholder.value, ref: innerRef },
|
||||
slots,
|
||||
);
|
||||
},
|
||||
});
|
||||
};
|
||||
|
@@ -5,6 +5,7 @@ import type { MenuOption } from '#/api/system/menu/model';
|
||||
|
||||
import { eachTree, treeToList } from '@vben/utils';
|
||||
|
||||
import { notification } from 'ant-design-vue';
|
||||
import { difference, isEmpty, isUndefined } from 'lodash-es';
|
||||
|
||||
/**
|
||||
@@ -48,6 +49,7 @@ export function rowAndChildrenChecked(
|
||||
*/
|
||||
export function menusWithPermissions(menus: MenuOption[]) {
|
||||
eachTree(menus, (item: MenuPermissionOption) => {
|
||||
validateMenuTree(item);
|
||||
if (item.children && item.children.length > 0) {
|
||||
/**
|
||||
* 所有为按钮的节点提取出来
|
||||
@@ -131,3 +133,50 @@ export function setTableChecked(
|
||||
tableApi.grid.setCheckboxRow(emptyRows, false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验是否符合规范 给出warning提示
|
||||
*
|
||||
* 不符合规范
|
||||
* 比如: 菜单下放目录 菜单下放菜单
|
||||
* 比如: 按钮下放目录 按钮下放菜单 按钮下放按钮
|
||||
* @param menu menu
|
||||
*/
|
||||
function validateMenuTree(menu: MenuOption) {
|
||||
/**
|
||||
* C: { icon: markRaw(MenuIcon), value: '菜单' },
|
||||
F: { icon: markRaw(OkButtonIcon), value: '按钮' },
|
||||
M: { icon: markRaw(FolderIcon), value: '目录' },
|
||||
*/
|
||||
// 菜单下不能放目录/菜单
|
||||
if (menu.menuType === 'C') {
|
||||
menu.children?.forEach?.((item) => {
|
||||
if (['C', 'M'].includes(item.menuType)) {
|
||||
const description = `错误用法: [${menu.label} - 菜单]下不能放 目录/菜单 -> [${item.label}]`;
|
||||
console.warn(description);
|
||||
notification.warning({
|
||||
message: '提示',
|
||||
description,
|
||||
duration: 0,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
// 按钮为最末级 不能再放置
|
||||
if (menu.menuType === 'F') {
|
||||
/**
|
||||
* 其实可以直接判断length 这里为了更准确知道label 采用遍历的形式
|
||||
*/
|
||||
menu.children?.forEach?.((item) => {
|
||||
if (['C', 'F', 'M'].includes(item.menuType)) {
|
||||
const description = `错误用法: [${menu.label} - 按钮]下不能放置'目录/菜单/按钮' -> [${item.label}]`;
|
||||
console.warn(description);
|
||||
notification.warning({
|
||||
message: '提示',
|
||||
description,
|
||||
duration: 0,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@@ -55,8 +55,7 @@ const props = withDefaults(
|
||||
/**
|
||||
* 是否节点关联
|
||||
*/
|
||||
const association = defineModel('association', {
|
||||
type: Boolean,
|
||||
const association = defineModel<boolean>('association', {
|
||||
default: true,
|
||||
});
|
||||
|
||||
|
@@ -20,9 +20,9 @@ import {
|
||||
MicromessengerIcon,
|
||||
OperaIcon,
|
||||
OSXIcon,
|
||||
QQIcon,
|
||||
QuarkIcon,
|
||||
SafariIcon,
|
||||
SvgQQIcon,
|
||||
UcIcon,
|
||||
WindowsIcon,
|
||||
} from '@vben/icons';
|
||||
@@ -197,7 +197,7 @@ const browserOptions = [
|
||||
{ icon: MicromessengerIcon, value: 'windowswechat' },
|
||||
{ icon: QuarkIcon, value: 'quark' },
|
||||
{ icon: MicromessengerIcon, value: 'wxwork' },
|
||||
{ icon: QQIcon, value: 'qq' },
|
||||
{ icon: SvgQQIcon, value: 'qq' },
|
||||
{ icon: DingtalkIcon, value: 'dingtalk' },
|
||||
{ icon: UcIcon, value: 'uc' },
|
||||
{ icon: BaiduIcon, value: 'baidu' },
|
||||
|
@@ -6,6 +6,7 @@ import type { TenantResp } from '#/api';
|
||||
import { computed, onMounted, ref, useTemplateRef } from 'vue';
|
||||
|
||||
import { AuthenticationCodeLogin, z } from '@vben/common-ui';
|
||||
import { DEFAULT_TENANT_ID } from '@vben/constants';
|
||||
import { $t } from '@vben/locales';
|
||||
|
||||
import { Alert, message } from 'ant-design-vue';
|
||||
@@ -50,7 +51,7 @@ const formSchema = computed((): VbenFormSchema[] => {
|
||||
})),
|
||||
placeholder: $t('authentication.selectAccount'),
|
||||
},
|
||||
defaultValue: '000000',
|
||||
defaultValue: DEFAULT_TENANT_ID,
|
||||
dependencies: {
|
||||
if: () => tenantInfo.value.tenantEnabled,
|
||||
triggerFields: [''],
|
||||
|
@@ -7,6 +7,7 @@ import type { CaptchaResponse } from '#/api/core/captcha';
|
||||
import { computed, onMounted, ref, useTemplateRef } from 'vue';
|
||||
|
||||
import { AuthenticationLogin, z } from '@vben/common-ui';
|
||||
import { DEFAULT_TENANT_ID } from '@vben/constants';
|
||||
import { $t } from '@vben/locales';
|
||||
|
||||
import { omit } from 'lodash-es';
|
||||
@@ -15,6 +16,7 @@ import { tenantList } from '#/api';
|
||||
import { captchaImage } from '#/api/core/captcha';
|
||||
import { useAuthStore } from '#/store';
|
||||
|
||||
import { useLoginTenantId } from '../oauth-common';
|
||||
import OAuthLogin from './oauth-login.vue';
|
||||
|
||||
defineOptions({ name: 'Login' });
|
||||
@@ -56,6 +58,8 @@ onMounted(async () => {
|
||||
await Promise.all([loadCaptcha(), loadTenant()]);
|
||||
});
|
||||
|
||||
const { loginTenantId } = useLoginTenantId();
|
||||
|
||||
const formSchema = computed((): VbenFormSchema[] => {
|
||||
return [
|
||||
{
|
||||
@@ -69,16 +73,13 @@ const formSchema = computed((): VbenFormSchema[] => {
|
||||
})),
|
||||
placeholder: $t('authentication.selectAccount'),
|
||||
},
|
||||
defaultValue: '000000',
|
||||
defaultValue: DEFAULT_TENANT_ID,
|
||||
dependencies: {
|
||||
if: () => tenantInfo.value.tenantEnabled,
|
||||
// 这里大致上是watch的一个效果
|
||||
componentProps: (model) => {
|
||||
localStorage.setItem(
|
||||
'__oauth_tenant_id',
|
||||
model?.tenantId ?? '000000',
|
||||
);
|
||||
return {};
|
||||
// 可以把这里当做watch
|
||||
trigger: (model) => {
|
||||
// 给oauth登录使用
|
||||
loginTenantId.value = model?.tenantId ?? DEFAULT_TENANT_ID;
|
||||
},
|
||||
triggerFields: ['', 'tenantId'],
|
||||
},
|
||||
|
@@ -3,21 +3,16 @@ import { $t } from '@vben/locales';
|
||||
|
||||
import { Col, Row, Tooltip } from 'ant-design-vue';
|
||||
|
||||
import { accountBindList } from '../oauth-common';
|
||||
import { accountBindList, handleAuthBinding } from '../oauth-common';
|
||||
|
||||
defineOptions({
|
||||
name: 'OAuthLogin',
|
||||
});
|
||||
|
||||
/**
|
||||
* 有action方法才会显示
|
||||
*/
|
||||
const clientList = accountBindList.filter((item) => item.action);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="w-full sm:mx-auto md:max-w-md">
|
||||
<div class="mt-4 flex items-center justify-between">
|
||||
<div class="my-4 flex items-center justify-between">
|
||||
<span class="border-input w-[35%] border-b dark:border-gray-600"></span>
|
||||
<span class="text-muted-foreground text-center text-xs uppercase">
|
||||
{{ $t('authentication.thirdPartyLogin') }}
|
||||
@@ -26,15 +21,20 @@ const clientList = accountBindList.filter((item) => item.action);
|
||||
</div>
|
||||
<Row class="enter-x flex items-center justify-evenly">
|
||||
<!-- todo 这里在点击登录时要disabled -->
|
||||
<Col v-for="item in clientList" :key="item.key" :span="4" class="my-2">
|
||||
<Col
|
||||
v-for="item in accountBindList"
|
||||
:key="item.source"
|
||||
:span="4"
|
||||
class="my-2"
|
||||
>
|
||||
<Tooltip :title="`${item.title}登录`">
|
||||
<span class="flex cursor-pointer items-center justify-center">
|
||||
<component
|
||||
:is="item.avatar"
|
||||
v-if="item.avatar"
|
||||
:style="{ color: item.color }"
|
||||
:is="item.avatar"
|
||||
:style="item?.style ?? {}"
|
||||
class="size-[24px]"
|
||||
@click="item.action"
|
||||
@click="handleAuthBinding(item.source)"
|
||||
/>
|
||||
</span>
|
||||
</Tooltip>
|
||||
|
@@ -1,104 +1,102 @@
|
||||
import type { Component } from 'vue';
|
||||
import type { Component, CSSProperties } from 'vue';
|
||||
|
||||
import { ref } from 'vue';
|
||||
|
||||
import { DEFAULT_TENANT_ID } from '@vben/constants';
|
||||
import {
|
||||
AlipayIcon,
|
||||
DingdingIcon,
|
||||
GiteeIcon,
|
||||
GithubOAuthIcon,
|
||||
TaobaoIcon,
|
||||
SvgMaxKeyIcon,
|
||||
SvgTopiamIcon,
|
||||
SvgWechatIcon,
|
||||
} from '@vben/icons';
|
||||
|
||||
import { createGlobalState } from '@vueuse/core';
|
||||
|
||||
import { authBinding } from '#/api/core/auth';
|
||||
|
||||
/**
|
||||
* @description: 菜单
|
||||
* @param key key
|
||||
* @description: oauth登录
|
||||
* @param title 标题
|
||||
* @param description 描述
|
||||
* @param extra 按钮文字
|
||||
* @param avatar 图标
|
||||
* @param color 图标颜色可直接写英文颜色/hex
|
||||
*/
|
||||
export interface ListItem {
|
||||
key: string;
|
||||
title: string;
|
||||
description: string;
|
||||
extra?: string;
|
||||
avatar?: Component;
|
||||
color?: string;
|
||||
style?: CSSProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: 绑定账号
|
||||
* @param source 来源 如gitee github 与后端的social-callback?source=xxx对应
|
||||
* @param bound 是否已经绑定
|
||||
* @param action 账号绑定回调
|
||||
*/
|
||||
export interface BindItem extends ListItem {
|
||||
source: string;
|
||||
bound?: boolean;
|
||||
action?: (source: string) => Promise<any>;
|
||||
}
|
||||
|
||||
/**
|
||||
* todo tenantId
|
||||
* 绑定授权从userStore.userInfo获取
|
||||
* 登录从localStorage获取
|
||||
* 这里存储登录页的tenantId 由于个人中心也会用到 需要共享
|
||||
* 所以使用`createGlobalState`
|
||||
* @see https://vueuse.org/shared/createGlobalState/
|
||||
*/
|
||||
export const useLoginTenantId = createGlobalState(() => {
|
||||
const loginTenantId = ref(DEFAULT_TENANT_ID);
|
||||
|
||||
return {
|
||||
loginTenantId,
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* 绑定授权
|
||||
* @param source
|
||||
*/
|
||||
async function handleAuthBinding(source: string) {
|
||||
const tenantId = localStorage.getItem('__oauth_tenant_id') ?? '000000';
|
||||
export async function handleAuthBinding(source: string) {
|
||||
const { loginTenantId } = useLoginTenantId();
|
||||
// 这里返回打开授权页面的链接
|
||||
const href = await authBinding(source, tenantId);
|
||||
const href = await authBinding(source, loginTenantId.value);
|
||||
window.location.href = href;
|
||||
}
|
||||
|
||||
/**
|
||||
* 账号绑定 list
|
||||
* 添加账号绑定只需要在这里增加即可
|
||||
* 添加过的项目会在个人主页-绑定账号中显示
|
||||
* action不为空的会在登录页显示
|
||||
*/
|
||||
export const accountBindList: BindItem[] = [
|
||||
{
|
||||
avatar: TaobaoIcon,
|
||||
color: '#ff4000',
|
||||
description: '绑定淘宝账号',
|
||||
key: '1',
|
||||
source: 'taobao',
|
||||
title: '淘宝',
|
||||
},
|
||||
{
|
||||
avatar: AlipayIcon,
|
||||
color: '#2eabff',
|
||||
description: '绑定支付宝账号',
|
||||
key: '2',
|
||||
source: 'alipay',
|
||||
title: '支付宝',
|
||||
},
|
||||
{
|
||||
avatar: DingdingIcon,
|
||||
color: '#2eabff',
|
||||
description: '绑定钉钉账号',
|
||||
key: '3',
|
||||
source: 'ding',
|
||||
title: '钉钉',
|
||||
},
|
||||
{
|
||||
action: () => handleAuthBinding('gitee'),
|
||||
avatar: GiteeIcon,
|
||||
color: '#c71d23',
|
||||
description: '绑定GITEE账号',
|
||||
key: '4',
|
||||
description: '绑定Gitee账号',
|
||||
source: 'gitee',
|
||||
title: 'GITEE',
|
||||
title: 'Gitee',
|
||||
style: { color: '#c71d23' },
|
||||
},
|
||||
{
|
||||
action: () => handleAuthBinding('github'),
|
||||
avatar: GithubOAuthIcon,
|
||||
color: '',
|
||||
description: '绑定GITHUB账号',
|
||||
key: '5',
|
||||
description: '绑定Github账号',
|
||||
source: 'github',
|
||||
title: 'GITHUB',
|
||||
title: 'Github',
|
||||
},
|
||||
{
|
||||
avatar: SvgMaxKeyIcon,
|
||||
description: '绑定MaxKey账号',
|
||||
source: 'maxkey',
|
||||
title: 'MaxKey',
|
||||
},
|
||||
{
|
||||
avatar: SvgTopiamIcon,
|
||||
description: '绑定topiam账号',
|
||||
source: 'topiam',
|
||||
title: 'Topiam',
|
||||
},
|
||||
{
|
||||
avatar: SvgWechatIcon,
|
||||
description: '绑定wechat账号',
|
||||
source: 'wechat',
|
||||
title: 'Wechat',
|
||||
},
|
||||
];
|
||||
|
@@ -7,27 +7,12 @@ import { computed, ref, unref } from 'vue';
|
||||
|
||||
import { useVbenVxeGrid } from '@vben/plugins/vxe-table';
|
||||
|
||||
import {
|
||||
Alert,
|
||||
Avatar,
|
||||
Card,
|
||||
List,
|
||||
ListItem,
|
||||
message,
|
||||
Modal,
|
||||
} from 'ant-design-vue';
|
||||
import { Alert, Avatar, Card, List, ListItem, Modal } from 'ant-design-vue';
|
||||
|
||||
import { authUnbinding } from '#/api';
|
||||
import { socialList } from '#/api/system/social';
|
||||
|
||||
import { accountBindList } from '../../oauth-common';
|
||||
|
||||
/**
|
||||
* 没有传递action事件则不支持绑定 弹出默认提示
|
||||
*/
|
||||
function defaultTip(title: string) {
|
||||
message.info({ content: `暂不支持绑定${title}` });
|
||||
}
|
||||
import { accountBindList, handleAuthBinding } from '../../oauth-common';
|
||||
|
||||
function buttonText(item: BindItem) {
|
||||
return item.bound ? '已绑定' : '绑定';
|
||||
@@ -46,12 +31,6 @@ const bindList = computed<BindItem[]>(() => {
|
||||
});
|
||||
|
||||
const gridOptions: VxeGridProps = {
|
||||
checkboxConfig: {
|
||||
// 高亮
|
||||
highlight: true,
|
||||
// 翻页时保留选中状态
|
||||
reserve: true,
|
||||
},
|
||||
columns: [
|
||||
{
|
||||
field: 'source',
|
||||
@@ -147,14 +126,12 @@ function handleUnbind(record: Record<string, any>) {
|
||||
<ListItem>
|
||||
<Card>
|
||||
<div class="flex w-full items-center gap-4">
|
||||
<div>
|
||||
<component
|
||||
:is="item.avatar"
|
||||
v-if="item.avatar"
|
||||
:style="{ color: item.color }"
|
||||
class="size-[40px]"
|
||||
/>
|
||||
</div>
|
||||
<component
|
||||
:is="item.avatar"
|
||||
v-if="item.avatar"
|
||||
:style="item?.style ?? {}"
|
||||
class="size-[40px]"
|
||||
/>
|
||||
<div class="flex flex-1 items-center justify-between">
|
||||
<div class="flex flex-col">
|
||||
<h4
|
||||
@@ -170,9 +147,7 @@ function handleUnbind(record: Record<string, any>) {
|
||||
:disabled="item.bound"
|
||||
size="small"
|
||||
type="link"
|
||||
@click="
|
||||
item.action ? item.action() : defaultTip(item.title)
|
||||
"
|
||||
@click="handleAuthBinding(item.source)"
|
||||
>
|
||||
{{ buttonText(item) }}
|
||||
</a-button>
|
||||
@@ -191,10 +166,6 @@ function handleUnbind(record: Record<string, any>) {
|
||||
</span>
|
||||
中accountBindList按模板添加
|
||||
</p>
|
||||
<p>
|
||||
添加对应模板后会在此处显示绑定, 但只有
|
||||
<span class="font-bold">实现了action才能在登录页显示</span>
|
||||
</p>
|
||||
</template>
|
||||
</Alert>
|
||||
</div>
|
||||
|
@@ -1,6 +1,4 @@
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
|
||||
<script setup lang="ts">
|
||||
import { TabPane, Tabs } from 'ant-design-vue';
|
||||
|
||||
import AccountBind from './components/account-bind.vue';
|
||||
@@ -8,52 +6,34 @@ import BaseSetting from './components/base-setting.vue';
|
||||
import OnlineDevice from './components/online-device.vue';
|
||||
import SecureSetting from './components/secure-setting.vue';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
AccountBind,
|
||||
BaseSetting,
|
||||
OnlineDevice,
|
||||
SecureSetting,
|
||||
TabPane,
|
||||
Tabs,
|
||||
const settingList = [
|
||||
{
|
||||
component: BaseSetting,
|
||||
key: '1',
|
||||
name: '基本设置',
|
||||
},
|
||||
setup() {
|
||||
const settingList = [
|
||||
{
|
||||
component: 'BaseSetting',
|
||||
key: '1',
|
||||
name: '基本设置',
|
||||
},
|
||||
{
|
||||
component: 'SecureSetting',
|
||||
key: '2',
|
||||
name: '安全设置',
|
||||
},
|
||||
{
|
||||
component: 'AccountBind',
|
||||
key: '3',
|
||||
name: '账号绑定',
|
||||
},
|
||||
{
|
||||
component: 'OnlineDevice',
|
||||
key: '4',
|
||||
name: '在线设备',
|
||||
},
|
||||
];
|
||||
|
||||
return {
|
||||
settingList,
|
||||
};
|
||||
{
|
||||
component: SecureSetting,
|
||||
key: '2',
|
||||
name: '安全设置',
|
||||
},
|
||||
});
|
||||
{
|
||||
component: AccountBind,
|
||||
key: '3',
|
||||
name: '账号绑定',
|
||||
},
|
||||
{
|
||||
component: OnlineDevice,
|
||||
key: '4',
|
||||
name: '在线设备',
|
||||
},
|
||||
];
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Tabs class="bg-background rounded-[var(--radius)] px-[16px] lg:flex-1">
|
||||
<template v-for="item in settingList" :key="item.key">
|
||||
<TabPane :tab="item.name">
|
||||
<component :is="item.component" v-bind="$attrs" />
|
||||
</TabPane>
|
||||
</template>
|
||||
<TabPane v-for="item in settingList" :key="item.key" :tab="item.name">
|
||||
<component :is="item.component" v-bind="$attrs" />
|
||||
</TabPane>
|
||||
</Tabs>
|
||||
</template>
|
||||
|
@@ -4,7 +4,7 @@ import type { AuthApi } from '#/api';
|
||||
import { onMounted } from 'vue';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
|
||||
import { DEFAULT_HOME_PATH } from '@vben/constants';
|
||||
import { DEFAULT_HOME_PATH, DEFAULT_TENANT_ID } from '@vben/constants';
|
||||
import { useAccessStore } from '@vben/stores';
|
||||
|
||||
import { message } from 'ant-design-vue';
|
||||
@@ -22,7 +22,7 @@ const stateJson = JSON.parse(atob(state));
|
||||
// 来源
|
||||
const source = route.query.source as string;
|
||||
// 租户ID
|
||||
const defaultTenantId = '000000';
|
||||
const defaultTenantId = DEFAULT_TENANT_ID;
|
||||
const tenantId = (stateJson.tenantId as string) ?? defaultTenantId;
|
||||
const domain = stateJson.domain as string;
|
||||
|
||||
@@ -44,7 +44,7 @@ onMounted(async () => {
|
||||
try {
|
||||
// 已经实现的平台
|
||||
const currentClient = accountBindList.find(
|
||||
(item) => item.source === source && item.action,
|
||||
(item) => item.source === source,
|
||||
);
|
||||
if (!currentClient) {
|
||||
message.error({ content: `未找到${source}平台` });
|
||||
|
@@ -1,3 +1,4 @@
|
||||
<!-- 建议通过菜单配置成外链/内嵌 达到相同的效果且灵活性更高 -->
|
||||
<template>
|
||||
<iframe
|
||||
class="size-full"
|
||||
|
@@ -1,72 +1,61 @@
|
||||
<script lang="ts">
|
||||
import type { PropType } from 'vue';
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { EchartsUIType } from '@vben/plugins/echarts';
|
||||
|
||||
import { defineComponent, onActivated, onMounted, ref, watch } from 'vue';
|
||||
import { onActivated, onMounted, ref, watch } from 'vue';
|
||||
|
||||
import { EchartsUI, useEcharts } from '@vben/plugins/echarts';
|
||||
|
||||
export default defineComponent({
|
||||
components: { EchartsUI },
|
||||
props: {
|
||||
data: {
|
||||
default: () => [],
|
||||
type: Array as PropType<{ name: string; value: string }[]>,
|
||||
},
|
||||
},
|
||||
setup(props, { expose }) {
|
||||
expose({});
|
||||
interface Props {
|
||||
data?: { name: string; value: string }[];
|
||||
}
|
||||
|
||||
const chartRef = ref<EchartsUIType>();
|
||||
const { renderEcharts, resize } = useEcharts(chartRef);
|
||||
|
||||
watch(
|
||||
() => props.data,
|
||||
() => {
|
||||
if (!chartRef.value) return;
|
||||
setEchartsOption(props.data);
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
setEchartsOption(props.data);
|
||||
});
|
||||
/**
|
||||
* 从其他页面切换回来会有一个奇怪的动画效果 需要调用resize
|
||||
* 该饼图组件需要关闭animation
|
||||
*/
|
||||
onActivated(() => resize(false));
|
||||
|
||||
type EChartsOption = Parameters<typeof renderEcharts>['0'];
|
||||
function setEchartsOption(data: any[]) {
|
||||
const option: EChartsOption = {
|
||||
series: [
|
||||
{
|
||||
animationDuration: 1000,
|
||||
animationEasing: 'cubicInOut',
|
||||
center: ['50%', '50%'],
|
||||
data,
|
||||
name: '命令',
|
||||
radius: [15, 95],
|
||||
roseType: 'radius',
|
||||
type: 'pie',
|
||||
},
|
||||
],
|
||||
tooltip: {
|
||||
formatter: '{a} <br/>{b} : {c} ({d}%)',
|
||||
trigger: 'item',
|
||||
},
|
||||
};
|
||||
renderEcharts(option);
|
||||
}
|
||||
|
||||
return {
|
||||
chartRef,
|
||||
};
|
||||
},
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
data: () => [],
|
||||
});
|
||||
|
||||
const chartRef = ref<EchartsUIType>();
|
||||
const { renderEcharts, resize } = useEcharts(chartRef);
|
||||
|
||||
watch(
|
||||
() => props.data,
|
||||
() => {
|
||||
if (!chartRef.value) return;
|
||||
setEchartsOption(props.data);
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
setEchartsOption(props.data);
|
||||
});
|
||||
/**
|
||||
* 从其他页面切换回来会有一个奇怪的动画效果 需要调用resize
|
||||
* 该饼图组件需要关闭animation
|
||||
*/
|
||||
onActivated(() => resize(false));
|
||||
|
||||
type EChartsOption = Parameters<typeof renderEcharts>['0'];
|
||||
function setEchartsOption(data: any[]) {
|
||||
const option: EChartsOption = {
|
||||
series: [
|
||||
{
|
||||
animationDuration: 1000,
|
||||
animationEasing: 'cubicInOut',
|
||||
center: ['50%', '50%'],
|
||||
data,
|
||||
name: '命令',
|
||||
radius: [15, 95],
|
||||
roseType: 'radius',
|
||||
type: 'pie',
|
||||
},
|
||||
],
|
||||
tooltip: {
|
||||
formatter: '{a} <br/>{b} : {c} ({d}%)',
|
||||
trigger: 'item',
|
||||
},
|
||||
};
|
||||
renderEcharts(option);
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@@ -1,96 +1,87 @@
|
||||
<script lang="ts">
|
||||
<script setup lang="ts">
|
||||
import type { EchartsUIType } from '@vben/plugins/echarts';
|
||||
|
||||
import { defineComponent, onActivated, onMounted, ref, watch } from 'vue';
|
||||
import { onActivated, onMounted, ref, watch } from 'vue';
|
||||
|
||||
import { EchartsUI, useEcharts } from '@vben/plugins/echarts';
|
||||
|
||||
export default defineComponent({
|
||||
components: { EchartsUI },
|
||||
props: {
|
||||
data: {
|
||||
default: '0',
|
||||
type: String,
|
||||
},
|
||||
interface Props {
|
||||
data?: string;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
data: '0',
|
||||
});
|
||||
|
||||
const memoryHtmlRef = ref<EchartsUIType>();
|
||||
const { renderEcharts, resize } = useEcharts(memoryHtmlRef);
|
||||
|
||||
watch(
|
||||
() => props.data,
|
||||
() => {
|
||||
if (!memoryHtmlRef.value) return;
|
||||
setEchartsOption(props.data);
|
||||
},
|
||||
setup(props, { expose }) {
|
||||
expose({});
|
||||
{ immediate: true },
|
||||
);
|
||||
|
||||
const memoryHtmlRef = ref<EchartsUIType>();
|
||||
const { renderEcharts, resize } = useEcharts(memoryHtmlRef);
|
||||
onMounted(() => {
|
||||
setEchartsOption(props.data);
|
||||
});
|
||||
// 从其他页面切换回来会有一个奇怪的动画效果 需要调用resize
|
||||
onActivated(resize);
|
||||
|
||||
watch(
|
||||
() => props.data,
|
||||
() => {
|
||||
if (!memoryHtmlRef.value) return;
|
||||
setEchartsOption(props.data);
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
/**
|
||||
* 获取最近的十的幂次
|
||||
* 该函数用于寻找大于给定数字num的最近的10的幂次
|
||||
* 主要解决的问题是确定一个数附近较大的十的幂次,这在某些算法中很有用
|
||||
*
|
||||
* @param num {number} 输入的数字,用于寻找最近的十的幂次
|
||||
*/
|
||||
function getNearestPowerOfTen(num: number) {
|
||||
let power = 10;
|
||||
while (power <= num) {
|
||||
power *= 10;
|
||||
}
|
||||
return power;
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
setEchartsOption(props.data);
|
||||
});
|
||||
// 从其他页面切换回来会有一个奇怪的动画效果 需要调用resize
|
||||
onActivated(resize);
|
||||
|
||||
/**
|
||||
* 获取最近的十的幂次
|
||||
* 该函数用于寻找大于给定数字num的最近的10的幂次
|
||||
* 主要解决的问题是确定一个数附近较大的十的幂次,这在某些算法中很有用
|
||||
*
|
||||
* @param num {number} 输入的数字,用于寻找最近的十的幂次
|
||||
*/
|
||||
function getNearestPowerOfTen(num: number) {
|
||||
let power = 10;
|
||||
while (power <= num) {
|
||||
power *= 10;
|
||||
}
|
||||
return power;
|
||||
}
|
||||
|
||||
type EChartsOption = Parameters<typeof renderEcharts>['0'];
|
||||
function setEchartsOption(value: string) {
|
||||
// x10
|
||||
const formattedValue = Math.floor(Number.parseFloat(value));
|
||||
// 最大值 10以内取10 100以内取100 以此类推
|
||||
const max = getNearestPowerOfTen(formattedValue);
|
||||
const options: EChartsOption = {
|
||||
series: [
|
||||
type EChartsOption = Parameters<typeof renderEcharts>['0'];
|
||||
function setEchartsOption(value: string) {
|
||||
// x10
|
||||
const formattedValue = Math.floor(Number.parseFloat(value));
|
||||
// 最大值 10以内取10 100以内取100 以此类推
|
||||
const max = getNearestPowerOfTen(formattedValue);
|
||||
const options: EChartsOption = {
|
||||
series: [
|
||||
{
|
||||
animation: true,
|
||||
animationDuration: 1000,
|
||||
data: [
|
||||
{
|
||||
animation: true,
|
||||
animationDuration: 1000,
|
||||
data: [
|
||||
{
|
||||
name: '内存消耗',
|
||||
value: Number.parseFloat(value),
|
||||
},
|
||||
],
|
||||
detail: {
|
||||
formatter: `${value}M`,
|
||||
valueAnimation: true,
|
||||
},
|
||||
max,
|
||||
min: 0,
|
||||
name: '峰值',
|
||||
progress: {
|
||||
show: true,
|
||||
},
|
||||
type: 'gauge',
|
||||
name: '内存消耗',
|
||||
value: Number.parseFloat(value),
|
||||
},
|
||||
],
|
||||
tooltip: {
|
||||
formatter: `{b} <br/>{a} : ${value}M`,
|
||||
detail: {
|
||||
formatter: `${value}M`,
|
||||
valueAnimation: true,
|
||||
},
|
||||
};
|
||||
renderEcharts(options);
|
||||
}
|
||||
|
||||
return {
|
||||
memoryHtmlRef,
|
||||
};
|
||||
},
|
||||
});
|
||||
max,
|
||||
min: 0,
|
||||
name: '峰值',
|
||||
progress: {
|
||||
show: true,
|
||||
},
|
||||
type: 'gauge',
|
||||
},
|
||||
],
|
||||
tooltip: {
|
||||
formatter: `{b} <br/>{a} : ${value}M`,
|
||||
},
|
||||
};
|
||||
renderEcharts(options);
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@@ -1,6 +1,4 @@
|
||||
<script setup lang="ts">
|
||||
import type { PropType } from 'vue';
|
||||
|
||||
import type { RedisInfo } from '#/api/monitor/cache';
|
||||
import type { DescItem } from '#/components/description';
|
||||
|
||||
@@ -12,12 +10,7 @@ interface IRedisInfo extends RedisInfo {
|
||||
dbSize: string;
|
||||
}
|
||||
|
||||
const props = defineProps({
|
||||
data: {
|
||||
required: true,
|
||||
type: Object as PropType<IRedisInfo>,
|
||||
},
|
||||
});
|
||||
const props = defineProps<{ data: IRedisInfo }>();
|
||||
|
||||
const descSchemas: DescItem[] = [
|
||||
{ field: 'redis_version', label: 'redis版本' },
|
||||
|
@@ -1,3 +1,4 @@
|
||||
<!-- 建议通过菜单配置成外链/内嵌 达到相同的效果且灵活性更高 -->
|
||||
<template>
|
||||
<iframe class="size-full" src="http://localhost:8800/snail-job"></iframe>
|
||||
</template>
|
||||
|
@@ -6,20 +6,13 @@ import { Input } from 'ant-design-vue';
|
||||
|
||||
defineOptions({ name: 'SecretInput' });
|
||||
|
||||
defineProps({
|
||||
disabled: {
|
||||
default: false,
|
||||
type: Boolean,
|
||||
},
|
||||
placeholder: {
|
||||
default: '请输入密钥或随机生成',
|
||||
type: String,
|
||||
},
|
||||
withDefaults(defineProps<{ disabled?: boolean; placeholder?: string }>(), {
|
||||
disabled: false,
|
||||
placeholder: '请输入密钥或随机生成',
|
||||
});
|
||||
|
||||
const value = defineModel<string>('value', {
|
||||
required: false,
|
||||
type: String,
|
||||
});
|
||||
|
||||
function refreshSecret() {
|
||||
|
@@ -76,7 +76,7 @@ const { validate, validateInfos, resetFields } = Form.useForm(
|
||||
|
||||
const [BasicModal, modalApi] = useVbenModal({
|
||||
class: 'w-[800px]',
|
||||
fullscreenButton: false,
|
||||
fullscreenButton: true,
|
||||
closeOnClickModal: false,
|
||||
onClosed: handleCancel,
|
||||
onConfirm: handleConfirm,
|
||||
|
@@ -160,7 +160,7 @@ export const drawerSchema: FormSchemaGetter = () => [
|
||||
component: 'Textarea',
|
||||
defaultValue: '',
|
||||
fieldName: 'remark',
|
||||
formItemClass: 'items-baseline col-span-2',
|
||||
formItemClass: 'col-span-2',
|
||||
label: '备注',
|
||||
},
|
||||
];
|
||||
@@ -219,7 +219,6 @@ export const authModalSchemas: FormSchemaGetter = () => [
|
||||
triggerFields: ['dataScope'],
|
||||
},
|
||||
fieldName: 'deptIds',
|
||||
formItemClass: 'items-start',
|
||||
help: '更改后立即生效',
|
||||
label: '部门权限',
|
||||
},
|
||||
|
@@ -174,7 +174,9 @@ function handleInfo(row: Required<LeaveForm>) {
|
||||
撤销
|
||||
</ghost-button>
|
||||
</Popconfirm>
|
||||
<ghost-button @click="handleInfo(row)">详情</ghost-button>
|
||||
<ghost-button v-if="row.status !== 'draft'" @click="handleInfo(row)">
|
||||
详情
|
||||
</ghost-button>
|
||||
<Popconfirm
|
||||
:get-popup-container="getVxePopupContainer"
|
||||
placement="left"
|
||||
|
@@ -62,7 +62,7 @@ function handleCancel() {
|
||||
:before-upload="() => false"
|
||||
:max-count="1"
|
||||
:show-upload-list="true"
|
||||
accept="text/json"
|
||||
accept="application/json"
|
||||
>
|
||||
<p class="ant-upload-drag-icon flex items-center justify-center">
|
||||
<InBoxIcon class="text-primary size-[48px]" />
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben/docs",
|
||||
"version": "5.5.3",
|
||||
"version": "5.5.4",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "vitepress build",
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben/commitlint-config",
|
||||
"version": "5.5.3",
|
||||
"version": "5.5.4",
|
||||
"private": true,
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben/stylelint-config",
|
||||
"version": "5.5.3",
|
||||
"version": "5.5.4",
|
||||
"private": true,
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben/node-utils",
|
||||
"version": "5.5.3",
|
||||
"version": "5.5.4",
|
||||
"private": true,
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben/tailwind-config",
|
||||
"version": "5.5.3",
|
||||
"version": "5.5.4",
|
||||
"private": true,
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben/tsconfig",
|
||||
"version": "5.5.3",
|
||||
"version": "5.5.4",
|
||||
"private": true,
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben/vite-config",
|
||||
"version": "5.5.3",
|
||||
"version": "5.5.4",
|
||||
"private": true,
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "vben-admin-monorepo",
|
||||
"version": "5.5.3",
|
||||
"version": "5.5.4",
|
||||
"private": true,
|
||||
"keywords": [
|
||||
"monorepo",
|
||||
@@ -28,6 +28,7 @@
|
||||
"build": "cross-env NODE_OPTIONS=--max-old-space-size=8192 turbo build",
|
||||
"build:analyze": "turbo build:analyze",
|
||||
"build:antd": "pnpm run build --filter=@vben/web-antd",
|
||||
"build:antd:test": "pnpm run build --filter=@vben/web-antd -- --mode test",
|
||||
"build:docker": "./scripts/deploy/build-local-docker-image.sh",
|
||||
"build:docs": "pnpm run build --filter=@vben/docs",
|
||||
"build:play": "pnpm run build --filter=@vben/playground",
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben-core/design",
|
||||
"version": "5.5.3",
|
||||
"version": "5.5.4",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben-core/icons",
|
||||
"version": "5.5.3",
|
||||
"version": "5.5.4",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben-core/shared",
|
||||
"version": "5.5.3",
|
||||
"version": "5.5.4",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
@@ -88,6 +88,7 @@
|
||||
"lodash.clonedeep": "catalog:",
|
||||
"lodash.get": "catalog:",
|
||||
"lodash.isequal": "catalog:",
|
||||
"lodash.set": "catalog:",
|
||||
"nprogress": "catalog:",
|
||||
"tailwind-merge": "catalog:",
|
||||
"theme-colors": "catalog:"
|
||||
@@ -96,6 +97,7 @@
|
||||
"@types/lodash.clonedeep": "catalog:",
|
||||
"@types/lodash.get": "catalog:",
|
||||
"@types/lodash.isequal": "catalog:",
|
||||
"@types/lodash.set": "catalog:",
|
||||
"@types/nprogress": "catalog:"
|
||||
}
|
||||
}
|
||||
|
@@ -17,3 +17,4 @@ export * from './window';
|
||||
export { default as cloneDeep } from 'lodash.clonedeep';
|
||||
export { default as get } from 'lodash.get';
|
||||
export { default as isEqual } from 'lodash.isequal';
|
||||
export { default as set } from 'lodash.set';
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben-core/typings",
|
||||
"version": "5.5.3",
|
||||
"version": "5.5.4",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben-core/composables",
|
||||
"version": "5.5.3",
|
||||
"version": "5.5.4",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben-core/preferences",
|
||||
"version": "5.5.3",
|
||||
"version": "5.5.4",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben-core/form-ui",
|
||||
"version": "5.5.3",
|
||||
"version": "5.5.4",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@@ -290,6 +290,7 @@ onUnmounted(() => {
|
||||
v-show="isShow"
|
||||
:class="{
|
||||
'form-valid-error': isInValid,
|
||||
'form-is-required': shouldRequired,
|
||||
'flex-col': isVertical,
|
||||
'flex-row items-center': !isVertical,
|
||||
'pb-6': !compact,
|
||||
@@ -320,7 +321,7 @@ onUnmounted(() => {
|
||||
<VbenRenderContent :content="label" />
|
||||
</template>
|
||||
</FormLabel>
|
||||
<div class="flex-auto overflow-hidden">
|
||||
<div class="flex-auto overflow-hidden p-[1px]">
|
||||
<div :class="cn('relative flex w-full items-center', wrapperClass)">
|
||||
<FormControl :class="cn(controlClass)">
|
||||
<slot
|
||||
|
@@ -7,7 +7,7 @@ import type { ExtendedFormApi, FormActions, VbenFormProps } from './types';
|
||||
import { computed, unref, useSlots } from 'vue';
|
||||
|
||||
import { createContext } from '@vben-core/shadcn-ui';
|
||||
import { isString } from '@vben-core/shared/utils';
|
||||
import { isString, mergeWithArrayOverride, set } from '@vben-core/shared/utils';
|
||||
|
||||
import { useForm } from 'vee-validate';
|
||||
import { object } from 'zod';
|
||||
@@ -50,7 +50,7 @@ export function useFormInitial(
|
||||
const zodObject: ZodRawShape = {};
|
||||
(unref(props).schema || []).forEach((item) => {
|
||||
if (Reflect.has(item, 'defaultValue')) {
|
||||
initialValues[item.fieldName] = item.defaultValue;
|
||||
set(initialValues, item.fieldName, item.defaultValue);
|
||||
} else if (item.rules && !isString(item.rules)) {
|
||||
zodObject[item.fieldName] = item.rules;
|
||||
}
|
||||
@@ -58,7 +58,11 @@ export function useFormInitial(
|
||||
|
||||
const schemaInitialValues = getDefaultsForSchema(object(zodObject));
|
||||
|
||||
return { ...initialValues, ...schemaInitialValues };
|
||||
const zodDefaults: Record<string, any> = {};
|
||||
for (const key in schemaInitialValues) {
|
||||
set(zodDefaults, key, schemaInitialValues[key]);
|
||||
}
|
||||
return mergeWithArrayOverride(initialValues, zodDefaults);
|
||||
}
|
||||
|
||||
return {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben-core/layout-ui",
|
||||
"version": "5.5.3",
|
||||
"version": "5.5.4",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben-core/menu-ui",
|
||||
"version": "5.5.3",
|
||||
"version": "5.5.4",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben-core/shadcn-ui",
|
||||
"version": "5.5.3",
|
||||
"version": "5.5.4",
|
||||
"#main": "./dist/index.mjs",
|
||||
"#module": "./dist/index.mjs",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
|
@@ -1,22 +1,18 @@
|
||||
<script setup lang="ts">
|
||||
import { Input as VbenInput } from '../../ui/input';
|
||||
/**
|
||||
* 非通用组件 直接按业务来写
|
||||
*/
|
||||
defineProps({
|
||||
captcha: {
|
||||
default: '',
|
||||
type: String,
|
||||
|
||||
withDefaults(
|
||||
defineProps<{
|
||||
captcha?: string;
|
||||
label?: string;
|
||||
placeholder?: string;
|
||||
}>(),
|
||||
{
|
||||
captcha: '',
|
||||
label: '验证码',
|
||||
placeholder: '请输入验证码',
|
||||
},
|
||||
label: {
|
||||
default: '验证码',
|
||||
type: String,
|
||||
},
|
||||
placeholder: {
|
||||
default: '验证码',
|
||||
type: String,
|
||||
},
|
||||
});
|
||||
);
|
||||
|
||||
defineEmits<{ captchaClick: [] }>();
|
||||
|
||||
@@ -31,7 +27,7 @@ const modelValue = defineModel({ default: '', type: String });
|
||||
autocomplete="off"
|
||||
id="code"
|
||||
v-model="modelValue"
|
||||
:class="$attrs.class ?? {}"
|
||||
:class="$attrs?.class ?? {}"
|
||||
:label="label"
|
||||
:placeholder="placeholder"
|
||||
name="code"
|
||||
@@ -41,7 +37,7 @@ const modelValue = defineModel({ default: '', type: String });
|
||||
</div>
|
||||
<img
|
||||
:src="captcha"
|
||||
class="h-[40px] w-[115px] rounded-r-md"
|
||||
class="h-[40px] w-[115px] cursor-pointer rounded-r-md"
|
||||
@click="$emit('captchaClick')"
|
||||
/>
|
||||
</div>
|
||||
|
@@ -34,4 +34,8 @@ const props = defineProps<Props>();
|
||||
button[role='combobox'][data-placeholder] {
|
||||
color: hsl(var(--muted-foreground));
|
||||
}
|
||||
|
||||
button {
|
||||
--ring: var(--primary);
|
||||
}
|
||||
</style>
|
||||
|
@@ -24,9 +24,14 @@ const modelValue = useVModel(props, 'modelValue', emits, {
|
||||
v-model="modelValue"
|
||||
:class="
|
||||
cn(
|
||||
'border-input bg-background ring-offset-background placeholder:text-muted-foreground focus-visible:ring-ring flex h-10 w-full rounded-md border px-3 py-2 text-sm file:border-0 file:bg-transparent file:text-sm file:font-medium focus-visible:outline-none focus-visible:ring-1 disabled:cursor-not-allowed disabled:opacity-50',
|
||||
'border-input bg-background ring-offset-background placeholder:text-muted-foreground flex h-10 w-full rounded-md border px-3 py-2 text-sm file:border-0 file:bg-transparent file:text-sm file:font-medium focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50',
|
||||
props.class,
|
||||
)
|
||||
"
|
||||
/>
|
||||
</template>
|
||||
<style lang="scss" scoped>
|
||||
input {
|
||||
--ring: var(--primary);
|
||||
}
|
||||
</style>
|
||||
|
@@ -1,12 +1,14 @@
|
||||
<script setup lang="ts">
|
||||
import type { SelectTriggerProps } from 'radix-vue';
|
||||
|
||||
import { cn } from '@vben-core/shared/utils';
|
||||
import { ChevronDown } from 'lucide-vue-next';
|
||||
import { SelectIcon, SelectTrigger, useForwardProps } from 'radix-vue';
|
||||
import { computed } from 'vue';
|
||||
|
||||
const props = defineProps<{ class?: any } & SelectTriggerProps>();
|
||||
import { cn } from '@vben-core/shared/utils';
|
||||
|
||||
import { ChevronDown } from 'lucide-vue-next';
|
||||
import { SelectIcon, SelectTrigger, useForwardProps } from 'radix-vue';
|
||||
|
||||
const props = defineProps<SelectTriggerProps & { class?: any }>();
|
||||
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props;
|
||||
@@ -22,7 +24,7 @@ const forwardedProps = useForwardProps(delegatedProps);
|
||||
v-bind="forwardedProps"
|
||||
:class="
|
||||
cn(
|
||||
'border-input ring-offset-background placeholder:text-muted-foreground focus:ring-ring flex h-10 w-full items-center justify-between whitespace-nowrap rounded-md border bg-transparent px-3 py-2 text-sm shadow-sm focus:outline-none focus:ring-1 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1',
|
||||
'border-input ring-offset-background placeholder:text-muted-foreground flex h-10 w-full items-center justify-between whitespace-nowrap rounded-md border bg-transparent px-3 py-2 text-sm shadow-sm focus:outline-none disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1',
|
||||
props.class,
|
||||
)
|
||||
"
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben-core/tabs-ui",
|
||||
"version": "5.5.3",
|
||||
"version": "5.5.4",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben/constants",
|
||||
"version": "5.5.3",
|
||||
"version": "5.5.4",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@@ -26,3 +26,8 @@ export const SUPPORT_LANGUAGES: LanguageOption[] = [
|
||||
value: 'en-US',
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* 默认租户ID
|
||||
*/
|
||||
export const DEFAULT_TENANT_ID = '000000';
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben/access",
|
||||
"version": "5.5.3",
|
||||
"version": "5.5.4",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben/common-ui",
|
||||
"version": "5.5.3",
|
||||
"version": "5.5.4",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@@ -2,7 +2,6 @@
|
||||
import {
|
||||
onBeforeUnmount,
|
||||
onMounted,
|
||||
type PropType,
|
||||
shallowRef,
|
||||
useTemplateRef,
|
||||
watch,
|
||||
@@ -14,18 +13,14 @@ import Vditor from 'vditor';
|
||||
|
||||
import 'vditor/dist/index.css';
|
||||
|
||||
const props = defineProps({
|
||||
// 编辑器高度
|
||||
height: {
|
||||
// string或者number类型
|
||||
type: [String, Number],
|
||||
default: 500,
|
||||
},
|
||||
// 其他配置项
|
||||
options: {
|
||||
type: Object as PropType<IOptions>,
|
||||
default: () => ({}),
|
||||
},
|
||||
interface Props {
|
||||
height?: number | string;
|
||||
options?: IOptions;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
height: 500,
|
||||
options: () => ({}),
|
||||
});
|
||||
|
||||
const emit = defineEmits<{
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben/hooks",
|
||||
"version": "5.5.3",
|
||||
"version": "5.5.4",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben/layouts",
|
||||
"version": "5.5.3",
|
||||
"version": "5.5.4",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@@ -17,6 +17,7 @@ interface Props {
|
||||
toolbar?: boolean;
|
||||
copyright?: boolean;
|
||||
toolbarList?: ToolbarType[];
|
||||
clickLogo?: () => void;
|
||||
}
|
||||
|
||||
withDefaults(defineProps<Props>(), {
|
||||
@@ -28,6 +29,7 @@ withDefaults(defineProps<Props>(), {
|
||||
sloganImage: '',
|
||||
toolbar: true,
|
||||
toolbarList: () => ['color', 'language', 'layout', 'theme'],
|
||||
clickLogo: () => {},
|
||||
});
|
||||
|
||||
const { authPanelCenter, authPanelLeft, authPanelRight, isDark } =
|
||||
@@ -61,7 +63,11 @@ const { authPanelCenter, authPanelLeft, authPanelRight, isDark } =
|
||||
</AuthenticationFormView>
|
||||
|
||||
<!-- 头部 Logo 和应用名称 -->
|
||||
<div v-if="logo || appName" class="absolute left-0 top-0 z-10 flex flex-1">
|
||||
<div
|
||||
v-if="logo || appName"
|
||||
class="absolute left-0 top-0 z-10 flex flex-1"
|
||||
@click="clickLogo"
|
||||
>
|
||||
<div
|
||||
class="text-foreground lg:text-foreground ml-4 mt-4 flex flex-1 items-center sm:left-6 sm:top-6"
|
||||
>
|
||||
|
@@ -34,7 +34,7 @@ import { LayoutTabbar } from './tabbar';
|
||||
|
||||
defineOptions({ name: 'BasicLayout' });
|
||||
|
||||
const emit = defineEmits<{ clearPreferencesAndLogout: [] }>();
|
||||
const emit = defineEmits<{ clearPreferencesAndLogout: []; clickLogo: [] }>();
|
||||
|
||||
const {
|
||||
isDark,
|
||||
@@ -149,6 +149,10 @@ function clearPreferencesAndLogout() {
|
||||
emit('clearPreferencesAndLogout');
|
||||
}
|
||||
|
||||
function clickLogo() {
|
||||
emit('clickLogo');
|
||||
}
|
||||
|
||||
watch(
|
||||
() => preferences.app.layout,
|
||||
async (val) => {
|
||||
@@ -221,6 +225,7 @@ const headerSlots = computed(() => {
|
||||
:src="preferences.logo.source"
|
||||
:text="preferences.app.name"
|
||||
:theme="showHeaderNav ? headerTheme : theme"
|
||||
@click="clickLogo"
|
||||
/>
|
||||
</template>
|
||||
<!-- 头部区域 -->
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben/plugins",
|
||||
"version": "5.5.3",
|
||||
"version": "5.5.4",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@@ -29,7 +29,7 @@ import { usePriorityValues } from '@vben/hooks';
|
||||
import { EmptyIcon } from '@vben/icons';
|
||||
import { $t } from '@vben/locales';
|
||||
import { usePreferences } from '@vben/preferences';
|
||||
import { cloneDeep, cn, mergeWithArrayOverride } from '@vben/utils';
|
||||
import { cloneDeep, cn, isEqual, mergeWithArrayOverride } from '@vben/utils';
|
||||
|
||||
import { VbenHelpTooltip, VbenLoading } from '@vben-core/shadcn-ui';
|
||||
|
||||
@@ -81,10 +81,14 @@ const [Form, formApi] = useTableForm({
|
||||
props.api.reload(formValues);
|
||||
},
|
||||
handleReset: async () => {
|
||||
const prevValues = await formApi.getValues();
|
||||
await formApi.resetForm();
|
||||
const formValues = await formApi.getValues();
|
||||
formApi.setLatestSubmissionValues(formValues);
|
||||
props.api.reload(formValues);
|
||||
// 如果值发生了变化,submitOnChange会触发刷新。所以只在submitOnChange为false或者值没有发生变化时,手动刷新
|
||||
if (isEqual(prevValues, formValues) || !formOptions.value?.submitOnChange) {
|
||||
props.api.reload(formValues);
|
||||
}
|
||||
},
|
||||
commonConfig: {
|
||||
componentProps: {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben/request",
|
||||
"version": "5.5.3",
|
||||
"version": "5.5.4",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben/icons",
|
||||
"version": "5.5.3",
|
||||
"version": "5.5.4",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
12
packages/icons/src/svg/icons/max-key.svg
Normal file
12
packages/icons/src/svg/icons/max-key.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 10 KiB |
1
packages/icons/src/svg/icons/qq.svg
Normal file
1
packages/icons/src/svg/icons/qq.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1742793724632" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6397" xmlns:xlink="http://www.w3.org/1999/xlink" width="256" height="256"><path d="M511.09761 957.257c-80.159 0-153.737-25.019-201.11-62.386-24.057 6.702-54.831 17.489-74.252 30.864-16.617 11.439-14.546 23.106-11.55 27.816 13.15 20.689 225.583 13.211 286.912 6.767v-3.061z" fill="#FAAD08" p-id="6398"></path><path d="M496.65061 957.257c80.157 0 153.737-25.019 201.11-62.386 24.057 6.702 54.83 17.489 74.253 30.864 16.616 11.439 14.543 23.106 11.55 27.816-13.15 20.689-225.584 13.211-286.914 6.767v-3.061z" fill="#FAAD08" p-id="6399"></path><path d="M497.12861 474.524c131.934-0.876 237.669-25.783 273.497-35.34 8.541-2.28 13.11-6.364 13.11-6.364 0.03-1.172 0.542-20.952 0.542-31.155C784.27761 229.833 701.12561 57.173 496.64061 57.162 292.15661 57.173 209.00061 229.832 209.00061 401.665c0 10.203 0.516 29.983 0.547 31.155 0 0 3.717 3.821 10.529 5.67 33.078 8.98 140.803 35.139 276.08 36.034h0.972z" fill="#000000" p-id="6400"></path><path d="M860.28261 619.782c-8.12-26.086-19.204-56.506-30.427-85.72 0 0-6.456-0.795-9.718 0.148-100.71 29.205-222.773 47.818-315.792 46.695h-0.962C410.88561 582.017 289.65061 563.617 189.27961 534.698 185.44461 533.595 177.87261 534.063 177.87261 534.063 166.64961 563.276 155.56661 593.696 147.44761 619.782 108.72961 744.168 121.27261 795.644 130.82461 796.798c20.496 2.474 79.78-93.637 79.78-93.637 0 97.66 88.324 247.617 290.576 248.996a718.01 718.01 0 0 1 5.367 0C708.80161 950.778 797.12261 800.822 797.12261 703.162c0 0 59.284 96.111 79.783 93.637 9.55-1.154 22.093-52.63-16.623-177.017" fill="#000000" p-id="6401"></path><path d="M434.38261 316.917c-27.9 1.24-51.745-30.106-53.24-69.956-1.518-39.877 19.858-73.207 47.764-74.454 27.875-1.224 51.703 30.109 53.218 69.974 1.527 39.877-19.853 73.2-47.742 74.436m206.67-69.956c-1.494 39.85-25.34 71.194-53.24 69.956-27.888-1.238-49.269-34.559-47.742-74.435 1.513-39.868 25.341-71.201 53.216-69.974 27.909 1.247 49.285 34.576 47.767 74.453" fill="#FFFFFF" p-id="6402"></path><path d="M683.94261 368.627c-7.323-17.609-81.062-37.227-172.353-37.227h-0.98c-91.29 0-165.031 19.618-172.352 37.227a6.244 6.244 0 0 0-0.535 2.505c0 1.269 0.393 2.414 1.006 3.386 6.168 9.765 88.054 58.018 171.882 58.018h0.98c83.827 0 165.71-48.25 171.881-58.016a6.352 6.352 0 0 0 1.002-3.395c0-0.897-0.2-1.736-0.531-2.498" fill="#FAAD08" p-id="6403"></path><path d="M467.63161 256.377c1.26 15.886-7.377 30-19.266 31.542-11.907 1.544-22.569-10.083-23.836-25.978-1.243-15.895 7.381-30.008 19.25-31.538 11.927-1.549 22.607 10.088 23.852 25.974m73.097 7.935c2.533-4.118 19.827-25.77 55.62-17.886 9.401 2.07 13.75 5.116 14.668 6.316 1.355 1.77 1.726 4.29 0.352 7.684-2.722 6.725-8.338 6.542-11.454 5.226-2.01-0.85-26.94-15.889-49.905 6.553-1.579 1.545-4.405 2.074-7.085 0.242-2.678-1.834-3.786-5.553-2.196-8.135" fill="#000000" p-id="6404"></path><path d="M504.33261 584.495h-0.967c-63.568 0.752-140.646-7.504-215.286-21.92-6.391 36.262-10.25 81.838-6.936 136.196 8.37 137.384 91.62 223.736 220.118 224.996H506.48461c128.498-1.26 211.748-87.612 220.12-224.996 3.314-54.362-0.547-99.938-6.94-136.203-74.654 14.423-151.745 22.684-215.332 21.927" fill="#FFFFFF" p-id="6405"></path><path d="M323.27461 577.016v137.468s64.957 12.705 130.031 3.91V591.59c-41.225-2.262-85.688-7.304-130.031-14.574" fill="#EB1C26" p-id="6406"></path><path d="M788.09761 432.536s-121.98 40.387-283.743 41.539h-0.962c-161.497-1.147-283.328-41.401-283.744-41.539l-40.854 106.952c102.186 32.31 228.837 53.135 324.598 51.926l0.96-0.002c95.768 1.216 222.4-19.61 324.6-51.924l-40.855-106.952z" fill="#EB1C26" p-id="6407"></path></svg>
|
After Width: | Height: | Size: 3.7 KiB |
29
packages/icons/src/svg/icons/topiam.svg
Normal file
29
packages/icons/src/svg/icons/topiam.svg
Normal file
@@ -0,0 +1,29 @@
|
||||
<svg width="200" height="200" viewBox="0 0 200 200" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_446_540)">
|
||||
<path d="M113.069 160.072C103.717 170.743 93.0453 180.216 81.5345 188.609C61.5105 174.46 44.3642 156.595 30.9349 135.971C23.5009 124.46 17.2659 112.11 12.4697 99.0407C9.592 91.3668 7.19392 83.3332 5.27545 75.2996C2.03803 61.3907 0.359375 47.0022 0.359375 32.1341C0.359375 30.6953 0.359375 29.1365 0.359375 27.6977C6.35459 23.9806 12.7095 20.7432 19.0644 17.7456C20.7431 32.1341 24.1004 46.043 28.8966 59.3524C31.6544 66.9063 34.7719 74.3404 38.4889 81.4147C44.604 93.5251 52.0381 104.796 60.4314 115.228C75.1796 133.093 92.9254 148.321 113.069 160.072Z" fill="url(#paint0_linear_446_540)"/>
|
||||
<path d="M196.643 67.6256C195.084 76.3786 192.926 84.8918 190.168 93.1652C178.897 91.1269 167.266 90.0477 155.276 90.0477C154.197 90.0477 153.118 90.0477 152.039 90.0477C126.859 90.4074 102.878 95.6832 80.9352 105.036C72.302 94.8439 64.868 83.453 58.9927 71.3427C81.6546 61.8702 106.475 56.7144 132.614 56.7144C141.487 56.7144 150.24 57.3139 158.753 58.5129C171.823 60.1916 184.533 63.3091 196.643 67.6256Z" fill="url(#paint1_linear_446_540)"/>
|
||||
<path d="M199.64 34.0528C199.64 39.2087 199.401 44.3646 199.041 49.4005C186.691 44.1247 173.621 40.048 160.072 37.53C148.321 35.2518 136.211 34.0528 123.981 34.0528C97.7218 34.0528 72.6619 39.3286 49.88 48.9209C42.6858 51.9185 35.7313 55.3958 29.0167 59.2327C24.2205 46.0432 20.8632 32.0144 19.1846 17.6259C26.6186 14.1487 34.2925 11.271 42.2062 8.75301C60.3117 3.11751 79.4964 0 99.4005 0C119.904 0 139.568 3.23741 158.153 9.11272C172.782 13.789 186.691 20.2638 199.52 28.1775C199.64 30.2159 199.64 32.1343 199.64 34.0528Z" fill="url(#paint2_linear_446_540)"/>
|
||||
<path d="M190.168 93.2855C182.494 116.547 170.384 137.65 154.796 155.875C149.76 161.751 144.364 167.386 138.609 172.542C126.858 183.214 113.789 192.446 99.7601 200C93.4052 196.523 87.41 192.686 81.5347 188.609C93.0455 180.336 103.717 170.744 113.069 160.072C117.866 154.676 122.302 148.921 126.499 143.046C137.65 127.098 146.403 109.233 152.158 90.1679C153.237 90.1679 154.316 90.1679 155.396 90.1679C167.146 90.048 178.777 91.1272 190.168 93.2855Z" fill="url(#paint3_linear_446_540)"/>
|
||||
</g>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_446_540" x1="15.8569" y1="27.5782" x2="86.4712" y2="182.06" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#57A4F7"/>
|
||||
<stop offset="1" stop-color="#2158F9"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_446_540" x1="58.9501" y1="80.8427" x2="196.648" y2="80.8427" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#2158F9"/>
|
||||
<stop offset="1" stop-color="#33E1E5"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint2_linear_446_540" x1="19.1564" y1="29.6353" x2="199.647" y2="29.6353" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#255DF9"/>
|
||||
<stop offset="1" stop-color="#7C35BA"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint3_linear_446_540" x1="95.3808" y1="192.567" x2="174.674" y2="97.4815" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#54A0F7"/>
|
||||
<stop offset="1" stop-color="#2158F9"/>
|
||||
</linearGradient>
|
||||
<clipPath id="clip0_446_540">
|
||||
<rect width="200" height="200" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 3.1 KiB |
1
packages/icons/src/svg/icons/wechat.svg
Normal file
1
packages/icons/src/svg/icons/wechat.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1742660391897" class="icon" viewBox="0 0 1170 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3162" xmlns:xlink="http://www.w3.org/1999/xlink" width="292.5" height="256"><path d="M331.429 263.429q0-23.429-14.286-37.715t-37.714-14.285q-24.572 0-43.429 14.571t-18.857 37.429q0 22.285 18.857 36.857t43.429 14.571q23.428 0 37.714-14t14.286-37.428zM756 553.143q0-16-14.571-28.572T704 512q-15.429 0-28.286 12.857t-12.857 28.286q0 16 12.857 28.857T704 594.857q22.857 0 37.429-12.571T756 553.143zM621.143 263.429q0-23.429-14-37.715t-37.429-14.285q-24.571 0-43.428 14.571t-18.857 37.429q0 22.285 18.857 36.857t43.428 14.571q23.429 0 37.429-14t14-37.428zM984 553.143q0-16-14.857-28.572T932 512q-15.429 0-28.286 12.857t-12.857 28.286q0 16 12.857 28.857T932 594.857q22.286 0 37.143-12.571T984 553.143zM832 326.286Q814.286 324 792 324q-96.571 0-177.714 44T486.57 487.143 440 651.429q0 44.571 13.143 86.857-20 1.714-38.857 1.714-14.857 0-28.572-0.857t-31.428-3.714-25.429-4-31.143-6-28.571-6L124.57 792l41.143-124.571Q0 551.429 0 387.429q0-96.572 55.714-177.715T206.571 82t207.715-46.571q100.571 0 190 37.714T754 177.429t78 148.857z m338.286 320.571q0 66.857-39.143 127.714t-106 110.572l31.428 103.428-113.714-62.285q-85.714 21.143-124.571 21.143-96.572 0-177.715-40.286T512.857 797.714t-46.571-150.857T512.857 496t127.714-109.429 177.715-40.285q92 0 173.143 40.285t130 109.715 48.857 150.571z" fill="#0e932e" p-id="3163"></path></svg>
|
After Width: | Height: | Size: 1.5 KiB |
@@ -11,6 +11,10 @@ const SvgCardIcon = createIconifyIcon('svg:card');
|
||||
const SvgBellIcon = createIconifyIcon('svg:bell');
|
||||
const SvgCakeIcon = createIconifyIcon('svg:cake');
|
||||
const SvgAntdvLogoIcon = createIconifyIcon('svg:antdv-logo');
|
||||
const SvgMaxKeyIcon = createIconifyIcon('svg:max-key');
|
||||
const SvgTopiamIcon = createIconifyIcon('svg:topiam');
|
||||
const SvgWechatIcon = createIconifyIcon('svg:wechat');
|
||||
const SvgQQIcon = createIconifyIcon('svg:qq');
|
||||
|
||||
export {
|
||||
SvgAntdvLogoIcon,
|
||||
@@ -22,6 +26,10 @@ export {
|
||||
SvgCakeIcon,
|
||||
SvgCardIcon,
|
||||
SvgDownloadIcon,
|
||||
SvgMaxKeyIcon,
|
||||
SvgQQIcon,
|
||||
SvgTopiamIcon,
|
||||
SvgWechatIcon,
|
||||
};
|
||||
|
||||
export { default as SvgMessageUrl } from './icons/message.svg';
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben/locales",
|
||||
"version": "5.5.3",
|
||||
"version": "5.5.4",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben/preferences",
|
||||
"version": "5.5.3",
|
||||
"version": "5.5.4",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben/stores",
|
||||
"version": "5.5.3",
|
||||
"version": "5.5.4",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben/styles",
|
||||
"version": "5.5.3",
|
||||
"version": "5.5.4",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben/types",
|
||||
"version": "5.5.3",
|
||||
"version": "5.5.4",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben/utils",
|
||||
"version": "5.5.3",
|
||||
"version": "5.5.4",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@@ -1,6 +1,7 @@
|
||||
import type { ExRouteRecordRaw, MenuRecordRaw } from '@vben-core/typings';
|
||||
import type { Router, RouteRecordRaw } from 'vue-router';
|
||||
|
||||
import type { ExRouteRecordRaw, MenuRecordRaw } from '@vben-core/typings';
|
||||
|
||||
import { filterTree, mapTree } from '@vben-core/shared/utils';
|
||||
|
||||
/**
|
||||
@@ -68,8 +69,8 @@ async function generateMenus(
|
||||
};
|
||||
});
|
||||
|
||||
// 对菜单进行排序
|
||||
menus = menus.sort((a, b) => (a.order || 999) - (b.order || 999));
|
||||
// 对菜单进行排序,避免order=0时被替换成999的问题
|
||||
menus = menus.sort((a, b) => (a?.order ?? 999) - (b?.order ?? 999));
|
||||
|
||||
const finalMenus = filterTree(menus, (menu) => {
|
||||
return !!menu.show;
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben/playground",
|
||||
"version": "5.5.3",
|
||||
"version": "5.5.4",
|
||||
"homepage": "https://vben.pro",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@@ -8,6 +8,7 @@ import { $t } from '#/locales';
|
||||
|
||||
const appName = computed(() => preferences.app.name);
|
||||
const logo = computed(() => preferences.logo.source);
|
||||
const clickLogo = () => {};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -16,6 +17,7 @@ const logo = computed(() => preferences.logo.source);
|
||||
:logo="logo"
|
||||
:page-description="$t('authentication.pageDesc')"
|
||||
:page-title="$t('authentication.pageTitle')"
|
||||
:click-logo="clickLogo"
|
||||
>
|
||||
<!-- 自定义工具栏 -->
|
||||
<!-- <template #toolbar></template> -->
|
||||
|
@@ -106,6 +106,8 @@ function handleMakeAll() {
|
||||
notifications.value.forEach((item) => (item.isRead = true));
|
||||
}
|
||||
|
||||
function handleClickLogo() {}
|
||||
|
||||
watch(
|
||||
() => preferences.app.watermark,
|
||||
async (enable) => {
|
||||
@@ -124,7 +126,10 @@ watch(
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<BasicLayout @clear-preferences-and-logout="handleLogout">
|
||||
<BasicLayout
|
||||
@clear-preferences-and-logout="handleLogout"
|
||||
@click-logo="handleClickLogo"
|
||||
>
|
||||
<template #user-dropdown>
|
||||
<UserDropdown
|
||||
:avatar
|
||||
|
@@ -32,7 +32,6 @@ const emit = defineEmits<{
|
||||
success: [];
|
||||
}>();
|
||||
const formData = ref<SystemMenuApi.SystemMenu>();
|
||||
const loading = ref(false);
|
||||
const titleSuffix = ref<string>();
|
||||
const schema: VbenFormSchema[] = [
|
||||
{
|
||||
@@ -445,9 +444,6 @@ const [Form, formApi] = useVbenForm({
|
||||
});
|
||||
|
||||
const [Drawer, drawerApi] = useVbenDrawer({
|
||||
onBeforeClose() {
|
||||
if (loading.value) return false;
|
||||
},
|
||||
onConfirm: onSubmit,
|
||||
onOpenChange(isOpen) {
|
||||
if (isOpen) {
|
||||
@@ -474,13 +470,7 @@ const [Drawer, drawerApi] = useVbenDrawer({
|
||||
async function onSubmit() {
|
||||
const { valid } = await formApi.validate();
|
||||
if (valid) {
|
||||
loading.value = true;
|
||||
drawerApi.setState({
|
||||
closeOnClickModal: false,
|
||||
closeOnPressEscape: false,
|
||||
confirmLoading: true,
|
||||
loading: true,
|
||||
});
|
||||
drawerApi.lock();
|
||||
const data =
|
||||
await formApi.getValues<
|
||||
Omit<SystemMenuApi.SystemMenu, 'children' | 'id'>
|
||||
@@ -498,13 +488,7 @@ async function onSubmit() {
|
||||
drawerApi.close();
|
||||
emit('success');
|
||||
} finally {
|
||||
loading.value = false;
|
||||
drawerApi.setState({
|
||||
closeOnClickModal: true,
|
||||
closeOnPressEscape: true,
|
||||
confirmLoading: false,
|
||||
loading: false,
|
||||
});
|
||||
drawerApi.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -45,6 +45,7 @@ catalog:
|
||||
'@types/lodash.clonedeep': ^4.5.9
|
||||
'@types/lodash.get': ^4.4.9
|
||||
'@types/lodash.isequal': ^4.5.8
|
||||
'@types/lodash.set': ^4.3.2
|
||||
'@types/node': ^22.13.10
|
||||
'@types/nprogress': ^0.2.3
|
||||
'@types/postcss-import': ^14.0.3
|
||||
@@ -116,6 +117,7 @@ catalog:
|
||||
lint-staged: ^15.4.3
|
||||
lodash.clonedeep: ^4.5.0
|
||||
lodash.get: ^4.4.2
|
||||
lodash.set: ^4.3.2
|
||||
lodash.isequal: ^4.5.0
|
||||
lucide-vue-next: ^0.469.0
|
||||
medium-zoom: ^1.1.0
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben/turbo-run",
|
||||
"version": "5.5.3",
|
||||
"version": "5.5.4",
|
||||
"private": true,
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben/vsh",
|
||||
"version": "5.5.3",
|
||||
"version": "5.5.4",
|
||||
"private": true,
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
|
@@ -13,7 +13,7 @@ async function runLint({ format }: LintCommandOptions) {
|
||||
// process.env.FORCE_COLOR = '3';
|
||||
|
||||
if (format) {
|
||||
await execaCommand(`stylelint "**/*.{vue,css,less.scss}" --cache --fix`, {
|
||||
await execaCommand(`stylelint "**/*.{vue,css,less,scss}" --cache --fix`, {
|
||||
stdio: 'inherit',
|
||||
});
|
||||
await execaCommand(`eslint . --cache --fix`, {
|
||||
@@ -31,7 +31,7 @@ async function runLint({ format }: LintCommandOptions) {
|
||||
execaCommand(`prettier . --ignore-unknown --check --cache`, {
|
||||
stdio: 'inherit',
|
||||
}),
|
||||
execaCommand(`stylelint "**/*.{vue,css,less.scss}" --cache`, {
|
||||
execaCommand(`stylelint "**/*.{vue,css,less,scss}" --cache`, {
|
||||
stdio: 'inherit',
|
||||
}),
|
||||
]);
|
||||
|
Reference in New Issue
Block a user