组件库:使用element-plus组件进行二次封装
组件名称说明:
search-form:搜索表单
form-item:单个输入组件
components:单个不同得组件的集合
search-table:搜索表单加表格
form-item 使用动态组件进行动态展示
form-item.vue
<template>
<div class="form-item">
<el-form-item :label="label">
<component
:is="components[type] || components.INPUT"
:params="params"
:value="value"
@get-value="getValue"
></component>
</el-form-item>
</div>
</template>
<script setup >
import { useRoute, useRouter } from 'vue-router'
import { toRefs, defineProps, defineEmits, onMounted } from 'vue'
import components from './components/index.js' // 将所有组件引入
const props = defineProps({
label: String,
value: String | Number,
type: String,
params: Object,
prop: String
})
const emit = defineEmits(['getValue'])
const { label, value, type, params, prop } = toRefs(props)
const getValue = (value) => {
emit('getValue', value, prop.value)
}
</script>
<style lang="scss" scoped>
:deep(.el-form-item__label){
color: rgba(255, 255, 255, 1);
font-size: 16px;
}
</style>
-
componets (来使用动态组件)
index.js
import sfInput from './sf-input.vue'
import sfSelect from './sf-select.vue'
export default {
INPUT: sfInput,
SELECT: sfSelect
}
sf-input.vue
<template>
<el-input :model-value="value" clearable @input="handleChange" />
</template>
<script setup>
import { ref, toRefs, defineProps, defineEmits } from 'vue'
const emit = defineEmits(['getValue'])
const props = defineProps({
params: Object,
value: String | Number,
prop: String
})
const { params, value } = toRefs(props)
const handleChange = (value) => {
emit('getValue', value)
}
</script>
<style scoped lang="scss">
:deep(.el-input__wrapper){
box-shadow: none;
background-color: transparent;
border: 1px solid rgba(37, 134, 241, 1);
border-radius: 0;
font-size: 16px;
}
:deep(.el-input__inner){
color: #fff;
height: 28px;
font-size: 16px;
}
</style>
sf-select.vue
<template>
<div class="select">
<el-select
:model-value="value"
:placeholder="params.placeholder"
:filterable="params.filterable"
style="width: 170px;--el-text-color-regular:#fff"
clearable
@change="handleChange"
>
<el-option
v-for="item in params.options"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</div>
</template>
<script setup>
import { ref, defineProps, toRefs, defineEmits } from 'vue'
const emit = defineEmits(['getValue'])
const props = defineProps({
params: {
options: Object,
placeholder: String
},
value: String
}
)
const { params, value } = toRefs(props)
const handleChange = (value) => {
emit('getValue', value)
}
</script>
<style scoped lang="scss">
.select{
:deep(.el-select__wrapper){
box-shadow: none;
background-color: transparent;
border: 1px solid rgba(37, 134, 241, 1);
border-radius: 0;
font-size: 16px;
&:focus{
box-shadow: none;
}
}
:deep(.el-select__input){
width: 100% !important;
}
:deep(.el-select__placeholder){
color: rgba(255, 255, 255, 1);
}
:deep(.el-select__caret){
color: #2586f1;
}
}
</style>
search-form 根据参数进行动态展示
search-form/index.vue
<template>
<div class="search-form">
<el-form :inline="true" :model="form" class="form-inline">
<FormItem
v-for="item in props.formData"
:key="item.label"
:label="item.label"
:prop="item.prop"
:value="form[item.prop] || ''"
:type="item.type"
:params="item.params"
@get-value="handleGetValue"
></FormItem>
<el-form-item>
<el-button type="primary" @click="onSubmit">搜索</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script setup>
import FormItem from './form-item.vue'
import { reactive, defineProps, onMounted, defineEmits, defineExpose } from 'vue'
const props = defineProps({
formData: Object
})
const emit = defineEmits(['search-data'])
const form = reactive({})
onMounted(() => {
props.formData?.forEach((f) => {
if (f.prop) {
form[f.prop] = f.initValue
}
})
})
const handleGetValue = (value, prop) => {
form[prop] = value
}
const onSubmit = () => {
emit('search-data', form, true)
}
defineExpose({
form,
})
</script>
<style lang="scss" scoped>
:deep(.el-form){
display: flex;
flex-wrap: wrap;
}
:deep(.el-button){
font-size: 16px;
}
</style>
search-from 和table结合
search-table/index.vue
<template>
<div class="search-table">
<SearchForm ref="formRef" :form-data="props.formData" @search-data="searchData"></SearchForm>
<slot name="otherFilters" :filterData="filterData"></slot>
<div class="table">
<el-table
header-row-class-name="table-header"
height="794px"
style="--el-table-border-color:transparent;
--el-bg-color:transparent;
--el-table-row-hover-bg-color:none;
width: 1770px"
:data="tableData"
:row-class-name="getCellClass"
v-loading="loading"
element-loading-text="加载中..."
:element-loading-spinner="svg"
element-loading-svg-view-box="-10, -10, 50, 50"
>
<el-table-column
v-for="c in props.colunms"
:key="c.prop"
:prop="c.prop"
:label="c.label"
align="center"
:width="c.width"
>
<template v-if="c?.isSlot" #default="scope">
<slot :name="c.prop" :data="scope.row">
<div>{{ scope?.row?.[c.prop] }}</div>
</slot>
</template>
</el-table-column>
</el-table>
<div v-if="props.isPagination" class="pagination">
<el-pagination
v-model:current-page="currentPage"
style="--el-pagination-button-bg-color:transparent;
--el-pagination-button-color:#fff;
--el-disabled-bg-color:transparent;
--el-text-color-placeholder:rgba(37, 134, 241, 0.59);
--el-pagination-font-size:16px;
--el-pagination-button-width: 24px;
--el-pagination-button-height: 24px;"
background
layout="prev, pager, next"
:total="total"
:page-size="props.paginationParams.pageSize"
@current-change="handleCurrentChange"
/>
<div class="total">共{{ total }}条</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref, provide, onMounted, onUnmounted, defineProps, defineEmits } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import SearchForm from './search-form/index.vue'
import { queryData } from './search-form/js/query'
const props = defineProps({
formData: Object,
colunms: Object,
url: String,
isPagination: Boolean,
paginationParams: {
type: Object,
default: {
pageSize: 20
}
}
})
const formRef = ref(null)
const loading = ref(true)
const emit = defineEmits(['handle-data'])
const tableData = ref([])
const total = ref(0)
const isChange = ref(false)
const currentPage = ref(1)
let otherFormData ={}
const getCellClass = (data) => {
const { rowIndex } = data
if (rowIndex % 2 === 0) {
return 'towBg'
}
}
const searchData = async (formData, isSearch, current) => {
if (!props.url) return console.error('传入数据的请求路径')
loading.value = true
if (props.isPagination) {
// 设置分页
formData.page_size = props.paginationParams.pageSize
formData.page_index = isSearch ? 0 : (current - 1 || currentPage.value - 1)
isSearch && (currentPage.value = 1)
}
const res = await queryData(props.url, {...formData,...otherFormData})
if (res.resultCode === 0) {
total.value = res.data.count
emit('handle-data', res.data.list || [], getData)
if (!isChange.value) {
tableData.value = res.data.list || []
}
loading.value = false
}
}
const filterData = (ohterForm) => {
if (formRef.value) {
let formData = formRef.value.form
formData = { ...formData, ...ohterForm }
otherFormData = ohterForm
searchData(formData, true)
}
}
const getData = (data) => {
if (data) {
tableData.value = data
isChange.value = true
}
}
const handleCurrentChange = (val) => {
if (formRef.value) {
const formData = formRef.value.form
searchData(formData, false, val)
}
}
onMounted(() => {
const formData = {}
props.formData?.forEach((f) => {
if (f.prop) {
formData[f.prop] = f.initValue
}
})
searchData(formData)
})
</script>
<style lang="scss" scoped>
.table{
margin-top: 12px;
border: 1px solid rgba(37, 134, 241, 1);
padding: 0 20px;
:deep(.el-loading-mask){
background-color: transparent;
.el-loading-spinner .el-loading-text{
color: rgba(138, 234, 255, 1);
font-size: 16px;
}
.el-loading-spinner .path{
stroke:rgba(138, 234, 255, 1);
}
}
:deep(.el-table){
background-color: transparent;
font-size: 16px;
color: #fff;
}
:deep(.el-table thead){
color: rgba(138, 234, 255, 1);
font-size: 18px;
}
:deep(.table-header){
height:72px !important;
}
:deep(.towBg){
background-color: rgba(85, 81, 255, .2);
&:hover{
background-color: rgba(85, 81, 255, .2) !important;
}
}
:deep(.el-table tr){
height: 60px;
}
:deep(.el-table td.el-table__cell, .el-table th.el-table__cell.is-leaf){
border-bottom: none;
}
:deep(.el-table__empty-text){
color: #fff;
}
}
.pagination{
display: flex;
width: 100%;
justify-content: flex-end;
align-items: center;
padding: 8px;
.total{
color: #fff;
font-size: 16px;
line-height: 16px;
}
:deep(.el-pagination .btn-next .el-icon, .el-pagination .btn-prev .el-icon){
color: rgba(37, 134, 241, 0.59);
}
:deep( .el-pagination.is-background .el-pager li.is-activ){
background-color: rgba(37, 134, 241, 1)
}
}
</style>