refactor: 重构用户管理搜索栏(支持多条件展开及折叠)

This commit is contained in:
2024-10-13 11:00:44 +08:00
parent ff879405d7
commit 50a6d17516
11 changed files with 98 additions and 42 deletions

View File

@@ -37,6 +37,7 @@ export interface UserImportResp {
export interface UserQuery { export interface UserQuery {
description?: string description?: string
status?: number status?: number
createTime?: Array<string>
deptId?: string deptId?: string
sort: Array<string> sort: Array<string>
} }

View File

@@ -1,5 +1,5 @@
<template> <template>
<a-form ref="formRef" v-bind="options.form" :model="modelValue" size="large" :auto-label-width="true"> <a-form ref="formRef" v-bind="options.form" :model="modelValue" :auto-label-width="true">
<a-row :gutter="14" v-bind="options.row" class="w-full"> <a-row :gutter="14" v-bind="options.row" class="w-full">
<template v-for="(item, index) in columns" :key="item.field"> <template v-for="(item, index) in columns" :key="item.field">
<a-col <a-col
@@ -150,10 +150,9 @@
</template> </template>
<template v-if="item.type === 'range-picker'"> <template v-if="item.type === 'range-picker'">
<a-range-picker <DateRangePicker v-bind="(item.props as A.RangePickerInstance['$props'])"
v-bind="(item.props as A.RangePickerInstance['$props'])" :model-value="modelValue[item.field as keyof typeof modelValue]"
:model-value="modelValue[item.field as keyof typeof modelValue]" @update:model-value="valueChange($event, item.field)" />
@update:model-value="valueChange($event, item.field)"></a-range-picker>
</template> </template>
<template v-if="item.type === 'color-picker'"> <template v-if="item.type === 'color-picker'">
@@ -191,7 +190,7 @@
</a-col> </a-col>
</template> </template>
<a-col v-if="!options.btns?.hide" :span="options.btns?.span || 12" v-bind="options.btns?.col"> <a-col v-if="!options.btns?.hide" :span="options.btns?.span || 12" v-bind="options.btns?.col">
<a-space wrap> <a-space wrap :size="[8, 16]">
<slot name="suffix"> <slot name="suffix">
<a-button type="primary" @click="emit('search')"> <a-button type="primary" @click="emit('search')">
<template #icon><icon-search /></template> <template #icon><icon-search /></template>
@@ -219,6 +218,7 @@
import type * as A from '@arco-design/web-vue' import type * as A from '@arco-design/web-vue'
import { cloneDeep } from 'lodash-es' import { cloneDeep } from 'lodash-es'
import type { Columns, ColumnsItem, ColumnsItemDisabled, ColumnsItemHide, Options } from './type' import type { Columns, ColumnsItem, ColumnsItemDisabled, ColumnsItemHide, Options } from './type'
import DateRangePicker from '@/components/DateRangePicker/index.vue'
interface Props { interface Props {
modelValue: any modelValue: any
@@ -304,4 +304,8 @@ watch(cloneForm as any, (newVal, oldVal) => {
}) })
</script> </script>
<style lang="scss" scoped></style> <style lang="scss" scoped>
:deep(.arco-form-item-layout-inline) {
margin-right: 0;
}
</style>

View File

@@ -39,7 +39,7 @@ const title = computed(
const formRef = ref<InstanceType<typeof GiForm>>() const formRef = ref<InstanceType<typeof GiForm>>()
const options: Options = { const options: Options = {
form: {}, form: { size: 'large' },
col: { xs: 24, sm: 24, md: 24, lg: 24, xl: 24, xxl: 24 }, col: { xs: 24, sm: 24, md: 24, lg: 24, xl: 24, xxl: 24 },
btns: { hide: true } btns: { hide: true }
} }

View File

@@ -24,7 +24,7 @@ import { useUserStore } from '@/stores'
const { width } = useWindowSize() const { width } = useWindowSize()
const options: Options = { const options: Options = {
form: {}, form: { size: 'large' },
col: { xs: 24, sm: 24, md: 24, lg: 24, xl: 24, xxl: 24 }, col: { xs: 24, sm: 24, md: 24, lg: 24, xl: 24, xxl: 24 },
btns: { hide: true } btns: { hide: true }
} }

View File

@@ -33,7 +33,7 @@ const title = computed(() => (isUpdate.value ? '修改部门' : '新增部门'))
const formRef = ref<InstanceType<typeof GiForm>>() const formRef = ref<InstanceType<typeof GiForm>>()
const options: Options = { const options: Options = {
form: {}, form: { size: 'large' },
col: { xs: 24, sm: 24, md: 24, lg: 24, xl: 24, xxl: 24 }, col: { xs: 24, sm: 24, md: 24, lg: 24, xl: 24, xxl: 24 },
btns: { hide: true } btns: { hide: true }
} }

View File

@@ -38,7 +38,7 @@ const title = computed(() => (isUpdate.value ? '修改字典项' : '新增字典
const formRef = ref<InstanceType<typeof GiForm>>() const formRef = ref<InstanceType<typeof GiForm>>()
const options: Options = { const options: Options = {
form: {}, form: { size: 'large' },
col: { xs: 24, sm: 24, md: 24, lg: 24, xl: 24, xxl: 24 }, col: { xs: 24, sm: 24, md: 24, lg: 24, xl: 24, xxl: 24 },
btns: { hide: true } btns: { hide: true }
} }

View File

@@ -29,7 +29,7 @@ const title = computed(() => (isUpdate.value ? '修改字典' : '新增字典'))
const formRef = ref<InstanceType<typeof GiForm>>() const formRef = ref<InstanceType<typeof GiForm>>()
const options: Options = { const options: Options = {
form: {}, form: { size: 'large' },
col: { xs: 24, sm: 24, md: 24, lg: 24, xl: 24, xxl: 24 }, col: { xs: 24, sm: 24, md: 24, lg: 24, xl: 24, xxl: 24 },
btns: { hide: true } btns: { hide: true }
} }

View File

@@ -49,7 +49,7 @@ const { form, resetForm } = useForm({
content: '' content: ''
}) })
const options: Options = { const options: Options = {
form: {}, form: { size: 'large' },
col: { xs: 24, sm: 24, md: 12, lg: 12, xl: 12, xxl: 12 }, col: { xs: 24, sm: 24, md: 12, lg: 12, xl: 12, xxl: 12 },
btns: { hide: true } btns: { hide: true }
} }

View File

@@ -28,7 +28,7 @@ const dataId = ref('')
const formRef = ref<InstanceType<typeof GiForm>>() const formRef = ref<InstanceType<typeof GiForm>>()
const options: Options = { const options: Options = {
form: {}, form: { size: 'large' },
col: { xs: 24, sm: 24, md: 24, lg: 24, xl: 24, xxl: 24 }, col: { xs: 24, sm: 24, md: 24, lg: 24, xl: 24, xxl: 24 },
btns: { hide: true } btns: { hide: true }
} }

View File

@@ -145,7 +145,7 @@ onMounted(() => {
height: 100%; height: 100%;
&__search { &__search {
margin-bottom: 10px; margin-bottom: 16px;
} }
&__container { &__container {

View File

@@ -8,24 +8,23 @@
</a-space> </a-space>
</a-row> </a-row>
<a-row align="stretch" :gutter="14" class="h-full page_content"> <a-row align="stretch" :gutter="14" class="h-full page_content">
<a-col :xs="0" :sm="8" :md="7" :lg="6" :xl="5" :xxl="4" flex="260px" class="h-full ov-hidden"> <a-col :xs="0" :sm="0" :md="6" :lg="5" :xl="5" :xxl="4" class="h-full ov-hidden">
<DeptTree placeholder="请输入名称" @node-click="handleSelectDept" /> <DeptTree placeholder="请输入名称" @node-click="handleSelectDept" />
</a-col> </a-col>
<a-col :xs="24" :sm="16" :md="17" :lg="18" :xl="19" :xxl="20" flex="1" class="h-full ov-hidden"> <a-col :xs="24" :sm="24" :md="18" :lg="19" :xl="19" :xxl="20" class="h-full ov-hidden">
<GiTable row-key="id" :data="dataList" :columns="columns" :loading="loading" <GiForm v-model="queryForm" :options="options" :columns="queryFormColumns" @search="search" @reset="reset"></GiForm>
:scroll="{ x: '100%', y: '100%', minWidth: 1500 }" :pagination="pagination" :disabled-tools="['size']" <GiTable
:disabled-column-keys="['username']" @refresh="search"> row-key="id"
:data="dataList"
:columns="columns"
:loading="loading"
:scroll="{ x: '100%', y: '100%', minWidth: 1500 }"
:pagination="pagination"
:disabled-tools="['size']"
:disabled-column-keys="['username']"
@refresh="search"
>
<template #custom-left> <template #custom-left>
<a-input v-model="queryForm.description" placeholder="请输入用户名/昵称/描述" allow-clear @change="search">
<template #prefix>
<icon-search />
</template>
</a-input>
<a-select v-model="queryForm.status" :options="DisEnableStatusList" placeholder="请选择状态" allow-clear
style="width: 150px" @change="search" />
<a-button @click="reset">重置</a-button>
</template>
<template #custom-right>
<a-button v-permission="['system:user:add']" type="primary" @click="onAdd"> <a-button v-permission="['system:user:add']" type="primary" @click="onAdd">
<template #icon> <template #icon>
<icon-plus /> <icon-plus />
@@ -38,13 +37,14 @@
</template> </template>
<span>导入</span> <span>导入</span>
</a-button> </a-button>
<a-tooltip content="导出"> </template>
<a-button v-permission="['system:user:export']" class="gi_hover_btn-border" @click="onExport"> <template #custom-right>
<template #icon> <a-button v-permission="['system:user:export']" @click="onExport">
<icon-download /> <template #icon>
</template> <icon-download />
</a-button> </template>
</a-tooltip> <template #default>导出</template>
</a-button>
</template> </template>
<template #username="{ record }"> <template #username="{ record }">
<GiCellAvatar :avatar="getAvatar(record.avatar, record.gender)" :name="record.username" is-link <GiCellAvatar :avatar="getAvatar(record.avatar, record.gender)" :name="record.username" is-link
@@ -66,9 +66,13 @@
<template #action="{ record }"> <template #action="{ record }">
<a-space> <a-space>
<a-link v-permission="['system:user:update']" @click="onUpdate(record)">修改</a-link> <a-link v-permission="['system:user:update']" @click="onUpdate(record)">修改</a-link>
<a-link v-permission="['system:user:delete']" status="danger" <a-link
:title="record.isSystem ? '系统内置数据不能删除' : '删除'" :disabled="record.disabled" v-permission="['system:user:delete']"
@click="onDelete(record)"> status="danger"
:title="record.isSystem ? '系统内置数据不能删除' : '删除'"
:disabled="record.disabled"
@click="onDelete(record)"
>
删除 删除
</a-link> </a-link>
<a-dropdown> <a-dropdown>
@@ -97,8 +101,9 @@ import UserImportDrawer from './UserImportDrawer.vue'
import UserDetailDrawer from './UserDetailDrawer.vue' import UserDetailDrawer from './UserDetailDrawer.vue'
import UserResetPwdModal from './UserResetPwdModal.vue' import UserResetPwdModal from './UserResetPwdModal.vue'
import { type UserQuery, type UserResp, deleteUser, exportUser, listUser } from '@/apis/system' import { type UserQuery, type UserResp, deleteUser, exportUser, listUser } from '@/apis/system'
import type { Columns, Options } from '@/components/GiForm'
import type { TableInstanceColumns } from '@/components/GiTable/type' import type { TableInstanceColumns } from '@/components/GiTable/type'
import { useDownload, useTable } from '@/hooks' import { useBreakpointIndex, useDownload, useTable } from '@/hooks'
import { isMobile } from '@/utils' import { isMobile } from '@/utils'
import getAvatar from '@/utils/avatar' import getAvatar from '@/utils/avatar'
import has from '@/utils/has' import has from '@/utils/has'
@@ -109,7 +114,6 @@ defineOptions({ name: 'SystemUser' })
const queryForm = reactive<UserQuery>({ const queryForm = reactive<UserQuery>({
sort: ['t1.createTime,desc'] sort: ['t1.createTime,desc']
}) })
const { const {
tableData: dataList, tableData: dataList,
loading, loading,
@@ -118,6 +122,52 @@ const {
handleDelete handleDelete
} = useTable((page) => listUser({ ...queryForm, ...page }), { immediate: false }) } = useTable((page) => listUser({ ...queryForm, ...page }), { immediate: false })
const options: Options = reactive({
form: { layout: 'inline' },
col: { xs: 24, sm: 24, md: 5, lg: 5, xl: 5, xxl: 5 },
btns: { col: { xs: 24, sm: 24, md: 7, lg: 7, xl: 7, xxl: 7 } },
fold: { enable: true, index: 2, defaultCollapsed: true }
})
useBreakpointIndex((index) => {
// 自适应折叠,让折叠后始终一行显示
options.fold && (options.fold.index = index)
})
const queryFormColumns: Columns = reactive([
{
type: 'input',
field: 'description',
item: {
hideLabel: true
},
props: {
placeholder: '请输入用户名/昵称/描述',
allowClear: true
}
},
{
type: 'select',
field: 'status',
options: DisEnableStatusList,
item: {
hideLabel: true
},
props: {
placeholder: '请选择状态',
allowClear: true
}
},
{
type: 'range-picker',
field: 'createTime',
item: {
hideLabel: true
},
col: { xs: 24, sm: 24, md: 10, lg: 10, xl: 10, xxl: 10 }
}
])
const columns: TableInstanceColumns[] = [ const columns: TableInstanceColumns[] = [
{ {
title: '序号', title: '序号',
@@ -162,6 +212,7 @@ const columns: TableInstanceColumns[] = [
const reset = () => { const reset = () => {
queryForm.description = undefined queryForm.description = undefined
queryForm.status = undefined queryForm.status = undefined
queryForm.createTime = []
search() search()
} }