Merge pull request #85 from cshaptx4869/patch-47
重构列表选择组件默认样式、增加列表选择组件使用示例
This commit is contained in:
@@ -1,16 +1,34 @@
|
|||||||
<template>
|
<template>
|
||||||
<div ref="tableSelectRef">
|
<div ref="tableSelectRef" :style="'width:' + width">
|
||||||
<el-popover
|
<el-popover
|
||||||
:visible="popoverVisible"
|
:visible="popoverVisible"
|
||||||
width="75%"
|
:width="popoverWidth"
|
||||||
placement="bottom-end"
|
placement="bottom-end"
|
||||||
v-bind="selectConfig.popover"
|
v-bind="selectConfig.popover"
|
||||||
@show="handleShow"
|
@show="handleShow"
|
||||||
>
|
>
|
||||||
<template #reference>
|
<template #reference>
|
||||||
<el-button @click="popoverVisible = !popoverVisible">
|
<div @click="popoverVisible = !popoverVisible">
|
||||||
<slot>选择列表</slot>
|
<slot>
|
||||||
</el-button>
|
<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>
|
</template>
|
||||||
<!-- 弹出框内容 -->
|
<!-- 弹出框内容 -->
|
||||||
<div ref="popoverContentRef">
|
<div ref="popoverContentRef">
|
||||||
@@ -89,8 +107,9 @@
|
|||||||
v-loading="loading"
|
v-loading="loading"
|
||||||
:data="pageData"
|
:data="pageData"
|
||||||
:border="true"
|
:border="true"
|
||||||
:max-height="315"
|
:max-height="250"
|
||||||
:row-key="pk"
|
:row-key="pk"
|
||||||
|
:highlight-current-row="true"
|
||||||
:class="{ radio: !isMultiple }"
|
:class="{ radio: !isMultiple }"
|
||||||
@select="handleSelect"
|
@select="handleSelect"
|
||||||
@select-all="handleSelectAll"
|
@select-all="handleSelectAll"
|
||||||
@@ -135,12 +154,18 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<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 type IObject = Record<string, any>;
|
||||||
// 定义接收的属性
|
// 定义接收的属性
|
||||||
export interface ISelectConfig<T = any> {
|
export interface ISelectConfig<T = any> {
|
||||||
|
// 宽度
|
||||||
|
width?: string;
|
||||||
|
// 占位符
|
||||||
|
placeholder?: string;
|
||||||
// popover组件属性
|
// popover组件属性
|
||||||
popover?: Partial<Omit<PopoverProps, "visible" | "v-model:visible">>;
|
popover?: Partial<Omit<PopoverProps, "visible" | "v-model:visible">>;
|
||||||
// 列表的网络请求函数(需返回promise)
|
// 列表的网络请求函数(需返回promise)
|
||||||
@@ -173,9 +198,15 @@ export interface ISelectConfig<T = any> {
|
|||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
}>;
|
}>;
|
||||||
}
|
}
|
||||||
const props = defineProps<{
|
const props = withDefaults(
|
||||||
selectConfig: ISelectConfig;
|
defineProps<{
|
||||||
}>();
|
selectConfig: ISelectConfig;
|
||||||
|
text?: string;
|
||||||
|
}>(),
|
||||||
|
{
|
||||||
|
text: "",
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
// 自定义事件
|
// 自定义事件
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
@@ -186,6 +217,10 @@ const emit = defineEmits<{
|
|||||||
const pk = props.selectConfig.pk ?? "id";
|
const pk = props.selectConfig.pk ?? "id";
|
||||||
// 是否多选
|
// 是否多选
|
||||||
const isMultiple = props.selectConfig.multiple === true;
|
const isMultiple = props.selectConfig.multiple === true;
|
||||||
|
// 宽度
|
||||||
|
const width = props.selectConfig.width ?? "100%";
|
||||||
|
// 占位符
|
||||||
|
const placeholder = props.selectConfig.placeholder ?? "请选择";
|
||||||
// 是否显示弹出框
|
// 是否显示弹出框
|
||||||
const popoverVisible = ref(false);
|
const popoverVisible = ref(false);
|
||||||
// 加载状态
|
// 加载状态
|
||||||
@@ -206,6 +241,13 @@ const queryParams = reactive<{
|
|||||||
pageSize: pageSize,
|
pageSize: pageSize,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 计算popover的宽度
|
||||||
|
const tableSelectRef = ref();
|
||||||
|
const popoverWidth = ref(width);
|
||||||
|
useResizeObserver(tableSelectRef, (entries) => {
|
||||||
|
popoverWidth.value = `${entries[0].contentRect.width}px`;
|
||||||
|
});
|
||||||
|
|
||||||
// 表单操作
|
// 表单操作
|
||||||
const formRef = ref<FormInstance>();
|
const formRef = ref<FormInstance>();
|
||||||
// 初始化搜索条件
|
// 初始化搜索条件
|
||||||
@@ -265,6 +307,7 @@ function handleSelect(selection: any[], row: any) {
|
|||||||
selectedItems.value = [selection[selection.length - 1]];
|
selectedItems.value = [selection[selection.length - 1]];
|
||||||
tableRef.value?.clearSelection();
|
tableRef.value?.clearSelection();
|
||||||
tableRef.value?.toggleRowSelection(selectedItems.value[0], true);
|
tableRef.value?.toggleRowSelection(selectedItems.value[0], true);
|
||||||
|
tableRef.value?.setCurrentRow(selectedItems.value[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function handleSelectAll(selection: any[]) {
|
function handleSelectAll(selection: any[]) {
|
||||||
@@ -304,7 +347,6 @@ function handleClear() {
|
|||||||
function handleClose() {
|
function handleClose() {
|
||||||
popoverVisible.value = false;
|
popoverVisible.value = false;
|
||||||
}
|
}
|
||||||
const tableSelectRef = ref();
|
|
||||||
const popoverContentRef = ref();
|
const popoverContentRef = ref();
|
||||||
/* onClickOutside(tableSelectRef, () => (popoverVisible.value = false), {
|
/* onClickOutside(tableSelectRef, () => (popoverVisible.value = false), {
|
||||||
ignore: [popoverContentRef],
|
ignore: [popoverContentRef],
|
||||||
@@ -312,6 +354,11 @@ const popoverContentRef = ref();
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
.reference :deep(.el-input__wrapper),
|
||||||
|
.reference :deep(.el-input__inner) {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
.feedback {
|
.feedback {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
|
|||||||
112
src/views/demo/table-select/config/select.ts
Normal file
112
src/views/demo/table-select/config/select.ts
Normal 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;
|
||||||
51
src/views/demo/table-select/index.vue
Normal file
51
src/views/demo/table-select/index.vue
Normal 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>
|
||||||
Reference in New Issue
Block a user