feat: 适配naive

pull/98/head^2
xingyu4j 2025-05-09 18:16:04 +08:00
parent 04d2cc2952
commit d59c137036
5 changed files with 173 additions and 141 deletions

View File

@ -1,4 +1,6 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { UploadFileInfo } from 'naive-ui';
import type { CropendResult, CropperModalProps, CropperType } from './typing'; import type { CropendResult, CropperModalProps, CropperType } from './typing';
import { ref } from 'vue'; import { ref } from 'vue';
@ -49,13 +51,13 @@ function modalLoading(loading: boolean) {
} }
// Block upload // Block upload
function handleBeforeUpload(file: File) { function handleBeforeUpload(file: UploadFileInfo) {
if (props.size > 0 && file.size > 1024 * 1024 * props.size) { if (props.size > 0 && file.size > 1024 * 1024 * props.size) {
emit('uploadError', { msg: $t('ui.cropper.imageTooBig') }); emit('uploadError', { msg: $t('ui.cropper.imageTooBig') });
return false; return false;
} }
const reader = new FileReader(); const reader = new FileReader();
reader.readAsDataURL(file); reader.readAsDataURL(file.file);
src.value = ''; src.value = '';
previewSource.value = ''; previewSource.value = '';
reader.addEventListener('load', (e) => { reader.addEventListener('load', (e) => {
@ -111,7 +113,7 @@ async function handleOk() {
:confirm-text="$t('ui.cropper.okText')" :confirm-text="$t('ui.cropper.okText')"
:fullscreen-button="false" :fullscreen-button="false"
:title="$t('ui.cropper.modalTitle')" :title="$t('ui.cropper.modalTitle')"
class="w-[800px]" class="w-[50%]"
> >
<div :class="prefixCls"> <div :class="prefixCls">
<div :class="`${prefixCls}-left`" class="w-full"> <div :class="`${prefixCls}-left`" class="w-full">
@ -127,130 +129,148 @@ async function handleOk() {
</div> </div>
<div :class="`${prefixCls}-toolbar`"> <div :class="`${prefixCls}-toolbar`">
<NUpload
:before-upload="handleBeforeUpload"
:file-list="[]"
accept="image/*"
>
<NTooltip :title="$t('ui.cropper.selectImage')" placement="bottom">
<NButton size="small" type="primary">
<template #icon>
<div class="flex items-center justify-center">
<span class="icon-[ant-design--upload-outlined]"></span>
</div>
</template>
</NButton>
</NTooltip>
</NUpload>
<NSpace> <NSpace>
<NTooltip :title="$t('ui.cropper.btn_reset')" placement="bottom"> <NUpload
<NButton @before-upload="handleBeforeUpload"
:disabled="!src" :file-list="[]"
size="small" accept="image/*"
type="primary"
@click="handlerToolbar('reset')"
>
<template #icon>
<div class="flex items-center justify-center">
<span class="icon-[ant-design--reload-outlined]"></span>
</div>
</template>
</NButton>
</NTooltip>
<NTooltip
:title="$t('ui.cropper.btn_rotate_left')"
placement="bottom"
> >
<NButton <NTooltip placement="bottom">
:disabled="!src" <template #trigger>
size="small" <NButton size="small" type="primary">
type="primary" <template #icon>
@click="handlerToolbar('rotate', -45)" <div class="flex items-center justify-center">
> <span class="icon-[ant-design--upload-outlined]"></span>
<template #icon> </div>
<div class="flex items-center justify-center"> </template>
<span </NButton>
class="icon-[ant-design--rotate-left-outlined]"
></span>
</div>
</template> </template>
</NButton> {{ $t('ui.cropper.selectImage') }}
</NTooltip>
</NUpload>
<NTooltip placement="bottom">
<template #trigger>
<NButton
:disabled="!src"
size="small"
type="primary"
@click="handlerToolbar('reset')"
>
<template #icon>
<div class="flex items-center justify-center">
<span class="icon-[ant-design--reload-outlined]"></span>
</div>
</template>
</NButton>
</template>
{{ $t('ui.cropper.btn_reset') }}
</NTooltip> </NTooltip>
<NTooltip <NTooltip placement="bottom">
:title="$t('ui.cropper.btn_rotate_right')" <template #trigger>
placement="bottom" <NButton
> :disabled="!src"
<NButton size="small"
:disabled="!src" type="primary"
pre-icon="ant-design:rotate-right-outlined" @click="handlerToolbar('rotate', -45)"
size="small" >
type="primary" <template #icon>
@click="handlerToolbar('rotate', 45)" <div class="flex items-center justify-center">
> <span
<template #icon> class="icon-[ant-design--rotate-left-outlined]"
<div class="flex items-center justify-center"> ></span>
<span </div>
class="icon-[ant-design--rotate-right-outlined]" </template>
></span> </NButton>
</div> </template>
</template> {{ $t('ui.cropper.btn_rotate_left') }}
</NButton>
</NTooltip> </NTooltip>
<NTooltip :title="$t('ui.cropper.btn_scale_x')" placement="bottom"> <NTooltip placement="bottom">
<NButton <template #trigger>
:disabled="!src" <NButton
size="small" :disabled="!src"
type="primary" pre-icon="ant-design:rotate-right-outlined"
@click="handlerToolbar('scaleX')" size="small"
> type="primary"
<template #icon> @click="handlerToolbar('rotate', 45)"
<div class="flex items-center justify-center"> >
<span class="icon-[vaadin--arrows-long-h]"></span> <template #icon>
</div> <div class="flex items-center justify-center">
</template> <span
</NButton> class="icon-[ant-design--rotate-right-outlined]"
></span>
</div>
</template>
</NButton>
</template>
{{ $t('ui.cropper.btn_rotate_right') }}
</NTooltip> </NTooltip>
<NTooltip :title="$t('ui.cropper.btn_scale_y')" placement="bottom"> <NTooltip placement="bottom">
<NButton <template #trigger>
:disabled="!src" <NButton
size="small" :disabled="!src"
type="primary" size="small"
@click="handlerToolbar('scaleY')" type="primary"
> @click="handlerToolbar('scaleX')"
<template #icon> >
<div class="flex items-center justify-center"> <template #icon>
<span class="icon-[vaadin--arrows-long-v]"></span> <div class="flex items-center justify-center">
</div> <span class="icon-[vaadin--arrows-long-h]"></span>
</template> </div>
</NButton> </template>
</NButton>
</template>
{{ $t('ui.cropper.btn_scale_x') }}
</NTooltip> </NTooltip>
<NTooltip :title="$t('ui.cropper.btn_zoom_in')" placement="bottom"> <NTooltip placement="bottom">
<NButton <template #trigger>
:disabled="!src" <NButton
size="small" :disabled="!src"
type="primary" size="small"
@click="handlerToolbar('zoom', 0.1)" type="primary"
> @click="handlerToolbar('scaleY')"
<template #icon> >
<div class="flex items-center justify-center"> <template #icon>
<span class="icon-[ant-design--zoom-in-outlined]"></span> <div class="flex items-center justify-center">
</div> <span class="icon-[vaadin--arrows-long-v]"></span>
</template> </div>
</NButton> </template>
</NButton>
</template>
{{ $t('ui.cropper.btn_scale_y') }}
</NTooltip> </NTooltip>
<NTooltip :title="$t('ui.cropper.btn_zoom_out')" placement="bottom"> <NTooltip placement="bottom">
<NButton <template #trigger>
:disabled="!src" <NButton
size="small" :disabled="!src"
type="primary" size="small"
@click="handlerToolbar('zoom', -0.1)" type="primary"
> @click="handlerToolbar('zoom', 0.1)"
<template #icon> >
<div class="flex items-center justify-center"> <template #icon>
<span class="icon-[ant-design--zoom-out-outlined]"></span> <div class="flex items-center justify-center">
</div> <span class="icon-[ant-design--zoom-in-outlined]"></span>
</template> </div>
</NButton> </template>
</NButton>
</template>
{{ $t('ui.cropper.btn_zoom_in') }}
</NTooltip>
<NTooltip placement="bottom">
<template #trigger>
<NButton
:disabled="!src"
size="small"
type="primary"
@click="handlerToolbar('zoom', -0.1)"
>
<template #icon>
<div class="flex items-center justify-center">
<span class="icon-[ant-design--zoom-out-outlined]"></span>
</div>
</template>
</NButton>
</template>
{{ $t('ui.cropper.btn_zoom_out') }}
</NTooltip> </NTooltip>
</NSpace> </NSpace>
</div> </div>

View File

@ -5,7 +5,7 @@ import { onMounted, ref } from 'vue';
import { Page } from '@vben/common-ui'; import { Page } from '@vben/common-ui';
import { NCard, NTabs } from 'naive-ui'; import { NCard, NTabPane, NTabs } from 'naive-ui';
import { getUserProfile } from '#/api/system/user/profile'; import { getUserProfile } from '#/api/system/user/profile';
import { useAuthStore } from '#/store'; import { useAuthStore } from '#/store';
@ -47,16 +47,16 @@ onMounted(loadProfile);
<!-- 右侧 标签页 --> <!-- 右侧 标签页 -->
<NCard class="ml-3 w-3/5"> <NCard class="ml-3 w-3/5">
<NTabs v-model:active-key="activeName" class="-mt-4"> <NTabs v-model:value="activeName" class="-mt-4">
<NTabs.TabPane key="basicInfo" tab="基本设置"> <NTabPane name="basicInfo" tab="基本设置">
<BaseInfo :profile="profile" @success="refreshProfile" /> <BaseInfo :profile="profile" @success="refreshProfile" />
</NTabs.TabPane> </NTabPane>
<NTabs.TabPane key="resetPwd" tab="密码设置"> <NTabPane name="resetPwd" tab="密码设置">
<ResetPwd /> <ResetPwd />
</NTabs.TabPane> </NTabPane>
<NTabs.TabPane key="userSocial" tab="社交绑定" force-render> <NTabPane name="userSocial" tab="社交绑定" force-render>
<UserSocial @update:active-name="activeName = $event" /> <UserSocial @update:active-name="activeName = $event" />
</NTabs.TabPane> </NTabPane>
<!-- TODO @芋艿在线设备 --> <!-- TODO @芋艿在线设备 -->
</NTabs> </NTabs>
</NCard> </NCard>

View File

@ -45,14 +45,17 @@ async function handelUpload({
<template> <template>
<div v-if="profile"> <div v-if="profile">
<div class="flex flex-col items-center"> <div class="flex flex-col items-center">
<NTooltip title="点击上传头像"> <NTooltip>
<CropperAvatar <template #trigger>
:show-btn="false" <CropperAvatar
:upload-api="handelUpload" :show-btn="false"
:value="avatar" :upload-api="handelUpload"
:width="120" :value="avatar"
@change="emit('success')" :width="120"
/> @change="emit('success')"
/>
</template>
点击上传头像
</NTooltip> </NTooltip>
</div> </div>
<div class="mt-8"> <div class="mt-8">

View File

@ -13,7 +13,10 @@ const [Form, formApi] = useVbenForm({
}, },
schema: [ schema: [
{ {
component: 'InputPassword', component: 'Input',
componentProps: {
type: 'password',
},
fieldName: 'oldPassword', fieldName: 'oldPassword',
label: '旧密码', label: '旧密码',
rules: z rules: z
@ -22,7 +25,10 @@ const [Form, formApi] = useVbenForm({
.max(20, '密码长度不能超过 20 个字符'), .max(20, '密码长度不能超过 20 个字符'),
}, },
{ {
component: 'InputPassword', component: 'Input',
componentProps: {
type: 'password',
},
dependencies: { dependencies: {
rules(values) { rules(values) {
return z return z
@ -41,7 +47,10 @@ const [Form, formApi] = useVbenForm({
rules: 'required', rules: 'required',
}, },
{ {
component: 'InputPassword', component: 'Input',
componentProps: {
type: 'password',
},
dependencies: { dependencies: {
rules(values) { rules(values) {
return z return z

View File

@ -192,9 +192,9 @@ onMounted(() => {
{{ item.socialUser?.nickname || item.socialUser?.openid }} {{ item.socialUser?.nickname || item.socialUser?.openid }}
</template> </template>
<template v-else> <template v-else>
绑定{{ 绑定
getDictLabel(DICT_TYPE.SYSTEM_SOCIAL_TYPE, item.type) {{ getDictLabel(DICT_TYPE.SYSTEM_SOCIAL_TYPE, item.type) }}
}}账号 账号
</template> </template>
</span> </span>
</div> </div>