新功能(前端组件封装): 强大CURD封装
parent
ff3f89c7a4
commit
80efc70ed1
|
@ -0,0 +1,63 @@
|
||||||
|
<!-- 部门选择器 -->
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<treeselect v-model="dept_value" :options="deptTree" :multiple="multiple" :show-count="true"
|
||||||
|
:placeholder="placeholder" :disable-branch-nodes="disable_branch_nodes"/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Treeselect from '@riophae/vue-treeselect'
|
||||||
|
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
|
||||||
|
import {treeselect} from '@/api/vadmin/permission/dept'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "DeptTree",
|
||||||
|
props: {
|
||||||
|
/* 选择器的内容 */
|
||||||
|
value: {type: Number | Array,},
|
||||||
|
/* 用于显示选项 */
|
||||||
|
placeholder: {type: String, default: "请选择归属部门",},
|
||||||
|
/* 是否多选 */
|
||||||
|
multiple: {type: Boolean, default: false,},
|
||||||
|
/* 是否只能选末级 */
|
||||||
|
disable_branch_nodes: {type: Boolean, default: false,},
|
||||||
|
},
|
||||||
|
components: {Treeselect},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
deptOptions: [],
|
||||||
|
deptTree: [],
|
||||||
|
dept_value: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
dept_value(newValue) {
|
||||||
|
this.$emit('update:value', newValue)
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
handler: function (newValue) {
|
||||||
|
this.dept_value = newValue
|
||||||
|
},
|
||||||
|
immediate: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.getTreeselect()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/** 查询部门下拉树结构 */
|
||||||
|
getTreeselect() {
|
||||||
|
treeselect().then(response => {
|
||||||
|
this.deptOptions = response.data
|
||||||
|
this.deptTree = this.handleTree(response.data, 'id')
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
|
@ -0,0 +1,870 @@
|
||||||
|
<!--
|
||||||
|
@description: 强大的CRUD组件封装
|
||||||
|
-->
|
||||||
|
<template>
|
||||||
|
<div style="padding-left: 10px;padding-top: 10px;">
|
||||||
|
<div class="grid-content bg-purple">
|
||||||
|
<el-form :model="queryParams" ref="queryForm" :inline="true" label-width="90px">
|
||||||
|
<el-row>
|
||||||
|
<el-form-item v-if="value.search" :label="value.label" :prop="value.prop" v-for="(value,index) in fields"
|
||||||
|
:key="index">
|
||||||
|
<!-- date/option/bool/users/depts -->
|
||||||
|
<el-switch
|
||||||
|
v-if="value.type==='boolean'"
|
||||||
|
v-model="queryParams[value.prop]"
|
||||||
|
active-color="#13ce66"
|
||||||
|
inactive-color="#ff4949">
|
||||||
|
</el-switch>
|
||||||
|
<dept-tree ref="dept_tree" v-else-if="value.type==='depts'" :value.sync="queryParams[value.prop]"
|
||||||
|
style="width: 150px;"></dept-tree>
|
||||||
|
<users-tree ref="users_tree" v-else-if="value.type==='users'" :value.sync="queryParams[value.prop]"
|
||||||
|
style="width: 150px;"></users-tree>
|
||||||
|
<el-date-picker
|
||||||
|
v-else-if="value.type==='date'"
|
||||||
|
v-model="dateRange"
|
||||||
|
size="small"
|
||||||
|
style="width: 240px"
|
||||||
|
value-format="yyyy-MM-dd HH:mm:ss"
|
||||||
|
type="daterange"
|
||||||
|
range-separator="-"
|
||||||
|
start-placeholder="开始日期"
|
||||||
|
end-placeholder="结束日期"
|
||||||
|
:default-time="['00:00:00', '23:59:59']"
|
||||||
|
></el-date-picker>
|
||||||
|
<el-select
|
||||||
|
v-else-if="value.type==='option' && value.option_key"
|
||||||
|
v-model="queryParams[value.prop]"
|
||||||
|
:placeholder="value.label"
|
||||||
|
clearable
|
||||||
|
size="small"
|
||||||
|
style="width: 240px"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="dict in DictsOptions[value.option_key]"
|
||||||
|
:key="dict.dictValue"
|
||||||
|
:label="dict.dictLabel"
|
||||||
|
:value="dict.dictValue"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
<el-input
|
||||||
|
v-else
|
||||||
|
v-model="queryParams[value.prop]"
|
||||||
|
:placeholder="value.label"
|
||||||
|
clearable
|
||||||
|
size="small"
|
||||||
|
@keyup.enter.native="handleQuery"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-row>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleSearchFormSubmit">搜索</el-button>
|
||||||
|
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
<el-row v-if="topLayout" style="margin-bottom: 20px">
|
||||||
|
<el-col v-if="topLayoutLeft" :span="18">
|
||||||
|
<el-row :gutter="10" class="mb8">
|
||||||
|
<el-col :span="1.5" v-for="(func,index) in funcs" :key="index">
|
||||||
|
<el-button
|
||||||
|
v-if="func.type==='add'"
|
||||||
|
type="primary"
|
||||||
|
plain
|
||||||
|
:icon="func.icon||'el-icon-plus'"
|
||||||
|
size="mini"
|
||||||
|
@click="handleAdd(func.api)"
|
||||||
|
v-hasPermi="func.permis"
|
||||||
|
>{{func.label}}
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
v-else-if="func.type==='update'"
|
||||||
|
type="success"
|
||||||
|
plain
|
||||||
|
:disabled="multipleSelection.length!==1"
|
||||||
|
:icon="func.icon||'el-icon-edit'"
|
||||||
|
size="mini"
|
||||||
|
@click="handleUpdate(func.api,{})"
|
||||||
|
v-hasPermi="func.permis"
|
||||||
|
>{{func.label}}
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
v-else-if="func.type==='delete'"
|
||||||
|
type="danger"
|
||||||
|
plain
|
||||||
|
:disabled="multipleSelection.length===0"
|
||||||
|
:icon="func.icon||'el-icon-delete'"
|
||||||
|
size="mini"
|
||||||
|
@click="handleDelete(func.api,{})"
|
||||||
|
v-hasPermi="func.permis"
|
||||||
|
>{{func.label}}
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
v-else-if="func.type==='export'"
|
||||||
|
type="warning"
|
||||||
|
plain
|
||||||
|
:icon="func.icon||'el-icon-download'"
|
||||||
|
size="mini"
|
||||||
|
@click="handleExport(func.api)"
|
||||||
|
v-hasPermi="func.permis"
|
||||||
|
>{{func.label}}
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
v-else-if="func.type==='import'"
|
||||||
|
type="info"
|
||||||
|
plain
|
||||||
|
:icon="func.icon||'el-icon-upload2'"
|
||||||
|
size="mini"
|
||||||
|
@click="handleImport(func.api)"
|
||||||
|
v-hasPermi="func.permis"
|
||||||
|
>{{func.label}}
|
||||||
|
</el-button>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-col>
|
||||||
|
<el-col v-if="topLayoutRight" :span="6">
|
||||||
|
<div class="grid-content bg-purple-light" style="text-align: right">
|
||||||
|
<slot name="tools"/>
|
||||||
|
<el-popover
|
||||||
|
placement="bottom"
|
||||||
|
width="200"
|
||||||
|
trigger="click">
|
||||||
|
<div style="width: 50px;">
|
||||||
|
<el-checkbox-group v-model="showFields">
|
||||||
|
<el-checkbox v-for="(field, index) in fields" :key="index" :label="field" :checked="field.show"
|
||||||
|
style="width: 100%" @change="handleSelectField($event, field)">{{ field.label }}
|
||||||
|
</el-checkbox>
|
||||||
|
</el-checkbox-group>
|
||||||
|
</div>
|
||||||
|
<el-button
|
||||||
|
slot="reference"
|
||||||
|
:size="$ELEMENT.size"
|
||||||
|
name="refresh"
|
||||||
|
type="info"
|
||||||
|
icon="el-icon-s-fold"
|
||||||
|
title="设置显示的字段"/>
|
||||||
|
</el-popover>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-table
|
||||||
|
v-loading="tableLoading"
|
||||||
|
ref="tableData"
|
||||||
|
:span-method="spanMethod"
|
||||||
|
:data="tableData"
|
||||||
|
:max-height="maxHeight"
|
||||||
|
:row-key="getRowKeys"
|
||||||
|
:stripe="stripe"
|
||||||
|
:fit="fit"
|
||||||
|
:border="border"
|
||||||
|
:empty-text="emptyText"
|
||||||
|
:highlight-current-row="highlightCurrentRow"
|
||||||
|
:show-overflow-tooltip="showOverflowTooltip"
|
||||||
|
@sort-change="handleSortChange"
|
||||||
|
@cell-click="handleCellClick"
|
||||||
|
@cell-dblclick="handleCellDbClick"
|
||||||
|
@header-click="handleHeaderClick"
|
||||||
|
@row-click="handleRowClick"
|
||||||
|
@row-dblclick="handleRowDblClick"
|
||||||
|
@selection-change="handleSelectionChange">
|
||||||
|
<el-table-column v-if="selection" :reserve-selection="true" type="selection" width="50"/>
|
||||||
|
<slot name="prependColumn"/>
|
||||||
|
<!--<el-table-column v-if="false" :index="getRowIndex" label="序号" type="index" width="50"/>-->
|
||||||
|
<template v-for="field in fields">
|
||||||
|
<el-table-column
|
||||||
|
v-if="field.show"
|
||||||
|
:key="field.prop"
|
||||||
|
:prop="field.prop"
|
||||||
|
:label="field.label"
|
||||||
|
:sortable="field.sortable"
|
||||||
|
:width="field.width || ''"
|
||||||
|
:sort-method="sortMethod"
|
||||||
|
show-overflow-tooltip>
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<slot :name="field.prop" :values="scope.row" :prop="field.prop" :field="field">
|
||||||
|
<span v-html="formatColumnData(scope.row, field)"/>
|
||||||
|
</slot>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</template>
|
||||||
|
<el-table-column
|
||||||
|
label="操作"
|
||||||
|
align="center"
|
||||||
|
class-name="small-padding fixed-width"
|
||||||
|
v-if="hasPermi(getOperationPermis())"
|
||||||
|
>
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<span v-for="(func,index) in funcs" :key="index">
|
||||||
|
<el-button
|
||||||
|
v-if="func.type==='select'"
|
||||||
|
size="mini"
|
||||||
|
type="text"
|
||||||
|
:icon="func.icon||'el-icon-view'"
|
||||||
|
@click="handleSelect(func.api,scope.row)"
|
||||||
|
v-hasPermi="func.permis"
|
||||||
|
>{{func.label}}</el-button>
|
||||||
|
|
||||||
|
<el-button
|
||||||
|
v-if="func.type==='update'"
|
||||||
|
size="mini"
|
||||||
|
type="text"
|
||||||
|
:icon="func.icon||'el-icon-edit'"
|
||||||
|
@click="handleUpdate(func.api,scope.row)"
|
||||||
|
v-hasPermi="func.permis"
|
||||||
|
>{{func.label}}</el-button>
|
||||||
|
|
||||||
|
<el-button
|
||||||
|
v-else-if="func.type==='delete'"
|
||||||
|
size="mini"
|
||||||
|
type="text"
|
||||||
|
:icon="func.icon||'el-icon-delete'"
|
||||||
|
@click="handleDelete(func.api,scope.row)"
|
||||||
|
v-hasPermi="func.permis"
|
||||||
|
>{{func.label}}</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<slot name="appendColumn"/>
|
||||||
|
<slot name="column"/>
|
||||||
|
</el-table>
|
||||||
|
<el-row>
|
||||||
|
<el-col v-if="selection" :span="6" style="margin-top: 20px">
|
||||||
|
<span>已选择:<span style="color: #ff00ff;font-weight: bold;">{{ multipleSelection.length }}</span>条</span>
|
||||||
|
<el-button v-show="multipleSelection.length" type="info" size="mini" title="清空多选"
|
||||||
|
@click="clearMultipleSelection">清空
|
||||||
|
</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-pagination
|
||||||
|
:current-page="pagination.page"
|
||||||
|
:page-size="pagination.page_size"
|
||||||
|
:total="pagination.total"
|
||||||
|
:page-sizes="paginationStyle.pageSizes || [10, 20, 50, 100]"
|
||||||
|
:disabled="tableLoading"
|
||||||
|
:small="paginationStyle.small || false"
|
||||||
|
:layout="paginationStyle.layout || 'total, sizes, prev, pager, next, jumper'"
|
||||||
|
background
|
||||||
|
class="right_pagination"
|
||||||
|
@size-change="handleChangePageSize"
|
||||||
|
@current-change="handleChangeCurrentPage"/>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<!-- 添加或修改参数配置对话框 -->
|
||||||
|
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
|
||||||
|
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
|
||||||
|
<el-form-item v-if="value.form" :label="value.label" :prop="value.prop" v-for="(value,index) in fields"
|
||||||
|
:key="index">
|
||||||
|
<!-- date/option/bool/users/depts -->
|
||||||
|
<el-switch
|
||||||
|
v-if="value.type==='boolean'"
|
||||||
|
v-model="form[value.prop]"
|
||||||
|
active-color="#13ce66"
|
||||||
|
inactive-color="#ff4949">
|
||||||
|
</el-switch>
|
||||||
|
<dept-tree ref="dept_tree" v-else-if="value.type==='depts'" :value.sync="form[value.prop]"
|
||||||
|
style="width: 200px;"></dept-tree>
|
||||||
|
<users-tree ref="users_tree" v-else-if="value.type==='users'" :value.sync="form[value.prop]"
|
||||||
|
style="width: 200px;"></users-tree>
|
||||||
|
<el-date-picker
|
||||||
|
v-else-if="value.type==='date'"
|
||||||
|
v-model="form[value.prop]"
|
||||||
|
type="date"
|
||||||
|
size="small"
|
||||||
|
style="width: 240px"
|
||||||
|
value-format="yyyy-MM-dd HH:mm:ss"
|
||||||
|
placeholder="选择日期">
|
||||||
|
</el-date-picker>
|
||||||
|
<el-select
|
||||||
|
v-else-if="value.type==='option' && value.option_key"
|
||||||
|
v-model="form[value.prop]"
|
||||||
|
:placeholder="value.label"
|
||||||
|
clearable
|
||||||
|
size="small"
|
||||||
|
style="width: 240px"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="dict in DictsOptions[value.option_key]"
|
||||||
|
:key="dict.dictValue"
|
||||||
|
:label="dict.dictLabel"
|
||||||
|
:value="dict.dictValue"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
<el-input
|
||||||
|
v-else
|
||||||
|
v-model="form[value.prop]"
|
||||||
|
:placeholder="value.label"
|
||||||
|
clearable
|
||||||
|
size="small"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<div slot="footer" class="dialog-footer">
|
||||||
|
<el-button type="primary" @click="submitForm" v-if="this.title!=='详情'">确 定</el-button>
|
||||||
|
<el-button @click="cancel">取 消</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import moment from 'moment';
|
||||||
|
import * as Utils from '@/utils';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'ModelDisplay',
|
||||||
|
props: {
|
||||||
|
value: {
|
||||||
|
// table的Data
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
},
|
||||||
|
spanMethod: {
|
||||||
|
type: Function,
|
||||||
|
default: null
|
||||||
|
},
|
||||||
|
// eslint-disable-next-line vue/require-prop-types
|
||||||
|
maxHeight: {
|
||||||
|
default: 700
|
||||||
|
},
|
||||||
|
stripe: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
fit: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
highlightCurrentRow: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
showOverflowTooltip: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
border: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
emptyText: {
|
||||||
|
type: String,
|
||||||
|
default: '暂无数据'
|
||||||
|
},
|
||||||
|
paginationParams: {
|
||||||
|
// 新增。分页参数, 当分页格式返回的属性名称不同使用, 可使用该属性覆盖默认分页属性名称
|
||||||
|
// 例如:{ page: 'page', pageSize: 'pageSize', count: 'total',results: 'list' }
|
||||||
|
type: Object,
|
||||||
|
default: () => {
|
||||||
|
return {
|
||||||
|
page: 'page',
|
||||||
|
pageSize: 'page_size',
|
||||||
|
count: 'count',
|
||||||
|
results: 'results'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
listApi: {
|
||||||
|
// 用于替换method + url属性
|
||||||
|
type: Function,
|
||||||
|
default: null
|
||||||
|
},
|
||||||
|
topLayout: {
|
||||||
|
// 用于控制表格顶部的按钮、工具的显示。默认左右的按钮、功能都显示
|
||||||
|
type: Array,
|
||||||
|
default: () => {
|
||||||
|
return ['left', 'right'];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fields: {
|
||||||
|
// 后端返回的字段
|
||||||
|
type: Array,
|
||||||
|
default: () => {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
funcs: {
|
||||||
|
// 菜单配置字段
|
||||||
|
type: Array,
|
||||||
|
default: () => {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
selection: {
|
||||||
|
// 开始开启多选(默认开启, true)
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
params: {
|
||||||
|
// 基本请求参数,最终请求参数=基本参数+基本高级搜索参数+组件封装的基本参数+租金组件封装的高级搜索参数
|
||||||
|
type: Object,
|
||||||
|
default: () => {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 默认分页样式
|
||||||
|
paginationStyle: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 默认页面大小
|
||||||
|
pageSizes: {
|
||||||
|
type: Array,
|
||||||
|
default: () => {
|
||||||
|
return [10, 20, 50, 100, 500];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
showFields: [], // 显示的字段
|
||||||
|
searchForm: {
|
||||||
|
search: '',
|
||||||
|
ordering: ''
|
||||||
|
},
|
||||||
|
queryParams: {},
|
||||||
|
tableLoading: false,
|
||||||
|
tableData: [],
|
||||||
|
rowKey: '',
|
||||||
|
dateRange: [],
|
||||||
|
multipleSelection: [],
|
||||||
|
pagination: {
|
||||||
|
page: 1,
|
||||||
|
page_size: 10,
|
||||||
|
total: 0
|
||||||
|
},
|
||||||
|
// 表单参数
|
||||||
|
form: {},
|
||||||
|
rules: this.getFormRules(),
|
||||||
|
open: false,
|
||||||
|
// 提交时api
|
||||||
|
submitFormApi: '',
|
||||||
|
// 单个查询api
|
||||||
|
selectApi: '',
|
||||||
|
DictsOptions: {},
|
||||||
|
getRowKeys: row => {
|
||||||
|
if (this.rowKey) {
|
||||||
|
return row[this.rowKey];
|
||||||
|
}
|
||||||
|
return row.id || row.uuid;
|
||||||
|
},
|
||||||
|
title: '',
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
topLayoutLeft() {
|
||||||
|
return this.topLayout.indexOf('left') >= 0;
|
||||||
|
},
|
||||||
|
topLayoutRight() {
|
||||||
|
return this.topLayout.indexOf('right') >= 0;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
params: {
|
||||||
|
deep: true,
|
||||||
|
handler: function (newValue, oldValue) {
|
||||||
|
this.getTableData();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.initComponentData();
|
||||||
|
this.initDictsOptions();
|
||||||
|
this.getTableData();
|
||||||
|
this.funcs.map(value => {
|
||||||
|
if (value.type === 'select') {
|
||||||
|
this.selectApi = value.api
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
initComponentData() {
|
||||||
|
this.pagination.page_size = this.pageSizes[0];
|
||||||
|
this.fields.forEach(field => {
|
||||||
|
field.show = (!!field.show);
|
||||||
|
field.type = (field.type || 'string').toLocaleLowerCase();
|
||||||
|
if (field.type.startsWith('bool')) {
|
||||||
|
field.type = 'boolean';
|
||||||
|
}
|
||||||
|
field.label = field.label || field.prop;
|
||||||
|
field.search = (!!field.search);
|
||||||
|
field.sortable = (!!field.sortable);
|
||||||
|
if (field.ordering && field.ordering.startsWith('desc')) {
|
||||||
|
this.searchForm.ordering = `-${field.prop}`;
|
||||||
|
} else if (field.ordering && field.ordering.startsWith('asc')) {
|
||||||
|
this.searchForm.ordering = `${field.prop}`;
|
||||||
|
}
|
||||||
|
field.width = field.width || '';
|
||||||
|
if (field.type === 'choices') {
|
||||||
|
if (Utils.isArray(field.choices) && field.choices.length > 0) {
|
||||||
|
if (!Utils.isObj(field.choices[0])) {
|
||||||
|
field.choices = field.choices.map(value => {
|
||||||
|
return {
|
||||||
|
label: value,
|
||||||
|
value: value
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
field.unique = (!!field.unique);
|
||||||
|
if (field.unique) {
|
||||||
|
this.rowKey = field.prop;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
formatColumnData(row, field) {
|
||||||
|
const type = field.type || 'string';
|
||||||
|
const prop = field.prop;
|
||||||
|
if (field.formatter && typeof field.formatter === 'function') {
|
||||||
|
return field.formatter(row, prop, type);
|
||||||
|
}
|
||||||
|
if (type === 'string') {
|
||||||
|
return row[prop];
|
||||||
|
} else if (type === 'datetime') {
|
||||||
|
return this.formatDatetime(row[prop]);
|
||||||
|
} else if (type === 'date') {
|
||||||
|
return this.formatDate(row[prop]);
|
||||||
|
} else if (type === 'time') {
|
||||||
|
return this.formatTime(row[prop]);
|
||||||
|
} else if (type === 'option') {
|
||||||
|
return this.formatOptions(field.option_key, row[prop]);
|
||||||
|
} else if (type === 'users') {
|
||||||
|
return this.formatUsers(row[prop]);
|
||||||
|
} else if (type === 'depts') {
|
||||||
|
return this.formatDepts(row[prop]);
|
||||||
|
} else if (type.startsWith('bool')) {
|
||||||
|
return row[prop] ? '是' : '否';
|
||||||
|
} else if (type === 'choices') {
|
||||||
|
const choices = field.choices;
|
||||||
|
return this.formatChoices(choices, row[prop]);
|
||||||
|
} else {
|
||||||
|
return row[prop];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
formatChoices(choices, value) {
|
||||||
|
for (const choice of choices) {
|
||||||
|
if (choice.value === value) {
|
||||||
|
return choice.label;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
},
|
||||||
|
formatDatetime(datetime) {
|
||||||
|
return moment(datetime).format('YYYY-MM-DD HH:mm:ss');
|
||||||
|
},
|
||||||
|
formatDate(date) {
|
||||||
|
return moment(date).format('YYYY-MM-DD');
|
||||||
|
},
|
||||||
|
formatTime(time) {
|
||||||
|
return moment(time).format('HH:mm:ss');
|
||||||
|
},
|
||||||
|
formatOptions(option_key, id) {
|
||||||
|
var data = this.DictsOptions[option_key]
|
||||||
|
if (!id || !data) return ""
|
||||||
|
for (var i = 0; i < data.length; i++) {
|
||||||
|
if (data[i].dictValue === id) {
|
||||||
|
return data[i].dictLabel
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
},
|
||||||
|
formatUsers(id) {
|
||||||
|
if (!id) return ""
|
||||||
|
var data = this.$refs.users_tree[0].usersOptions
|
||||||
|
for (var i = 0; i < data.length; i++) {
|
||||||
|
if (data[i].id === id) {
|
||||||
|
return data[i].label
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
},
|
||||||
|
formatDepts(id) {
|
||||||
|
if (!id) return ""
|
||||||
|
var data = this.$refs.dept_tree[0].deptOptions
|
||||||
|
for (var i = 0; i < data.length; i++) {
|
||||||
|
if (data[i].id === id) {
|
||||||
|
return data[i].label
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
},
|
||||||
|
sortMethod(a, b) {
|
||||||
|
return -1;
|
||||||
|
},
|
||||||
|
getTableData() {
|
||||||
|
this.listInterfaceData(this.getRequestParams());
|
||||||
|
return this.tableData;
|
||||||
|
},
|
||||||
|
getFormattedPaginationParams() {
|
||||||
|
const pageParamName = this.paginationParams.page;
|
||||||
|
const pageSizeParamName = this.paginationParams.pageSize;
|
||||||
|
const params = {};
|
||||||
|
params[pageParamName] = this.pagination.page;
|
||||||
|
params[pageSizeParamName] = this.pagination.page_size;
|
||||||
|
return params;
|
||||||
|
},
|
||||||
|
// 根据搜索框的内容, 组装请求参数
|
||||||
|
getRequestParams() {
|
||||||
|
// 组装分页参数、高级搜索参数
|
||||||
|
const tmpParams = {...this.params, ...this.getFormattedPaginationParams(), ...this.queryParams};
|
||||||
|
const params = {};
|
||||||
|
for (const prop of Object.keys(tmpParams)) {
|
||||||
|
if (tmpParams[prop]) {
|
||||||
|
params[prop] = tmpParams[prop];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 组装普遍模糊搜索的参数
|
||||||
|
if (this.searchForm.search) {
|
||||||
|
params['search'] = this.searchForm.search;
|
||||||
|
}
|
||||||
|
// 组装普遍排序搜索的参数
|
||||||
|
if (this.searchForm.ordering) {
|
||||||
|
params['ordering'] = this.searchForm.ordering;
|
||||||
|
}
|
||||||
|
// console.dir(params);
|
||||||
|
return this.addDateRange(params, this.dateRange);
|
||||||
|
},
|
||||||
|
// 封装后端接口, 后端接口返回数据必须规范一致
|
||||||
|
listInterfaceData(params) {
|
||||||
|
this.tableLoading = true;
|
||||||
|
this.listApi(params).then(response => {
|
||||||
|
this.tableLoading = false;
|
||||||
|
if (response.status === 'success') {
|
||||||
|
const resultsParamName = this.paginationParams.results;
|
||||||
|
const countParamName = this.paginationParams.count;
|
||||||
|
this.tableData = response.data[resultsParamName] || [];
|
||||||
|
this.pagination.total = response.data[countParamName] || 0;
|
||||||
|
} else {
|
||||||
|
this.$message.warning(response.msg || '获取接口信息失败!');
|
||||||
|
}
|
||||||
|
}).catch(error => {
|
||||||
|
this.tableLoading = false;
|
||||||
|
console.error(error);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
/** 清空已选择 */
|
||||||
|
clearMultipleSelection() {
|
||||||
|
this.clearSelection();
|
||||||
|
},
|
||||||
|
/** 清空已选择 */
|
||||||
|
clearSelection() {
|
||||||
|
this.$refs.tableData.clearSelection();
|
||||||
|
},
|
||||||
|
handleSelectField(e, field) {
|
||||||
|
field.show = e;
|
||||||
|
},
|
||||||
|
// 处理提交表单, 点击搜索按钮事件
|
||||||
|
handleSearchFormSubmit() {
|
||||||
|
this.pagination.page = 1;
|
||||||
|
this.getTableData();
|
||||||
|
},
|
||||||
|
/** 搜索按钮操作 */
|
||||||
|
handleQuery() {
|
||||||
|
this.queryParams.pageNum = 1;
|
||||||
|
this.getTableData();
|
||||||
|
},
|
||||||
|
/** 重置按钮操作 */
|
||||||
|
resetQuery() {
|
||||||
|
this.dateRange = [];
|
||||||
|
this.queryParams = {}
|
||||||
|
this.resetForm("queryForm");
|
||||||
|
this.handleQuery();
|
||||||
|
},
|
||||||
|
/** 获取Dicts值 */
|
||||||
|
initDictsOptions() {
|
||||||
|
this.fields.map(value => {
|
||||||
|
if (value.option_key) {
|
||||||
|
this.getDicts(value.option_key).then(response => {
|
||||||
|
this.DictsOptions[value.option_key] = response.data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 处理修改多选的值
|
||||||
|
handleSelectionChange(val) {
|
||||||
|
this.$emit('selection-change', val);
|
||||||
|
this.multipleSelection = val;
|
||||||
|
},
|
||||||
|
// 处理修改表格分页器的页面大小(再次获取接口数据)
|
||||||
|
handleChangePageSize(val) {
|
||||||
|
this.pagination.page_size = val;
|
||||||
|
this.getTableData();
|
||||||
|
},
|
||||||
|
// 处理修改表格分页器的页码(再次获取接口数据)
|
||||||
|
handleChangeCurrentPage(val) {
|
||||||
|
this.pagination.page = val;
|
||||||
|
this.getTableData();
|
||||||
|
},
|
||||||
|
handleSortChange(info) {
|
||||||
|
const {prop, order} = info;
|
||||||
|
if (!order) {
|
||||||
|
this.searchForm.ordering = '';
|
||||||
|
} else if (order.startsWith('desc')) {
|
||||||
|
this.searchForm.ordering = `-${prop}`;
|
||||||
|
} else {
|
||||||
|
this.searchForm.ordering = `${prop}`;
|
||||||
|
}
|
||||||
|
this.getTableData();
|
||||||
|
},
|
||||||
|
handleCellClick(row, column, cell, event) {
|
||||||
|
this.$emit('cell-click', row, column, cell, event);
|
||||||
|
},
|
||||||
|
handleCellDbClick(row, column, cell, event) {
|
||||||
|
this.$emit('cell-dblclick', row, column, cell, event);
|
||||||
|
},
|
||||||
|
handleRowClick(row, column, event) {
|
||||||
|
this.$emit('row-click', row, column, event);
|
||||||
|
},
|
||||||
|
handleRowDblClick(row, column, event) {
|
||||||
|
this.$emit('row-dblclick', row, column, event);
|
||||||
|
},
|
||||||
|
handleHeaderClick(column, event) {
|
||||||
|
this.$emit('header-click', column, event);
|
||||||
|
},
|
||||||
|
/**新增按钮*/
|
||||||
|
handleAdd(api) {
|
||||||
|
this.dateRange = [];
|
||||||
|
this.queryParams = {}
|
||||||
|
this.resetForm("queryForm");
|
||||||
|
this.open = true;
|
||||||
|
this.title = "新增";
|
||||||
|
this.submitFormApi = api
|
||||||
|
|
||||||
|
},
|
||||||
|
/**修改按钮*/
|
||||||
|
handleUpdate(api, row) {
|
||||||
|
this.dateRange = [];
|
||||||
|
this.queryParams = {}
|
||||||
|
this.resetForm("queryForm");
|
||||||
|
this.submitFormApi = api
|
||||||
|
const id = row.id || this.multipleSelection.map(item => item.id);
|
||||||
|
if (this.selectApi) {
|
||||||
|
this.selectApi(id).then(response => {
|
||||||
|
this.form = response.data;
|
||||||
|
this.open = true;
|
||||||
|
this.title = "修改";
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.open = true;
|
||||||
|
this.title = "修改";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**修改按钮*/
|
||||||
|
handleSelect(api, row) {
|
||||||
|
this.dateRange = [];
|
||||||
|
this.queryParams = {}
|
||||||
|
this.resetForm("queryForm");
|
||||||
|
this.submitFormApi = api
|
||||||
|
const id = row.id || this.multipleSelection.map(item => item.id);
|
||||||
|
if (this.selectApi) {
|
||||||
|
this.selectApi(id).then(response => {
|
||||||
|
this.form = response.data;
|
||||||
|
this.open = true;
|
||||||
|
this.title = "详情";
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.open = true;
|
||||||
|
this.title = "详情";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/** 删除按钮操作 */
|
||||||
|
handleDelete(api, row) {
|
||||||
|
const ids = row.id || this.multipleSelection.map(item => item.id);
|
||||||
|
this.$confirm('是否确认删除编号为"' + ids + '"的数据项?', "警告", {
|
||||||
|
confirmButtonText: "确定",
|
||||||
|
cancelButtonText: "取消",
|
||||||
|
type: "warning"
|
||||||
|
}).then(function () {
|
||||||
|
return api(ids);
|
||||||
|
}).then(() => {
|
||||||
|
this.getTableData();
|
||||||
|
this.msgSuccess("删除成功");
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/** 导出按钮操作 */
|
||||||
|
handleExport(api) {
|
||||||
|
const queryParams = this.queryParams;
|
||||||
|
this.$confirm('是否确认导出所有符合条件的数据项?', "警告", {
|
||||||
|
confirmButtonText: "确定",
|
||||||
|
cancelButtonText: "取消",
|
||||||
|
type: "warning"
|
||||||
|
}).then(function () {
|
||||||
|
return api(queryParams);
|
||||||
|
}).then(response => {
|
||||||
|
this.download(response.data.file_url, response.data.name);
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/** 导入按钮操作 */
|
||||||
|
handleImport() {
|
||||||
|
this.upload.title = '用户导入'
|
||||||
|
this.upload.open = true
|
||||||
|
}, /** 获取表单校验 */
|
||||||
|
getFormRules() {
|
||||||
|
let dict = {}
|
||||||
|
this.fields.map(value => {
|
||||||
|
if (value.form) {
|
||||||
|
dict[value.prop] = [{
|
||||||
|
required: value.required,
|
||||||
|
message: value.rules_message || value.label + "不能为空",
|
||||||
|
trigger: value.trigger || "blur"
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
console.log(2, dict)
|
||||||
|
return dict
|
||||||
|
},
|
||||||
|
/** 提交按钮 */
|
||||||
|
submitForm() {
|
||||||
|
this.$refs["form"].validate(valid => {
|
||||||
|
if (valid) {
|
||||||
|
if (this.form.id !== undefined) {
|
||||||
|
this.submitFormApi(this.form).then(response => {
|
||||||
|
this.msgSuccess("修改成功");
|
||||||
|
this.open = false;
|
||||||
|
this.getTableData();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.submitFormApi(this.form).then(response => {
|
||||||
|
this.msgSuccess("新增成功");
|
||||||
|
this.open = false;
|
||||||
|
this.getTableData();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 取消按钮
|
||||||
|
cancel() {
|
||||||
|
this.open = false;
|
||||||
|
},
|
||||||
|
// 获取操作的权限列表
|
||||||
|
getOperationPermis() {
|
||||||
|
let Permis = []
|
||||||
|
this.funcs.map(value => {
|
||||||
|
if (['update', 'delete', 'select'].indexOf(value.type) !== 0) {
|
||||||
|
Permis.push(value.permis)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return Permis
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.picker {
|
||||||
|
width: 240px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-pagination {
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right_pagination {
|
||||||
|
text-align: right;
|
||||||
|
padding-top: 20px;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,62 @@
|
||||||
|
<!-- 用户选择器 -->
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<treeselect v-model="users_value" :options="usersOptions" :multiple="multiple" :show-count="true"
|
||||||
|
:placeholder="placeholder" :disable-branch-nodes="disable_branch_nodes"/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Treeselect from '@riophae/vue-treeselect'
|
||||||
|
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
|
||||||
|
import {listUser} from '@/api/vadmin/permission/user'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "DeptTree",
|
||||||
|
props: {
|
||||||
|
/* 选择器的内容 */
|
||||||
|
value: {type: Number | Array,},
|
||||||
|
/* 用于显示选项 */
|
||||||
|
placeholder: {type: String, default: "请选择用户",},
|
||||||
|
/* 是否多选 */
|
||||||
|
multiple: {type: Boolean, default: false,},
|
||||||
|
/* 是否只能选末级 */
|
||||||
|
disable_branch_nodes: {type: Boolean, default: false,},
|
||||||
|
},
|
||||||
|
components: {Treeselect},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
usersOptions: [],
|
||||||
|
users_value: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
users_value(newValue) {
|
||||||
|
this.$emit('update:value', newValue)
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
handler: function(newValue) {
|
||||||
|
this.users_value = newValue
|
||||||
|
},
|
||||||
|
immediate: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.getTreeselect()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/** 查询所有用户信息 **/
|
||||||
|
getTreeselect() {
|
||||||
|
listUser({pageNum: "all", _fields: "id,name"}).then(response => {
|
||||||
|
response.data.map(val => { val["label"] = val['name'] })
|
||||||
|
this.usersOptions = this.handleTree(response.data, 'id')
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
|
@ -30,6 +30,9 @@ import Pagination from "@/components/Pagination";
|
||||||
// 自定义表格工具扩展
|
// 自定义表格工具扩展
|
||||||
import RightToolbar from "@/components/RightToolbar"
|
import RightToolbar from "@/components/RightToolbar"
|
||||||
import SmallDialog from '@/components/SmallDialog';
|
import SmallDialog from '@/components/SmallDialog';
|
||||||
|
import DeptTree from '@/components/DeptTree';
|
||||||
|
import UsersTree from '@/components/UsersTree';
|
||||||
|
import ModelDisplay from '@/components/ModelDisplay';
|
||||||
import CommonIcon from '@/components/CommonIcon';
|
import CommonIcon from '@/components/CommonIcon';
|
||||||
import CommonStaticTable from '@/components/CommonStaticTable';
|
import CommonStaticTable from '@/components/CommonStaticTable';
|
||||||
import {getCrontabData, getIntervalData} from "./utils/validate"; // 通用图标组件
|
import {getCrontabData, getIntervalData} from "./utils/validate"; // 通用图标组件
|
||||||
|
@ -67,6 +70,9 @@ Vue.prototype.msgInfo = function (msg) {
|
||||||
}
|
}
|
||||||
// 自定义组件
|
// 自定义组件
|
||||||
Vue.component('small-dialog', SmallDialog);
|
Vue.component('small-dialog', SmallDialog);
|
||||||
|
Vue.component('dept-tree', DeptTree);
|
||||||
|
Vue.component('users-tree', UsersTree);
|
||||||
|
Vue.component('model-display', ModelDisplay);
|
||||||
// 全局组件挂载
|
// 全局组件挂载
|
||||||
Vue.component('Pagination', Pagination)
|
Vue.component('Pagination', Pagination)
|
||||||
Vue.component('RightToolbar', RightToolbar)
|
Vue.component('RightToolbar', RightToolbar)
|
||||||
|
|
Loading…
Reference in New Issue