no message

This commit is contained in:
小陌 2024-03-17 21:50:27 +08:00
parent 4211f52de0
commit ecb9ea7749
3 changed files with 166 additions and 112 deletions

View File

@ -110,7 +110,7 @@
</template> </template>
<!-- xUserSelect --> <!-- xUserSelect -->
<template v-else-if="item.component == 'xuserselect'"> <template v-else-if="item.component == 'xuserselect'">
<x-user-select v-model="data[item.name]" :type="item.type"></x-user-select> <x-user-select v-model="data[item.name]" v-bind="bind"></x-user-select>
</template> </template>
<template v-else-if="item.component == 'formtable'"> <template v-else-if="item.component == 'formtable'">
<x-form-table ref="xformtable" v-model="data[item.name]" v-bind="bind"> </x-form-table> <x-form-table ref="xformtable" v-model="data[item.name]" v-bind="bind"> </x-form-table>

View File

@ -3,130 +3,169 @@
--> -->
<template> <template>
<div class="x-form-table" ref="xFormTable"> <div class="x-form-table" ref="xFormTable">
<el-table :data="data" ref="table" border stripe> <el-table :data="data" ref="table" border stripe>
<el-table-column type="index" width="50" fixed="left"> <el-table-column type="index" width="50" fixed="left">
<template #header> <template #header>
<el-button v-if="!hideAdd" type="primary" icon="el-icon-plus" size="small" circle @click="rowAdd"></el-button> <el-button v-if="!hideAdd" type="primary" icon="el-icon-plus" size="small" circle @click="rowAdd"></el-button>
</template> </template>
<template #default="scope"> <template #default="scope">
<div :class="['x-form-table-handle', {'x-form-table-handle-delete':!hideDelete}]"> <div :class="['x-form-table-handle', { 'x-form-table-handle-delete': !hideDelete }]">
<span>{{scope.$index + 1}}</span> <span>{{ scope.$index + 1 }}</span>
<el-button v-if="!hideDelete" type="danger" icon="el-icon-delete" size="small" plain circle @click="rowDel(scope.row, scope.$index)"></el-button> <el-button v-if="!hideDelete" type="danger" icon="el-icon-delete" size="small" plain circle @click="rowDel(scope.row, scope.$index)"></el-button>
</div> </div>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="" width="50" v-if="dragSort"> <el-table-column label="" width="50" v-if="dragSort">
<template #default> <template #default>
<div class="move" style="cursor: move;"><el-icon-d-caret style="width: 1em; height: 1em;"/></div> <div class="move" style="cursor: move;"><el-icon-d-caret style="width: 1em; height: 1em;" /></div>
</template> </template>
</el-table-column> </el-table-column>
<template v-for="(item, index) in column" :key="index"> <template v-for="(item, index) in column" :key="index">
<el-table-column v-if="!item.hide && item.name" :column-key="item.name" v-bind="item"> <el-table-column v-if="!item.hide && item.name" :column-key="item.name" v-bind="item">
<template #default="scope"> <template #default="scope">
<el-input v-if="item.type=='input'" v-bind="item.options" v-model="scope.row[item.name]"> </el-input> <el-input v-if="(item.type || item.component) == 'input'" v-bind="item.bind" v-model="scope.row[item.name]"> </el-input>
<el-link v-else-if="item.type=='link'" :href="scope.row[item.name]" v-bind="item.options"> <el-select v-else-if="(item.type || item.component) == 'select'" v-model="scope.row[item.name]" v-bind="item.bind" clearable filterable style="width: 100%;">
<el-option v-for="(option, index) in item.options" :key="index" v-bind="option"></el-option>
</el-select>
<el-switch v-else-if="(item.type || item.component) == 'switch'" v-model="scope.row[item.name]" v-bind="item.bind" />
<el-link v-else-if="(item.type || item.component) == 'link'" :href="scope.row[item.name]" v-bind="item.bind">
{{ item.options && item.options.label || scope.row[item.name] }} {{ item.options && item.options.label || scope.row[item.name] }}
</el-link> </el-link>
<p v-else> <p v-else>
{{scope.row[item.name]}} <span class="text">{{ scope.row[item.name] }}</span>
</p> </p>
</template> </template>
</el-table-column> </el-table-column>
</template> </template>
<slot></slot> <slot></slot>
<template #empty> <template #empty>
{{placeholder}} {{ placeholder }}
</template> </template>
</el-table> </el-table>
</div> </div>
</template> </template>
<script> <script>
import Sortable from 'sortablejs' import Sortable from 'sortablejs'
export default { export default {
props: { props: {
modelValue: { type: Array, default: () => [] }, modelValue: { type: Array, default: () => [] },
addTemplate: { type: Object, default: () => {} }, addTemplate: { type: Object, default: () => { } },
column: { type: Array, default: () => [] }, column: { type: Array, default: () => [] },
placeholder: { type: String, default: "暂无数据" }, placeholder: { type: String, default: "暂无数据" },
dragSort: { type: Boolean, default: false }, dragSort: { type: Boolean, default: false },
hideAdd: { type: Boolean, default: false }, hideAdd: { type: Boolean, default: false },
hideDelete: { type: Boolean, default: false } hideDelete: { type: Boolean, default: false }
}, },
data(){ data() {
return { return {
data: [], data: [],
} }
}, },
mounted(){ mounted() {
this.data = this.modelValue
if (this.dragSort) {
this.rowDrop()
}
},
watch: {
modelValue() {
this.data = this.modelValue this.data = this.modelValue
if(this.dragSort){
this.rowDrop()
}
}, },
watch:{ data: {
modelValue(){ handler() {
this.data = this.modelValue this.$emit('update:modelValue', this.data);
}, },
data: { deep: true
handler(){ }
this.$emit('update:modelValue', this.data); },
}, methods: {
deep: true rowDrop() {
} const _this = this
}, const tbody = this.$refs.table.$el.querySelector('.el-table__body-wrapper tbody')
methods: { Sortable.create(tbody, {
rowDrop(){ handle: ".move",
const _this = this animation: 300,
const tbody = this.$refs.table.$el.querySelector('.el-table__body-wrapper tbody') ghostClass: "ghost",
Sortable.create(tbody, { onEnd({ newIndex, oldIndex }) {
handle: ".move", _this.data.splice(newIndex, 0, _this.data.splice(oldIndex, 1)[0])
animation: 300, const newArray = _this.data.slice(0)
ghostClass: "ghost", const tmpHeight = _this.$refs.xFormTable.offsetHeight
onEnd({ newIndex, oldIndex }) { _this.$refs.xFormTable.style.setProperty('height', tmpHeight + 'px')
_this.data.splice(newIndex, 0, _this.data.splice(oldIndex, 1)[0]) _this.data = []
const newArray = _this.data.slice(0) _this.$nextTick(() => {
const tmpHeight = _this.$refs.xFormTable.offsetHeight _this.data = newArray
_this.$refs.xFormTable.style.setProperty('height', tmpHeight + 'px')
_this.data = []
_this.$nextTick(() => { _this.$nextTick(() => {
_this.data = newArray _this.$refs.xFormTable.style.removeProperty('height')
_this.$nextTick(() => {
_this.$refs.xFormTable.style.removeProperty('height')
})
}) })
}
}) })
}, }
rowAdd(){ })
const temp = JSON.parse(JSON.stringify(this.addTemplate || {})) },
this.data.push(temp) rowAdd() {
}, const temp = JSON.parse(JSON.stringify(this.addTemplate || {}))
rowDel(row, index){ this.data.push(temp)
this.data.splice(index, 1) },
}, rowDel(row, index) {
// this.$emit('update:modelValue', this.data);
pushRow(row){ //
const temp = row || JSON.parse(JSON.stringify(this.addTemplate || {})) this.$emit('delete', index, row)
this.data.push(temp) this.data.splice(index, 1)
}, },
//index //
deleteRow(index){ pushRow(row) {
this.data.splice(index, 1) const temp = row || JSON.parse(JSON.stringify(this.addTemplate || {}))
} this.data.push(temp)
},
//index
deleteRow(index) {
this.data.splice(index, 1)
} }
} }
}
</script> </script>
<style scoped> <style scoped>
.x-form-table {width: 100%;} .text {
.x-form-table .x-form-table-handle {text-align: center;} cursor: pointer;
.x-form-table .x-form-table-handle span {display: inline-block;} display: inline;
.x-form-table .x-form-table-handle button {display: none;} white-space: nowrap;
.x-form-table .hover-row .x-form-table-handle-delete span {display: none;} overflow: hidden;
.x-form-table .hover-row .x-form-table-handle-delete button {display: inline-block;} /* 隐藏溢出的内容 */
.x-form-table .move {text-align: center;font-size: 14px;margin-top: 3px;} text-overflow: ellipsis;
/* 在文本溢出处显示省略号 */
}
.x-form-table {
width: 100%;
}
.x-form-table .x-form-table-handle {
text-align: center;
}
.x-form-table .x-form-table-handle span {
display: inline-block;
}
.x-form-table .x-form-table-handle button {
display: none;
}
.x-form-table .hover-row .x-form-table-handle-delete span {
display: none;
}
.x-form-table .hover-row .x-form-table-handle-delete button {
display: inline-block;
}
.x-form-table .move {
text-align: center;
font-size: 14px;
margin-top: 3px;
}
</style> </style>

View File

@ -7,7 +7,7 @@
<div class="x-user-select" :style="{ 'height': _height, 'width': _width }"> <div class="x-user-select" :style="{ 'height': _height, 'width': _width }">
<div class="x-user-select__left"> <div class="x-user-select__left">
<div class="x-user-select__search"> <div class="x-user-select__search">
<el-input v-model="keyword" prefix-icon="el-icon-search" placeholder="搜索成员"> <el-input v-model="keyword" prefix-icon="el-icon-search" :placeholder="config.placeholder || '搜索用户'">
<template #append> <template #append>
<el-button icon="el-icon-search" @click="search"></el-button> <el-button icon="el-icon-search" @click="search"></el-button>
</template> </template>
@ -36,15 +36,16 @@
<header>已选 ({{ selected.length }})</header> <header>已选 ({{ selected.length }})</header>
<ul> <ul>
<el-scrollbar> <el-scrollbar>
<li v-for="(item, index) in selected" :key="item.id"> <x-form-table v-model="selected" :hideAdd="true" placeholder="暂无数据" :column="config.column" @delete="setCheckedKeys" />
<!-- <li v-for="(item, index) in selected" :key="item.id">
<span class="name"> <span class="name">
<el-avatar size="small">{{ item.name.substring(0, 1) }}</el-avatar> <el-avatar size="small">{{ item.name.toString().substring(0, 1) }}</el-avatar>
<label>{{ item.name }}</label> <label>{{ item.name }}</label>
</span> </span>
<span class="delete"> <span class="delete">
<el-button type="danger" icon="el-icon-delete" circle size="small" @click="deleteSelected(index)"></el-button> <el-button type="danger" icon="el-icon-delete" circle size="small" @click="deleteSelected(index)"></el-button>
</span> </span>
</li> </li> -->
</el-scrollbar> </el-scrollbar>
</ul> </ul>
</div> </div>
@ -108,12 +109,22 @@ export default {
modelValue: { type: Array, default: () => [] }, modelValue: { type: Array, default: () => [] },
type: { type: [String, Number], default: 1 }, type: { type: [String, Number], default: 1 },
height: { type: [String, Number], default: 280 }, height: { type: [String, Number], default: 280 },
width: { type: [String, Number], default: 600 }, width: { type: [String, Number], default: '100%' },
datatype: { type: [String, Number], default: 'id' },
config: {
type: Object, default: () => ({
config: []
})
},
}, },
watch: { watch: {
// selected // selected
selectedIds(newVal) { selectedIds(newVal) {
this.$emit('update:modelValue', newVal); if (this.datatype == 'id') {
this.$emit('update:modelValue', newVal);
return true;
}
this.$emit('update:modelValue', this.selected);
}, },
}, },
computed: { computed: {
@ -128,7 +139,8 @@ export default {
} }
}, },
mounted() { mounted() {
this.value = this.modelValue; this.userProps = Object.assign({}, config.user.props, this.config.userProps || {});
this.groupProps = Object.assign({}, config.group.props, this.config.groupProps || {});
this.open() this.open()
}, },
methods: { methods: {
@ -154,16 +166,18 @@ export default {
async getUser() { async getUser() {
this.showUserloading = true; this.showUserloading = true;
var params = { var params = {
[config.user.request.keyword]: this.keyword || null, [this.config.keyword || config.user.request.keyword]: this.keyword || null,
[config.user.request.groupid]: this.groupid || null, [this.config.groupid || config.user.request.groupid]: this.groupid || null,
[config.user.request.page]: this.currentPage, [this.config.page || config.user.request.page]: this.currentPage,
[config.user.request.limit]: this.limit [this.config.limit || config.user.request.limit]: this.limit
} }
var res = await this.$http.get('user/index/lists', params); var res = await this.$http.get(this.config.url || 'user/index/lists', params);
this.showUserloading = false; this.showUserloading = false;
this.user = config.user.parseData(res).rows; this.user = config.user.parseData(res).rows;
this.total = config.user.parseData(res).total || 0; this.total = config.user.parseData(res).total || 0;
this.$refs.userScrollbar.setScrollTop(0) this.$refs.userScrollbar.setScrollTop(0)
this.selected = this.modelValue
}, },
// //
async getRole() { async getRole() {
@ -171,8 +185,6 @@ export default {
var res = await this.$http.get('user/group/roleList', { type: 'system' }); var res = await this.$http.get('user/group/roleList', { type: 'system' });
this.showGrouploading = false; this.showGrouploading = false;
this.role = res.data this.role = res.data
// 使filterID // 使filterID
this.selected = this.role.filter(item => this.modelValue.includes(item.id)).map(item => ({ this.selected = this.role.filter(item => this.modelValue.includes(item.id)).map(item => ({
id: item[config.role.props.key], id: item[config.role.props.key],
@ -191,11 +203,11 @@ export default {
userClick(data, checked) { userClick(data, checked) {
if (checked) { if (checked) {
this.selected.push({ this.selected.push({
id: data[config.user.props.key], id: data[this.userProps.key],
name: data[config.user.props.label] name: data[this.userProps.label]
}) })
} else { } else {
this.selected = this.selected.filter(item => item.id != data[config.user.props.key]) this.selected = this.selected.filter(item => item.id != data[this.userProps.key])
} }
}, },
// //
@ -209,14 +221,16 @@ export default {
this.currentPage = 1 this.currentPage = 1
this.getUser() this.getUser()
}, },
//
setCheckedKeys() {
this.$nextTick(() => {
this.type == 1 ? this.$refs.userTree.setCheckedKeys(this.selectedIds) : this.$refs.groupTree.setCheckedKeys(this.selectedIds)
})
},
// //
deleteSelected(index) { deleteSelected(index) {
this.selected.splice(index, 1); this.selected.splice(index, 1);
if (this.type == 1) { this.setCheckedKeys()
this.$refs.userTree.setCheckedKeys(this.selectedIds)
} else if (this.type == 2) {
this.$refs.groupTree.setCheckedKeys(this.selectedIds)
}
}, },
// //
roleClick(data, checked) { roleClick(data, checked) {
@ -245,7 +259,8 @@ export default {
} }
.x-user-select__left { .x-user-select__left {
width: calc((100%*0.7 - 10px)); min-width: 320px;
flex: none;
} }
.x-user-select__right { .x-user-select__right {
@ -264,13 +279,13 @@ export default {
} }
.x-user-select__tree { .x-user-select__tree {
width: 50%; width: 40%;
height: 100%; height: 100%;
border-right: 1px solid var(--el-border-color-light); border-right: 1px solid var(--el-border-color-light);
} }
.x-user-select__user { .x-user-select__user {
width: 50%; width: 60%;
height: 100%; height: 100%;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -308,7 +323,7 @@ export default {
} }
.x-user-select__selected { .x-user-select__selected {
width: calc((100%*0.3 - 20px)); width: 100%;
border: 1px solid var(--el-border-color-light); border: 1px solid var(--el-border-color-light);
background: var(--el-color-white); background: var(--el-color-white);
} }
@ -368,7 +383,7 @@ export default {
} }
.x-user-select-role .x-user-select__left { .x-user-select-role .x-user-select__left {
width: calc((100% - 20px)/2); min-width: 200px;
} }
.x-user-select-role .x-user-select__tree { .x-user-select-role .x-user-select__tree {
@ -377,7 +392,7 @@ export default {
} }
.x-user-select-role .x-user-select__selected { .x-user-select-role .x-user-select__selected {
width: calc((100% - 20px)/2); width: 100%;
} }
.x-user-select-role .x-user-select__select { .x-user-select-role .x-user-select__select {