Merge pull request #85 from cshaptx4869/patch-47

重构列表选择组件默认样式、增加列表选择组件使用示例
This commit is contained in:
Ray Hao
2024-05-09 21:33:33 +08:00
committed by GitHub
3 changed files with 221 additions and 11 deletions

View File

@@ -1,16 +1,34 @@
<template>
<div ref="tableSelectRef">
<div ref="tableSelectRef" :style="'width:' + width">
<el-popover
:visible="popoverVisible"
width="75%"
:width="popoverWidth"
placement="bottom-end"
v-bind="selectConfig.popover"
@show="handleShow"
>
<template #reference>
<el-button @click="popoverVisible = !popoverVisible">
<slot>选择列表</slot>
</el-button>
<div @click="popoverVisible = !popoverVisible">
<slot>
<el-input
class="reference"
:model-value="text"
:readonly="true"
:placeholder="placeholder"
>
<template #suffix>
<el-icon
:style="{
transform: popoverVisible ? 'rotate(180deg)' : 'rotate(0)',
transition: 'transform .5s',
}"
>
<ArrowDown />
</el-icon>
</template>
</el-input>
</slot>
</div>
</template>
<!-- 弹出框内容 -->
<div ref="popoverContentRef">
@@ -89,8 +107,9 @@
v-loading="loading"
:data="pageData"
:border="true"
:max-height="315"
:max-height="250"
:row-key="pk"
:highlight-current-row="true"
:class="{ radio: !isMultiple }"
@select="handleSelect"
@select-all="handleSelectAll"
@@ -135,12 +154,18 @@
</template>
<script lang="ts" setup>
import type { TableInstance, FormInstance, PopoverProps } from "element-plus";
import { ref, reactive, computed } from "vue";
import { onClickOutside, useResizeObserver } from "@vueuse/core";
import type { FormInstance, PopoverProps, TableInstance } from "element-plus";
// 对象类型
export type IObject = Record<string, any>;
// 定义接收的属性
export interface ISelectConfig<T = any> {
// 宽度
width?: string;
// 占位符
placeholder?: string;
// popover组件属性
popover?: Partial<Omit<PopoverProps, "visible" | "v-model:visible">>;
// 列表的网络请求函数(需返回promise)
@@ -173,9 +198,15 @@ export interface ISelectConfig<T = any> {
[key: string]: any;
}>;
}
const props = defineProps<{
selectConfig: ISelectConfig;
}>();
const props = withDefaults(
defineProps<{
selectConfig: ISelectConfig;
text?: string;
}>(),
{
text: "",
}
);
// 自定义事件
const emit = defineEmits<{
@@ -186,6 +217,10 @@ const emit = defineEmits<{
const pk = props.selectConfig.pk ?? "id";
// 是否多选
const isMultiple = props.selectConfig.multiple === true;
// 宽度
const width = props.selectConfig.width ?? "100%";
// 占位符
const placeholder = props.selectConfig.placeholder ?? "请选择";
// 是否显示弹出框
const popoverVisible = ref(false);
// 加载状态
@@ -206,6 +241,13 @@ const queryParams = reactive<{
pageSize: pageSize,
});
// 计算popover的宽度
const tableSelectRef = ref();
const popoverWidth = ref(width);
useResizeObserver(tableSelectRef, (entries) => {
popoverWidth.value = `${entries[0].contentRect.width}px`;
});
// 表单操作
const formRef = ref<FormInstance>();
// 初始化搜索条件
@@ -265,6 +307,7 @@ function handleSelect(selection: any[], row: any) {
selectedItems.value = [selection[selection.length - 1]];
tableRef.value?.clearSelection();
tableRef.value?.toggleRowSelection(selectedItems.value[0], true);
tableRef.value?.setCurrentRow(selectedItems.value[0]);
}
}
function handleSelectAll(selection: any[]) {
@@ -304,7 +347,6 @@ function handleClear() {
function handleClose() {
popoverVisible.value = false;
}
const tableSelectRef = ref();
const popoverContentRef = ref();
/* onClickOutside(tableSelectRef, () => (popoverVisible.value = false), {
ignore: [popoverContentRef],
@@ -312,6 +354,11 @@ const popoverContentRef = ref();
</script>
<style scoped lang="scss">
.reference :deep(.el-input__wrapper),
.reference :deep(.el-input__inner) {
cursor: pointer;
}
.feedback {
display: flex;
justify-content: flex-end;

View File

@@ -0,0 +1,112 @@
import UserAPI from "@/api/user";
import type { ISelectConfig } from "@/components/TableSelect/index.vue";
const selectConfig: ISelectConfig = {
pk: "id",
width: "70%",
placeholder: "请选择用户",
formItems: [
{
type: "input",
label: "关键字",
prop: "keywords",
attrs: {
placeholder: "用户名/昵称/手机号",
clearable: true,
style: {
width: "200px",
},
},
},
{
type: "tree-select",
label: "部门",
prop: "deptId",
attrs: {
placeholder: "请选择",
data: [
{
value: 1,
label: "有来技术",
children: [
{
value: 2,
label: "研发部门",
},
{
value: 3,
label: "测试部门",
},
],
},
],
filterable: true,
"check-strictly": true,
"render-after-expand": false,
clearable: true,
style: {
width: "150px",
},
},
},
{
type: "select",
label: "状态",
prop: "status",
attrs: {
placeholder: "全部",
clearable: true,
style: {
width: "100px",
},
},
options: [
{ label: "启用", value: 1 },
{ label: "禁用", value: 0 },
],
},
{
type: "date-picker",
label: "创建时间",
prop: "createAt",
attrs: {
type: "daterange",
"range-separator": "~",
"start-placeholder": "开始时间",
"end-placeholder": "截止时间",
"value-format": "YYYY-MM-DD",
style: {
width: "240px",
},
},
},
],
indexAction: function (params) {
if ("createAt" in params) {
const createAt = params.createAt as string[];
params.startTime = createAt[0];
params.endTime = createAt[1];
delete params.createAt;
}
return UserAPI.getPage(params);
},
tableColumns: [
{ type: "selection", width: 50, align: "center" },
{ label: "编号", align: "center", prop: "id", width: 100 },
{ label: "用户名", align: "center", prop: "username" },
{ label: "用户昵称", align: "center", prop: "nickname", width: 120 },
{ label: "性别", align: "center", prop: "genderLabel", width: 100 },
{ label: "部门", align: "center", prop: "deptName", width: 120 },
{ label: "手机号码", align: "center", prop: "mobile", width: 120 },
{
label: "状态",
align: "center",
prop: "status",
templet: "custom",
slotName: "status",
},
{ label: "创建时间", align: "center", prop: "createTime", width: 180 },
],
};
export default selectConfig;

View File

@@ -0,0 +1,51 @@
<!-- 列表选择器示例 -->
<script setup lang="ts">
import selectConfig from "./config/select";
interface IUser {
id: number;
username: string;
nickname: string;
mobile: string;
genderLabel: string;
avatar: string;
email: string | null;
status: number;
deptName: string;
roleNames: string;
createTime: string;
}
const selectedUser = ref<IUser>();
function handleConfirm(data: IUser[]) {
selectedUser.value = data[0];
}
const text = computed(() => {
return selectedUser.value
? `${selectedUser.value.username} - ${selectedUser.value.genderLabel} - ${selectedUser.value.deptName}`
: "";
});
</script>
<template>
<div class="app-container">
<el-link
href="https://gitee.com/youlaiorg/vue3-element-admin/blob/master/src/views/demo/table-select/index.vue"
type="primary"
target="_blank"
class="mb-10"
>
示例源码 请点击>>>>
</el-link>
<table-select
:text="text"
:select-config="selectConfig"
@confirm-click="handleConfirm"
>
<template #status="scope">
<el-tag :type="scope.row[scope.prop] == 1 ? 'success' : 'info'">
{{ scope.row[scope.prop] == 1 ? "启用" : "禁用" }}
</el-tag>
</template>
</table-select>
</div>
</template>