替换组件

This commit is contained in:
2023-01-11 14:23:09 +08:00
parent 9e9d6dde22
commit 703813eafd
40 changed files with 195 additions and 890 deletions

View File

@@ -1,71 +0,0 @@
<template>
<div class="baseDialog">
<el-dialog
v-el-drag-dialog
:visible.sync="dialogShow"
v-bind="$attrs"
v-on="$listeners"
:close-on-click-modal="false"
>
<slot />
<template #footer>
<!--对外继续暴露footer插槽有个别弹框按钮需要自定义-->
<slot name="footer">
<!--将取消与确定按钮集成到内部-->
<el-row slot="footer" type="flex" justify="end">
<el-col :span="6">
<el-button size="small" @click="$_handleCancel">取消</el-button>
<el-button type="primary" size="small" @click="$_handleConfirm">
确定
</el-button>
</el-col>
</el-row>
</slot>
</template>
</el-dialog>
</div>
</template>
<script>
import elDragDialog from '@/directive/el-drag-dialog'
export default {
inheritAttrs: false,
name: 'BaseDialog',
directives: { elDragDialog },
props: {
dialogVisible: {
type: Boolean,
default: false
}
},
computed: {
dialogShow: {
get() {
return this.dialogVisible
},
set(val) {
this.$emit('update:dialogVisible', val)
}
}
},
methods: {
$_handleConfirm() {
this.$emit('confirm')
},
$_handleCancel() {
this.$emit('cancel')
}
}
}
</script>
<style lang="scss">
.baseDialog {
.el-dialog__title {
font-size: 16px;
font-weight: 500;
}
.el-dialog__header {
padding: 12px 20px;
border-bottom: 1px solid #e9e9e9;
}
}
</style>

View File

@@ -1,243 +0,0 @@
<template>
<div class="baseTable">
<el-table
border
:ref="id"
:data="renderData"
v-bind="$attrs"
@current-change="currentChange"
@selection-change="handleSelectionChange"
style="width: 100%"
:header-cell-style="{
background: '#F2F4F9',
color: '#606266'
}"
>
<!-- 多选 -->
<el-table-column
v-if="selectWidth"
type="selection"
:width="selectWidth"
/>
<!-- 序号 -->
<el-table-column
v-if="page && limit"
prop="_pageIndex"
:width="pageWidth"
align="center"
fixed
>
<template slot="header">
<el-popover placement="bottom-start" width="300" trigger="click">
<div
class="setting-box"
style="max-height: 400px; overflow-y: auto"
>
<el-checkbox
v-for="(item, index) in tableProps"
:key="'cb' + index"
v-model="selectedBox[index]"
:label="item.label"
/>
</div>
<i slot="reference" class="el-icon-s-tools" />
</el-popover>
</template>
</el-table-column>
<el-table-column
v-for="item in renderTableHeadList"
:key="item.prop"
v-bind="item"
:label="item.label"
:prop="item.prop"
:fixed="item.fixed || false"
:showOverflowTooltip="true"
:sortable="item.sortable || false"
>
<template slot="header">
<span>{{ item.label }}</span>
</template>
<!-- 多表头 -->
<template v-if="item.children">
<el-table-column
v-for="sub in item.children"
:prop="sub.prop"
:key="sub.prop"
v-bind="sub"
:label="sub.label"
>
<template slot-scope="scopeInner">
<component
:is="sub.subcomponent"
v-if="sub.subcomponent"
:key="scopeInner.row.id"
:inject-data="{ ...scopeInner.row, ...sub }"
@emitData="emitData"
/>
<span v-else>{{
scopeInner.row[sub.prop] | commonFilter(sub.filter)
}}</span>
</template>
</el-table-column>
</template>
<template slot-scope="scope">
<component
:is="item.subcomponent"
v-if="item.subcomponent"
:key="scope.row.id"
:itemProp="item.prop"
:inject-data="{ ...scope.row, ...item }"
@emitData="emitData"
/>
<span v-else>{{
scope.row[item.prop] | commonFilter(item.filter)
}}</span>
</template>
</el-table-column>
<slot name="handleBtn" />
</el-table>
<el-button
v-if="addButtonShow"
class="addButton"
icon="el-icon-plus"
@click="emitButtonClick"
>{{ addButtonShow }}</el-button
>
</div>
</template>
<script>
export default {
name: 'BaseTable',
filters: {
commonFilter: (source, filterType = (a) => a) => {
return filterType(source)
}
},
props: {
tableData: {
type: Array,
required: true,
default: () => {
return []
}
},
tableProps: {
type: Array,
default: () => {
return []
}
},
id: {
type: String,
required: false,
default: ''
},
page: {
type: Number,
required: false,
default: 0
},
pageWidth: {
type: Number,
required: false,
default: 70
},
limit: {
type: Number,
required: false,
default: 0
},
selectWidth: {
type: Number,
required: false,
default: 0
},
addButtonShow: {
type: String,
required: false,
default: ''
}
},
data() {
return {
selectedBox: new Array(100).fill(true)
}
},
computed: {
renderTableHeadList() {
return this.tableProps.filter((item, index) => {
return this.selectedBox[index]
})
},
renderData() {
return this.tableData.map((item, index) => {
return {
...item,
_pageIndex: (this.page - 1) * this.limit + index + 1
}
})
}
},
beforeMount() {
this.selectedBox = new Array(100).fill(true)
},
methods: {
currentChange(newVal, oldVal) {
this.$emit('current-change', { newVal, oldVal })
},
emitData(val) {
this.$emit('emitFun', val)
},
emitButtonClick() {
this.$emit('emitButtonClick')
},
handleSelectionChange(val) {
this.$emit('selection-change', val)
},
setCurrent(name, index) {
let _this = this
let obj = _this.$refs[name].data[index]
_this.$refs[name].setCurrentRow(obj)
}
}
}
</script>
<style lang="scss" scoped>
.baseTable {
.show-col-btn {
margin-right: 5px;
line-height: inherit;
cursor: pointer;
}
.el-icon-refresh {
cursor: pointer;
}
}
</style>
<style lang="scss">
.el-table .el-table__cell {
padding: 0;
height: 35px;
}
.baseTable {
.addButton {
width: 100%;
height: 35px;
border-top: none;
color: #0b58ff;
border-color: #ebeef5;
border-radius: 0;
}
.addButton:hover {
color: #0b58ff;
border-color: #ebeef5;
background-color: #fff;
}
.addButton:focus {
border-color: #ebeef5;
background-color: #fff;
}
}
</style>

View File

@@ -1,37 +0,0 @@
<template>
<div class="tableInner">
<el-input v-model="list[itemProp]" @blur="changeInput" />
</div>
</template>
<script>
export default {
name: 'inputArea',
props: {
injectData: {
type: Object,
default: () => ({})
},
itemProp: {
type: String
}
},
data() {
return {
list: this.injectData
}
},
methods: {
changeInput() {
console.log(this.list)
this.$emit('emitData', this.list)
}
}
}
</script>
<style lang="css">
.tableInner .el-input__inner {
border: none;
padding: 0;
height: 33px;
}
</style>

View File

@@ -1,147 +0,0 @@
<template>
<el-table-column
v-if="methodList.length > 0"
slot="handleBtn"
prop="operation"
v-bind="$attrs"
>
<template slot-scope="scope">
<span v-for="(item, index) in methodList" :key="'btn' + index">
<span
v-show="index === 0 ? false : true"
style="margin: 0 4px; font-size: 18px; color: #e5e7eb"
>|</span
>
<el-button
:disabled="
item.showParam ? !showFilter(item.showParam, scope.row) : false
"
type="text"
style="margin: 5px 0; padding: 0"
@click="
clickButton({
data: scope.row,
type: item.type
})
"
>
<i
v-if="
item.type === 'delete' ||
item.type === 'edit' ||
item.type === 'detail'
"
:class="
item.type === 'delete'
? 'el-icon-delete' +
(item.showParam
? !showFilter(item.showParam, scope.row)
? ''
: ' delete-color'
: ' delete-color')
: item.type === 'edit'
? 'el-icon-edit-outline'
: item.type === 'detail'
? 'el-icon-view'
: ''
"
style="font-size: 16px"
></i>
<span v-else>{{ item.btnName }}</span>
</el-button>
</span>
</template>
</el-table-column>
</template>
<script>
/**
* 传入的组件prop格式
* methodList<MethodItem> = []
* Interface MethodItem = {
* btnName: string,
* type: string
* }
*
*/
export default {
props: {
methodList: {
type: Array,
default: () => {
return []
}
}
},
methods: {
clickButton(raw) {
this.$emit('clickBtn', {
data: raw.data,
type: raw.type
})
},
showFilter(showParam, row) {
let showStatus = true
const showStatusArr = showParam.data.map((item) => {
let showStatusItem = true
if (item.type === 'unequal') {
if (row[item.name] !== item.value) {
showStatusItem = true
} else {
showStatusItem = false
}
}
if (item.type === 'equal') {
if (row[item.name] === item.value) {
showStatusItem = true
} else {
showStatusItem = false
}
}
if (item.type === 'more') {
if (row[item.name] >= item.value) {
showStatusItem = true
} else {
showStatusItem = false
}
}
if (item.type === 'less') {
if (row[item.name] <= item.value) {
showStatusItem = true
} else {
showStatusItem = false
}
}
if (item.type === 'indexof') {
if (item.value.indexOf(row[item.name]) >= 0) {
showStatusItem = true
} else {
showStatusItem = false
}
}
if (item.type === 'unindexof') {
if (item.value.indexOf(row[item.name]) < 0) {
showStatusItem = true
} else {
showStatusItem = false
}
}
return showStatusItem
})
if (showStatusArr.indexOf(false) >= 0 && showParam.type === '&') {
showStatus = false
}
if (showStatusArr.indexOf(true) < 0 && showParam.type === '|') {
showStatus = false
}
return showStatus
}
}
}
</script>
<style>
.delete-color {
color: #ff5454;
}
</style>

View File

@@ -1,102 +0,0 @@
<template>
<div v-show="total > 0" class="pagination-container">
<el-pagination
small
:current-page.sync="currentPage"
:page-size.sync="pageSize"
:layout="layout"
:page-sizes="pageSizes"
:total="total"
v-bind="$attrs"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>
</template>
<script>
export default {
name: 'PaginationPage',
props: {
total: {
required: true,
type: Number
},
page: {
type: Number,
default: 1
},
limit: {
type: Number,
default: 20
},
pageSizes: {
type: Array,
default() {
return [10, 20, 30, 50]
}
},
layout: {
type: String,
default: 'total, sizes, prev, pager, next, jumper'
}
},
computed: {
currentPage: {
get() {
return this.page
},
set(val) {
this.$emit('update:page', val)
}
},
pageSize: {
get() {
return this.limit
},
set(val) {
this.$emit('update:limit', val)
}
}
},
methods: {
handleSizeChange(val) {
this.$emit('pagination', { page: this.currentPage, limit: val })
},
handleCurrentChange(val) {
this.$emit('pagination', { page: val, limit: this.pageSize })
}
}
}
</script>
<style scoped>
.pagination-container {
background: #fff;
padding-top: 20px;
text-align: right;
}
</style>
<style>
.el-pagination {
position: relative;
}
.el-pagination__jump {
margin-left: 125px;
}
.el-pagination__sizes {
position: absolute;
right: 100px;
}
.el-pager li.active {
background-color: #0b58ff;
color: #fff;
}
.el-input--mini .el-input__inner {
height: 22px;
}
</style>

View File

@@ -1,235 +0,0 @@
<template>
<el-form
:inline="true"
ref="searchBarForm"
:model="formInline"
class="searchBar"
>
<template v-for="item in formConfig">
<el-form-item
v-if="item.type !== ''"
:key="item.param"
:label="item.label ? item.label : ''"
:required="item.required ? item.required : false"
:style="{ float: item.float ? item.float : 'left' }"
>
<el-input
v-if="item.type === 'input'"
v-model="formInline[item.param]"
:size="item.size ? item.size : 'small'"
clearable
:disabled="item.disabled ? item.disabled : false"
:style="item.width ? 'width:' + item.width + 'px' : 'width:200px'"
:placeholder="item.placeholder ? item.placeholder : ''"
/>
<el-select
v-if="item.type === 'select'"
v-model="formInline[item.param]"
:size="item.size ? item.size : 'small'"
:filterable="item.filterable ? item.filterable : false"
:multiple="item.multiple ? item.multiple : false"
:clearable="item.clearable === false ? false : true"
:style="item.width ? 'width:' + item.width + 'px' : 'width:200px'"
:placeholder="item.label"
@change="
item.onchange
? $emit('select-changed', {
param: item.param,
value: formInline[item.param]
})
: null
"
>
<el-option
v-for="(sub, i) in item.selectOptions"
:key="i"
:label="item.labelField ? sub[item.labelField] : sub['name']"
:value="item.valueField ? sub[item.valueField] : sub['id']"
/>
</el-select>
<el-date-picker
v-if="item.type === 'datePicker'"
:key="item.param"
:size="item.size ? item.size : 'small'"
v-model="formInline[item.param]"
:type="item.dateType"
:format="item.format ? item.format : 'yyyy-MM-dd'"
:value-format="item.valueFormat ? item.valueFormat : null"
:default-time="item.defaultTime || null"
:range-separator="item.rangeSeparator || null"
:start-placeholder="item.startPlaceholder || null"
:end-placeholder="item.endPlaceholder || null"
:placeholder="item.placeholder"
:picker-options="item.pickerOptions ? item.pickerOptions : null"
:style="item.width ? 'width:' + item.width + 'px' : 'width:250px'"
/>
<el-autocomplete
v-if="item.type === 'autocomplete'"
v-model="formInline[item.param]"
:value-key="item.valueKey ? item.valueKey : 'value'"
:fetch-suggestions="item.querySearch"
:placeholder="item.placeholder"
:clearable="item.clearable === false ? false : true"
:style="item.width ? 'width:' + item.width + 'px' : 'width:200px'"
filterable
/>
<el-cascader
v-if="item.type === 'cascader'"
v-model="formInline[item.param]"
:options="item.selectOptions"
:props="item.cascaderProps"
:clearable="item.clearable === false ? false : true"
:show-all-levels="item.showAllLevels === false ? false : true"
:collapse-tags="item.collapseTags === true ? true : false"
:style="item.width ? 'width:' + item.width + 'px' : 'width:200px'"
@change="
item.onChange
? $emit('cascader-change', {
param: item.param,
value: formInline[item.param]
})
: null
"
></el-cascader>
<el-button
v-if="item.type === 'button'"
:type="item.color"
:size="item.size ? item.size : 'small'"
:plain="item.plain ? item.plain : false"
:round="item.round ? item.round : false"
@click="headBtnClick(item.name)"
>{{ item.btnName }}</el-button
>
<!-- 可用于显示其他按钮 -->
</el-form-item>
</template>
<el-form-item>
<slot></slot>
</el-form-item>
</el-form>
</template>
<script>
export default {
name: 'SearchBar',
props: {
formConfigs: {
type: Array,
default: () => {
return []
}
}
},
data() {
const formInline = {}
const formConfig = this.formConfigs
let hasExtraOptions = false
for (const obj of formConfig) {
if (obj.type !== 'button') {
if (obj.defaultSelect === false || obj.defaultSelect === 0) {
formInline[obj.param] = obj.defaultSelect
} else {
formInline[obj.param] = obj.defaultSelect || '' // defaultSelect下拉框默认选中项
}
}
if (obj.extraOptions) {
hasExtraOptions = true
}
}
return {
formInline,
formConfig,
hasExtraOptions
}
},
watch: {
formConfig: {
handler() {
for (const obj of this.formConfig) {
if (obj.defaultSelect) {
this.formInline[obj.param] = obj.defaultSelect
} else if (obj.defaultSelect === null) {
// 需要手动从外部清除选项缓存的情况确保在外部配置项中可直接设置null
this.formInline[obj.param] = ''
}
}
},
deep: true,
immediate: true
},
formInline: {
handler: function () {
this.$forceUpdate()
},
deep: true,
immediate: true
}
},
mounted() {
this.$nextTick(() => {
this.init()
})
},
methods: {
init() {
if (this.hasExtraOptions) {
// 如果有额外参数就处理,如果没有就算了
for (const obj of this.formConfig) {
if (obj.extraOptions) {
// 注: 对obj.extraOptions的选择是互斥的!
this.$watch(
`formInline.${obj.param}`,
function (newVal) {
let deleteCount = 0
if (obj.index + 1 < this.formConfig.length) {
// 如果obj不是最后一个配置
const nextConfig = this.formConfig[obj.index + 1]
if (nextConfig.parent && nextConfig.parent === obj.param)
deleteCount = 1
}
const currentConfig = Object.assign(
{},
obj.extraOptions[newVal]
)
this.formConfig.splice(
obj.index + 1,
deleteCount,
currentConfig
)
// 修改 formInline
this.$set(this.formInline, currentConfig.param, '')
},
{ immediate: true }
)
}
}
}
},
headBtnClick(btnName) {
this.formInline.btnName = btnName
this.$emit('headBtnClick', this.formInline)
},
resetForm() {
this.$refs.searchBarForm.resetFields()
const formInline = {}
const formConfig = this.formConfigs
for (const obj of formConfig) {
if (obj.type !== 'button') {
if (obj.defaultSelect === false || obj.defaultSelect === 0) {
formInline[obj.param] = obj.defaultSelect
} else {
formInline[obj.param] = obj.defaultSelect || '' // defaultSelect下拉框默认选中项
}
}
}
this.formInline = formInline
}
}
}
</script>
<style lang="scss">
.searchBar {
.el-form-item {
margin-bottom: 10px;
}
}
</style>