262 lines
7.0 KiB
Vue
262 lines
7.0 KiB
Vue
<!--
|
|
* @Author: zhaojinfeng 121016171@qq.com
|
|
* @Date: 2023-08-14 11:07:15
|
|
* @LastEditors: zhaojinfeng 121016171@qq.com
|
|
* @LastEditTime: 2023-12-14 18:05:02
|
|
* @FilePath: \vue3\packages\select-transfer-modal\index.vue
|
|
* @Description:
|
|
*
|
|
-->
|
|
<template>
|
|
<span v-if="!hideButton" @click="openDialog">
|
|
<slot>
|
|
<el-button type="primary" plain>点击选择</el-button>
|
|
</slot>
|
|
</span>
|
|
<el-config-provider :locale="locale">
|
|
<el-dialog v-model="showDialog" class="select-transfer-modal" :title="title" :width="width" append-to-body
|
|
:z-index="zIndex" @open="getList" @closed="closed">
|
|
<div flex>
|
|
<slot name="left" />
|
|
<div grow>
|
|
<el-form ref="queryRef" :model="queryParams" inline>
|
|
<el-form-item v-for="formItem in formItems" :key="formItem.prop" :label="formItem.label"
|
|
:prop="formItem.prop">
|
|
<el-select v-if="formItem.selectOptions" :placeholder="formItem.placeholder">
|
|
<el-option v-for="option in formItem.selectOptions" :key="option.value" :value="option.value">
|
|
{{ option.label }}
|
|
</el-option>
|
|
</el-select>
|
|
<el-input v-else v-model="queryParams[formItem.prop]" :placeholder="formItem.placeholder" />
|
|
</el-form-item>
|
|
<el-form-item>
|
|
<el-button type="primary" :loading="loading" @click="handleQuery">
|
|
查询
|
|
</el-button>
|
|
<el-button :loading="loading" @click="resetQuery">
|
|
重置
|
|
</el-button>
|
|
</el-form-item>
|
|
</el-form>
|
|
<el-transfer v-model="transferValue" v-loading="loading" inline-block text-left
|
|
style="--el-transfer-panel-width:25vw" :titles="['待选项', '已选项']" :button-texts="['移除', '添加']" :format="{
|
|
noChecked: '${total}',
|
|
hasChecked: '${checked}/${total}',
|
|
}" :data="data" :filter-method="filterMethod" :props="props">
|
|
<template #default="{ option }">
|
|
<slot name="transfer" :option="option">
|
|
{{ option[props.label] }}
|
|
</slot>
|
|
</template>
|
|
<template #left-footer>
|
|
<el-pagination v-if="!hidePagination && total > queryParams.pageSize"
|
|
v-model:current-page="queryParams.pageNum" v-model:page-size="queryParams.pageSize" background small
|
|
layout="total, sizes, prev, next, jumper" mt-9px :page-sizes="pageSizes" :pager-count="pagerCount"
|
|
:total="total" @size-change="handleSizeChange" @current-change="getList" />
|
|
</template>
|
|
</el-transfer>
|
|
</div>
|
|
</div>
|
|
|
|
<template #footer>
|
|
<el-space>
|
|
<el-button type="primary" @click="confirm">
|
|
确定
|
|
</el-button>
|
|
<el-button @click="showDialog = false">
|
|
取消
|
|
</el-button>
|
|
</el-space>
|
|
</template>
|
|
</el-dialog>
|
|
</el-config-provider>
|
|
</template>
|
|
|
|
<script lang="ts" setup name="ThSelectTransferModal">
|
|
import type { FormInstance, TransferDataItem, TransferKey, TransferPropsAlias } from 'element-plus'
|
|
import locale from 'element-plus/es/locale/lang/zh-cn'
|
|
|
|
const properties = withDefaults(
|
|
defineProps<{
|
|
value?: any[]
|
|
show?: boolean
|
|
defaultParams?: Record<string, any>
|
|
formItems?: FormItem[]
|
|
request: (args: any) => Promise<Page>
|
|
pageSizes?: number[]
|
|
pagerCount?: number
|
|
/** 禁用按钮 */
|
|
disabledButton?: boolean
|
|
hideButton?: boolean
|
|
hidePagination?: boolean
|
|
title?: string
|
|
width?: string | number
|
|
zIndex?: number
|
|
props?: TransferPropsAlias
|
|
lockList?: TransferKey[]
|
|
formattter?: (row: Record<string, any>) => any
|
|
}>(),
|
|
{
|
|
props: () => ({ key: 'id', label: 'name', disabled: 'disabled' }),
|
|
show: false,
|
|
defaultParams: () => ({}),
|
|
pageSizes: () => [20, 50, 100, 200],
|
|
pagerCount: document.body.clientWidth < 992 ? 5 : 7,
|
|
hidePagination: false,
|
|
title: '选择',
|
|
width: '70%',
|
|
zIndex: 2023,
|
|
formattter: (row: Record<string, any>) => {
|
|
return { ...row }
|
|
},
|
|
},
|
|
)
|
|
const emit = defineEmits<{
|
|
(event: 'update:show', show: boolean): void
|
|
(event: 'update:value', value: any[]): void
|
|
(event: 'confirm', rows: Record<string, any>[], keys: TransferKey[]): void
|
|
}>()
|
|
|
|
const showDialog = ref(false)
|
|
|
|
let transferValue = $ref<TransferKey[]>([])
|
|
|
|
let temp = $ref({})
|
|
|
|
let currentKeyList = $ref<TransferKey[]>([])
|
|
|
|
function filterMethod(_query: string, item: TransferDataItem) {
|
|
const { key = 'id' } = properties.props
|
|
return currentKeyList.includes(item[key]) || transferValue.includes(item[key])
|
|
}
|
|
|
|
const queryParams = reactive({
|
|
pageNum: 1,
|
|
pageSize: properties.pageSizes[0] || 10,
|
|
})
|
|
|
|
const data = computed(() => {
|
|
const all: any[] = []
|
|
const { props: { disabled = 'disabled', key = 'id' }, lockList } = properties
|
|
for (const i in temp) {
|
|
all.push({
|
|
...temp[i],
|
|
[disabled]: lockList?.includes(temp[i][key]),
|
|
})
|
|
}
|
|
|
|
return all
|
|
})
|
|
|
|
let total = $ref(0)
|
|
let loading = $ref(false)
|
|
|
|
/* 表单绑定的ref */
|
|
const queryRef = $ref<FormInstance>(null)
|
|
|
|
function handleQuery() {
|
|
queryParams.pageNum = 1
|
|
return getList()
|
|
}
|
|
|
|
/** 查询表格数据 */
|
|
async function getList() {
|
|
loading = true
|
|
try {
|
|
const response = await properties.request({
|
|
...properties.defaultParams,
|
|
...queryParams,
|
|
})
|
|
const { key = 'id' } = properties.props
|
|
currentKeyList = response.rows.map((e) => {
|
|
temp[e[key]] = e
|
|
return e[key]
|
|
})
|
|
total = response.total
|
|
}
|
|
finally {
|
|
loading = false
|
|
}
|
|
}
|
|
function openDialog() {
|
|
if (properties.disabledButton)
|
|
return
|
|
|
|
if (properties.hideButton)
|
|
emit('update:show', true)
|
|
else
|
|
showDialog.value = true
|
|
}
|
|
|
|
function closeDialog() {
|
|
if (properties.hideButton)
|
|
emit('update:show', false)
|
|
else
|
|
showDialog.value = false
|
|
}
|
|
|
|
function confirm() {
|
|
const selections = transferValue.map(key => properties.formattter(temp[key]))
|
|
emit('update:value', selections)
|
|
emit('confirm', selections, [...transferValue])
|
|
closeDialog()
|
|
}
|
|
|
|
function closed() {
|
|
queryRef?.resetFields()
|
|
queryParams.pageNum = 1
|
|
currentKeyList = []
|
|
closeDialog()
|
|
}
|
|
|
|
/** 重置按钮操作 */
|
|
function resetQuery() {
|
|
queryRef?.resetFields()
|
|
handleQuery()
|
|
}
|
|
|
|
function handleSizeChange(val: number) {
|
|
if (queryParams.pageNum * val > total)
|
|
queryParams.pageNum = 1
|
|
}
|
|
|
|
function transferValueInit() {
|
|
const { value = [] } = properties
|
|
const { key = 'id' } = properties.props
|
|
const newTemp = {}
|
|
transferValue = value.map((e) => {
|
|
newTemp[e[key]] = e
|
|
return e[key]
|
|
})
|
|
temp = newTemp
|
|
}
|
|
|
|
transferValueInit()
|
|
|
|
watch(() => properties.defaultParams, () => {
|
|
if (showDialog.value)
|
|
handleQuery()
|
|
}, { deep: true })
|
|
watch(() => properties.value, transferValueInit)
|
|
watch(() => properties.show, (show) => {
|
|
showDialog.value = show
|
|
})
|
|
</script>
|
|
|
|
<style lang="scss">
|
|
.select-transfer-modal {
|
|
.el-checkbox:last-of-type {
|
|
margin-right: 30px;
|
|
}
|
|
|
|
.el-transfer {
|
|
width: 100%;
|
|
display: flex;
|
|
|
|
.el-transfer-panel {
|
|
flex: 1;
|
|
}
|
|
}
|
|
}
|
|
</style>
|