⚡ perf(custom): 修复新增页面存留问题,完善其他功能
This commit is contained in:
27
CHANGELOG.md
27
CHANGELOG.md
@@ -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))
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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": "请选择",
|
||||
|
||||
@@ -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),
|
||||
/*续签 请求*/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
2
src/typings/components.d.ts
vendored
2
src/typings/components.d.ts
vendored
@@ -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
9
src/utils/Common.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
export class Common {
|
||||
/**
|
||||
* 去除两边空格
|
||||
* @param value 待处理字符串
|
||||
*/
|
||||
public static noSideSpace(value: string): boolean {
|
||||
return !value.startsWith(' ') && !value.endsWith(' ')
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
export class RegExpUtils {
|
||||
export class RegExp {
|
||||
/**
|
||||
* 使用正则来校验邮箱是否正确
|
||||
* @param email 邮箱
|
||||
@@ -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)
|
||||
|
||||
@@ -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 () => ({
|
||||
|
||||
@@ -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
|
||||
}>()
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
})
|
||||
}
|
||||
|
||||
/*搜索事件*/
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user