This commit is contained in:
AN
2025-07-08 22:18:32 +08:00
8 changed files with 73 additions and 34 deletions

View File

@ -20,44 +20,45 @@ const fileList = ref<UploadFileInfo[]>([]);
async function handleFetchOssList(ossIds: string[]) { async function handleFetchOssList(ossIds: string[]) {
startLoading(); startLoading();
const { error, data } = await fetchGetOssListByIds(ossIds); try {
if (error) return; const { error, data } = await fetchGetOssListByIds(ossIds);
fileList.value = data.map(item => ({ if (error) return;
id: String(item.ossId), fileList.value = data.map(item => ({
url: item.url, id: String(item.ossId),
name: item.originalName, url: item.url,
status: 'finished' name: item.originalName,
})); status: 'finished'
endLoading(); }));
} catch (error) {
window.$message?.error(`获取文件列表失败: ${error}`);
} finally {
endLoading();
}
} }
watch( watch(
value, value,
async val => { async val => {
const ossIds = val?.split(',')?.filter(item => isNotNull(item)) || []; const ossIds = val?.split(',')?.filter(item => isNotNull(item)) || [];
const fileIds = new Set(fileList.value.filter(item => item.status === 'finished').map(item => item.id));
if (ossIds.every(item => fileIds.has(item))) {
return;
}
if (ossIds.length === 0) { if (ossIds.length === 0) {
fileList.value = []; fileList.value = [];
return; return;
} }
const fileIds = new Set(fileList.value.filter(item => item.status === 'finished').map(item => item.id));
if (ossIds.every(item => fileIds.has(item))) {
return;
}
await handleFetchOssList(ossIds); await handleFetchOssList(ossIds);
}, },
{ immediate: true } { immediate: true }
); );
watch( watch(fileList, val => {
fileList, value.value = val
val => { .filter(item => item.status === 'finished')
value.value = val .map(item => item.id)
.filter(item => item.status === 'finished') .join(',');
.map(item => item.id) });
.join(',');
},
{ deep: true }
);
</script> </script>
<template> <template>

View File

@ -2,6 +2,7 @@ import { ref, toValue } from 'vue';
import type { ComputedRef, Ref } from 'vue'; import type { ComputedRef, Ref } from 'vue';
import type { FormInst } from 'naive-ui'; import type { FormInst } from 'naive-ui';
import { REG_CODE_SIX, REG_EMAIL, REG_PHONE, REG_PWD, REG_USER_NAME } from '@/constants/reg'; import { REG_CODE_SIX, REG_EMAIL, REG_PHONE, REG_PWD, REG_USER_NAME } from '@/constants/reg';
import { isNull } from '@/utils/common';
import { $t } from '@/locales'; import { $t } from '@/locales';
export function useFormRules() { export function useFormRules() {
@ -52,7 +53,7 @@ export function useFormRules() {
required: true, required: true,
trigger: ['input', 'blur'], trigger: ['input', 'blur'],
validator: (_rule: any, value: any) => { validator: (_rule: any, value: any) => {
if (value === null || value === undefined || value === '') { if (isNull(value) || (Array.isArray(value) && value.length === 0)) {
return new Error(message); return new Error(message);
} }
return true; return true;

View File

@ -107,12 +107,12 @@ export async function loadDynamicComponent<T extends object = any>(
/** 判断是否为空 */ /** 判断是否为空 */
export function isNotNull(value: any) { export function isNotNull(value: any) {
return value !== undefined && value !== null && value !== '' && value !== 'undefined' && value !== 'null'; return value !== undefined && value !== null && value !== '';
} }
/** 判断是否为空 */ /** 判断是否为空 */
export function isNull(value: any) { export function isNull(value: any) {
return value === undefined || value === null || value === '' || value === 'undefined' || value === 'null'; return value === undefined || value === null || value === '';
} }
/** 判断是否为图片类型 */ /** 判断是否为图片类型 */

View File

@ -28,7 +28,9 @@ const accept = computed(() => (props.uploadType === 'file' ? AcceptType.File : A
const fileList = ref<UploadFileInfo[]>([]); const fileList = ref<UploadFileInfo[]>([]);
function handleUpdateModelWhenUpload() {} function handleUpdateModelWhenUpload() {
fileList.value = [];
}
function closeDrawer() { function closeDrawer() {
visible.value = false; visible.value = false;

View File

@ -273,7 +273,7 @@ function handleAuthUser(row: Api.System.Role) {
:data="data" :data="data"
size="small" size="small"
:flex-height="!appStore.isMobile" :flex-height="!appStore.isMobile"
:scroll-x="962" :scroll-x="1200"
:loading="loading" :loading="loading"
remote remote
:row-key="row => row.roleId" :row-key="row => row.roleId"

View File

@ -1,5 +1,6 @@
<script setup lang="tsx"> <script setup lang="tsx">
import { computed, watch } from 'vue'; import { computed, ref, watch } from 'vue';
import { NDatePicker } from 'naive-ui';
import { fetchGetRoleUserList, fetchGetUserList } from '@/service/api/system'; import { fetchGetRoleUserList, fetchGetUserList } from '@/service/api/system';
import { useAppStore } from '@/store/modules/app'; import { useAppStore } from '@/store/modules/app';
import { useDict } from '@/hooks/business/dict'; import { useDict } from '@/hooks/business/dict';
@ -133,6 +134,22 @@ watch(visible, () => {
handleUpdateModelWhenEdit(); handleUpdateModelWhenEdit();
} }
}); });
const dateRangeCreateTime = ref<[string, string] | null>(null);
const datePickerRef = ref<InstanceType<typeof NDatePicker>>();
function onDateRangeCreateTimeUpdate(value: [string, string] | null) {
if (value?.length) {
searchParams.params!.beginTime = value[0];
searchParams.params!.endTime = value[1];
}
}
function reset() {
dateRangeCreateTime.value = null;
resetSearchParams();
}
</script> </script>
<template> <template>
@ -158,9 +175,22 @@ watch(visible, () => {
<NFormItemGi span="24 s:12 m:8" label="手机号码" path="phonenumber" class="pr-24px"> <NFormItemGi span="24 s:12 m:8" label="手机号码" path="phonenumber" class="pr-24px">
<NInput v-model:value="searchParams.phonenumber" placeholder="请输入手机号码" /> <NInput v-model:value="searchParams.phonenumber" placeholder="请输入手机号码" />
</NFormItemGi> </NFormItemGi>
<NFormItemGi span="24 s:12 m:24" class="pr-24px" :show-feedback="false"> <NFormItemGi span="24 s:12 m:8" label="所属部门" path="deptId" class="pr-24px">
<DeptTreeSelect v-model:value="searchParams.deptId" placeholder="请选择部门" />
</NFormItemGi>
<NFormItemGi span="24 s:12 m:10" label="创建时间" path="createTime" class="pr-24px">
<NDatePicker
ref="datePickerRef"
v-model:formatted-value="dateRangeCreateTime"
type="datetimerange"
value-format="yyyy-MM-dd HH:mm:ss"
clearable
@update:formatted-value="onDateRangeCreateTimeUpdate"
/>
</NFormItemGi>
<NFormItemGi span="24 s:12 m:6" class="pr-24px" :show-feedback="false">
<NSpace class="w-full" justify="end"> <NSpace class="w-full" justify="end">
<NButton @click="resetSearchParams"> <NButton @click="reset">
<template #icon> <template #icon>
<icon-ic-round-refresh class="text-icon" /> <icon-ic-round-refresh class="text-icon" />
</template> </template>

View File

@ -142,8 +142,12 @@ watch(visible, () => {
<div class="flex-center"> <div class="flex-center">
<NCheckbox v-model="data.updateSupport">{{ $t('common.updateExisting') }}</NCheckbox> <NCheckbox v-model="data.updateSupport">{{ $t('common.updateExisting') }}</NCheckbox>
</div> </div>
<NAlert v-if="message" :title="$t('common.importResult')" :type="success ? 'success' : 'error'" :bordered="false"> <NAlert v-if="message" :title="$t('common.importResult')" :type="success ? 'success' : 'error'" :bordered="false">
{{ message }} <NScrollbar class="max-h-200px">
<!-- eslint-disable-next-line vue/no-v-html -->
<span v-html="message" />
</NScrollbar>
</NAlert> </NAlert>
<template #footer> <template #footer>
<NSpace justify="end" :size="16"> <NSpace justify="end" :size="16">

View File

@ -65,14 +65,15 @@ function createDefaultModel(): Model {
}; };
} }
type RuleKey = Extract<keyof Model, 'userName' | 'nickName' | 'password' | 'status' | 'phonenumber'>; type RuleKey = Extract<keyof Model, 'userName' | 'nickName' | 'password' | 'status' | 'phonenumber' | 'roleIds'>;
const rules: Record<RuleKey, App.Global.FormRule[]> = { const rules: Record<RuleKey, App.Global.FormRule[]> = {
userName: [createRequiredRule($t('page.system.user.form.userName.required'))], userName: [createRequiredRule($t('page.system.user.form.userName.required'))],
nickName: [createRequiredRule($t('page.system.user.form.nickName.required'))], nickName: [createRequiredRule($t('page.system.user.form.nickName.required'))],
password: [{ ...patternRules.pwd, required: props.operateType === 'add' }], password: [{ ...patternRules.pwd, required: props.operateType === 'add' }],
phonenumber: [patternRules.phone], phonenumber: [patternRules.phone],
status: [createRequiredRule($t('page.system.user.form.status.required'))] status: [createRequiredRule($t('page.system.user.form.status.required'))],
roleIds: [{ ...createRequiredRule('请选择角色'), type: 'array' }]
}; };
async function getUserInfo() { async function getUserInfo() {