Merge remote-tracking branch 'yudao/dev' into dev

This commit is contained in:
jason
2025-04-29 15:45:48 +08:00
189 changed files with 2174 additions and 1516 deletions

View File

@@ -2,5 +2,5 @@ ports:
- port: 5555 - port: 5555
onOpen: open-preview onOpen: open-preview
tasks: tasks:
- init: corepack enable && pnpm install - init: npm i -g corepack && pnpm install
command: pnpm run dev:play command: pnpm run dev:play

13
.vscode/settings.json vendored
View File

@@ -223,16 +223,5 @@
"commentTranslate.multiLineMerge": true, "commentTranslate.multiLineMerge": true,
"vue.server.hybridMode": true, "vue.server.hybridMode": true,
"typescript.tsdk": "node_modules/typescript/lib", "typescript.tsdk": "node_modules/typescript/lib",
"oxc.enable": false, "oxc.enable": false
"cSpell.words": [
"archiver",
"axios",
"dotenv",
"isequal",
"jspm",
"napi",
"nolebase",
"rollup",
"vitest"
]
} }

View File

@@ -3,6 +3,10 @@ VITE_APP_TITLE=芋道管理系统
# 应用命名空间用于缓存、store等功能的前缀确保隔离 # 应用命名空间用于缓存、store等功能的前缀确保隔离
VITE_APP_NAMESPACE=yudao-vben-antd VITE_APP_NAMESPACE=yudao-vben-antd
# 对store进行加密的密钥在将store持久化到localStorage时会使用该密钥进行加密
VITE_APP_STORE_SECURE_KEY=please-replace-me-with-your-own-key
# 是否开启模拟数据 # 是否开启模拟数据
VITE_NITRO_MOCK=false VITE_NITRO_MOCK=false

View File

@@ -1,6 +1,6 @@
{ {
"name": "@vben/web-antd", "name": "@vben/web-antd",
"version": "5.5.4", "version": "5.5.5",
"homepage": "https://vben.pro", "homepage": "https://vben.pro",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": { "repository": {

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

View File

@@ -76,8 +76,8 @@ const withDefaultPlaceholder = <T extends Component>(
componentProps: Recordable<any> = {}, componentProps: Recordable<any> = {},
) => { ) => {
return defineComponent({ return defineComponent({
inheritAttrs: false,
name: component.name, name: component.name,
inheritAttrs: false,
setup: (props: any, { attrs, expose, slots }) => { setup: (props: any, { attrs, expose, slots }) => {
const placeholder = const placeholder =
props?.placeholder || props?.placeholder ||
@@ -142,20 +142,34 @@ async function initComponentAdapter() {
// 如果你的组件体积比较大,可以使用异步加载 // 如果你的组件体积比较大,可以使用异步加载
// Button: () => // Button: () =>
// import('xxx').then((res) => res.Button), // import('xxx').then((res) => res.Button),
ApiSelect: withDefaultPlaceholder(ApiComponent, 'select', { ApiSelect: withDefaultPlaceholder(
component: Select, {
loadingSlot: 'suffixIcon', ...ApiComponent,
visibleEvent: 'onDropdownVisibleChange', name: 'ApiSelect',
modelPropName: 'value', },
}), 'select',
ApiTreeSelect: withDefaultPlaceholder(ApiComponent, 'select', { {
component: TreeSelect, component: Select,
fieldNames: { label: 'label', value: 'value', children: 'children' }, loadingSlot: 'suffixIcon',
loadingSlot: 'suffixIcon', visibleEvent: 'onDropdownVisibleChange',
modelPropName: 'value', modelPropName: 'value',
optionsPropName: 'treeData', },
visibleEvent: 'onVisibleChange', ),
}), ApiTreeSelect: withDefaultPlaceholder(
{
...ApiComponent,
name: 'ApiTreeSelect',
},
'select',
{
component: TreeSelect,
fieldNames: { label: 'label', value: 'value', children: 'children' },
loadingSlot: 'suffixIcon',
modelPropName: 'value',
optionsPropName: 'treeData',
visibleEvent: 'onVisibleChange',
},
),
AutoComplete, AutoComplete,
Checkbox, Checkbox,
CheckboxGroup, CheckboxGroup,

View File

@@ -7,7 +7,6 @@ import { preferences } from '@vben/preferences';
import { initStores } from '@vben/stores'; import { initStores } from '@vben/stores';
import '@vben/styles'; import '@vben/styles';
import '@vben/styles/antd'; import '@vben/styles/antd';
import 'vxe-table/styles/cssvar.scss'; // TODO @puhui999这个必须导入哇我看 use-vxe-grid.vue 已经导入了
import { useTitle } from '@vueuse/core'; import { useTitle } from '@vueuse/core';
@@ -18,6 +17,8 @@ import { initComponentAdapter } from './adapter/component';
import App from './app.vue'; import App from './app.vue';
import { router } from './router'; import { router } from './router';
import 'vxe-table/styles/cssvar.scss'; // TODO @puhui999这个必须导入哇我看 use-vxe-grid.vue 已经导入了
async function bootstrap(namespace: string) { async function bootstrap(namespace: string) {
// 初始化组件适配器 // 初始化组件适配器
await initComponentAdapter(); await initComponentAdapter();

View File

@@ -3,7 +3,7 @@ import type { NotificationItem } from '@vben/layouts';
import { computed, onMounted, ref, watch } from 'vue'; import { computed, onMounted, ref, watch } from 'vue';
import { AuthenticationLoginExpiredModal } from '@vben/common-ui'; import { AuthenticationLoginExpiredModal, useVbenModal } from '@vben/common-ui';
import { VBEN_DOC_URL, VBEN_GITHUB_URL } from '@vben/constants'; import { VBEN_DOC_URL, VBEN_GITHUB_URL } from '@vben/constants';
import { useWatermark } from '@vben/hooks'; import { useWatermark } from '@vben/hooks';
import { import {
@@ -33,6 +33,8 @@ import { router } from '#/router';
import { useAuthStore } from '#/store'; import { useAuthStore } from '#/store';
import LoginForm from '#/views/_core/authentication/login.vue'; import LoginForm from '#/views/_core/authentication/login.vue';
import Help from './components/help.vue';
const userStore = useUserStore(); const userStore = useUserStore();
const authStore = useAuthStore(); const authStore = useAuthStore();
const accessStore = useAccessStore(); const accessStore = useAccessStore();
@@ -42,6 +44,10 @@ const notifications = ref<NotificationItem[]>([]);
const unreadCount = ref(0); const unreadCount = ref(0);
const showDot = computed(() => unreadCount.value > 0); const showDot = computed(() => unreadCount.value > 0);
const [HelpModal, helpModalApi] = useVbenModal({
connectedComponent: Help,
});
const menus = computed(() => [ const menus = computed(() => [
{ {
handler: () => { handler: () => {
@@ -70,9 +76,7 @@ const menus = computed(() => [
}, },
{ {
handler: () => { handler: () => {
openWindow(`${VBEN_GITHUB_URL}/issues`, { helpModalApi.open();
target: '_blank',
});
}, },
icon: CircleHelp, icon: CircleHelp,
text: $t('ui.widgets.qa'), text: $t('ui.widgets.qa'),
@@ -210,4 +214,5 @@ watch(
<LockScreen :avatar @to-login="handleLogout" /> <LockScreen :avatar @to-login="handleLogout" />
</template> </template>
</BasicLayout> </BasicLayout>
<HelpModal />
</template> </template>

View File

@@ -0,0 +1,93 @@
<script lang="ts" setup>
import { useVbenModal, VbenButton, VbenButtonGroup } from '@vben/common-ui';
import { Image, Tag } from 'ant-design-vue';
import { $t } from '#/locales';
const [Modal, modalApi] = useVbenModal({
draggable: true,
overlayBlur: 5,
footer: false,
onCancel() {
modalApi.close();
},
});
function openWindow(url: string) {
window.open(url, '_blank');
}
</script>
<template>
<Modal class="w-[40%]" :title="$t('ui.widgets.qa')">
<div class="mt-2 flex flex-col">
<div class="mt-2 flex flex-row">
<VbenButtonGroup class="basis-1/3" :gap="2" border size="large">
<p class="p-2">项目地址:</p>
<VbenButton
variant="link"
@click="
openWindow('https://gitee.com/yudaocode/yudao-ui-admin-vben')
"
>
Gitee
</VbenButton>
<VbenButton
variant="link"
@click="
openWindow('https://github.com/yudaocode/yudao-ui-admin-vben')
"
>
Github
</VbenButton>
</VbenButtonGroup>
<VbenButtonGroup class="basis-1/3" :gap="2" border size="large">
<p class="p-2">issues:</p>
<VbenButton
variant="link"
@click="
openWindow(
'https://gitee.com/yudaocode/yudao-ui-admin-vben/issues',
)
"
>
Gitee
</VbenButton>
<VbenButton
variant="link"
@click="
openWindow(
'https://github.com/yudaocode/yudao-ui-admin-vben/issues',
)
"
>
Github
</VbenButton>
</VbenButtonGroup>
<VbenButtonGroup class="basis-1/3" :gap="2" border size="large">
<p class="p-2">开发文档:</p>
<VbenButton
variant="link"
@click="openWindow('https://doc.iocoder.cn/quick-start/')"
>
项目文档
</VbenButton>
<VbenButton variant="link" @click="openWindow('https://antdv.com/')">
antdv 文档
</VbenButton>
</VbenButtonGroup>
</div>
<p class="mt-2 flex justify-center">
<span>
<Image src="../../../public/wx-xingyu.png" alt="数舵科技" />
</span>
</p>
<p class="mt-2 flex justify-center pt-4 text-sm italic">
本项目采用<Tag color="blue">MIT</Tag>开源协议个人与企业可100%
免费使用
</p>
</div>
</Modal>
</template>

View File

@@ -30,7 +30,7 @@ const loginRef = ref();
/** 获取租户列表,并默认选中 */ /** 获取租户列表,并默认选中 */
const tenantList = ref<AuthApi.TenantResult[]>([]); // 租户列表 const tenantList = ref<AuthApi.TenantResult[]>([]); // 租户列表
const fetchTenantList = async () => { async function fetchTenantList() {
if (!tenantEnable) { if (!tenantEnable) {
return; return;
} }
@@ -56,11 +56,11 @@ const fetchTenantList = async () => {
// 设置选中的租户编号 // 设置选中的租户编号
accessStore.setTenantId(tenantId); accessStore.setTenantId(tenantId);
loginRef.value.getFormApi().setFieldValue('tenantId', tenantId); loginRef.value.getFormApi().setFieldValue('tenantId', tenantId?.toString());
} catch (error) { } catch (error) {
console.error('获取租户列表失败:', error); console.error('获取租户列表失败:', error);
} }
}; }
/** 组件挂载时获取租户信息 */ /** 组件挂载时获取租户信息 */
onMounted(() => { onMounted(() => {
@@ -74,19 +74,19 @@ const formSchema = computed((): VbenFormSchema[] => {
componentProps: { componentProps: {
options: tenantList.value.map((item) => ({ options: tenantList.value.map((item) => ({
label: item.name, label: item.name,
value: item.id, value: item.id.toString(),
})), })),
placeholder: $t('authentication.tenantTip'), placeholder: $t('authentication.tenantTip'),
}, },
fieldName: 'tenantId', fieldName: 'tenantId',
label: $t('authentication.tenant'), label: $t('authentication.tenant'),
rules: z.number().positive(), rules: z.string().min(1, { message: $t('authentication.tenantTip') }),
dependencies: { dependencies: {
triggerFields: ['tenantId'], triggerFields: ['tenantId'],
if: tenantEnable, if: tenantEnable,
trigger(values) { trigger(values) {
if (values.tenantId) { if (values.tenantId) {
accessStore.setTenantId(values.tenantId); accessStore.setTenantId(Number(values.tenantId));
} }
}, },
}, },

View File

@@ -29,7 +29,7 @@ const forgetPasswordRef = ref();
/** 获取租户列表,并默认选中 */ /** 获取租户列表,并默认选中 */
const tenantList = ref<AuthApi.TenantResult[]>([]); // 租户列表 const tenantList = ref<AuthApi.TenantResult[]>([]); // 租户列表
const fetchTenantList = async () => { async function fetchTenantList() {
if (!tenantEnable) { if (!tenantEnable) {
return; return;
} }
@@ -55,11 +55,13 @@ const fetchTenantList = async () => {
// 设置选中的租户编号 // 设置选中的租户编号
accessStore.setTenantId(tenantId); accessStore.setTenantId(tenantId);
forgetPasswordRef.value.getFormApi().setFieldValue('tenantId', tenantId); forgetPasswordRef.value
.getFormApi()
.setFieldValue('tenantId', tenantId?.toString());
} catch (error) { } catch (error) {
console.error('获取租户列表失败:', error); console.error('获取租户列表失败:', error);
} }
}; }
/** 组件挂载时获取租户信息 */ /** 组件挂载时获取租户信息 */
onMounted(() => { onMounted(() => {
@@ -73,19 +75,19 @@ const formSchema = computed((): VbenFormSchema[] => {
componentProps: { componentProps: {
options: tenantList.value.map((item) => ({ options: tenantList.value.map((item) => ({
label: item.name, label: item.name,
value: item.id, value: item.id.toString(),
})), })),
placeholder: $t('authentication.tenantTip'), placeholder: $t('authentication.tenantTip'),
}, },
fieldName: 'tenantId', fieldName: 'tenantId',
label: $t('authentication.tenant'), label: $t('authentication.tenant'),
rules: z.number().positive(), rules: z.string().min(1, { message: $t('authentication.tenantTip') }),
dependencies: { dependencies: {
triggerFields: ['tenantId'], triggerFields: ['tenantId'],
if: tenantEnable, if: tenantEnable,
trigger(values) { trigger(values) {
if (values.tenantId) { if (values.tenantId) {
accessStore.setTenantId(values.tenantId); accessStore.setTenantId(Number(values.tenantId));
} }
}, },
}, },

View File

@@ -35,7 +35,7 @@ const captchaType = 'blockPuzzle'; // 验证码类型:'blockPuzzle' | 'clickWo
/** 获取租户列表,并默认选中 */ /** 获取租户列表,并默认选中 */
const tenantList = ref<AuthApi.TenantResult[]>([]); // 租户列表 const tenantList = ref<AuthApi.TenantResult[]>([]); // 租户列表
const fetchTenantList = async () => { async function fetchTenantList() {
if (!tenantEnable) { if (!tenantEnable) {
return; return;
} }
@@ -61,26 +61,25 @@ const fetchTenantList = async () => {
// 设置选中的租户编号 // 设置选中的租户编号
accessStore.setTenantId(tenantId); accessStore.setTenantId(tenantId);
loginRef.value.getFormApi().setFieldValue('tenantId', tenantId); loginRef.value.getFormApi().setFieldValue('tenantId', tenantId?.toString());
} catch (error) { } catch (error) {
console.error('获取租户列表失败:', error); console.error('获取租户列表失败:', error);
} }
}; }
/** 处理登录 */ /** 处理登录 */
const handleLogin = async (values: any) => { async function handleLogin(values: any) {
// 如果开启验证码,则先验证验证码 // 如果开启验证码,则先验证验证码
if (captchaEnable) { if (captchaEnable) {
verifyRef.value.show(); verifyRef.value.show();
return; return;
} }
// 无验证码,直接登录 // 无验证码,直接登录
await authStore.authLogin('username', values); await authStore.authLogin('username', values);
}; }
/** 验证码通过,执行登录 */ /** 验证码通过,执行登录 */
const handleVerifySuccess = async ({ captchaVerification }: any) => { async function handleVerifySuccess({ captchaVerification }: any) {
try { try {
await authStore.authLogin('username', { await authStore.authLogin('username', {
...(await loginRef.value.getFormApi().getValues()), ...(await loginRef.value.getFormApi().getValues()),
@@ -89,11 +88,11 @@ const handleVerifySuccess = async ({ captchaVerification }: any) => {
} catch (error) { } catch (error) {
console.error('Error in handleLogin:', error); console.error('Error in handleLogin:', error);
} }
}; }
/** 处理第三方登录 */ /** 处理第三方登录 */
const redirect = query?.redirect; const redirect = query?.redirect;
const handleThirdLogin = async (type: number) => { async function handleThirdLogin(type: number) {
if (type <= 0) { if (type <= 0) {
return; return;
} }
@@ -111,7 +110,7 @@ const handleThirdLogin = async (type: number) => {
} catch (error) { } catch (error) {
console.error('第三方登录处理失败:', error); console.error('第三方登录处理失败:', error);
} }
}; }
/** 组件挂载时获取租户信息 */ /** 组件挂载时获取租户信息 */
onMounted(() => { onMounted(() => {
@@ -125,19 +124,19 @@ const formSchema = computed((): VbenFormSchema[] => {
componentProps: { componentProps: {
options: tenantList.value.map((item) => ({ options: tenantList.value.map((item) => ({
label: item.name, label: item.name,
value: item.id, value: item.id.toString(),
})), })),
placeholder: $t('authentication.tenantTip'), placeholder: $t('authentication.tenantTip'),
}, },
fieldName: 'tenantId', fieldName: 'tenantId',
label: $t('authentication.tenant'), label: $t('authentication.tenant'),
rules: z.number().positive(), rules: z.string().min(1, { message: $t('authentication.tenantTip') }),
dependencies: { dependencies: {
triggerFields: ['tenantId'], triggerFields: ['tenantId'],
if: tenantEnable, if: tenantEnable,
trigger(values) { trigger(values) {
if (values.tenantId) { if (values.tenantId) {
accessStore.setTenantId(values.tenantId); accessStore.setTenantId(Number(values.tenantId));
} }
}, },
}, },

View File

@@ -34,7 +34,7 @@ const captchaType = 'blockPuzzle'; // 验证码类型:'blockPuzzle' | 'clickWo
/** 获取租户列表,并默认选中 */ /** 获取租户列表,并默认选中 */
const tenantList = ref<AuthApi.TenantResult[]>([]); // 租户列表 const tenantList = ref<AuthApi.TenantResult[]>([]); // 租户列表
const fetchTenantList = async () => { async function fetchTenantList() {
if (!tenantEnable) { if (!tenantEnable) {
return; return;
} }
@@ -60,14 +60,16 @@ const fetchTenantList = async () => {
// 设置选中的租户编号 // 设置选中的租户编号
accessStore.setTenantId(tenantId); accessStore.setTenantId(tenantId);
registerRef.value.getFormApi().setFieldValue('tenantId', tenantId); registerRef.value
.getFormApi()
.setFieldValue('tenantId', tenantId?.toString());
} catch (error) { } catch (error) {
console.error('获取租户列表失败:', error); console.error('获取租户列表失败:', error);
} }
}; }
/** 执行注册 */ /** 执行注册 */
const handleRegister = async (values: any) => { async function handleRegister(values: any) {
// 如果开启验证码,则先验证验证码 // 如果开启验证码,则先验证验证码
if (captchaEnable) { if (captchaEnable) {
verifyRef.value.show(); verifyRef.value.show();
@@ -76,7 +78,7 @@ const handleRegister = async (values: any) => {
// 无验证码,直接登录 // 无验证码,直接登录
await authStore.authLogin('register', values); await authStore.authLogin('register', values);
}; }
/** 验证码通过,执行注册 */ /** 验证码通过,执行注册 */
const handleVerifySuccess = async ({ captchaVerification }: any) => { const handleVerifySuccess = async ({ captchaVerification }: any) => {
@@ -108,13 +110,13 @@ const formSchema = computed((): VbenFormSchema[] => {
}, },
fieldName: 'tenantId', fieldName: 'tenantId',
label: $t('authentication.tenant'), label: $t('authentication.tenant'),
rules: z.number().positive(), rules: z.string().min(1, { message: $t('authentication.tenantTip') }),
dependencies: { dependencies: {
triggerFields: ['tenantId'], triggerFields: ['tenantId'],
if: tenantEnable, if: tenantEnable,
trigger(values) { trigger(values) {
if (values.tenantId) { if (values.tenantId) {
accessStore.setTenantId(values.tenantId); accessStore.setTenantId(Number(values.tenantId));
} }
}, },
}, },

View File

@@ -35,7 +35,7 @@ const captchaType = 'blockPuzzle'; // 验证码类型:'blockPuzzle' | 'clickWo
/** 获取租户列表,并默认选中 */ /** 获取租户列表,并默认选中 */
const tenantList = ref<AuthApi.TenantResult[]>([]); // 租户列表 const tenantList = ref<AuthApi.TenantResult[]>([]); // 租户列表
const fetchTenantList = async () => { async function fetchTenantList() {
if (!tenantEnable) { if (!tenantEnable) {
return; return;
} }
@@ -66,14 +66,14 @@ const fetchTenantList = async () => {
} catch (error) { } catch (error) {
console.error('获取租户列表失败:', error); console.error('获取租户列表失败:', error);
} }
}; }
/** 尝试登录当账号已经绑定socialLogin 会直接获得 token */ /** 尝试登录当账号已经绑定socialLogin 会直接获得 token */
const socialType = Number(getUrlValue('type')); const socialType = Number(getUrlValue('type'));
const redirect = getUrlValue('redirect'); const redirect = getUrlValue('redirect');
const socialCode = query?.code as string; const socialCode = query?.code as string;
const socialState = query?.state as string; const socialState = query?.state as string;
const tryLogin = async () => { async function tryLogin() {
// 用于登录后,基于 redirect 的重定向 // 用于登录后,基于 redirect 的重定向
if (redirect) { if (redirect) {
await router.replace({ await router.replace({
@@ -90,10 +90,10 @@ const tryLogin = async () => {
code: socialCode, code: socialCode,
state: socialState, state: socialState,
}); });
}; }
/** 处理登录 */ /** 处理登录 */
const handleLogin = async (values: any) => { async function handleLogin(values: any) {
// 如果开启验证码,则先验证验证码 // 如果开启验证码,则先验证验证码
if (captchaEnable) { if (captchaEnable) {
verifyRef.value.show(); verifyRef.value.show();
@@ -107,10 +107,10 @@ const handleLogin = async (values: any) => {
socialCode, socialCode,
socialState, socialState,
}); });
}; }
/** 验证码通过,执行登录 */ /** 验证码通过,执行登录 */
const handleVerifySuccess = async ({ captchaVerification }: any) => { async function handleVerifySuccess({ captchaVerification }: any) {
try { try {
await authStore.authLogin('username', { await authStore.authLogin('username', {
...(await loginRef.value.getFormApi().getValues()), ...(await loginRef.value.getFormApi().getValues()),
@@ -122,7 +122,7 @@ const handleVerifySuccess = async ({ captchaVerification }: any) => {
} catch (error) { } catch (error) {
console.error('Error in handleLogin:', error); console.error('Error in handleLogin:', error);
} }
}; }
/** tricky: 配合 login.vue 中redirectUri 需要对参数进行 encode需要在回调后进行decode */ /** tricky: 配合 login.vue 中redirectUri 需要对参数进行 encode需要在回调后进行decode */
function getUrlValue(key: string): string { function getUrlValue(key: string): string {
@@ -144,19 +144,19 @@ const formSchema = computed((): VbenFormSchema[] => {
componentProps: { componentProps: {
options: tenantList.value.map((item) => ({ options: tenantList.value.map((item) => ({
label: item.name, label: item.name,
value: item.id, value: item.id.toString(),
})), })),
placeholder: $t('authentication.tenantTip'), placeholder: $t('authentication.tenantTip'),
}, },
fieldName: 'tenantId', fieldName: 'tenantId',
label: $t('authentication.tenant'), label: $t('authentication.tenant'),
rules: z.number().positive(), rules: z.string().min(1, { message: $t('authentication.tenantTip') }),
dependencies: { dependencies: {
triggerFields: ['tenantId'], triggerFields: ['tenantId'],
if: tenantEnable, if: tenantEnable,
trigger(values) { trigger(values) {
if (values.tenantId) { if (values.tenantId) {
accessStore.setTenantId(values.tenantId); accessStore.setTenantId(Number(values.tenantId));
} }
}, },
}, },

View File

@@ -29,7 +29,7 @@ const queryParams = reactive({
const loading = ref(false); // 表单是否提交中 const loading = ref(false); // 表单是否提交中
/** 初始化授权信息 */ /** 初始化授权信息 */
const init = async () => { async function init() {
// 防止在没有登录的情况下循环弹窗 // 防止在没有登录的情况下循环弹窗
if (query.client_id === undefined) { if (query.client_id === undefined) {
return; return;
@@ -75,10 +75,10 @@ const init = async () => {
'scopes', 'scopes',
scopes.filter((scope) => scope.value).map((scope) => scope.key), scopes.filter((scope) => scope.value).map((scope) => scope.key),
); );
}; }
/** 处理授权的提交 */ /** 处理授权的提交 */
const handleSubmit = async (approved: boolean) => { async function handleSubmit(approved: boolean) {
// 计算 checkedScopes + uncheckedScopes // 计算 checkedScopes + uncheckedScopes
let checkedScopes: string[]; let checkedScopes: string[];
let uncheckedScopes: string[]; let uncheckedScopes: string[];
@@ -107,7 +107,7 @@ const handleSubmit = async (approved: boolean) => {
} finally { } finally {
loading.value = false; loading.value = false;
} }
}; }
/** 调用授权 API 接口 */ /** 调用授权 API 接口 */
const doAuthorize = ( const doAuthorize = (
@@ -127,7 +127,7 @@ const doAuthorize = (
}; };
/** 格式化 scope 文本 */ /** 格式化 scope 文本 */
const formatScope = (scope: string) => { function formatScope(scope: string) {
// 格式化 scope 授权范围,方便用户理解。 // 格式化 scope 授权范围,方便用户理解。
// 这里仅仅是一个 demo可以考虑录入到字典数据中例如说字典类型 "system_oauth2_scope",它的每个 scope 都是一条字典数据。 // 这里仅仅是一个 demo可以考虑录入到字典数据中例如说字典类型 "system_oauth2_scope",它的每个 scope 都是一条字典数据。
switch (scope) { switch (scope) {
@@ -141,7 +141,7 @@ const formatScope = (scope: string) => {
return scope; return scope;
} }
} }
}; }
const formSchema = computed((): VbenFormSchema[] => { const formSchema = computed((): VbenFormSchema[] => {
return [ return [

View File

@@ -1,17 +1,20 @@
<script setup lang="ts"> <script setup lang="ts">
import type { SystemUserProfileApi } from '#/api/system/user/profile'; import type { SystemUserProfileApi } from '#/api/system/user/profile';
import { Card, Tabs } from 'ant-design-vue';
import { Page } from '@vben/common-ui';
import ProfileUser from './modules/profile-user.vue';
import BaseInfo from './modules/base-info.vue';
import ResetPwd from './modules/reset-pwd.vue';
import UserSocial from './modules/user-social.vue';
import { onMounted, ref } from 'vue'; import { onMounted, ref } from 'vue';
import { Page } from '@vben/common-ui';
import { Card, Tabs } from 'ant-design-vue';
import { getUserProfile } from '#/api/system/user/profile'; import { getUserProfile } from '#/api/system/user/profile';
import { useAuthStore } from '#/store'; import { useAuthStore } from '#/store';
import BaseInfo from './modules/base-info.vue';
import ProfileUser from './modules/profile-user.vue';
import ResetPwd from './modules/reset-pwd.vue';
import UserSocial from './modules/user-social.vue';
const authStore = useAuthStore(); const authStore = useAuthStore();
const activeName = ref('basicInfo'); const activeName = ref('basicInfo');
@@ -46,13 +49,13 @@ onMounted(loadProfile);
<Card class="ml-3 w-3/5"> <Card class="ml-3 w-3/5">
<Tabs v-model:active-key="activeName" class="-mt-4"> <Tabs v-model:active-key="activeName" class="-mt-4">
<Tabs.TabPane key="basicInfo" tab="基本设置"> <Tabs.TabPane key="basicInfo" tab="基本设置">
<BaseInfo :profile="profile" @success="refreshProfile" /> <BaseInfo :profile="profile" @success="refreshProfile" />
</Tabs.TabPane> </Tabs.TabPane>
<Tabs.TabPane key="resetPwd" tab="密码设置"> <Tabs.TabPane key="resetPwd" tab="密码设置">
<ResetPwd /> <ResetPwd />
</Tabs.TabPane> </Tabs.TabPane>
<Tabs.TabPane key="userSocial" tab="社交绑定" force-render> <Tabs.TabPane key="userSocial" tab="社交绑定" force-render>
<UserSocial @update:active-name="activeName = $event" /> <UserSocial @update:active-name="activeName = $event" />
</Tabs.TabPane> </Tabs.TabPane>
<!-- TODO @芋艿在线设备 --> <!-- TODO @芋艿在线设备 -->
</Tabs> </Tabs>

View File

@@ -1,16 +1,21 @@
<script setup lang="ts"> <script setup lang="ts">
import type { Recordable } from '@vben/types'; import type { Recordable } from '@vben/types';
import type { SystemUserProfileApi } from '#/api/system/user/profile'; import type { SystemUserProfileApi } from '#/api/system/user/profile';
import { watch } from 'vue';
import { $t } from '@vben/locales';
import { message } from 'ant-design-vue'; import { message } from 'ant-design-vue';
import { watch } from 'vue';
import { useVbenForm, z } from '#/adapter/form'; import { useVbenForm, z } from '#/adapter/form';
import { DICT_TYPE, getDictOptions } from '#/utils/dict';
import { updateUserProfile } from '#/api/system/user/profile'; import { updateUserProfile } from '#/api/system/user/profile';
import { $t } from '@vben/locales'; import { DICT_TYPE, getDictOptions } from '#/utils/dict';
const props = defineProps<{ profile?: SystemUserProfileApi.UserProfileRespVO }>(); const props = defineProps<{
profile?: SystemUserProfileApi.UserProfileRespVO;
}>();
const emit = defineEmits<{ const emit = defineEmits<{
(e: 'success'): void; (e: 'success'): void;
}>(); }>();
@@ -87,11 +92,15 @@ async function handleSubmit(values: Recordable<any>) {
} }
/** 监听 profile 变化 */ /** 监听 profile 变化 */
watch(() => props.profile, (newProfile) => { watch(
if (newProfile) { () => props.profile,
formApi.setValues(newProfile); (newProfile) => {
} if (newProfile) {
}, { immediate: true }); formApi.setValues(newProfile);
}
},
{ immediate: true },
);
</script> </script>
<template> <template>

View File

@@ -63,7 +63,6 @@ export function useFormSchema(): VbenFormSchema[] {
component: 'InputNumber', component: 'InputNumber',
componentProps: { componentProps: {
min: 0, min: 0,
class: 'w-full',
controlsPosition: 'right', controlsPosition: 'right',
placeholder: '请输入分类排序', placeholder: '请输入分类排序',
}, },

View File

@@ -1,18 +1,34 @@
<script lang="ts" setup> <script lang="ts" setup>
import { DocAlert } from '#/components/doc-alert';
import { Button } from 'ant-design-vue';
import { Page } from '@vben/common-ui'; import { Page } from '@vben/common-ui';
import { Button } from 'ant-design-vue';
import { DocAlert } from '#/components/doc-alert';
</script> </script>
<template> <template>
<Page> <Page>
<DocAlert title="审批接入(流程表单)" url="https://doc.iocoder.cn/bpm/use-bpm-form/" /> <DocAlert
<Button danger type="link" target="_blank" href="https://github.com/yudaocode/yudao-ui-admin-vue3"> title="审批接入(流程表单)"
url="https://doc.iocoder.cn/bpm/use-bpm-form/"
/>
<Button
danger
type="link"
target="_blank"
href="https://github.com/yudaocode/yudao-ui-admin-vue3"
>
该功能支持 Vue3 + element-plus 版本 该功能支持 Vue3 + element-plus 版本
</Button> </Button>
<br /> <br />
<Button type="link" target="_blank" href="https://github.com/yudaocode/yudao-ui-admin-vue3/blob/master/src/views/bpm/form/index"> <Button
可参考 https://github.com/yudaocode/yudao-ui-admin-vue3/blob/master/src/views/bpm/form/index 代码pull request 贡献给我们! type="link"
target="_blank"
href="https://github.com/yudaocode/yudao-ui-admin-vue3/blob/master/src/views/bpm/form/index"
>
可参考
https://github.com/yudaocode/yudao-ui-admin-vue3/blob/master/src/views/bpm/form/index
代码pull request 贡献给我们
</Button> </Button>
</Page> </Page>
</template> </template>

View File

@@ -1,18 +1,31 @@
<script lang="ts" setup> <script lang="ts" setup>
import { DocAlert } from '#/components/doc-alert';
import { Button } from 'ant-design-vue';
import { Page } from '@vben/common-ui'; import { Page } from '@vben/common-ui';
import { Button } from 'ant-design-vue';
import { DocAlert } from '#/components/doc-alert';
</script> </script>
<template> <template>
<Page> <Page>
<DocAlert title="工作流手册" url="https://doc.iocoder.cn/bpm/" /> <DocAlert title="工作流手册" url="https://doc.iocoder.cn/bpm/" />
<Button danger type="link" target="_blank" href="https://github.com/yudaocode/yudao-ui-admin-vue3"> <Button
danger
type="link"
target="_blank"
href="https://github.com/yudaocode/yudao-ui-admin-vue3"
>
该功能支持 Vue3 + element-plus 版本 该功能支持 Vue3 + element-plus 版本
</Button> </Button>
<br /> <br />
<Button type="link" target="_blank" href="https://github.com/yudaocode/yudao-ui-admin-vue3/blob/master/src/views/bpm/group/index"> <Button
可参考 https://github.com/yudaocode/yudao-ui-admin-vue3/blob/master/src/views/bpm/group/index 代码pull request 贡献给我们! type="link"
target="_blank"
href="https://github.com/yudaocode/yudao-ui-admin-vue3/blob/master/src/views/bpm/group/index"
>
可参考
https://github.com/yudaocode/yudao-ui-admin-vue3/blob/master/src/views/bpm/group/index
代码pull request 贡献给我们
</Button> </Button>
</Page> </Page>
</template> </template>

View File

@@ -1,18 +1,34 @@
<script lang="ts" setup> <script lang="ts" setup>
import { DocAlert } from '#/components/doc-alert';
import { Button } from 'ant-design-vue';
import { Page } from '@vben/common-ui'; import { Page } from '@vben/common-ui';
import { Button } from 'ant-design-vue';
import { DocAlert } from '#/components/doc-alert';
</script> </script>
<template> <template>
<Page> <Page>
<DocAlert title="审批接入(业务表单)" url="https://doc.iocoder.cn/bpm/use-business-form/" /> <DocAlert
<Button danger type="link" target="_blank" href="https://github.com/yudaocode/yudao-ui-admin-vue3"> title="审批接入(业务表单)"
url="https://doc.iocoder.cn/bpm/use-business-form/"
/>
<Button
danger
type="link"
target="_blank"
href="https://github.com/yudaocode/yudao-ui-admin-vue3"
>
该功能支持 Vue3 + element-plus 版本 该功能支持 Vue3 + element-plus 版本
</Button> </Button>
<br /> <br />
<Button type="link" target="_blank" href="https://github.com/yudaocode/yudao-ui-admin-vue3/blob/master/src/views/bpm/oa/leave/index"> <Button
可参考 https://github.com/yudaocode/yudao-ui-admin-vue3/blob/master/src/views/bpm/oa/leave/index 代码pull request 贡献给我们! type="link"
target="_blank"
href="https://github.com/yudaocode/yudao-ui-admin-vue3/blob/master/src/views/bpm/oa/leave/index"
>
可参考
https://github.com/yudaocode/yudao-ui-admin-vue3/blob/master/src/views/bpm/oa/leave/index
代码pull request 贡献给我们
</Button> </Button>
</Page> </Page>
</template> </template>

View File

@@ -1,18 +1,31 @@
<script lang="ts" setup> <script lang="ts" setup>
import { DocAlert } from '#/components/doc-alert';
import { Button } from 'ant-design-vue';
import { Page } from '@vben/common-ui'; import { Page } from '@vben/common-ui';
import { Button } from 'ant-design-vue';
import { DocAlert } from '#/components/doc-alert';
</script> </script>
<template> <template>
<Page> <Page>
<DocAlert title="流程表达式" url="https://doc.iocoder.cn/bpm/expression/" /> <DocAlert title="流程表达式" url="https://doc.iocoder.cn/bpm/expression/" />
<Button danger type="link" target="_blank" href="https://github.com/yudaocode/yudao-ui-admin-vue3"> <Button
danger
type="link"
target="_blank"
href="https://github.com/yudaocode/yudao-ui-admin-vue3"
>
该功能支持 Vue3 + element-plus 版本 该功能支持 Vue3 + element-plus 版本
</Button> </Button>
<br /> <br />
<Button type="link" target="_blank" href="https://github.com/yudaocode/yudao-ui-admin-vue3/blob/master/src/views/bpm/processExpression/index"> <Button
可参考 https://github.com/yudaocode/yudao-ui-admin-vue3/blob/master/src/views/bpm/processExpression/index 代码pull request 贡献给我们! type="link"
target="_blank"
href="https://github.com/yudaocode/yudao-ui-admin-vue3/blob/master/src/views/bpm/processExpression/index"
>
可参考
https://github.com/yudaocode/yudao-ui-admin-vue3/blob/master/src/views/bpm/processExpression/index
代码pull request 贡献给我们
</Button> </Button>
</Page> </Page>
</template> </template>

View File

@@ -1,18 +1,34 @@
<script lang="ts" setup> <script lang="ts" setup>
import { DocAlert } from '#/components/doc-alert';
import { Button } from 'ant-design-vue';
import { Page } from '@vben/common-ui'; import { Page } from '@vben/common-ui';
import { Button } from 'ant-design-vue';
import { DocAlert } from '#/components/doc-alert';
</script> </script>
<template> <template>
<Page> <Page>
<DocAlert title="流程发起、取消、重新发起" url="https://doc.iocoder.cn/bpm/process-instance/" /> <DocAlert
<Button danger type="link" target="_blank" href="https://github.com/yudaocode/yudao-ui-admin-vue3"> title="流程发起、取消、重新发起"
url="https://doc.iocoder.cn/bpm/process-instance/"
/>
<Button
danger
type="link"
target="_blank"
href="https://github.com/yudaocode/yudao-ui-admin-vue3"
>
该功能支持 Vue3 + element-plus 版本 该功能支持 Vue3 + element-plus 版本
</Button> </Button>
<br /> <br />
<Button type="link" target="_blank" href="https://github.com/yudaocode/yudao-ui-admin-vue3/blob/master/src/views/bpm/processInstance/index"> <Button
可参考 https://github.com/yudaocode/yudao-ui-admin-vue3/blob/master/src/views/bpm/processInstance/index 代码pull request 贡献给我们! type="link"
target="_blank"
href="https://github.com/yudaocode/yudao-ui-admin-vue3/blob/master/src/views/bpm/processInstance/index"
>
可参考
https://github.com/yudaocode/yudao-ui-admin-vue3/blob/master/src/views/bpm/processInstance/index
代码pull request 贡献给我们
</Button> </Button>
</Page> </Page>
</template> </template>

View File

@@ -1,18 +1,31 @@
<script lang="ts" setup> <script lang="ts" setup>
import { DocAlert } from '#/components/doc-alert';
import { Button } from 'ant-design-vue';
import { Page } from '@vben/common-ui'; import { Page } from '@vben/common-ui';
import { Button } from 'ant-design-vue';
import { DocAlert } from '#/components/doc-alert';
</script> </script>
<template> <template>
<Page> <Page>
<DocAlert title="工作流手册" url="https://doc.iocoder.cn/bpm/" /> <DocAlert title="工作流手册" url="https://doc.iocoder.cn/bpm/" />
<Button danger type="link" target="_blank" href="https://github.com/yudaocode/yudao-ui-admin-vue3"> <Button
danger
type="link"
target="_blank"
href="https://github.com/yudaocode/yudao-ui-admin-vue3"
>
该功能支持 Vue3 + element-plus 版本 该功能支持 Vue3 + element-plus 版本
</Button> </Button>
<br /> <br />
<Button type="link" target="_blank" href="https://github.com/yudaocode/yudao-ui-admin-vue3/blob/master/src/views/bpm/processInstance/manager/index"> <Button
可参考 https://github.com/yudaocode/yudao-ui-admin-vue3/blob/master/src/views/bpm/processInstance/manager/index 代码pull request 贡献给我们! type="link"
target="_blank"
href="https://github.com/yudaocode/yudao-ui-admin-vue3/blob/master/src/views/bpm/processInstance/manager/index"
>
可参考
https://github.com/yudaocode/yudao-ui-admin-vue3/blob/master/src/views/bpm/processInstance/manager/index
代码pull request 贡献给我们
</Button> </Button>
</Page> </Page>
</template> </template>

View File

@@ -1,18 +1,34 @@
<script lang="ts" setup> <script lang="ts" setup>
import { DocAlert } from '#/components/doc-alert';
import { Button } from 'ant-design-vue';
import { Page } from '@vben/common-ui'; import { Page } from '@vben/common-ui';
import { Button } from 'ant-design-vue';
import { DocAlert } from '#/components/doc-alert';
</script> </script>
<template> <template>
<Page> <Page>
<DocAlert title="执行监听器、任务监听器" url="https://doc.iocoder.cn/bpm/listener/" /> <DocAlert
<Button danger type="link" target="_blank" href="https://github.com/yudaocode/yudao-ui-admin-vue3"> title="执行监听器、任务监听器"
url="https://doc.iocoder.cn/bpm/listener/"
/>
<Button
danger
type="link"
target="_blank"
href="https://github.com/yudaocode/yudao-ui-admin-vue3"
>
该功能支持 Vue3 + element-plus 版本 该功能支持 Vue3 + element-plus 版本
</Button> </Button>
<br /> <br />
<Button type="link" target="_blank" href="https://github.com/yudaocode/yudao-ui-admin-vue3/blob/master/src/views/bpm/processListener/index"> <Button
可参考 https://github.com/yudaocode/yudao-ui-admin-vue3/blob/master/src/views/bpm/processListener/index 代码pull request 贡献给我们! type="link"
target="_blank"
href="https://github.com/yudaocode/yudao-ui-admin-vue3/blob/master/src/views/bpm/processListener/index"
>
可参考
https://github.com/yudaocode/yudao-ui-admin-vue3/blob/master/src/views/bpm/processListener/index
代码pull request 贡献给我们
</Button> </Button>
</Page> </Page>
</template> </template>

View File

@@ -1,18 +1,34 @@
<script lang="ts" setup> <script lang="ts" setup>
import { DocAlert } from '#/components/doc-alert';
import { Button } from 'ant-design-vue';
import { Page } from '@vben/common-ui'; import { Page } from '@vben/common-ui';
import { Button } from 'ant-design-vue';
import { DocAlert } from '#/components/doc-alert';
</script> </script>
<template> <template>
<Page> <Page>
<DocAlert title="审批转办、委派、抄送" url="https://doc.iocoder.cn/bpm/task-delegation-and-cc/" /> <DocAlert
<Button danger type="link" target="_blank" href="https://github.com/yudaocode/yudao-ui-admin-vue3"> title="审批转办、委派、抄送"
url="https://doc.iocoder.cn/bpm/task-delegation-and-cc/"
/>
<Button
danger
type="link"
target="_blank"
href="https://github.com/yudaocode/yudao-ui-admin-vue3"
>
该功能支持 Vue3 + element-plus 版本 该功能支持 Vue3 + element-plus 版本
</Button> </Button>
<br /> <br />
<Button type="link" target="_blank" href="https://github.com/yudaocode/yudao-ui-admin-vue3/blob/master/src/views/bpm/task/copy/index"> <Button
可参考 https://github.com/yudaocode/yudao-ui-admin-vue3/blob/master/src/views/bpm/task/copy/index 代码pull request 贡献给我们! type="link"
target="_blank"
href="https://github.com/yudaocode/yudao-ui-admin-vue3/blob/master/src/views/bpm/task/copy/index"
>
可参考
https://github.com/yudaocode/yudao-ui-admin-vue3/blob/master/src/views/bpm/task/copy/index
代码pull request 贡献给我们
</Button> </Button>
</Page> </Page>
</template> </template>

View File

@@ -1,21 +1,40 @@
<script lang="ts" setup> <script lang="ts" setup>
import { DocAlert } from '#/components/doc-alert';
import { Button } from 'ant-design-vue';
import { Page } from '@vben/common-ui'; import { Page } from '@vben/common-ui';
import { Button } from 'ant-design-vue';
import { DocAlert } from '#/components/doc-alert';
</script> </script>
<template> <template>
<Page> <Page>
<DocAlert title="审批通过、不通过、驳回" url="https://doc.iocoder.cn/bpm/task-todo-done/" /> <DocAlert
title="审批通过、不通过、驳回"
url="https://doc.iocoder.cn/bpm/task-todo-done/"
/>
<DocAlert title="审批加签、减签" url="https://doc.iocoder.cn/bpm/sign/" /> <DocAlert title="审批加签、减签" url="https://doc.iocoder.cn/bpm/sign/" />
<DocAlert title="审批转办、委派、抄送" url="https://doc.iocoder.cn/bpm/task-delegation-and-cc/" /> <DocAlert
title="审批转办、委派、抄送"
url="https://doc.iocoder.cn/bpm/task-delegation-and-cc/"
/>
<DocAlert title="审批加签、减签" url="https://doc.iocoder.cn/bpm/sign/" /> <DocAlert title="审批加签、减签" url="https://doc.iocoder.cn/bpm/sign/" />
<Button danger type="link" target="_blank" href="https://github.com/yudaocode/yudao-ui-admin-vue3"> <Button
danger
type="link"
target="_blank"
href="https://github.com/yudaocode/yudao-ui-admin-vue3"
>
该功能支持 Vue3 + element-plus 版本 该功能支持 Vue3 + element-plus 版本
</Button> </Button>
<br /> <br />
<Button type="link" target="_blank" href="https://github.com/yudaocode/yudao-ui-admin-vue3/blob/master/src/views/bpm/task/done/index"> <Button
可参考 https://github.com/yudaocode/yudao-ui-admin-vue3/blob/master/src/views/bpm/task/done/index 代码pull request 贡献给我们! type="link"
target="_blank"
href="https://github.com/yudaocode/yudao-ui-admin-vue3/blob/master/src/views/bpm/task/done/index"
>
可参考
https://github.com/yudaocode/yudao-ui-admin-vue3/blob/master/src/views/bpm/task/done/index
代码pull request 贡献给我们
</Button> </Button>
</Page> </Page>
</template> </template>

View File

@@ -1,18 +1,31 @@
<script lang="ts" setup> <script lang="ts" setup>
import { DocAlert } from '#/components/doc-alert';
import { Button } from 'ant-design-vue';
import { Page } from '@vben/common-ui'; import { Page } from '@vben/common-ui';
import { Button } from 'ant-design-vue';
import { DocAlert } from '#/components/doc-alert';
</script> </script>
<template> <template>
<Page> <Page>
<DocAlert title="工作流手册" url="https://doc.iocoder.cn/bpm/" /> <DocAlert title="工作流手册" url="https://doc.iocoder.cn/bpm/" />
<Button danger type="link" target="_blank" href="https://github.com/yudaocode/yudao-ui-admin-vue3"> <Button
danger
type="link"
target="_blank"
href="https://github.com/yudaocode/yudao-ui-admin-vue3"
>
该功能支持 Vue3 + element-plus 版本 该功能支持 Vue3 + element-plus 版本
</Button> </Button>
<br /> <br />
<Button type="link" target="_blank" href="https://github.com/yudaocode/yudao-ui-admin-vue3/blob/master/src/views/bpm/task/manager/index"> <Button
可参考 https://github.com/yudaocode/yudao-ui-admin-vue3/blob/master/src/views/bpm/task/manager/index 代码pull request 贡献给我们! type="link"
target="_blank"
href="https://github.com/yudaocode/yudao-ui-admin-vue3/blob/master/src/views/bpm/task/manager/index"
>
可参考
https://github.com/yudaocode/yudao-ui-admin-vue3/blob/master/src/views/bpm/task/manager/index
代码pull request 贡献给我们
</Button> </Button>
</Page> </Page>
</template> </template>

View File

@@ -1,21 +1,40 @@
<script lang="ts" setup> <script lang="ts" setup>
import { DocAlert } from '#/components/doc-alert';
import { Button } from 'ant-design-vue';
import { Page } from '@vben/common-ui'; import { Page } from '@vben/common-ui';
import { Button } from 'ant-design-vue';
import { DocAlert } from '#/components/doc-alert';
</script> </script>
<template> <template>
<Page> <Page>
<DocAlert title="审批通过、不通过、驳回" url="https://doc.iocoder.cn/bpm/task-todo-done/" /> <DocAlert
title="审批通过、不通过、驳回"
url="https://doc.iocoder.cn/bpm/task-todo-done/"
/>
<DocAlert title="审批加签、减签" url="https://doc.iocoder.cn/bpm/sign/" /> <DocAlert title="审批加签、减签" url="https://doc.iocoder.cn/bpm/sign/" />
<DocAlert title="审批转办、委派、抄送" url="https://doc.iocoder.cn/bpm/task-delegation-and-cc/" /> <DocAlert
title="审批转办、委派、抄送"
url="https://doc.iocoder.cn/bpm/task-delegation-and-cc/"
/>
<DocAlert title="审批加签、减签" url="https://doc.iocoder.cn/bpm/sign/" /> <DocAlert title="审批加签、减签" url="https://doc.iocoder.cn/bpm/sign/" />
<Button danger type="link" target="_blank" href="https://github.com/yudaocode/yudao-ui-admin-vue3"> <Button
danger
type="link"
target="_blank"
href="https://github.com/yudaocode/yudao-ui-admin-vue3"
>
该功能支持 Vue3 + element-plus 版本 该功能支持 Vue3 + element-plus 版本
</Button> </Button>
<br /> <br />
<Button type="link" target="_blank" href="https://github.com/yudaocode/yudao-ui-admin-vue3/blob/master/src/views/bpm/task/todo/index"> <Button
可参考 https://github.com/yudaocode/yudao-ui-admin-vue3/blob/master/src/views/bpm/task/todo/index 代码pull request 贡献给我们! type="link"
target="_blank"
href="https://github.com/yudaocode/yudao-ui-admin-vue3/blob/master/src/views/bpm/task/todo/index"
>
可参考
https://github.com/yudaocode/yudao-ui-admin-vue3/blob/master/src/views/bpm/task/todo/index
代码pull request 贡献给我们
</Button> </Button>
</Page> </Page>
</template> </template>

View File

@@ -210,14 +210,14 @@ initDataSourceConfig();
<DocAlert <DocAlert
title="代码生成(单表)" title="代码生成(单表)"
url="https://doc.iocoder.cn/new-feature/" url="https://doc.iocoder.cn/new-feature/"
/> />
<DocAlert <DocAlert
title="代码生成(树表)" title="代码生成(树表)"
url="https://doc.iocoder.cn/new-feature/tree/" url="https://doc.iocoder.cn/new-feature/tree/"
/> />
<DocAlert <DocAlert
title="代码生成(主子表)" title="代码生成(主子表)"
url="https://doc.iocoder.cn/new-feature/master-sub/" url="https://doc.iocoder.cn/new-feature/master-sub/"
/> />
<DocAlert title="单元测试" url="https://doc.iocoder.cn/unit-test/" /> <DocAlert title="单元测试" url="https://doc.iocoder.cn/unit-test/" />
</template> </template>

View File

@@ -1,9 +1,10 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { InfraCodegenApi } from '#/api/infra/codegen'; import type { InfraCodegenApi } from '#/api/infra/codegen';
import { useVbenForm } from '#/adapter/form';
import { watch } from 'vue'; import { watch } from 'vue';
import { useVbenForm } from '#/adapter/form';
import { useBasicInfoFormSchema } from '../data'; import { useBasicInfoFormSchema } from '../data';
const props = defineProps<{ const props = defineProps<{

View File

@@ -2,11 +2,12 @@
import type { InfraCodegenApi } from '#/api/infra/codegen'; import type { InfraCodegenApi } from '#/api/infra/codegen';
import type { SystemDictTypeApi } from '#/api/system/dict/type'; import type { SystemDictTypeApi } from '#/api/system/dict/type';
import { nextTick, onMounted, ref, watch } from 'vue';
import { Checkbox, Input, Select } from 'ant-design-vue'; import { Checkbox, Input, Select } from 'ant-design-vue';
import { useVbenVxeGrid } from '#/adapter/vxe-table'; import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { getSimpleDictTypeList } from '#/api/system/dict/type'; import { getSimpleDictTypeList } from '#/api/system/dict/type';
import { nextTick, onMounted, ref, watch } from 'vue';
import { useCodegenColumnTableColumns } from '../data'; import { useCodegenColumnTableColumns } from '../data';

View File

@@ -22,6 +22,13 @@ const getTitle = computed(() => {
}); });
const [Form, formApi] = useVbenForm({ const [Form, formApi] = useVbenForm({
commonConfig: {
componentProps: {
class: 'w-full',
},
formItemClass: 'col-span-2',
labelWidth: 80,
},
layout: 'horizontal', layout: 'horizontal',
schema: useFormSchema(), schema: useFormSchema(),
showDefaultActions: false, showDefaultActions: false,

View File

@@ -26,6 +26,13 @@ const getTitle = computed(() => {
}); });
const [Form, formApi] = useVbenForm({ const [Form, formApi] = useVbenForm({
commonConfig: {
componentProps: {
class: 'w-full',
},
formItemClass: 'col-span-2',
labelWidth: 80,
},
layout: 'horizontal', layout: 'horizontal',
schema: useFormSchema(), schema: useFormSchema(),
showDefaultActions: false, showDefaultActions: false,

View File

@@ -1,7 +1,5 @@
import type { VxeTableGridOptions } from '@vben/plugins/vxe-table';
import type { VbenFormSchema } from '#/adapter/form'; import type { VbenFormSchema } from '#/adapter/form';
import type { OnActionClickFn } from '#/adapter/vxe-table'; import type { OnActionClickFn, VxeTableGridOptions } from '#/adapter/vxe-table';
import type { Demo01ContactApi } from '#/api/infra/demo/demo01'; import type { Demo01ContactApi } from '#/api/infra/demo/demo01';
import { useAccess } from '@vben/access'; import { useAccess } from '@vben/access';

View File

@@ -26,6 +26,13 @@ const getTitle = computed(() => {
}); });
const [Form, formApi] = useVbenForm({ const [Form, formApi] = useVbenForm({
commonConfig: {
componentProps: {
class: 'w-full',
},
formItemClass: 'col-span-2',
labelWidth: 80,
},
layout: 'horizontal', layout: 'horizontal',
schema: useFormSchema(), schema: useFormSchema(),
showDefaultActions: false, showDefaultActions: false,

View File

@@ -1,7 +1,5 @@
import type { VxeTableGridOptions } from '@vben/plugins/vxe-table';
import type { VbenFormSchema } from '#/adapter/form'; import type { VbenFormSchema } from '#/adapter/form';
import type { OnActionClickFn } from '#/adapter/vxe-table'; import type { OnActionClickFn, VxeTableGridOptions } from '#/adapter/vxe-table';
import type { Demo02CategoryApi } from '#/api/infra/demo/demo02'; import type { Demo02CategoryApi } from '#/api/infra/demo/demo02';
import { useAccess } from '@vben/access'; import { useAccess } from '@vben/access';
@@ -36,7 +34,6 @@ export function useFormSchema(): VbenFormSchema[] {
}); });
return handleTree(data); return handleTree(data);
}, },
class: 'w-full',
labelField: 'name', labelField: 'name',
valueField: 'id', valueField: 'id',
childrenField: 'children', childrenField: 'children',

View File

@@ -31,6 +31,13 @@ const getTitle = computed(() => {
}); });
const [Form, formApi] = useVbenForm({ const [Form, formApi] = useVbenForm({
commonConfig: {
componentProps: {
class: 'w-full',
},
formItemClass: 'col-span-2',
labelWidth: 80,
},
layout: 'horizontal', layout: 'horizontal',
schema: useFormSchema(), schema: useFormSchema(),
showDefaultActions: false, showDefaultActions: false,

View File

@@ -1,7 +1,5 @@
import type { VxeTableGridOptions } from '@vben/plugins/vxe-table';
import type { VbenFormSchema } from '#/adapter/form'; import type { VbenFormSchema } from '#/adapter/form';
import type { OnActionClickFn } from '#/adapter/vxe-table'; import type { OnActionClickFn, VxeTableGridOptions } from '#/adapter/vxe-table';
import type { Demo03StudentApi } from '#/api/infra/demo/demo03/erp'; import type { Demo03StudentApi } from '#/api/infra/demo/demo03/erp';
import { useAccess } from '@vben/access'; import { useAccess } from '@vben/access';

View File

@@ -26,6 +26,13 @@ const getTitle = computed(() => {
}); });
const [Form, formApi] = useVbenForm({ const [Form, formApi] = useVbenForm({
commonConfig: {
componentProps: {
class: 'w-full',
},
formItemClass: 'col-span-2',
labelWidth: 80,
},
layout: 'horizontal', layout: 'horizontal',
schema: useDemo03CourseFormSchema(), schema: useDemo03CourseFormSchema(),
showDefaultActions: false, showDefaultActions: false,

View File

@@ -26,6 +26,13 @@ const getTitle = computed(() => {
}); });
const [Form, formApi] = useVbenForm({ const [Form, formApi] = useVbenForm({
commonConfig: {
componentProps: {
class: 'w-full',
},
formItemClass: 'col-span-2',
labelWidth: 80,
},
layout: 'horizontal', layout: 'horizontal',
schema: useDemo03GradeFormSchema(), schema: useDemo03GradeFormSchema(),
showDefaultActions: false, showDefaultActions: false,

View File

@@ -26,6 +26,13 @@ const getTitle = computed(() => {
}); });
const [Form, formApi] = useVbenForm({ const [Form, formApi] = useVbenForm({
commonConfig: {
componentProps: {
class: 'w-full',
},
formItemClass: 'col-span-2',
labelWidth: 80,
},
layout: 'horizontal', layout: 'horizontal',
schema: useFormSchema(), schema: useFormSchema(),
showDefaultActions: false, showDefaultActions: false,

View File

@@ -1,7 +1,5 @@
import type { VxeTableGridOptions } from '@vben/plugins/vxe-table';
import type { VbenFormSchema } from '#/adapter/form'; import type { VbenFormSchema } from '#/adapter/form';
import type { OnActionClickFn } from '#/adapter/vxe-table'; import type { OnActionClickFn, VxeTableGridOptions } from '#/adapter/vxe-table';
import type { Demo03StudentApi } from '#/api/infra/demo/demo03/inner'; import type { Demo03StudentApi } from '#/api/infra/demo/demo03/inner';
import { useAccess } from '@vben/access'; import { useAccess } from '@vben/access';

View File

@@ -33,6 +33,13 @@ const demo03CourseFormRef = ref<InstanceType<typeof Demo03CourseForm>>();
const demo03GradeFormRef = ref<InstanceType<typeof Demo03GradeForm>>(); const demo03GradeFormRef = ref<InstanceType<typeof Demo03GradeForm>>();
const [Form, formApi] = useVbenForm({ const [Form, formApi] = useVbenForm({
commonConfig: {
componentProps: {
class: 'w-full',
},
formItemClass: 'col-span-2',
labelWidth: 80,
},
layout: 'horizontal', layout: 'horizontal',
schema: useFormSchema(), schema: useFormSchema(),
showDefaultActions: false, showDefaultActions: false,

View File

@@ -1,7 +1,5 @@
import type { VxeTableGridOptions } from '@vben/plugins/vxe-table';
import type { VbenFormSchema } from '#/adapter/form'; import type { VbenFormSchema } from '#/adapter/form';
import type { OnActionClickFn } from '#/adapter/vxe-table'; import type { OnActionClickFn, VxeTableGridOptions } from '#/adapter/vxe-table';
import type { Demo03StudentApi } from '#/api/infra/demo/demo03/normal'; import type { Demo03StudentApi } from '#/api/infra/demo/demo03/normal';
import { useAccess } from '@vben/access'; import { useAccess } from '@vben/access';

View File

@@ -33,6 +33,13 @@ const demo03CourseFormRef = ref<InstanceType<typeof Demo03CourseForm>>();
const demo03GradeFormRef = ref<InstanceType<typeof Demo03GradeForm>>(); const demo03GradeFormRef = ref<InstanceType<typeof Demo03GradeForm>>();
const [Form, formApi] = useVbenForm({ const [Form, formApi] = useVbenForm({
commonConfig: {
componentProps: {
class: 'w-full',
},
formItemClass: 'col-span-2',
labelWidth: 80,
},
layout: 'horizontal', layout: 'horizontal',
schema: useFormSchema(), schema: useFormSchema(),
showDefaultActions: false, showDefaultActions: false,

View File

@@ -14,12 +14,17 @@ import { useFormSchema } from '../data';
const emit = defineEmits(['success']); const emit = defineEmits(['success']);
const [Form, formApi] = useVbenForm({ const [Form, formApi] = useVbenForm({
commonConfig: {
componentProps: {
class: 'w-full',
},
formItemClass: 'col-span-2',
labelWidth: 80,
hideLabel: true,
},
layout: 'horizontal', layout: 'horizontal',
schema: useFormSchema().map((item) => ({ ...item, label: '' })), // 去除label schema: useFormSchema().map((item) => ({ ...item, label: '' })), // 去除label
showDefaultActions: false, showDefaultActions: false,
commonConfig: {
hideLabel: true,
},
}); });
const [Modal, modalApi] = useVbenModal({ const [Modal, modalApi] = useVbenModal({

View File

@@ -36,7 +36,6 @@ export function useFormSchema(): VbenFormSchema[] {
componentProps: { componentProps: {
options: getDictOptions(DICT_TYPE.INFRA_FILE_STORAGE, 'number'), options: getDictOptions(DICT_TYPE.INFRA_FILE_STORAGE, 'number'),
placeholder: '请选择存储器', placeholder: '请选择存储器',
class: 'w-full',
}, },
rules: 'required', rules: 'required',
dependencies: { dependencies: {
@@ -87,7 +86,6 @@ export function useFormSchema(): VbenFormSchema[] {
component: 'InputNumber', component: 'InputNumber',
componentProps: { componentProps: {
min: 0, min: 0,
class: 'w-full',
controlsPosition: 'right', controlsPosition: 'right',
placeholder: '请输入主机端口', placeholder: '请输入主机端口',
}, },

View File

@@ -27,7 +27,11 @@ const getTitle = computed(() => {
const [Form, formApi] = useVbenForm({ const [Form, formApi] = useVbenForm({
commonConfig: { commonConfig: {
labelWidth: 120, componentProps: {
class: 'w-full',
},
formItemClass: 'col-span-2',
labelWidth: 80,
}, },
layout: 'horizontal', layout: 'horizontal',
schema: useFormSchema(), schema: useFormSchema(),

View File

@@ -65,7 +65,6 @@ export function useFormSchema(): VbenFormSchema[] {
componentProps: { componentProps: {
placeholder: '请输入重试次数。设置为 0 时,不进行重试', placeholder: '请输入重试次数。设置为 0 时,不进行重试',
min: 0, min: 0,
class: 'w-full',
}, },
rules: 'required', rules: 'required',
}, },
@@ -76,7 +75,6 @@ export function useFormSchema(): VbenFormSchema[] {
componentProps: { componentProps: {
placeholder: '请输入重试间隔,单位:毫秒。设置为 0 时,无需间隔', placeholder: '请输入重试间隔,单位:毫秒。设置为 0 时,无需间隔',
min: 0, min: 0,
class: 'w-full',
}, },
rules: 'required', rules: 'required',
}, },
@@ -87,7 +85,6 @@ export function useFormSchema(): VbenFormSchema[] {
componentProps: { componentProps: {
placeholder: '请输入监控超时时间,单位:毫秒', placeholder: '请输入监控超时时间,单位:毫秒',
min: 0, min: 0,
class: 'w-full',
}, },
}, },
]; ];

View File

@@ -22,12 +22,16 @@ const getTitle = computed(() => {
}); });
const [Form, formApi] = useVbenForm({ const [Form, formApi] = useVbenForm({
commonConfig: {
componentProps: {
class: 'w-full',
},
formItemClass: 'col-span-2',
labelWidth: 80,
},
layout: 'horizontal', layout: 'horizontal',
schema: useFormSchema(), schema: useFormSchema(),
showDefaultActions: false, showDefaultActions: false,
commonConfig: {
labelWidth: 140,
},
}); });
const [Modal, modalApi] = useVbenModal({ const [Modal, modalApi] = useVbenModal({

View File

@@ -1,6 +1,5 @@
import type { VxeTableGridOptions } from '@vben/plugins/vxe-table';
import type { VbenFormSchema } from '#/adapter/form'; import type { VbenFormSchema } from '#/adapter/form';
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import type { SystemAreaApi } from '#/api/system/area'; import type { SystemAreaApi } from '#/api/system/area';
/** 查询 IP 的表单 */ /** 查询 IP 的表单 */

View File

@@ -10,6 +10,13 @@ import { $t } from '#/locales';
import { useFormSchema } from '../data'; import { useFormSchema } from '../data';
const [Form, { setFieldValue, validate, getValues }] = useVbenForm({ const [Form, { setFieldValue, validate, getValues }] = useVbenForm({
commonConfig: {
componentProps: {
class: 'w-full',
},
formItemClass: 'col-span-2',
labelWidth: 80,
},
layout: 'horizontal', layout: 'horizontal',
schema: useFormSchema(), schema: useFormSchema(),
showDefaultActions: false, showDefaultActions: false,

View File

@@ -1,7 +1,5 @@
import type { VxeTableGridOptions } from '@vben/plugins/vxe-table';
import type { VbenFormSchema } from '#/adapter/form'; import type { VbenFormSchema } from '#/adapter/form';
import type { OnActionClickFn } from '#/adapter/vxe-table'; import type { OnActionClickFn, VxeTableGridOptions } from '#/adapter/vxe-table';
import type { SystemDeptApi } from '#/api/system/dept'; import type { SystemDeptApi } from '#/api/system/dept';
import { useAccess } from '@vben/access'; import { useAccess } from '@vben/access';
@@ -40,7 +38,6 @@ export function useFormSchema(): VbenFormSchema[] {
}); });
return handleTree(data); return handleTree(data);
}, },
class: 'w-full',
labelField: 'name', labelField: 'name',
valueField: 'id', valueField: 'id',
childrenField: 'children', childrenField: 'children',
@@ -64,7 +61,6 @@ export function useFormSchema(): VbenFormSchema[] {
component: 'InputNumber', component: 'InputNumber',
componentProps: { componentProps: {
min: 0, min: 0,
class: 'w-full',
controlsPosition: 'right', controlsPosition: 'right',
placeholder: '请输入显示顺序', placeholder: '请输入显示顺序',
}, },
@@ -76,7 +72,6 @@ export function useFormSchema(): VbenFormSchema[] {
component: 'ApiSelect', component: 'ApiSelect',
componentProps: { componentProps: {
api: getSimpleUserList, api: getSimpleUserList,
class: 'w-full',
labelField: 'nickname', labelField: 'nickname',
valueField: 'id', valueField: 'id',
placeholder: '请选择负责人', placeholder: '请选择负责人',

View File

@@ -22,6 +22,13 @@ const getTitle = computed(() => {
}); });
const [Form, formApi] = useVbenForm({ const [Form, formApi] = useVbenForm({
commonConfig: {
componentProps: {
class: 'w-full',
},
formItemClass: 'col-span-2',
labelWidth: 80,
},
layout: 'horizontal', layout: 'horizontal',
schema: useFormSchema(), schema: useFormSchema(),
showDefaultActions: false, showDefaultActions: false,

View File

@@ -204,7 +204,6 @@ export function useDataFormSchema(): VbenFormSchema[] {
return { return {
api: getSimpleDictTypeList, api: getSimpleDictTypeList,
placeholder: '请输入字典类型', placeholder: '请输入字典类型',
class: 'w-full',
labelField: 'name', labelField: 'name',
valueField: 'type', valueField: 'type',
disabled: !!values.id, disabled: !!values.id,
@@ -239,7 +238,6 @@ export function useDataFormSchema(): VbenFormSchema[] {
component: 'InputNumber', component: 'InputNumber',
componentProps: { componentProps: {
placeholder: '请输入显示排序', placeholder: '请输入显示排序',
class: 'w-full',
}, },
rules: 'required', rules: 'required',
}, },
@@ -262,7 +260,6 @@ export function useDataFormSchema(): VbenFormSchema[] {
componentProps: { componentProps: {
options: colorOptions, options: colorOptions,
placeholder: '请选择颜色类型', placeholder: '请选择颜色类型',
class: 'w-full',
}, },
}, },
{ {

View File

@@ -28,6 +28,13 @@ const getTitle = computed(() => {
}); });
const [Form, formApi] = useVbenForm({ const [Form, formApi] = useVbenForm({
commonConfig: {
componentProps: {
class: 'w-full',
},
formItemClass: 'col-span-2',
labelWidth: 80,
},
layout: 'horizontal', layout: 'horizontal',
schema: useDataFormSchema(), schema: useDataFormSchema(),
showDefaultActions: false, showDefaultActions: false,

View File

@@ -26,6 +26,13 @@ const getTitle = computed(() => {
}); });
const [Form, formApi] = useVbenForm({ const [Form, formApi] = useVbenForm({
commonConfig: {
componentProps: {
class: 'w-full',
},
formItemClass: 'col-span-2',
labelWidth: 80,
},
layout: 'horizontal', layout: 'horizontal',
schema: useTypeFormSchema(), schema: useTypeFormSchema(),
showDefaultActions: false, showDefaultActions: false,

View File

@@ -26,12 +26,16 @@ const getTitle = computed(() => {
}); });
const [Form, formApi] = useVbenForm({ const [Form, formApi] = useVbenForm({
commonConfig: {
componentProps: {
class: 'w-full',
},
formItemClass: 'col-span-2',
labelWidth: 80,
},
layout: 'horizontal', layout: 'horizontal',
schema: useFormSchema(), schema: useFormSchema(),
showDefaultActions: false, showDefaultActions: false,
commonConfig: {
labelWidth: 140,
},
}); });
const [Modal, modalApi] = useVbenModal({ const [Modal, modalApi] = useVbenModal({

View File

@@ -47,7 +47,6 @@ export function useFormSchema(): VbenFormSchema[] {
component: 'ApiSelect', component: 'ApiSelect',
componentProps: { componentProps: {
api: async () => await getSimpleMailAccountList(), api: async () => await getSimpleMailAccountList(),
class: 'w-full',
labelField: 'mail', labelField: 'mail',
valueField: 'id', valueField: 'id',
placeholder: '请选择邮箱账号', placeholder: '请选择邮箱账号',

View File

@@ -26,6 +26,13 @@ const getTitle = computed(() => {
}); });
const [Form, formApi] = useVbenForm({ const [Form, formApi] = useVbenForm({
commonConfig: {
componentProps: {
class: 'w-full',
},
formItemClass: 'col-span-2',
labelWidth: 80,
},
layout: 'horizontal', layout: 'horizontal',
schema: useFormSchema(), schema: useFormSchema(),
showDefaultActions: false, showDefaultActions: false,

View File

@@ -16,6 +16,13 @@ const emit = defineEmits(['success']);
const formData = ref<SystemMailTemplateApi.MailTemplate>(); const formData = ref<SystemMailTemplateApi.MailTemplate>();
const [Form, formApi] = useVbenForm({ const [Form, formApi] = useVbenForm({
commonConfig: {
componentProps: {
class: 'w-full',
},
formItemClass: 'col-span-2',
labelWidth: 80,
},
layout: 'horizontal', layout: 'horizontal',
showDefaultActions: false, showDefaultActions: false,
}); });

View File

@@ -44,7 +44,6 @@ export function useFormSchema(): VbenFormSchema[] {
} as SystemMenuApi.Menu); } as SystemMenuApi.Menu);
return handleTree(data); return handleTree(data);
}, },
class: 'w-full',
labelField: 'name', labelField: 'name',
valueField: 'id', valueField: 'id',
childrenField: 'children', childrenField: 'children',
@@ -167,7 +166,6 @@ export function useFormSchema(): VbenFormSchema[] {
component: 'AutoComplete', component: 'AutoComplete',
componentProps: { componentProps: {
allowClear: true, allowClear: true,
class: 'w-full',
filterOption(input: string, option: { value: string }) { filterOption(input: string, option: { value: string }) {
return option.value.toLowerCase().includes(input.toLowerCase()); return option.value.toLowerCase().includes(input.toLowerCase());
}, },
@@ -203,7 +201,6 @@ export function useFormSchema(): VbenFormSchema[] {
component: 'InputNumber', component: 'InputNumber',
componentProps: { componentProps: {
min: 0, min: 0,
class: 'w-full',
controlsPosition: 'right', controlsPosition: 'right',
placeholder: '请输入显示顺序', placeholder: '请输入显示顺序',
}, },

View File

@@ -22,6 +22,13 @@ const getTitle = computed(() =>
); );
const [Form, formApi] = useVbenForm({ const [Form, formApi] = useVbenForm({
commonConfig: {
componentProps: {
class: 'w-full',
},
formItemClass: 'col-span-2',
labelWidth: 100,
},
layout: 'horizontal', layout: 'horizontal',
schema: useFormSchema(), schema: useFormSchema(),
showDefaultActions: false, showDefaultActions: false,
@@ -75,7 +82,7 @@ const [Modal, modalApi] = useVbenModal({
</script> </script>
<template> <template>
<Modal :title="getTitle"> <Modal class="w-[40%]" :title="getTitle">
<Form class="mx-4" /> <Form class="mx-4" />
</Modal> </Modal>
</template> </template>

View File

@@ -22,6 +22,13 @@ const getTitle = computed(() => {
}); });
const [Form, formApi] = useVbenForm({ const [Form, formApi] = useVbenForm({
commonConfig: {
componentProps: {
class: 'w-full',
},
formItemClass: 'col-span-2',
labelWidth: 80,
},
layout: 'horizontal', layout: 'horizontal',
schema: useFormSchema(), schema: useFormSchema(),
showDefaultActions: false, showDefaultActions: false,

View File

@@ -68,7 +68,6 @@ export function useFormSchema(): VbenFormSchema[] {
DICT_TYPE.SYSTEM_NOTIFY_TEMPLATE_TYPE, DICT_TYPE.SYSTEM_NOTIFY_TEMPLATE_TYPE,
'number', 'number',
), ),
class: 'w-full',
placeholder: '请选择模板类型', placeholder: '请选择模板类型',
}, },
rules: 'required', rules: 'required',
@@ -201,7 +200,6 @@ export function useSendNotifyFormSchema(): VbenFormSchema[] {
component: 'ApiSelect', component: 'ApiSelect',
componentProps: { componentProps: {
api: getSimpleUserList, api: getSimpleUserList,
class: 'w-full',
labelField: 'nickname', labelField: 'nickname',
valueField: 'id', valueField: 'id',
placeholder: '请选择接收人', placeholder: '请选择接收人',

View File

@@ -26,6 +26,13 @@ const getTitle = computed(() => {
}); });
const [Form, formApi] = useVbenForm({ const [Form, formApi] = useVbenForm({
commonConfig: {
componentProps: {
class: 'w-full',
},
formItemClass: 'col-span-2',
labelWidth: 80,
},
layout: 'horizontal', layout: 'horizontal',
schema: useFormSchema(), schema: useFormSchema(),
showDefaultActions: false, showDefaultActions: false,

View File

@@ -17,11 +17,15 @@ const emit = defineEmits(['success']);
const formData = ref<SystemNotifyTemplateApi.NotifyTemplate>(); const formData = ref<SystemNotifyTemplateApi.NotifyTemplate>();
const [Form, formApi] = useVbenForm({ const [Form, formApi] = useVbenForm({
commonConfig: {
componentProps: {
class: 'w-full',
},
formItemClass: 'col-span-2',
labelWidth: 80,
},
layout: 'horizontal', layout: 'horizontal',
showDefaultActions: false, showDefaultActions: false,
commonConfig: {
labelWidth: 120,
},
}); });
const [Modal, modalApi] = useVbenModal({ const [Modal, modalApi] = useVbenModal({

View File

@@ -84,7 +84,6 @@ export function useFormSchema(): VbenFormSchema[] {
componentProps: { componentProps: {
placeholder: '请输入访问令牌的有效期,单位:秒', placeholder: '请输入访问令牌的有效期,单位:秒',
min: 0, min: 0,
class: 'w-full',
controlsPosition: 'right', controlsPosition: 'right',
}, },
rules: 'required', rules: 'required',
@@ -96,7 +95,6 @@ export function useFormSchema(): VbenFormSchema[] {
componentProps: { componentProps: {
placeholder: '请输入刷新令牌的有效期,单位:秒', placeholder: '请输入刷新令牌的有效期,单位:秒',
min: 0, min: 0,
class: 'w-full',
controlsPosition: 'right', controlsPosition: 'right',
}, },
rules: 'required', rules: 'required',
@@ -109,7 +107,6 @@ export function useFormSchema(): VbenFormSchema[] {
options: getDictOptions(DICT_TYPE.SYSTEM_OAUTH2_GRANT_TYPE), options: getDictOptions(DICT_TYPE.SYSTEM_OAUTH2_GRANT_TYPE),
mode: 'multiple', mode: 'multiple',
placeholder: '请输入授权类型', placeholder: '请输入授权类型',
class: 'w-full',
}, },
rules: 'required', rules: 'required',
}, },
@@ -120,7 +117,6 @@ export function useFormSchema(): VbenFormSchema[] {
componentProps: { componentProps: {
placeholder: '请输入授权范围', placeholder: '请输入授权范围',
mode: 'tags', mode: 'tags',
class: 'w-full',
}, },
}, },
{ {
@@ -130,7 +126,6 @@ export function useFormSchema(): VbenFormSchema[] {
componentProps: { componentProps: {
placeholder: '请输入自动授权范围', placeholder: '请输入自动授权范围',
mode: 'multiple', mode: 'multiple',
class: 'w-full',
// TODO @芋艿:根据权限,自动授权范围 // TODO @芋艿:根据权限,自动授权范围
}, },
}, },
@@ -141,7 +136,6 @@ export function useFormSchema(): VbenFormSchema[] {
componentProps: { componentProps: {
placeholder: '请输入可重定向的 URI 地址', placeholder: '请输入可重定向的 URI 地址',
mode: 'tags', mode: 'tags',
class: 'w-full',
}, },
rules: 'required', rules: 'required',
}, },
@@ -152,7 +146,6 @@ export function useFormSchema(): VbenFormSchema[] {
componentProps: { componentProps: {
placeholder: '请输入权限', placeholder: '请输入权限',
mode: 'tags', mode: 'tags',
class: 'w-full',
}, },
}, },
{ {
@@ -162,7 +155,6 @@ export function useFormSchema(): VbenFormSchema[] {
componentProps: { componentProps: {
mode: 'tags', mode: 'tags',
placeholder: '请输入资源', placeholder: '请输入资源',
class: 'w-full',
}, },
}, },
{ {

View File

@@ -26,12 +26,16 @@ const getTitle = computed(() => {
}); });
const [Form, formApi] = useVbenForm({ const [Form, formApi] = useVbenForm({
commonConfig: {
componentProps: {
class: 'w-full',
},
formItemClass: 'col-span-2',
labelWidth: 80,
},
layout: 'horizontal', layout: 'horizontal',
schema: useFormSchema(), schema: useFormSchema(),
showDefaultActions: false, showDefaultActions: false,
commonConfig: {
labelWidth: 140,
},
}); });
const [Modal, modalApi] = useVbenModal({ const [Modal, modalApi] = useVbenModal({

View File

@@ -40,7 +40,6 @@ export function useFormSchema(): VbenFormSchema[] {
component: 'InputNumber', component: 'InputNumber',
componentProps: { componentProps: {
min: 0, min: 0,
class: 'w-full',
controlsPosition: 'right', controlsPosition: 'right',
placeholder: '请输入显示顺序', placeholder: '请输入显示顺序',
}, },
@@ -97,7 +96,6 @@ export function useAssignDataPermissionFormSchema(): VbenFormSchema[] {
fieldName: 'dataScope', fieldName: 'dataScope',
label: '权限范围', label: '权限范围',
componentProps: { componentProps: {
class: 'w-full',
options: getDictOptions(DICT_TYPE.SYSTEM_DATA_SCOPE, 'number'), options: getDictOptions(DICT_TYPE.SYSTEM_DATA_SCOPE, 'number'),
}, },
}, },

View File

@@ -7,7 +7,7 @@ import { ref } from 'vue';
import { useVbenModal, VbenTree } from '@vben/common-ui'; import { useVbenModal, VbenTree } from '@vben/common-ui';
import { handleTree } from '@vben/utils'; import { handleTree } from '@vben/utils';
import { Checkbox, message, Spin } from 'ant-design-vue'; import { Checkbox, message } from 'ant-design-vue';
import { useVbenForm } from '#/adapter/form'; import { useVbenForm } from '#/adapter/form';
import { getDeptList } from '#/api/system/dept'; import { getDeptList } from '#/api/system/dept';
@@ -28,6 +28,13 @@ const isCheckStrictly = ref(true); // 父子联动状态
const expandedKeys = ref<number[]>([]); // 展开的节点 const expandedKeys = ref<number[]>([]); // 展开的节点
const [Form, formApi] = useVbenForm({ const [Form, formApi] = useVbenForm({
commonConfig: {
componentProps: {
class: 'w-full',
},
formItemClass: 'col-span-2',
labelWidth: 80,
},
layout: 'horizontal', layout: 'horizontal',
schema: useAssignDataPermissionFormSchema(), schema: useAssignDataPermissionFormSchema(),
showDefaultActions: false, showDefaultActions: false,
@@ -128,23 +135,23 @@ function getAllNodeIds(nodes: any[], ids: number[] = []): number[] {
</script> </script>
<template> <template>
<Modal title="数据权限"> <Modal title="数据权限" class="w-[40%]">
<Form class="mx-4"> <Form class="mx-4">
<template #dataScopeDeptIds="slotProps"> <template #dataScopeDeptIds="slotProps">
<Spin :spinning="deptLoading" class="w-full"> <!-- <Spin :spinning="deptLoading"> -->
<!-- TODO @芋艿可优化使用 antd tree原因是更原生 --> <!-- TODO @芋艿可优化使用 antd tree原因是更原生 -->
<VbenTree <VbenTree
:tree-data="deptTree" :tree-data="deptTree"
multiple multiple
bordered bordered
:expanded="expandedKeys" :expanded="expandedKeys"
v-bind="slotProps" v-bind="slotProps"
value-field="id" value-field="id"
label-field="name" label-field="name"
:auto-check-parent="false" :auto-check-parent="false"
:check-strictly="!isCheckStrictly" :check-strictly="!isCheckStrictly"
/> />
</Spin> <!-- </Spin> -->
</template> </template>
</Form> </Form>
<template #prepend-footer> <template #prepend-footer>

View File

@@ -7,7 +7,7 @@ import { ref } from 'vue';
import { useVbenModal, VbenTree } from '@vben/common-ui'; import { useVbenModal, VbenTree } from '@vben/common-ui';
import { handleTree } from '@vben/utils'; import { handleTree } from '@vben/utils';
import { Checkbox, message, Spin } from 'ant-design-vue'; import { Checkbox, message } from 'ant-design-vue';
import { useVbenForm } from '#/adapter/form'; import { useVbenForm } from '#/adapter/form';
import { getMenuList } from '#/api/system/menu'; import { getMenuList } from '#/api/system/menu';
@@ -25,6 +25,13 @@ const isExpanded = ref(false); // 展开状态
const expandedKeys = ref<number[]>([]); // 展开的节点 const expandedKeys = ref<number[]>([]); // 展开的节点
const [Form, formApi] = useVbenForm({ const [Form, formApi] = useVbenForm({
commonConfig: {
componentProps: {
class: 'w-full',
},
formItemClass: 'col-span-2',
labelWidth: 80,
},
layout: 'horizontal', layout: 'horizontal',
schema: useAssignMenuFormSchema(), schema: useAssignMenuFormSchema(),
showDefaultActions: false, showDefaultActions: false,
@@ -120,21 +127,21 @@ function getAllNodeIds(nodes: any[], ids: number[] = []): number[] {
</script> </script>
<template> <template>
<Modal title="数据权限"> <Modal title="数据权限" class="w-[40%]">
<Form class="mx-4"> <Form class="mx-4">
<template #menuIds="slotProps"> <template #menuIds="slotProps">
<Spin :spinning="menuLoading" class="w-full"> <!-- <Spin :spinning="menuLoading" class="w-full"> -->
<!-- TODO @芋艿可优化使用 antd tree原因是更原生 --> <!-- TODO @芋艿可优化使用 antd tree原因是更原生 -->
<VbenTree <VbenTree
:tree-data="menuTree" :tree-data="menuTree"
multiple multiple
bordered bordered
:expanded="expandedKeys" :expanded="expandedKeys"
v-bind="slotProps" v-bind="slotProps"
value-field="id" value-field="id"
label-field="name" label-field="name"
/> />
</Spin> <!-- </Spin> -->
</template> </template>
</Form> </Form>
<template #prepend-footer> <template #prepend-footer>

View File

@@ -22,6 +22,13 @@ const getTitle = computed(() => {
}); });
const [Form, formApi] = useVbenForm({ const [Form, formApi] = useVbenForm({
commonConfig: {
componentProps: {
class: 'w-full',
},
formItemClass: 'col-span-2',
labelWidth: 80,
},
layout: 'horizontal', layout: 'horizontal',
schema: useFormSchema(), schema: useFormSchema(),
showDefaultActions: false, showDefaultActions: false,

View File

@@ -37,7 +37,6 @@ export function useFormSchema(): VbenFormSchema[] {
component: 'Select', component: 'Select',
componentProps: { componentProps: {
options: getDictOptions(DICT_TYPE.SYSTEM_SMS_CHANNEL_CODE, 'string'), options: getDictOptions(DICT_TYPE.SYSTEM_SMS_CHANNEL_CODE, 'string'),
class: 'w-full',
placeholder: '请选择短信渠道', placeholder: '请选择短信渠道',
}, },
rules: 'required', rules: 'required',

View File

@@ -26,12 +26,16 @@ const getTitle = computed(() => {
}); });
const [Form, formApi] = useVbenForm({ const [Form, formApi] = useVbenForm({
commonConfig: {
componentProps: {
class: 'w-full',
},
formItemClass: 'col-span-2',
labelWidth: 80,
},
layout: 'horizontal', layout: 'horizontal',
schema: useFormSchema(), schema: useFormSchema(),
showDefaultActions: false, showDefaultActions: false,
commonConfig: {
labelWidth: 120,
},
}); });
const [Modal, modalApi] = useVbenModal({ const [Modal, modalApi] = useVbenModal({

View File

@@ -29,7 +29,6 @@ export function useFormSchema(): VbenFormSchema[] {
component: 'Select', component: 'Select',
componentProps: { componentProps: {
options: getDictOptions(DICT_TYPE.SYSTEM_SMS_TEMPLATE_TYPE, 'number'), options: getDictOptions(DICT_TYPE.SYSTEM_SMS_TEMPLATE_TYPE, 'number'),
class: 'w-full',
placeholder: '请选择短信类型', placeholder: '请选择短信类型',
}, },
rules: 'required', rules: 'required',
@@ -58,7 +57,6 @@ export function useFormSchema(): VbenFormSchema[] {
component: 'ApiSelect', component: 'ApiSelect',
componentProps: { componentProps: {
api: async () => await getSimpleSmsChannelList(), api: async () => await getSimpleSmsChannelList(),
class: 'w-full',
labelField: 'signature', labelField: 'signature',
valueField: 'id', valueField: 'id',
placeholder: '请选择短信渠道', placeholder: '请选择短信渠道',

View File

@@ -26,12 +26,16 @@ const getTitle = computed(() => {
}); });
const [Form, formApi] = useVbenForm({ const [Form, formApi] = useVbenForm({
commonConfig: {
componentProps: {
class: 'w-full',
},
formItemClass: 'col-span-2',
labelWidth: 80,
},
layout: 'horizontal', layout: 'horizontal',
schema: useFormSchema(), schema: useFormSchema(),
showDefaultActions: false, showDefaultActions: false,
commonConfig: {
labelWidth: 140,
},
}); });
const [Modal, modalApi] = useVbenModal({ const [Modal, modalApi] = useVbenModal({

View File

@@ -16,11 +16,15 @@ const emit = defineEmits(['success']);
const formData = ref<SystemSmsTemplateApi.SmsTemplate>(); const formData = ref<SystemSmsTemplateApi.SmsTemplate>();
const [Form, formApi] = useVbenForm({ const [Form, formApi] = useVbenForm({
commonConfig: {
componentProps: {
class: 'w-full',
},
formItemClass: 'col-span-2',
labelWidth: 80,
},
layout: 'horizontal', layout: 'horizontal',
showDefaultActions: false, showDefaultActions: false,
commonConfig: {
labelWidth: 120,
},
}); });
const [Modal, modalApi] = useVbenModal({ const [Modal, modalApi] = useVbenModal({

View File

@@ -36,7 +36,6 @@ export function useFormSchema(): VbenFormSchema[] {
component: 'Select', component: 'Select',
componentProps: { componentProps: {
options: getDictOptions(DICT_TYPE.SYSTEM_SOCIAL_TYPE, 'number'), options: getDictOptions(DICT_TYPE.SYSTEM_SOCIAL_TYPE, 'number'),
class: 'w-full',
}, },
rules: 'required', rules: 'required',
}, },

View File

@@ -26,6 +26,13 @@ const getTitle = computed(() => {
}); });
const [Form, formApi] = useVbenForm({ const [Form, formApi] = useVbenForm({
commonConfig: {
componentProps: {
class: 'w-full',
},
formItemClass: 'col-span-2',
labelWidth: 80,
},
layout: 'horizontal', layout: 'horizontal',
schema: useFormSchema(), schema: useFormSchema(),
showDefaultActions: false, showDefaultActions: false,

View File

@@ -27,9 +27,6 @@ export function useFormSchema(): VbenFormSchema[] {
fieldName: 'name', fieldName: 'name',
label: '租户名称', label: '租户名称',
component: 'Input', component: 'Input',
componentProps: {
placeholder: '请输入租户名称',
},
rules: 'required', rules: 'required',
}, },
{ {
@@ -38,7 +35,6 @@ export function useFormSchema(): VbenFormSchema[] {
component: 'ApiSelect', component: 'ApiSelect',
componentProps: { componentProps: {
api: () => getTenantPackageList(), api: () => getTenantPackageList(),
class: 'w-full',
labelField: 'name', labelField: 'name',
valueField: 'id', valueField: 'id',
placeholder: '请选择租户套餐', placeholder: '请选择租户套餐',
@@ -49,26 +45,18 @@ export function useFormSchema(): VbenFormSchema[] {
fieldName: 'contactName', fieldName: 'contactName',
label: '联系人', label: '联系人',
component: 'Input', component: 'Input',
componentProps: {
placeholder: '请输入联系人',
},
rules: 'required', rules: 'required',
}, },
{ {
fieldName: 'contactMobile', fieldName: 'contactMobile',
label: '联系手机', label: '联系手机',
component: 'Input', component: 'Input',
componentProps: { rules: 'mobile',
placeholder: '请输入联系手机',
},
}, },
{ {
label: '用户名称', label: '用户名称',
fieldName: 'username', fieldName: 'username',
component: 'Input', component: 'Input',
componentProps: {
placeholder: '请输入用户名称',
},
rules: 'required', rules: 'required',
dependencies: { dependencies: {
triggerFields: ['id'], triggerFields: ['id'],
@@ -79,9 +67,6 @@ export function useFormSchema(): VbenFormSchema[] {
label: '用户密码', label: '用户密码',
fieldName: 'password', fieldName: 'password',
component: 'InputPassword', component: 'InputPassword',
componentProps: {
placeholder: '请输入用户密码',
},
rules: 'required', rules: 'required',
dependencies: { dependencies: {
triggerFields: ['id'], triggerFields: ['id'],
@@ -92,10 +77,6 @@ export function useFormSchema(): VbenFormSchema[] {
label: '账号额度', label: '账号额度',
fieldName: 'accountCount', fieldName: 'accountCount',
component: 'InputNumber', component: 'InputNumber',
componentProps: {
class: 'w-full',
placeholder: '请输入账号额度',
},
rules: 'required', rules: 'required',
}, },
{ {
@@ -105,7 +86,6 @@ export function useFormSchema(): VbenFormSchema[] {
componentProps: { componentProps: {
format: 'YYYY-MM-DD', format: 'YYYY-MM-DD',
valueFormat: 'x', valueFormat: 'x',
class: 'w-full',
placeholder: '请选择过期时间', placeholder: '请选择过期时间',
}, },
rules: 'required', rules: 'required',
@@ -114,9 +94,6 @@ export function useFormSchema(): VbenFormSchema[] {
label: '绑定域名', label: '绑定域名',
fieldName: 'website', fieldName: 'website',
component: 'Input', component: 'Input',
componentProps: {
placeholder: '请输入绑定域名',
},
rules: 'required', rules: 'required',
}, },
{ {

View File

@@ -22,6 +22,13 @@ const getTitle = computed(() => {
}); });
const [Form, formApi] = useVbenForm({ const [Form, formApi] = useVbenForm({
commonConfig: {
componentProps: {
class: 'w-full',
},
formItemClass: 'col-span-2',
labelWidth: 80,
},
layout: 'horizontal', layout: 'horizontal',
schema: useFormSchema(), schema: useFormSchema(),
showDefaultActions: false, showDefaultActions: false,

View File

@@ -26,9 +26,6 @@ export function useFormSchema(): VbenFormSchema[] {
fieldName: 'name', fieldName: 'name',
label: '套餐名称', label: '套餐名称',
component: 'Input', component: 'Input',
componentProps: {
placeholder: '请输入套餐名称',
},
rules: 'required', rules: 'required',
}, },
{ {
@@ -52,9 +49,6 @@ export function useFormSchema(): VbenFormSchema[] {
fieldName: 'remark', fieldName: 'remark',
label: '备注', label: '备注',
component: 'Textarea', component: 'Textarea',
componentProps: {
placeholder: '请输入备注',
},
}, },
]; ];
} }

View File

@@ -6,6 +6,7 @@ import type {
import type { SystemTenantPackageApi } from '#/api/system/tenant-package'; import type { SystemTenantPackageApi } from '#/api/system/tenant-package';
import { Page, useVbenModal } from '@vben/common-ui'; import { Page, useVbenModal } from '@vben/common-ui';
import { Plus } from '@vben/icons';
import { Button, message } from 'ant-design-vue'; import { Button, message } from 'ant-design-vue';

View File

@@ -34,6 +34,13 @@ const isExpanded = ref(false); // 展开状态
const expandedKeys = ref<number[]>([]); // 展开的节点 const expandedKeys = ref<number[]>([]); // 展开的节点
const [Form, formApi] = useVbenForm({ const [Form, formApi] = useVbenForm({
commonConfig: {
componentProps: {
class: 'w-full',
},
formItemClass: 'col-span-2',
labelWidth: 80,
},
layout: 'horizontal', layout: 'horizontal',
schema: useFormSchema(), schema: useFormSchema(),
showDefaultActions: false, showDefaultActions: false,
@@ -127,21 +134,21 @@ function getAllNodeIds(nodes: any[], ids: number[] = []): number[] {
</script> </script>
<template> <template>
<Modal :title="getTitle"> <Modal :title="getTitle" class="w-[40%]">
<Form class="mx-6"> <Form class="mx-6">
<template #menuIds="slotProps"> <template #menuIds="slotProps">
<Spin :spinning="menuLoading" class="w-full"> <!-- TODO @芋艿可优化使用 antd tree原因是更原生 -->
<!-- TODO @芋艿可优化使用 antd tree原因是更原生 --> <VbenTree
<VbenTree class="max-h-[400px] overflow-y-auto"
:tree-data="menuTree" :loading="menuLoading"
multiple :tree-data="menuTree"
bordered multiple
:expanded="expandedKeys" bordered
v-bind="slotProps" :expanded="expandedKeys"
value-field="id" v-bind="slotProps"
label-field="name" value-field="id"
/> label-field="name"
</Spin> />
</template> </template>
</Form> </Form>
<template #prepend-footer> <template #prepend-footer>

View File

@@ -29,18 +29,12 @@ export function useFormSchema(): VbenFormSchema[] {
fieldName: 'username', fieldName: 'username',
label: '用户名称', label: '用户名称',
component: 'Input', component: 'Input',
componentProps: {
placeholder: '请输入用户名称',
},
rules: 'required', rules: 'required',
}, },
{ {
label: '用户密码', label: '用户密码',
fieldName: 'password', fieldName: 'password',
component: 'InputPassword', component: 'InputPassword',
componentProps: {
placeholder: '请输入用户密码',
},
rules: 'required', rules: 'required',
dependencies: { dependencies: {
triggerFields: ['id'], triggerFields: ['id'],
@@ -51,9 +45,6 @@ export function useFormSchema(): VbenFormSchema[] {
fieldName: 'nickname', fieldName: 'nickname',
label: '用户昵称', label: '用户昵称',
component: 'Input', component: 'Input',
componentProps: {
placeholder: '请输入用户昵称',
},
rules: 'required', rules: 'required',
}, },
{ {
@@ -65,7 +56,6 @@ export function useFormSchema(): VbenFormSchema[] {
const data = await getDeptList(); const data = await getDeptList();
return handleTree(data); return handleTree(data);
}, },
class: 'w-full',
labelField: 'name', labelField: 'name',
valueField: 'id', valueField: 'id',
childrenField: 'children', childrenField: 'children',
@@ -79,7 +69,6 @@ export function useFormSchema(): VbenFormSchema[] {
component: 'ApiSelect', component: 'ApiSelect',
componentProps: { componentProps: {
api: getSimplePostList, api: getSimplePostList,
class: 'w-full',
labelField: 'name', labelField: 'name',
valueField: 'id', valueField: 'id',
mode: 'multiple', mode: 'multiple',
@@ -90,18 +79,12 @@ export function useFormSchema(): VbenFormSchema[] {
fieldName: 'email', fieldName: 'email',
label: '邮箱', label: '邮箱',
component: 'Input', component: 'Input',
componentProps: {
placeholder: '请输入邮箱',
},
rules: z.string().email('邮箱格式不正确').optional(), rules: z.string().email('邮箱格式不正确').optional(),
}, },
{ {
fieldName: 'mobile', fieldName: 'mobile',
label: '手机号码', label: '手机号码',
component: 'Input', component: 'Input',
componentProps: {
placeholder: '请输入手机号码',
},
}, },
{ {
fieldName: 'sex', fieldName: 'sex',
@@ -129,9 +112,6 @@ export function useFormSchema(): VbenFormSchema[] {
fieldName: 'remark', fieldName: 'remark',
label: '备注', label: '备注',
component: 'Textarea', component: 'Textarea',
componentProps: {
placeholder: '请输入备注',
},
}, },
]; ];
} }
@@ -210,7 +190,6 @@ export function useAssignRoleFormSchema(): VbenFormSchema[] {
component: 'ApiSelect', component: 'ApiSelect',
componentProps: { componentProps: {
api: getSimpleRoleList, api: getSimpleRoleList,
class: 'w-full',
labelField: 'name', labelField: 'name',
valueField: 'id', valueField: 'id',
mode: 'multiple', mode: 'multiple',

View File

@@ -215,13 +215,13 @@ const [Grid, gridApi] = useVbenVxeGrid({
<AssignRoleModal @success="onRefresh" /> <AssignRoleModal @success="onRefresh" />
<ImportModal @success="onRefresh" /> <ImportModal @success="onRefresh" />
<div class="flex h-full"> <div class="flex h-full w-full">
<!-- 左侧部门树 --> <!-- 左侧部门树 -->
<div class="w-4/24 pr-3"> <div class="h-full w-1/6 pr-4">
<DeptTree @select="onDeptSelect" /> <DeptTree @select="onDeptSelect" />
</div> </div>
<!-- 右侧用户列表 --> <!-- 右侧用户列表 -->
<div class="w-18/24"> <div class="w-5/6">
<Grid table-title="用户列表"> <Grid table-title="用户列表">
<template #toolbar-tools> <template #toolbar-tools>
<Button <Button

View File

@@ -13,6 +13,13 @@ import { useAssignRoleFormSchema } from '../data';
const emit = defineEmits(['success']); const emit = defineEmits(['success']);
const [Form, formApi] = useVbenForm({ const [Form, formApi] = useVbenForm({
commonConfig: {
componentProps: {
class: 'w-full',
},
formItemClass: 'col-span-2',
labelWidth: 80,
},
layout: 'horizontal', layout: 'horizontal',
schema: useAssignRoleFormSchema(), schema: useAssignRoleFormSchema(),
showDefaultActions: false, showDefaultActions: false,

View File

@@ -22,6 +22,13 @@ const getTitle = computed(() => {
}); });
const [Form, formApi] = useVbenForm({ const [Form, formApi] = useVbenForm({
commonConfig: {
componentProps: {
class: 'w-full',
},
formItemClass: 'col-span-2',
labelWidth: 80,
},
layout: 'horizontal', layout: 'horizontal',
schema: useFormSchema(), schema: useFormSchema(),
showDefaultActions: false, showDefaultActions: false,

View File

@@ -15,6 +15,13 @@ import { useImportFormSchema } from '../data';
const emit = defineEmits(['success']); const emit = defineEmits(['success']);
const [Form, formApi] = useVbenForm({ const [Form, formApi] = useVbenForm({
commonConfig: {
componentProps: {
class: 'w-full',
},
formItemClass: 'col-span-2',
labelWidth: 80,
},
layout: 'horizontal', layout: 'horizontal',
schema: useImportFormSchema(), schema: useImportFormSchema(),
showDefaultActions: false, showDefaultActions: false,

View File

@@ -13,6 +13,13 @@ import { useResetPasswordFormSchema } from '../data';
const emit = defineEmits(['success']); const emit = defineEmits(['success']);
const [Form, formApi] = useVbenForm({ const [Form, formApi] = useVbenForm({
commonConfig: {
componentProps: {
class: 'w-full',
},
formItemClass: 'col-span-2',
labelWidth: 80,
},
layout: 'horizontal', layout: 'horizontal',
schema: useResetPasswordFormSchema(), schema: useResetPasswordFormSchema(),
showDefaultActions: false, showDefaultActions: false,

View File

@@ -3,3 +3,6 @@ VITE_APP_TITLE=Vben Admin Ele
# 应用命名空间用于缓存、store等功能的前缀确保隔离 # 应用命名空间用于缓存、store等功能的前缀确保隔离
VITE_APP_NAMESPACE=vben-web-ele VITE_APP_NAMESPACE=vben-web-ele
# 对store进行加密的密钥在将store持久化到localStorage时会使用该密钥进行加密
VITE_APP_STORE_SECURE_KEY=please-replace-me-with-your-own-key

View File

@@ -1,6 +1,6 @@
{ {
"name": "@vben/web-ele", "name": "@vben/web-ele",
"version": "5.5.4", "version": "5.5.5",
"homepage": "https://vben.pro", "homepage": "https://vben.pro",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": { "repository": {

View File

@@ -130,8 +130,8 @@ const withDefaultPlaceholder = <T extends Component>(
componentProps: Recordable<any> = {}, componentProps: Recordable<any> = {},
) => { ) => {
return defineComponent({ return defineComponent({
inheritAttrs: false,
name: component.name, name: component.name,
inheritAttrs: false,
setup: (props: any, { attrs, expose, slots }) => { setup: (props: any, { attrs, expose, slots }) => {
const placeholder = const placeholder =
props?.placeholder || props?.placeholder ||
@@ -184,19 +184,33 @@ async function initComponentAdapter() {
// 如果你的组件体积比较大,可以使用异步加载 // 如果你的组件体积比较大,可以使用异步加载
// Button: () => // Button: () =>
// import('xxx').then((res) => res.Button), // import('xxx').then((res) => res.Button),
ApiSelect: withDefaultPlaceholder(ApiComponent, 'select', { ApiSelect: withDefaultPlaceholder(
component: ElSelectV2, {
loadingSlot: 'loading', ...ApiComponent,
visibleEvent: 'onVisibleChange', name: 'ApiSelect',
}), },
ApiTreeSelect: withDefaultPlaceholder(ApiComponent, 'select', { 'select',
component: ElTreeSelect, {
props: { label: 'label', children: 'children' }, component: ElSelectV2,
nodeKey: 'value', loadingSlot: 'loading',
loadingSlot: 'loading', visibleEvent: 'onVisibleChange',
optionsPropName: 'data', },
visibleEvent: 'onVisibleChange', ),
}), ApiTreeSelect: withDefaultPlaceholder(
{
...ApiComponent,
name: 'ApiTreeSelect',
},
'select',
{
component: ElTreeSelect,
props: { label: 'label', children: 'children' },
nodeKey: 'value',
loadingSlot: 'loading',
optionsPropName: 'data',
visibleEvent: 'onVisibleChange',
},
),
Checkbox: ElCheckbox, Checkbox: ElCheckbox,
CheckboxGroup: (props, { attrs, slots }) => { CheckboxGroup: (props, { attrs, slots }) => {
let defaultSlot; let defaultSlot;

View File

@@ -3,3 +3,6 @@ VITE_APP_TITLE=Vben Admin Naive
# 应用命名空间用于缓存、store等功能的前缀确保隔离 # 应用命名空间用于缓存、store等功能的前缀确保隔离
VITE_APP_NAMESPACE=vben-web-naive VITE_APP_NAMESPACE=vben-web-naive
# 对store进行加密的密钥在将store持久化到localStorage时会使用该密钥进行加密
VITE_APP_STORE_SECURE_KEY=please-replace-me-with-your-own-key

View File

@@ -1,6 +1,6 @@
{ {
"name": "@vben/web-naive", "name": "@vben/web-naive",
"version": "5.5.4", "version": "5.5.5",
"homepage": "https://vben.pro", "homepage": "https://vben.pro",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": { "repository": {

View File

@@ -76,8 +76,8 @@ const withDefaultPlaceholder = <T extends Component>(
componentProps: Recordable<any> = {}, componentProps: Recordable<any> = {},
) => { ) => {
return defineComponent({ return defineComponent({
inheritAttrs: false,
name: component.name, name: component.name,
inheritAttrs: false,
setup: (props: any, { attrs, expose, slots }) => { setup: (props: any, { attrs, expose, slots }) => {
const placeholder = const placeholder =
props?.placeholder || props?.placeholder ||
@@ -131,19 +131,33 @@ async function initComponentAdapter() {
// Button: () => // Button: () =>
// import('xxx').then((res) => res.Button), // import('xxx').then((res) => res.Button),
ApiSelect: withDefaultPlaceholder(ApiComponent, 'select', { ApiSelect: withDefaultPlaceholder(
component: NSelect, {
modelPropName: 'value', ...ApiComponent,
}), name: 'ApiSelect',
ApiTreeSelect: withDefaultPlaceholder(ApiComponent, 'select', { },
component: NTreeSelect, 'select',
nodeKey: 'value', {
loadingSlot: 'arrow', component: NSelect,
keyField: 'value', modelPropName: 'value',
modelPropName: 'value', },
optionsPropName: 'options', ),
visibleEvent: 'onVisibleChange', ApiTreeSelect: withDefaultPlaceholder(
}), {
...ApiComponent,
name: 'ApiTreeSelect',
},
'select',
{
component: NTreeSelect,
nodeKey: 'value',
loadingSlot: 'arrow',
keyField: 'value',
modelPropName: 'value',
optionsPropName: 'options',
visibleEvent: 'onVisibleChange',
},
),
Checkbox: NCheckbox, Checkbox: NCheckbox,
CheckboxGroup: (props, { attrs, slots }) => { CheckboxGroup: (props, { attrs, slots }) => {
let defaultSlot; let defaultSlot;

View File

@@ -52,7 +52,21 @@
"vitepress", "vitepress",
"vnode", "vnode",
"vueuse", "vueuse",
"yxxx" "yxxx",
"archiver",
"axios",
"cropperjs",
"dotenv",
"gitee",
"isequal",
"jspm",
"napi",
"nolebase",
"rollup",
"Tinymce",
"vitest",
"xingyu",
"yudao"
], ],
"ignorePaths": [ "ignorePaths": [
"**/node_modules/**", "**/node_modules/**",

View File

@@ -1,6 +1,6 @@
{ {
"name": "@vben/docs", "name": "@vben/docs",
"version": "5.5.4", "version": "5.5.5",
"private": true, "private": true,
"scripts": { "scripts": {
"build": "vitepress build", "build": "vitepress build",

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