perf(custom): 修复新增页面存留问题,完善其他功能

This commit is contained in:
nongyehong
2023-11-25 23:53:10 +08:00
committed by Dawn
parent 1c9205dec3
commit 93eadc0b4a
19 changed files with 183 additions and 80 deletions

View File

@@ -1,3 +1,30 @@
## 1.1.0-beta (2023-11-25)
* :bug: fix(custom): 适配不同分辨率第一版 ([ecbca69](https://gitee.com/nongyehong/vue3-ts/commits/ecbca69))
* :bug: fix(custom): 修复除了媒体查询外样式不显示问题 ([5c334eb](https://gitee.com/nongyehong/vue3-ts/commits/5c334eb))
* :bug: fix(custom): 修复关于我们页面已知问题,修复抽屉和表格数据关联问题 ([325f016](https://gitee.com/nongyehong/vue3-ts/commits/325f016))
* :bug: fix(custom): 修复全局设置侧边栏颜色功能 ([e775709](https://gitee.com/nongyehong/vue3-ts/commits/e775709))
* :bug: fix(custom): 修复全局设置动画问题 ([a1d062a](https://gitee.com/nongyehong/vue3-ts/commits/a1d062a))
* :lipstick: style(custom): 使用storyset来做项目插画完善alert样式 ([0c6903f](https://gitee.com/nongyehong/vue3-ts/commits/0c6903f))
* :lipstick: style(custom): 自定义alert样式 ([489da6c](https://gitee.com/nongyehong/vue3-ts/commits/489da6c))
* :new: version(custom): 发布v1.1.0-beta版本 ([148535e](https://gitee.com/nongyehong/vue3-ts/commits/148535e))
* :sparkles: feat(custom): 封装全局快捷键功能 ([80bcf56](https://gitee.com/nongyehong/vue3-ts/commits/80bcf56))
* :sparkles: feat(custom): 设置预览更换系统主题功能 ([9451b15](https://gitee.com/nongyehong/vue3-ts/commits/9451b15))
* :sparkles: feat(custom): 新增多租户选项功能 ([e95a5b8](https://gitee.com/nongyehong/vue3-ts/commits/e95a5b8))
* :sparkles: feat(custom): 新增全局搜索功能,优化部分功能 ([35a0241](https://gitee.com/nongyehong/vue3-ts/commits/35a0241))
* :sparkles: feat(custom): 新增全局搜索删除记录功能 ([46643af](https://gitee.com/nongyehong/vue3-ts/commits/46643af))
* :sparkles: feat(custom): tabs标签页第一版 ([8fa62aa](https://gitee.com/nongyehong/vue3-ts/commits/8fa62aa))
* :zap: perf(custom): 使用localforage来做indexedDB存储优化角色权限下拉框 ([65dced8](https://gitee.com/nongyehong/vue3-ts/commits/65dced8))
* :zap: perf(custom): 完善角色下拉框功能 ([ddf8f35](https://gitee.com/nongyehong/vue3-ts/commits/ddf8f35))
* :zap: perf(custom): 完善快捷键功能 ([06667e5](https://gitee.com/nongyehong/vue3-ts/commits/06667e5))
* :zap: perf(custom): 完善全局的一些功能 ([97e242a](https://gitee.com/nongyehong/vue3-ts/commits/97e242a))
* :zap: perf(custom): 完善页面样式,增强页面交互 ([710f60c](https://gitee.com/nongyehong/vue3-ts/commits/710f60c))
* :zap: perf(custom): 优化个别功能逻辑和性能 ([0ac9d63](https://gitee.com/nongyehong/vue3-ts/commits/0ac9d63))
* :zap: perf(custom): 优化全局搜索框 ([4299f82](https://gitee.com/nongyehong/vue3-ts/commits/4299f82))
* :zap: perf(custom): tabs标签页功能完善 ([b86752d](https://gitee.com/nongyehong/vue3-ts/commits/b86752d))
## <small>1.0.5-alpha (2023-09-24)</small>
* :rewind: revert(custom): 回退到重构版本 ([39fe8f8](https://gitee.com/nongyehong/vue3-ts/commits/39fe8f8))

View File

@@ -31,7 +31,7 @@ import * as vicons from '@vicons/tabler'
const store = mainStore()
const tabsStore = tabs()
const { BGC, TEXT_COLOR } = storeToRefs(store)
const { BGC, TEXT_COLOR, TAB_ACTIVE_BGC, HOVER_BGC } = storeToRefs(store)
const { data } = storeToRefs(tabsStore)
const currentPath = computed(() => router.currentRoute.value.path)
@@ -82,19 +82,20 @@ onMounted(() => {
}
}
.del {
color: rgba(60, 60, 60);
color: v-bind(TEXT_COLOR);
border-radius: 50px;
transition: 0.5s;
&:hover {
background: rgba(60, 60, 60, 0.2);
background: v-bind(HOVER_BGC);
}
}
}
/*当前选中页面样式*/
.active-tab {
color: #189f57;
background: #e5f3ec;
background: v-bind(TAB_ACTIVE_BGC);
}
/*end*/
@keyframes twinkle {
0% {
transform: scale(0);

View File

@@ -2,7 +2,7 @@ import { WithNameQuery } from '@/api/user'
import typeState from '@/hooks/useState'
import { ref } from 'vue'
import { i18n } from '@/i18n'
import { RegExpUtils } from '@/utils/RegExpUtils'
import { RegExp } from '@/utils/RegExp'
const { AddOrEdit, tagType1, tagType2, tagType3, passwordComplexity, complexityShow, loadingPaw, ValidationStatus } =
typeState
@@ -18,8 +18,8 @@ const { t } = i18n.global
const validateLoginUsername = (rule: any, value: any, callback: any) => {
if (!value) {
callback(new Error(t('input_username')))
} else if (!RegExpUtils.isEngORNub(value) || value.length > 12) {
callback(new Error(t(!RegExpUtils.isEngORNub(value) ? 'is_standard' : 'UN_EX_limit')))
} else if (!RegExp.isEngORNub(value) || value.length > 12) {
callback(new Error(t(!RegExp.isEngORNub(value) ? 'is_standard' : 'UN_EX_limit')))
} else {
callback()
}
@@ -127,7 +127,7 @@ const validateIsNull = (rule: any, value: any, callback: any) => {
const validateEmail = (rule: any, value: any, callback: any) => {
if (value === '' || value === undefined) {
callback(new Error(t('no_null')))
} else if (!RegExpUtils.isEmail(value)) {
} else if (!RegExp.isEmail(value)) {
callback(new Error(t('check_email')))
} else {
callback()
@@ -140,7 +140,7 @@ const validateEmail = (rule: any, value: any, callback: any) => {
*/
const pawComplexity = (val: any) => {
complexityShow.value = true
if (RegExpUtils.isPasswordComplex(val)) {
if (RegExp.isPasswordComplex(val)) {
passwordComplexity.value = t('complexity_st')
tagType1.value = 'success'
tagType2.value = 'success'

View File

@@ -100,10 +100,8 @@
"error_tip": "Error Tip",
"not_found": "The current page cannot be found",
"timeout_verify": "Enter the code or we're dead",
"license_number": "licenseNumber",
"phone_number": "phoneNumber",
"address": "Address",
"familiar_traffic_signs": "familiar Traffic Signs",
"delete": "delete",
"delete_success": "Delete Success",
"add_success": "Add Success",
@@ -113,6 +111,7 @@
"add_error": "Add Error",
"edit_error": "Edit Error",
"delete_batch_error": "Delete Batch Error",
"batch_error_msg": "No row is currently selected or no id is passed",
"coding": "Coding",
"content": "Content",
"type": "Type",

View File

@@ -100,10 +100,8 @@
"error_tip": "错误提示",
"not_found": "无法找到当前页面",
"timeout_verify": "看一下输入密码能不能救",
"license_number": "牌照号码",
"phone_number": "手机号码",
"address": "地址",
"familiar_traffic_signs": "熟悉的交通标志",
"delete": "删除",
"delete_success": "删除成功",
"add_success": "新增成功",
@@ -113,6 +111,7 @@
"add_error": "新增失败",
"edit_error": "编辑失败",
"delete_batch_error": "批量删除失败",
"batch_error_msg": "当前没有选中任何行或没有传入id",
"coding": "编码",
"content": "内容",
"select": "请选择",

View File

@@ -1,6 +1,6 @@
import { createAxios } from '@/services/request'
import urls from '@/services/urls'
import type { Response, UpdateUser, User, parameter, Renew, login } from '@/services/types'
import type { Response, UpdateUser, User, parameter, Renew, login, BatchDeleteUser } from '@/services/types'
const request = createAxios()
@@ -21,6 +21,8 @@ export default {
/*删除单个 用户*/
deleteUser: (id: number, username: string, uid: string): Promise<Response> =>
DELETE(urls.userCRUD + '/' + id + '/' + username + '/' + uid),
/*批量删除 用户*/
batchDeleteUsers: (data: BatchDeleteUser): Promise<Response> => POST(urls.userCRUD + '/delete/batch', data),
/*修改 用户*/
editUser: (form: UpdateUser): Promise<Response> => PUT(urls.userCRUD, form),
/*续签 请求*/

View File

@@ -4,6 +4,7 @@
* @see TSDoc规范https://tsdoc.org/
**/
import { GlobalStatusEnum, RCodeEnum } from '@/enums'
import { DataTableRowKey } from 'naive-ui'
/*响应请求体*/
export type Response = {
@@ -76,6 +77,11 @@ export type UpdateUser = {
status: number
avatar: string
}
/*批量删除用户*/
export type BatchDeleteUser = {
ids: DataTableRowKey[]
uids: string[]
}
/*记住我*/
export type Renew = {
userName: string

View File

@@ -15,6 +15,10 @@ export const mainStore = defineStore('main', {
MASK_BGC: 'rgba(231, 229, 228, 0.75)',
/*菜单栏的按钮颜色*/
BTN: 'rgb(229, 243, 237)',
/*tabs选中时的背景颜色*/
TAB_ACTIVE_BGC: '#e5f3ec',
/*hover时的背景颜色*/
HOVER_BGC: 'rgba(60, 60, 60, 0.2)',
/*文本的颜色*/
TEXT_COLOR: '#000',
/*侧边栏文本颜色*/
@@ -37,6 +41,8 @@ export const mainStore = defineStore('main', {
this.LOGIN_BGC = this.LOGIN_BGC === '#FFF' ? '#141414' : '#FFF'
this.BTN = this.BTN === 'rgb(229, 243, 237)' ? 'rgba(229, 243, 237, .1)' : 'rgb(229, 243, 237)'
this.MASK_BGC = this.EYE_THEME ? 'rgba(41, 37, 36, 0.75)' : 'rgba(231, 229, 228, 0.75)'
this.TAB_ACTIVE_BGC = this.EYE_THEME ? '#233633' : '#e5f3ec'
this.HOVER_BGC = this.EYE_THEME ? 'rgba(255, 255, 255, 0.2)' : 'rgba(60, 60, 60, 0.2)'
this.BGC_OTHER = this.BGC_OTHER === '#f4f4f4' ? '#1d1d1d' : '#f4f4f4'
this.TEXT_COLOR = this.TEXT_COLOR === '#000' ? '#cdd1da' : '#000'
this.ASIDE_TEXT_COLOR = this.TEXT_COLOR

View File

@@ -14,12 +14,14 @@ declare module 'vue' {
Language: typeof import('./../components/Language/index.vue')['default']
Modal: typeof import('./../components/modal/index.vue')['default']
NA: typeof import('naive-ui')['NA']
NAutoComplete: typeof import('naive-ui')['NAutoComplete']
NAvatar: typeof import('naive-ui')['NAvatar']
NBadge: typeof import('naive-ui')['NBadge']
NBlockquote: typeof import('naive-ui')['NBlockquote']
NButton: typeof import('naive-ui')['NButton']
NCard: typeof import('naive-ui')['NCard']
NCheckbox: typeof import('naive-ui')['NCheckbox']
NCollapseTransition: typeof import('naive-ui')['NCollapseTransition']
NConfigProvider: typeof import('naive-ui')['NConfigProvider']
NDataTable: typeof import('naive-ui')['NDataTable']
NDescriptions: typeof import('naive-ui')['NDescriptions']

9
src/utils/Common.ts Normal file
View File

@@ -0,0 +1,9 @@
export class Common {
/**
* 去除两边空格
* @param value 待处理字符串
*/
public static noSideSpace(value: string): boolean {
return !value.startsWith(' ') && !value.endsWith(' ')
}
}

View File

@@ -1,4 +1,4 @@
export class RegExpUtils {
export class RegExp {
/**
* 使
* @param email

View File

@@ -26,10 +26,14 @@
<n-form ref="formRef" :model="contentData" :rules="rules" style="padding: 10px 0">
<n-form-item :label="t('user_name')" path="userName">
<n-input v-model:value="contentData.userName" :placeholder="t('placeholder')" />
<n-input
:allow-input="Common.noSideSpace"
v-model:value="contentData.userName"
:placeholder="t('placeholder')" />
</n-form-item>
<n-form-item :label="t('nick_name')">
<n-input
:allow-input="Common.noSideSpace"
:status="handleStatus(contentData.nickName)"
v-model:value="contentData.nickName"
:placeholder="t('placeholder')" />
@@ -103,8 +107,9 @@ import apis from '@/services/apis'
import paging from '@/hooks/usePaging'
import UserVar from './userVar'
import { AlertIze } from '@/customize'
import { handRelativeTime } from '@/utils/day'
import { handRelativeTime } from '@/utils/Day'
import { animation } from '@/components/modal/type'
import { Common } from '@/utils/Common'
const { t } = i18n.global
const { pageNum, pageSize } = paging
@@ -150,23 +155,6 @@ const saveData = async (form: any) => {
// 清空临时对象
// contentData.value = {} as pageUser
}
/*新增事件*/
const AddInfo = async (formEl: any) => {
const addRoleSuccessMessage = '添加成功'
const addRoleErrorMessage = '添加失败'
await performAction(
formEl,
() => apis.addUser(contentData as any),
() =>
apis.userPage({
pageSize: pageSize.value,
pageNum: pageNum.value,
userName: input.value
}),
addRoleSuccessMessage,
addRoleErrorMessage
)
}
const clone = () => {
// TODO animation是全局的值如果当其他地方的值改变了就要在其他地方初始化的时候来初始化动画 (nyh-2023-10-03 03:56:34)

View File

@@ -18,7 +18,7 @@ const rules = reactive({
userName: { required: true, message: t('user_name') + t('no_null'), trigger: 'blur' },
password: { required: true, message: t('password') + t('no_null'), trigger: 'blur' },
role: { required: true, message: t('role_flag') + t('no_null'), trigger: ['blur', 'change'] },
email: { required: true, message: t('email') + t('no_null'), trigger: 'blur' }
email: { required: true, message: t('email') + t('no_null'), trigger: ['blur', 'change'] }
})
export default () => ({

View File

@@ -40,30 +40,45 @@
:rules="rules"
style="padding: 10px 0">
<n-form-item :label="t('user_name')" path="userName">
<n-input v-model:value="contentData.userName" :placeholder="t('please_enter') + t('user_name')" />
<n-input
:allow-input="Common.noSideSpace"
v-model:value="contentData.userName"
:placeholder="t('please_enter') + t('user_name')" />
</n-form-item>
<n-form-item :label="t('password')" path="password">
<n-form-item :allow-input="Common.noSideSpace" :label="t('password')" path="password">
<n-input v-model:value="contentData.password" :placeholder="t('please_enter') + t('password')" />
</n-form-item>
<n-form-item :label="t('role_flag')" path="role">
<RoleOptions />
</n-form-item>
<n-form-item :label="t('email')" path="email">
<n-input v-model:value="contentData.email" :placeholder="t('please_enter') + t('email')" />
<n-auto-complete
clearable
v-model:value="contentData.email"
:options="emailOptions"
:placeholder="t('please_enter') + t('email')" />
</n-form-item>
<!--不是必填的选项进行隐藏-->
<n-space justify="center" v-if="!showMore" @click="showMore = true">
<n-space vertical align="center" style="cursor: pointer; color: #afabab">
<n-space justify="center" v-if="!showMore">
<n-space style="cursor: pointer; color: #afabab" @click="showMore = true">
<span>展开更多选项</span>
<n-icon size="22" :component="Badges" />
</n-space>
</n-space>
<n-form-item v-show="showMore" :label="t('nick_name')">
<n-input v-model:value="contentData.nickName" :placeholder="t('please_enter') + t('nick_name')" />
</n-form-item>
<n-form-item v-show="showMore" :label="t('phone_number')">
<n-input v-model:value="contentData.mobile" :placeholder="t('please_enter') + t('phone_number')" />
</n-form-item>
<n-collapse-transition v-show="showMore">
<n-form-item :label="t('nick_name')">
<n-input v-model:value="contentData.nickName" :placeholder="t('please_enter') + t('nick_name')" />
</n-form-item>
<n-form-item :label="t('phone_number')">
<n-input v-model:value="contentData.mobile" :placeholder="t('please_enter') + t('phone_number')" />
</n-form-item>
<n-space justify="center">
<n-space style="cursor: pointer; color: #afabab" @click="showMore = false">
<span>收起</span>
<n-icon size="22" :component="ArrowBigUpLines" />
</n-space>
</n-space>
</n-collapse-transition>
</n-form>
</n-scrollbar>
<template #footer>
@@ -85,11 +100,12 @@ import { useBase } from '@/hooks/useBase'
import { i18n } from '@/i18n'
import UserVar from '@/views/composables/drawer/userDrawer/userVar'
import { AlertIze } from '@/customize'
import { DragDrop, Badges } from '@vicons/tabler'
import { DragDrop, Badges, ArrowBigUpLines } from '@vicons/tabler'
import apis from '@/services/apis'
import paging from '@/hooks/usePaging'
import { userStore } from '@/stores/user'
import { NIcon } from 'naive-ui'
import { Common } from '@/utils/Common'
const { t } = i18n.global
const { pageNum, pageSize } = paging
@@ -99,6 +115,22 @@ const { performAction, contentData, warn, showWarn, butText, loadingBut, butType
const userInfoStore = userStore()
const tenantId = userInfoStore.getTenantId
const showMore = ref(false)
/*邮箱字段自动填充*/
const emailOptions = computed(() => {
return [
['谷歌', '@gmail.com'],
['网易', '@163.com'],
['腾讯', '@qq.com']
].map((emailInfo) => {
const email = contentData.value.email || ''
return {
type: 'group',
label: emailInfo[0],
key: emailInfo[0],
children: [email.split('@')[0] + emailInfo[1]]
}
})
})
const { title } = defineProps<{
title: string
}>()

View File

@@ -10,16 +10,17 @@ import {
NAvatar,
NPopconfirm,
NButton,
DataTableRowKey
DataTableRowKey,
NText
} from 'naive-ui'
import { pageUser } from '@/services/types'
import { i18n } from '@/i18n'
import type { Ref } from 'vue'
import { RCodeEnum, RoleEnum } from '@/enums'
import { EditCircle, LetterM, LetterR, LetterU, Power, TrashX, X, Minus, AlertTriangle } from '@vicons/tabler'
import { EditCircle, LetterM, LetterR, LetterU, Power, TrashX, X, Minus } from '@vicons/tabler'
import { Report } from 'notiflix'
import { useAuth } from '@/hooks/useAuth'
import { handRelativeTime } from '@/utils/day'
import { handRelativeTime } from '@/utils/Day'
import { useBase } from '@/hooks/useBase'
import apis from '@/services/apis'
import paging from '@/hooks/usePaging'
@@ -34,7 +35,7 @@ export const userTable = (data: Ref<any[]>) => {
const { judgmentRole } = useAuth()
const { input } = UserVar()
const { pagingLoad, contentData, rawData, showDrawer, total } = useBase()
const checkedRowKeysRef = ref<DataTableRowKey[]>([])
const checkedRowKeys = ref<DataTableRowKey[]>([])
/*受控过滤器*/
const statusColumn = reactive<DataTableBaseColumn<pageUser>>({
@@ -242,7 +243,6 @@ export const userTable = (data: Ref<any[]>) => {
<NPopconfirm onPositiveClick={() => handleDeleteTable(row)}>
{{
default: () => t('confirm_delete'),
icon: () => <NIcon color={'#ce304f'} size={18} component={AlertTriangle} />,
trigger: () => (
<NIconWrapper size={26} borderRadius={6} color={'#f5dce1'} iconColor={'#ce304f'}>
<NIcon size={22} style={{ cursor: 'pointer' }} component={TrashX}></NIcon>
@@ -274,14 +274,12 @@ export const userTable = (data: Ref<any[]>) => {
if (res.code !== RCodeEnum.OK) {
return window.$message.error(res.msg)
}
await pagingLoad(
() =>
apis.userPage({
pageSize: pageSize.value,
pageNum: pageNum.value,
userName: input.value
}),
window.$loadingBar
await pagingLoad(() =>
apis.userPage({
pageSize: pageSize.value,
pageNum: pageNum.value,
userName: input.value
})
).then(() => {
window.$message.success(res.msg)
})
@@ -301,13 +299,13 @@ export const userTable = (data: Ref<any[]>) => {
bordered={false}
type={'success'}
style={{
display: checkedRowKeysRef.value.length > 0 ? '' : 'none',
display: checkedRowKeys.value.length > 0 ? '' : 'none',
padding: '0 20px',
borderRadius: '6px'
}}>
{checkedRowKeysRef.value.length}
{checkedRowKeys.value.length}
</NTag>
<span> {total.value} </span>
<NText> {total.value} </NText>
</div>
)
},
@@ -322,13 +320,14 @@ export const userTable = (data: Ref<any[]>) => {
/*多选选中的方法*/
const handleCheck = (rowKeys: DataTableRowKey[]) => {
checkedRowKeysRef.value = rowKeys
checkedRowKeys.value = rowKeys
}
return {
columns,
statusColumn,
pagination,
checkedRowKeys,
handleCheck
}
}

View File

@@ -42,7 +42,7 @@
<n-form-item path="userName" :label="t('un_or_el')" label-style="font-size: 14px;color: #cccccc">
<n-input
clearable
:allow-input="noSideSpace"
:allow-input="Common.noSideSpace"
@keydown.enter="SignIn(formRef)"
v-model:value="ruleForm.userName"
style="border-radius: 8px"
@@ -70,7 +70,7 @@
show-password-on="mousedown"
type="password"
clearable
:allow-input="noSideSpace"
:allow-input="Common.noSideSpace"
:loading="loadingPaw"
@keydown.enter="SignIn(formRef)"
v-model:value="ruleForm.password"
@@ -177,6 +177,7 @@ import { delay } from 'lodash-es'
import apis from '@/services/apis'
import type { SelectGroupOption, SelectOption, SelectRenderTag, SelectRenderLabel } from 'naive-ui'
import { NText, NAvatar } from 'naive-ui'
import { Common } from '@/utils/Common'
const { t } = i18n.global
const store = mainStore()
@@ -255,9 +256,9 @@ const renderLabel: SelectRenderLabel = (option) => {
)
}
/*处理输入空格事件*/
const noSideSpace = (value: string) => {
return !value.startsWith(' ') && !value.endsWith(' ')
}
// const noSideSpace = (value: string) => {
// return !value.startsWith(' ') && !value.endsWith(' ')
// }
type Itenant = {
companyName: string

View File

@@ -6,10 +6,15 @@
{{ t('add') }}
</n-button>
<n-button style="border-radius: 8px" secondary type="error" @click="handleBatch">
<template #icon><n-icon :component="PlaylistX" /></template>
{{ t('delete_batch') }}
</n-button>
<n-popconfirm placement="bottom" @positive-click="handleBatch">
<template #trigger>
<n-button style="border-radius: 8px" secondary type="error">
<template #icon><n-icon :component="PlaylistX" /></template>
{{ t('delete_batch') }}
</n-button>
</template>
{{ t('confirm_delete_batch') }}
</n-popconfirm>
<n-input
:maxlength="10"
@@ -82,6 +87,8 @@ import userVar from '@/views/composables/drawer/userDrawer/userVar'
import { userTable } from '@/views/composables/table/userTable'
import { userModal } from '@/views/composables/modal/index'
import { useDebounceFn } from '@vueuse/core'
import { Report } from 'notiflix'
import { RCodeEnum } from '@/enums'
const { t } = i18n.global
const { pageNum, pageSize } = paging
@@ -89,7 +96,7 @@ const loadingBarTargetRef = ref()
const title = ref('添加用户')
const { input } = userVar()
const { pagingLoad, tableData, loading, NoAccess, contentData, showModal } = useBase()
const { handleCheck, columns, statusColumn, pagination } = userTable(tableData)
const { handleCheck, columns, statusColumn, pagination, checkedRowKeys } = userTable(tableData)
/**使用defineComponent重新构建组件*/
const LoadingBarTrigger = defineComponent({
@@ -127,8 +134,33 @@ const handleAdd = () => {
}
/*批量删除事件*/
const handleBatch = () => {
console.log('批量删除')
const handleBatch = async () => {
if (checkedRowKeys.value.length === 0) {
Report.failure(t('delete_batch_error'), t('batch_error_msg'), t('close'), {
titleFontSize: '18px',
messageFontSize: '16px'
})
return
}
const uids = tableData.value
.filter((item: any) => checkedRowKeys.value.includes(item.id))
.map((item: any) => item.uid)
const data = { ids: checkedRowKeys.value, uids }
const res = await apis.batchDeleteUsers(data)
if (res.code !== RCodeEnum.OK) {
return window.$message.error(res.code === RCodeEnum.PARAM_ERROR ? (res.data as any)[0] : res.msg)
}
await pagingLoad(() =>
apis.userPage({
pageSize: pageSize.value,
pageNum: pageNum.value,
userName: input.value
})
).then(() => {
window.$message.success(res.msg)
/*初始化选中的行*/
checkedRowKeys.value.length = 0
})
}
/*搜索事件*/

View File

@@ -1,5 +1,5 @@
import { createPinia, setActivePinia } from 'pinia'
import { RegExpUtils } from '@/utils/RegExpUtils'
import { RegExp } from '@/utils/RegExp'
import { useAuth } from '@/hooks/useAuth'
import { expect } from 'vitest'
@@ -16,11 +16,11 @@ describe('测试组件', () => {
test('测试用户输入格式是否符合标准', () => {
/*判断邮箱格式*/
const email = RegExpUtils.isEmail('123@123.com')
const email = RegExp.isEmail('123@123.com')
/*判断密码的复杂度*/
const paw = RegExpUtils.isPasswordComplex('Kk.123456')
const paw = RegExp.isPasswordComplex('Kk.123456')
/*判断输入的内容是否只包含数字和英文*/
const engOrNub = RegExpUtils.isEngORNub('婚纱店静安寺')
const engOrNub = RegExp.isEngORNub('婚纱店静安寺')
expect(email).toBe(true)
expect(paw).toBe(true)
expect(engOrNub).toBe(false)