feat: 布局调整&卡片组件调整
This commit is contained in:
parent
8be2a18195
commit
5bd61bf764
|
@ -1,18 +1,26 @@
|
||||||
<template>
|
<template>
|
||||||
<a-spin class="block h-full" :loading="props.loading" :size="28">
|
<a-spin class="block h-full" :loading="props.loading" :size="28">
|
||||||
<div class="ms-card relative h-full pr-[10px]">
|
<div
|
||||||
|
:class="[
|
||||||
|
'ms-card',
|
||||||
|
'relative',
|
||||||
|
'h-full',
|
||||||
|
props.autoHeight ? '' : 'min-h-[500px]',
|
||||||
|
props.noContentPadding ? 'ms-card--noContentPadding' : 'p-[24px]',
|
||||||
|
]"
|
||||||
|
>
|
||||||
<div v-if="!props.simple" class="card-header">
|
<div v-if="!props.simple" class="card-header">
|
||||||
<div v-if="!props.hideBack" class="back-btn" @click="back"><icon-arrow-left /></div>
|
<div v-if="!props.hideBack" class="back-btn" @click="back"><icon-arrow-left /></div>
|
||||||
<div class="text-[var(--color-text-000)]">{{ props.title }}</div>
|
<div class="text-[var(--color-text-000)]">{{ props.title }}</div>
|
||||||
</div>
|
</div>
|
||||||
<a-divider v-if="!props.simple" class="mb-[16px]" />
|
<a-divider v-if="!props.simple" class="mb-[16px]" />
|
||||||
<div class="mr-[-10px]">
|
<div class="ms-card-container">
|
||||||
<a-scrollbar
|
<a-scrollbar
|
||||||
class="pr-[10px]"
|
class="pr-[5px]"
|
||||||
:style="{
|
:style="{
|
||||||
overflowY: 'auto',
|
overflowY: 'auto',
|
||||||
minWidth: 1000,
|
minWidth: 1000,
|
||||||
height: `calc(100vh - ${cardOverHeight}px)`,
|
height: props.autoHeight ? 'auto' : `calc(100vh - ${cardOverHeight}px)`,
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
|
@ -49,15 +57,18 @@
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<
|
defineProps<
|
||||||
Partial<{
|
Partial<{
|
||||||
simple: boolean;
|
simple: boolean; // 简单模式,没有标题和底部栏
|
||||||
title: string;
|
title: string; // 卡片标题
|
||||||
hideContinue: boolean;
|
hideContinue: boolean; // 隐藏保存并继续创建按钮
|
||||||
hideFooter: boolean;
|
hideFooter: boolean; // 隐藏底部栏
|
||||||
loading: boolean;
|
loading: boolean; // 卡片 loading 状态
|
||||||
isEdit: boolean;
|
isEdit: boolean; // 是否编辑状态
|
||||||
specialHeight: number; // 特殊高度,例如某些页面有面包屑
|
specialHeight: number; // 特殊高度,例如某些页面有面包屑
|
||||||
hideBack: boolean;
|
hideBack: boolean; // 隐藏返回按钮
|
||||||
handleBack: () => void;
|
autoHeight: boolean; // 内容区域高度是否自适应
|
||||||
|
hasBreadcrumb: boolean; // 是否有面包屑,如果有面包屑,高度需要减去面包屑的高度
|
||||||
|
noContentPadding: boolean; // 内容区域是否有padding
|
||||||
|
handleBack: () => void; // 自定义返回按钮触发事件
|
||||||
}>
|
}>
|
||||||
>(),
|
>(),
|
||||||
{
|
{
|
||||||
|
@ -67,6 +78,9 @@
|
||||||
isEdit: false,
|
isEdit: false,
|
||||||
specialHeight: 0,
|
specialHeight: 0,
|
||||||
hideBack: false,
|
hideBack: false,
|
||||||
|
autoHeight: false,
|
||||||
|
hasBreadcrumb: false,
|
||||||
|
noContentPadding: false,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -75,16 +89,18 @@
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
const _spcialHeight = props.hasBreadcrumb ? 31 + props.specialHeight : props.specialHeight; // 有面包屑的话,默认面包屑高度31
|
||||||
|
|
||||||
const cardOverHeight = computed(() => {
|
const cardOverHeight = computed(() => {
|
||||||
if (props.simple) {
|
if (props.simple) {
|
||||||
// 简单模式没有标题、没有底部
|
// 简单模式没有标题、没有底部
|
||||||
return 163;
|
return 136 + _spcialHeight;
|
||||||
}
|
}
|
||||||
if (props.hideFooter) {
|
if (props.hideFooter) {
|
||||||
// 隐藏底部
|
// 隐藏底部
|
||||||
return 192;
|
return 192;
|
||||||
}
|
}
|
||||||
return 256 + props.specialHeight;
|
return 246 + _spcialHeight;
|
||||||
});
|
});
|
||||||
|
|
||||||
function back() {
|
function back() {
|
||||||
|
@ -98,6 +114,22 @@
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.ms-card {
|
.ms-card {
|
||||||
|
@apply overflow-hidden bg-white;
|
||||||
|
|
||||||
|
border-radius: var(--border-radius-large);
|
||||||
|
box-shadow: 0 0 10px rgb(120 56 135 / 5%);
|
||||||
|
&--noContentPadding {
|
||||||
|
border-radius: var(--border-radius-large) var(--border-radius-large) 0 0;
|
||||||
|
.card-header {
|
||||||
|
padding: 24px 24px 0;
|
||||||
|
}
|
||||||
|
.arco-divider {
|
||||||
|
@apply mb-0;
|
||||||
|
}
|
||||||
|
.ms-card-container {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
.card-header {
|
.card-header {
|
||||||
@apply flex items-center;
|
@apply flex items-center;
|
||||||
.back-btn {
|
.back-btn {
|
||||||
|
|
|
@ -14,12 +14,4 @@
|
||||||
|
|
||||||
<script lang="ts" setup></script>
|
<script lang="ts" setup></script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped></style>
|
||||||
.page-content {
|
|
||||||
@apply overflow-hidden bg-white;
|
|
||||||
|
|
||||||
padding: 24px 14px 24px 24px;
|
|
||||||
border-radius: var(--border-radius-large);
|
|
||||||
box-shadow: 0 0 10px rgb(120 56 135 / 5%);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
:title="title"
|
:title="title"
|
||||||
:is-edit="isEdit"
|
:is-edit="isEdit"
|
||||||
:special-height="34"
|
has-breadcrumb
|
||||||
@save="beforeSave"
|
@save="beforeSave"
|
||||||
@save-and-continue="beforeSave(true)"
|
@save-and-continue="beforeSave(true)"
|
||||||
>
|
>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<MsCard :loading="loading" simple>
|
<MsCard :loading="loading" has-breadcrumb simple>
|
||||||
<div class="mb-4 flex items-center justify-between">
|
<div class="mb-4 flex items-center justify-between">
|
||||||
<a-button type="primary" @click="addPool">
|
<a-button type="primary" @click="addPool">
|
||||||
{{ t('system.resourcePool.createPool') }}
|
{{ t('system.resourcePool.createPool') }}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<MsCard simple>
|
||||||
<div class="mb-4 flex items-center justify-between">
|
<div class="mb-4 flex items-center justify-between">
|
||||||
<div>
|
<div>
|
||||||
<a-button class="mr-3" type="primary" @click="showUserModal('create')">
|
<a-button class="mr-3" type="primary" @click="showUserModal('create')">
|
||||||
|
@ -84,136 +84,134 @@
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</ms-base-table>
|
</ms-base-table>
|
||||||
<a-modal
|
</MsCard>
|
||||||
v-model:visible="visible"
|
<a-modal
|
||||||
:title="userFormMode === 'create' ? t('system.user.createUserModalTitle') : t('system.user.editUserModalTitle')"
|
v-model:visible="visible"
|
||||||
title-align="start"
|
:title="userFormMode === 'create' ? t('system.user.createUserModalTitle') : t('system.user.editUserModalTitle')"
|
||||||
class="ms-modal-form ms-modal-medium"
|
title-align="start"
|
||||||
:mask-closable="false"
|
class="ms-modal-form ms-modal-medium"
|
||||||
@close="handleUserModalClose"
|
:mask-closable="false"
|
||||||
>
|
@close="handleUserModalClose"
|
||||||
<a-form ref="userFormRef" class="rounded-[4px]" :model="userForm" layout="vertical">
|
>
|
||||||
<MsBatchForm
|
<a-form ref="userFormRef" class="rounded-[4px]" :model="userForm" layout="vertical">
|
||||||
ref="batchFormRef"
|
<MsBatchForm
|
||||||
:models="batchFormModels"
|
ref="batchFormRef"
|
||||||
:form-mode="userFormMode"
|
:models="batchFormModels"
|
||||||
add-text="system.user.addUser"
|
:form-mode="userFormMode"
|
||||||
:default-vals="userForm.list"
|
add-text="system.user.addUser"
|
||||||
max-height="250px"
|
:default-vals="userForm.list"
|
||||||
></MsBatchForm>
|
max-height="250px"
|
||||||
<a-form-item class="mb-0" field="userGroup" :label="t('system.user.createUserUserGroup')">
|
></MsBatchForm>
|
||||||
<a-select
|
<a-form-item class="mb-0" field="userGroup" :label="t('system.user.createUserUserGroup')">
|
||||||
v-model="userForm.userGroup"
|
<a-select
|
||||||
multiple
|
v-model="userForm.userGroup"
|
||||||
:placeholder="t('system.user.createUserUserGroupPlaceholder')"
|
multiple
|
||||||
allow-clear
|
:placeholder="t('system.user.createUserUserGroupPlaceholder')"
|
||||||
>
|
allow-clear
|
||||||
<a-option
|
|
||||||
v-for="item of userGroupOptions"
|
|
||||||
:key="item.id"
|
|
||||||
:tag-props="{ closable: item.closeable }"
|
|
||||||
:value="item.id"
|
|
||||||
:disabled="item.selected"
|
|
||||||
>
|
|
||||||
{{ item.name }}
|
|
||||||
</a-option>
|
|
||||||
</a-select>
|
|
||||||
</a-form-item>
|
|
||||||
</a-form>
|
|
||||||
<template #footer>
|
|
||||||
<a-button type="secondary" :disabled="loading" @click="cancelCreate">
|
|
||||||
{{ t('system.user.editUserModalCancelCreate') }}
|
|
||||||
</a-button>
|
|
||||||
<a-button v-if="userFormMode === 'create'" type="secondary" :loading="loading" @click="saveAndContinue">
|
|
||||||
{{ t('system.user.editUserModalSaveAndContinue') }}
|
|
||||||
</a-button>
|
|
||||||
<a-button type="primary" :loading="loading" @click="beforeCreateUser">
|
|
||||||
{{
|
|
||||||
t(userFormMode === 'create' ? 'system.user.editUserModalCreateUser' : 'system.user.editUserModalEditUser')
|
|
||||||
}}
|
|
||||||
</a-button>
|
|
||||||
</template>
|
|
||||||
</a-modal>
|
|
||||||
<a-modal
|
|
||||||
v-model:visible="importVisible"
|
|
||||||
:title="t('system.user.importModalTitle')"
|
|
||||||
title-align="start"
|
|
||||||
class="ms-modal-upload"
|
|
||||||
>
|
|
||||||
<a-alert class="mb-[16px]" closable>
|
|
||||||
{{ t('system.user.importModalTip') }}
|
|
||||||
<a-button type="text" size="small" @click="downLoadUserTemplate">
|
|
||||||
{{ t('system.user.importDownload') }}
|
|
||||||
</a-button>
|
|
||||||
</a-alert>
|
|
||||||
<MsUpload
|
|
||||||
v-model:file-list="userImportFile"
|
|
||||||
accept="excel"
|
|
||||||
:show-file-list="false"
|
|
||||||
:auto-upload="false"
|
|
||||||
:disabled="importLoading"
|
|
||||||
></MsUpload>
|
|
||||||
<template #footer>
|
|
||||||
<a-button type="secondary" :disabled="importLoading" @click="cancelImport">
|
|
||||||
{{ t('system.user.importModalCancel') }}
|
|
||||||
</a-button>
|
|
||||||
<a-button type="primary" :loading="importLoading" :disabled="userImportFile.length === 0" @click="importUser">
|
|
||||||
{{ t('system.user.importModalConfirm') }}
|
|
||||||
</a-button>
|
|
||||||
</template>
|
|
||||||
</a-modal>
|
|
||||||
<a-modal v-model:visible="importResultVisible" title-align="start" class="ms-modal-upload">
|
|
||||||
<template #title>
|
|
||||||
<icon-exclamation-circle-fill
|
|
||||||
v-if="importResult === 'fail'"
|
|
||||||
class="mr-[8px] text-[20px] text-[rgb(var(--warning-6))]"
|
|
||||||
/>
|
|
||||||
<icon-close-circle-fill
|
|
||||||
v-if="importResult === 'allFail'"
|
|
||||||
class="mr-[8px] text-[20px] text-[rgb(var(--danger-6))]"
|
|
||||||
/>
|
|
||||||
{{ importResultTitle }}
|
|
||||||
</template>
|
|
||||||
<div v-if="importResult === 'success'" class="flex flex-col items-center justify-center">
|
|
||||||
<icon-check-circle-fill class="text-[32px] text-[rgb(var(--success-6))]" />
|
|
||||||
<div class="mb-[8px] mt-[16px] text-[16px] font-medium text-[var(--color-text-000)]">
|
|
||||||
{{ t('system.user.importSuccess') }}
|
|
||||||
</div>
|
|
||||||
<div class="sub-text">
|
|
||||||
{{ t('system.user.importResultSuccessContent', { successNum: importSuccessCount }) }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<template v-else>
|
|
||||||
<div>
|
|
||||||
{{ t('system.user.importResultContent', { successNum: importSuccessCount, failNum: importFailCount }) }}
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
{{ t('system.user.importResultContentSubStart') }}
|
|
||||||
<a-link
|
|
||||||
class="text-[rgb(var(--primary-5))]"
|
|
||||||
:href="importErrorFileUrl"
|
|
||||||
:download="`${t('system.user.importErrorFile')}.pdf`"
|
|
||||||
>{{ t('system.user.importResultContentDownload') }}</a-link
|
|
||||||
>{{ t('system.user.importResultContentSubEnd') }}</div
|
|
||||||
>
|
>
|
||||||
</template>
|
<a-option
|
||||||
<template #footer>
|
v-for="item of userGroupOptions"
|
||||||
<a-button type="text" class="!text-[var(--color-text-1)]" @click="cancelImport">
|
:key="item.id"
|
||||||
{{ t('system.user.importResultReturn') }}
|
:tag-props="{ closable: item.closeable }"
|
||||||
</a-button>
|
:value="item.id"
|
||||||
<a-button type="text" @click="continueImport">
|
:disabled="item.selected"
|
||||||
{{ t('system.user.importResultContinue') }}
|
>
|
||||||
</a-button>
|
{{ item.name }}
|
||||||
</template>
|
</a-option>
|
||||||
</a-modal>
|
</a-select>
|
||||||
<inviteModal v-model:visible="inviteVisible"></inviteModal>
|
</a-form-item>
|
||||||
<batchModal
|
</a-form>
|
||||||
v-model:visible="showBatchModal"
|
<template #footer>
|
||||||
:table-selected="tableSelected"
|
<a-button type="secondary" :disabled="loading" @click="cancelCreate">
|
||||||
:action="batchAction"
|
{{ t('system.user.editUserModalCancelCreate') }}
|
||||||
:tree-data="treeData"
|
</a-button>
|
||||||
></batchModal>
|
<a-button v-if="userFormMode === 'create'" type="secondary" :loading="loading" @click="saveAndContinue">
|
||||||
</div>
|
{{ t('system.user.editUserModalSaveAndContinue') }}
|
||||||
|
</a-button>
|
||||||
|
<a-button type="primary" :loading="loading" @click="beforeCreateUser">
|
||||||
|
{{ t(userFormMode === 'create' ? 'system.user.editUserModalCreateUser' : 'system.user.editUserModalEditUser') }}
|
||||||
|
</a-button>
|
||||||
|
</template>
|
||||||
|
</a-modal>
|
||||||
|
<a-modal
|
||||||
|
v-model:visible="importVisible"
|
||||||
|
:title="t('system.user.importModalTitle')"
|
||||||
|
title-align="start"
|
||||||
|
class="ms-modal-upload"
|
||||||
|
>
|
||||||
|
<a-alert class="mb-[16px]" closable>
|
||||||
|
{{ t('system.user.importModalTip') }}
|
||||||
|
<a-button type="text" size="small" @click="downLoadUserTemplate">
|
||||||
|
{{ t('system.user.importDownload') }}
|
||||||
|
</a-button>
|
||||||
|
</a-alert>
|
||||||
|
<MsUpload
|
||||||
|
v-model:file-list="userImportFile"
|
||||||
|
accept="excel"
|
||||||
|
:show-file-list="false"
|
||||||
|
:auto-upload="false"
|
||||||
|
:disabled="importLoading"
|
||||||
|
></MsUpload>
|
||||||
|
<template #footer>
|
||||||
|
<a-button type="secondary" :disabled="importLoading" @click="cancelImport">
|
||||||
|
{{ t('system.user.importModalCancel') }}
|
||||||
|
</a-button>
|
||||||
|
<a-button type="primary" :loading="importLoading" :disabled="userImportFile.length === 0" @click="importUser">
|
||||||
|
{{ t('system.user.importModalConfirm') }}
|
||||||
|
</a-button>
|
||||||
|
</template>
|
||||||
|
</a-modal>
|
||||||
|
<a-modal v-model:visible="importResultVisible" title-align="start" class="ms-modal-upload">
|
||||||
|
<template #title>
|
||||||
|
<icon-exclamation-circle-fill
|
||||||
|
v-if="importResult === 'fail'"
|
||||||
|
class="mr-[8px] text-[20px] text-[rgb(var(--warning-6))]"
|
||||||
|
/>
|
||||||
|
<icon-close-circle-fill
|
||||||
|
v-if="importResult === 'allFail'"
|
||||||
|
class="mr-[8px] text-[20px] text-[rgb(var(--danger-6))]"
|
||||||
|
/>
|
||||||
|
{{ importResultTitle }}
|
||||||
|
</template>
|
||||||
|
<div v-if="importResult === 'success'" class="flex flex-col items-center justify-center">
|
||||||
|
<icon-check-circle-fill class="text-[32px] text-[rgb(var(--success-6))]" />
|
||||||
|
<div class="mb-[8px] mt-[16px] text-[16px] font-medium text-[var(--color-text-000)]">
|
||||||
|
{{ t('system.user.importSuccess') }}
|
||||||
|
</div>
|
||||||
|
<div class="sub-text">
|
||||||
|
{{ t('system.user.importResultSuccessContent', { successNum: importSuccessCount }) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<template v-else>
|
||||||
|
<div>
|
||||||
|
{{ t('system.user.importResultContent', { successNum: importSuccessCount, failNum: importFailCount }) }}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{{ t('system.user.importResultContentSubStart') }}
|
||||||
|
<a-link
|
||||||
|
class="text-[rgb(var(--primary-5))]"
|
||||||
|
:href="importErrorFileUrl"
|
||||||
|
:download="`${t('system.user.importErrorFile')}.pdf`"
|
||||||
|
>{{ t('system.user.importResultContentDownload') }}</a-link
|
||||||
|
>{{ t('system.user.importResultContentSubEnd') }}</div
|
||||||
|
>
|
||||||
|
</template>
|
||||||
|
<template #footer>
|
||||||
|
<a-button type="text" class="!text-[var(--color-text-1)]" @click="cancelImport">
|
||||||
|
{{ t('system.user.importResultReturn') }}
|
||||||
|
</a-button>
|
||||||
|
<a-button type="text" @click="continueImport">
|
||||||
|
{{ t('system.user.importResultContinue') }}
|
||||||
|
</a-button>
|
||||||
|
</template>
|
||||||
|
</a-modal>
|
||||||
|
<inviteModal v-model:visible="inviteVisible"></inviteModal>
|
||||||
|
<batchModal
|
||||||
|
v-model:visible="showBatchModal"
|
||||||
|
:table-selected="tableSelected"
|
||||||
|
:action="batchAction"
|
||||||
|
:tree-data="treeData"
|
||||||
|
></batchModal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
@ -248,6 +246,7 @@
|
||||||
import type { ActionsItem } from '@/components/pure/ms-table-more-action/types';
|
import type { ActionsItem } from '@/components/pure/ms-table-more-action/types';
|
||||||
import type { SimpleUserInfo, SystemRole, UserListItem } from '@/models/setting/user';
|
import type { SimpleUserInfo, SystemRole, UserListItem } from '@/models/setting/user';
|
||||||
import type { FormItemModel, MsBatchFormInstance } from '@/components/bussiness/ms-batch-form/types';
|
import type { FormItemModel, MsBatchFormInstance } from '@/components/bussiness/ms-batch-form/types';
|
||||||
|
import MsCard from '@/components/pure/ms-card/index.vue';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue