<!-- * @name: 页面基本结构组件 * @author: zhangpengcheng * @date: 2022-08-23 --> <!-- style="overflow: auto;" --> <template> <div class="container" v-loading="loading" :style="'backgroundColor:' + bgColor + ';paddingBottom:' + paddingBottom + ';height:' + bodyHight " ref="baseLayout"> <!-- 标题 --> <div flex="cross:center" style="padding: 10px" :style="{ 'justify-content': searchShow || showTitle ? 'space-between' : 'flex-end', }" v-if="showTitle"> <div class="title" v-if="showTitle"> <span v-if="showTitle">{{ title }}</span> </div> <div flex="cross:center" v-if="searchShow"> <i class="queryIcon" :class="queryShow ? 'el-icon-arrow-down' : 'el-icon-arrow-right'" @click="queryShowChange"></i> <el-dropdown trigger="click"> <span class="el-dropdown-link" style="cursor: pointer; color: #303133; font-size: 14px"> 默认条件<i class="el-icon-arrow-down el-icon--right" style="margin-left: 8px"></i> </span> <el-dropdown-menu slot="dropdown" style=" padding: 7px 20px; background-color: #f5f7fa; border: 1px soild #dcdfe6; "> <el-dropdown-item command="a" class="requirementList">默认查询 </el-dropdown-item> <el-dropdown-item v-for="(item, index) in requirementList" :key="item.command" :command="item.command"> <div flex="cross:center main:justify"> <p>{{ item.title }}</p> <div flex="cross:center "> <i class="el-icon-edit" @click="edit(item)"></i> <i class="el-icon-close" @click="del(item)"></i> </div> </div> </el-dropdown-item> <el-dropdown-item command="d">创建方案</el-dropdown-item> <el-dropdown-item command="e">高级查询</el-dropdown-item> </el-dropdown-menu> </el-dropdown> <!-- <p>高级查询</p> --> </div> <div flex="cross:centet" v-if="buttonList && buttonList.length > 0"> <el-dropdown v-for="(item, index) in buttonList" class="buttonList" :key="index" @command="dropClick"> <el-button :type="item.type ? item.type : 'primary'" size="small" class="iconfont" :icon="item.icon" @keyup.prevent.native @keydown.enter.prevent.native @click="funNewClick(item)"> {{ item.menuName }}<i v-if="item.dropList && item.dropList.length > 0" class="el-icon-arrow-down el-icon--right"></i> </el-button> <el-dropdown-menu slot="dropdown"> <!-- <i class="el-icon-arrow-down el-icon--right"> --> <el-dropdown-item v-for="(dropItem, dropIndex) in item.dropList" :key="dropIndex" :icon="dropItem.icon" :command="dropItem.dropFun">{{ dropItem.title }} </el-dropdown-item> </el-dropdown-menu> </el-dropdown> </div> </div> <!-- <div class="main":style="'backgroundColor:'+ mainColor " > --> <!-- 搜索 --> <div class="main" :style="'height:' + mainHight + ';backgroundColor:' + mainColor"> <!-- 搜索 --> <div v-show="queryShow" style="padding: 16px;" flex="cross:center" ref="serchRefs" class="searchContainer"> <div v-for="(row, indexRow) in searchList" class="searchBox" :key="indexRow"> <el-input v-model="ruleForm[row.prop]" clearable :type="row.type ? row.type : 'text'" style="width: 100%" :placeholder="!row.placeholder ? '请输入' : row.placeholder" v-if="row.tag === 'elInput'" min="1"> </el-input> <el-date-picker v-model="ruleForm[row.prop]" v-if="row.tag === 'elDatePicker'" :class="{ one: row.type ? 'date' : row.type }" style="width: 100%" :value-format="!row.valueFormat ? 'yyyy-MM-dd' : row.valueFormat" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" :type="!row.type ? 'date' : row.type" :placeholder="!row.placeholder ? '请选择' : row.placeholder"> </el-date-picker> <el-radio-group v-model="ruleForm[row.prop]" v-if="row.tag === 'elRadio'"> <el-radio-button v-for="el in row.options" :label="el.value" :key="el.value">{{ el.label }} </el-radio-button> </el-radio-group> <div v-if="row.tag === 'elDialog'" class="elDialog" style="cursor: pointer; height: 32px; ine-height: 32px"> <p :style="{ color: ruleForm[row.prop] ? '#000' : '#c0c4cc' }" style="width: 100%; margin: 0" @click="elDialogClick(row, indexRow, indexRow)"> {{ ruleForm[row.prop] ? ruleForm[row.prop] : row.placeholder ? row.placeholder : "请点击选择" }} </p> <i class="el-icon-more" @click="elDialogClick(row, index, indexRow)" v-if="!row.disabled && !ruleForm[row.prop]"></i> <i class="el-icon-circle-close" v-if="!row.disabled && ruleForm[row.prop]" @click="elDialogClear(row)" style="margin-left: 10px"></i> </div> <el-select v-model="ruleForm[row.prop]" filterable style="width: 100%" @change="selectChange($event, indexRow, indexRow, row)" :clearable="row.clearable ? row.clearable : true" :placeholder="!row.placeholder ? '请选择' : row.placeholder" v-if="row.tag === 'elSelect'"> <el-option v-for="(el, elIndex) in row.options" :key="!row.optionValue ? el['value'] : el[row.optionValue]" :label="!row.optionLabel ? el['label'] : el[row.optionLabel]" :value="!row.optionValue ? el['value'] : el[row.optionValue]"> </el-option> </el-select> </div> <!-- 搜索按钮 --> <!-- <el-input auto-complete="off" placeholder="验证码" style="width: calc(100% - 130px)" v-show="false" clearable @keyup.enter.native="testEnter" > </el-input> --> <el-button type="primary" icon="el-icon-search searchIcon" class="searchIcon" v-if="searchBtnShow" @click="search" @keyup.enter="testEnter" style="margin-left: 15px"> </el-button> <el-button type="primary" icon="el-icon-refresh searchIcon" class="searchIcon" v-if="resetBtnShow" @click="refresh"> </el-button> <el-button v-for="item in searchBtnList" :key="item.btnFunction" :type="item.type ? item.type : 'primary'" size="small" class="searchIcon" :icon="item.icon" style="font-size:14px;" @click="funSearchBtnClick(item)"> {{ item.name }} </el-button> </div> <div flex="cross:center" v-if="(searchModel.length != 0 && bottonShow) || nowBtns.length != 0"> <el-button type="primary" icon="el-icon-search" size="small" @click="showSearch" v-if="searchModel.length != 0">检索 </el-button> <el-button type="primary" icon="el-icon-refresh" :plain="true" size="small" @click="refresh" v-if="false">刷新 </el-button> </div> <!-- 主要内容 --> <slot name="main" :tableHeight="tableHeight"></slot> <!-- 分页 --> <base-page v-if="isPage" :pageModel.sync="pageModel" @onPageChange="onPageChange"></base-page> </div> </div> </template> <script> // import heightTransition from '@/common/js/heightTransition' // import customCascader from "@/components/customCascader"; import elementResizeDetectorMaker from "element-resize-detector"; import { exportDown, wordDown, zipDown } from "@/utils/util.js"; import basePage from "@/components/base/basePage"; import { TokenKeys } from "@/utils/variable"; // import fetch from '../../api/request' import { getApiSign } from "@/utils/apiSign"; // import domainsFuc from '@/api/domains.js' export default { components: { // heightTransition, basePage, // customCascader }, props: { // 搜索按钮列表 searchBtnList: { type: Array, default: () => { return []; }, }, // 是否展示标题 showTitle: { type: Boolean, default: true, }, // 是否显示搜索按钮 searchBtnShow: { type: Boolean, default: true, }, // 是否显示重置按钮 resetBtnShow: { type: Boolean, default: true, }, // main高度 mainHight: { type: [Number, String, Boolean], default: "auto", }, // 标题 title: { type: String, default: "", }, // 标题 fixModel: { type: String | Array, default: () => { return []; }, }, // 查询列表 requirementList: { type: Array, default: () => { return []; }, }, // 搜索列表 searchList: { type: Array, default: () => { return []; }, }, // 背景颜色 bgColor: { type: String, default: "#ffffff", }, // 背景颜色 mainColor: { type: String, default: "", }, // 底部padding paddingBottom: { type: String, // default: '68px' }, // 高度 bodyHight: { type: [Number, String], default: "calc(100vh - 88px)", }, // 搜索配置 searchModel: { type: Array, default: () => { return []; }, }, // 搜索配置 nowBtnTab: { type: Array, default: () => { return []; }, }, // 按钮配置 nowBtns: { type: Array, default: () => { return []; }, }, // 按钮配置 buttonList: { type: Array, default: () => { return []; }, }, // 是否展示分页 isPage: { type: Boolean, default: false, }, // 搜索按钮显示 bottonShow: { type: Boolean, default: true, }, // 默认条件隐藏显示 searchShow: { type: Boolean, default: false, }, queryShow: { type: Boolean, default: true, }, enterClickType: { type: Boolean, default: true, }, // 导出接口地址 exportUrl: { default: "", }, // 导入接口地址 importUrl: { default: "", }, //多选 selectTable: { default: "", }, //单选 only: { default: "", }, }, watch: {}, data() { return { // 表单数据 ruleForm: {}, // queryShow: true, onlyUrl: "", clientHeight: "", // 上传请求头 uploadHeaders: {}, // uurl: domainsFuc().domain, uurl: "http://www.wldxt.cn:8089/taizhou/daxitong/crm/", // 参数 model: {}, // 收起/展开搜索 isSearch: false, // 分页数据 pageModel: { total: 0, pageIndex: 1, pageSize: 10, }, // 清除状态 clearState: 0, // 操作按钮 tableHeight: "calc(100vh - 218px)", loading: false, }; }, created() { }, mounted() { this.watchSize(); document.addEventListener("keydown", (e) => { let key = window.event.keyCode; if (key == 13) { this.testEnter(); } }); // window.onresize = () => { // this.clientHeight = document.documentElement.clientHeight; // }, // this.importUpload(); //初始化上传 }, computed: { // menuJson() { // return JSON.parse(localStorage.getItem(TokenKeys.MENU_JSON)) // } }, methods: { watchSize() { const _this = this; var erd = elementResizeDetectorMaker(); if (!this.queryShow) { _this.getTableHight(); } else { erd.listenTo(this.$refs.serchRefs, (element) => { // 这里的this.$refs.fan指定要监听的元素对象,对应的是<div ref=“fan”></div> var height = element.offsetHeight; _this.$nextTick(() => { _this.getTableHight(height); }); }); } }, getTableHight(height = 0) { // 导航栏+标签栏 102 按钮列表64 查询条件64 分页32 102 + 64 + 32 let reduceHight = 0; let windowHeight = this.$refs.baseLayout.offsetHeight; if (this.isPage) { reduceHight = reduceHight + 52; } if (this.queryShow) { let searchHeight = this.$refs.serchRefs.offsetHeight; reduceHight = reduceHight + searchHeight; } if (this.buttonList && this.buttonList.length > 0) { reduceHight = reduceHight + 68; } this.tableHeight = windowHeight - reduceHight + "px"; }, //参数propLabel , 值value getField(propLabel, value) { this.$set(this.ruleForm, propLabel, value); }, setQueryShow(type) { this.queryShow = type; }, elDialogClick(row, index, indexRow) { if (row.disabled) { return; } this.$emit("elDialogClick", row, index); }, elDialogClear(row) { this.resetField(row.prop); this.$emit("elDialogClear", row); }, // 重置表单字段 resetField(field) { if (this.ruleForm[field]) { this.$set(this.ruleForm, field, ""); } }, edit(item) { }, del(item) { }, pageClear() { this.pageModel.pageIndex = 1; }, // importUpload() { // const timestamp = new Date().getTime() + ''; // const sign = getApiSign(timestamp); // this.uploadHeaders['timestamp'] = timestamp; // this.uploadHeaders['appKey'] = TokenKeys.APP_KEY; // this.uploadHeaders['sign'] = sign; // this.uploadHeaders[TokenKeys.ACCESS_TOKEN] = localStorage.getItem(TokenKeys.ACCESS_TOKEN); // }, handleSuccess(res) { const { code, msg, data } = res; if (code && code == 10000) { this.loading = false; this.$vmNews("上传成功", "success"); } else { this.$vmNews(msg); this.loading = false; } }, handleProgress() { this.loading = true; }, handleError() { this.$vmNews("上传失败", "error"); }, // 设置按钮 // 自定义级联选择器返回值 getCascader(value, field) { this.$set(this.model, field, value); }, // 设置分页total值 setPageTotal(total) { this.$set(this.pageModel, "total", total); }, setPageNum(pageNum) { this.$set(this.pageModel, "page", pageNum); }, // 搜索按钮点击事件 funSearchBtnClick(item) { this.$emit("onFuncSearchBtn", item); }, // 返回 goBack() { this.$router.go(-1); }, // 按钮点击事件 funNewClick(item) { if (item.menuName == "刷新") { this.$tab.refreshPage(this.$route); } else { this.$emit("onFuncBtn", item); } }, dropClick(item) { this.$emit("dropClick", item); }, // 查询隐藏展示 queryShowChange() { this.queryShow = !this.queryShow; this.$nextTick(() => { this.watchSize(); }); this.$emit("queryShowChange", this.queryShow); }, // 操作按钮点击事件 funcClick(btnItem) { // console.log(btnItem,"btnItem") this.$emit("onFuncBtn", btnItem); }, // 导出函数 eventExport(params) { // return fetch.get(this.onlyUrl ? this.onlyUrl : this.exportUrl, { // params, // responseType: 'blob' // }) }, // 设置某个参数的值 setSomeParam(field, value = null) { this.$set(this.model, field, value); }, // 查询、重置事件 queryEvent(state) { this.$emit("onQuery", this.mergeParam(true)); }, // 条件查询-下拉框 selectChange(event, index, indexItem, row) { // if (typeof event == "number" && event < 3) { // if (Number(event) == 2) { // event = 0; // } else { // event = event - 1; // } // } if (event !== "" && event != undefined) { this.$emit("onElSelect", event, index, indexItem, this.model, row); } }, // 刷新 refresh() { }, // 页数或每页条数更改时触发 onPageChange() { this.$emit("pageChange", this.mergeParam()); }, // 合并参数 mergeParam(state) { if (state) { this.pageModel.pageIndex = 1; } let page = { pageIndex: this.pageModel.pageIndex, pageSize: this.pageModel.pageSize, }; for (let i in this.model) { if (!this.model[i]) { this.model[i] = null; } } let search = Object.assign({}, page, this.model); return Object.assign({}, page, this.model); }, // 收起展开分页 showSearch() { this.isSearch = !this.isSearch; }, search() { this.$emit("search", this.ruleForm); }, refresh() { this.ruleForm = Object.assign({}, ""); this.$emit("onQuery", this.mergeParam(true)); }, testEnter() { if (this.enterClickType) { this.search(); } }, }, }; </script> <style scoped lang='scss'> p { margin: 0; } ::v-deep .iconfont { font-size: 12px; } .queryIcon { font-size: 16px; color: #606266; margin-right: 16px; cursor: pointer; } .searchIcon { font-size: 18px; /* padding: 0 12px; */ height: 32px; /* line-height: 32px; */ margin-left: 8px; display: flex; justify-content: center; align-items: center; } .requirementList { width: 160px; height: 30px; line-height: 30px; } .container { width: 100%; height: 100%; overflow: auto; .title { /* @include boxBase(100%, 48px, $base-color); */ /* @include fontBase(16px, #fff); */ font-size: 14px; padding: 12px; } .buttonList {} .buttonList+.buttonList { margin-left: 8px; } .main { /* height: auto !important; */ overflow-y: auto; flex-wrap: wrap; /* padding:0 12px; */ .search { height: auto; background: #f5f5f5; border: 1px solid #d8d8d8; padding: 12px; transition: all 0.2s ease-in-out; .row { /* @include fontBase(14px, #333) */ } } .hide { height: 0; } } .main::-webkit-scrollbar { width: 5px; /* background-color: #D8D8D8; */ } .main::-webkit-scrollbar-thumb { border-radius: 5px; width: 5px; background: #b4bccc; } .w-100 { width: 100%; } .mb-12 { margin-bottom: 12px; } .back { cursor: pointer; } } .elDialog { display: flex; /* width: calc(100% - 14px);1 */ align-items: center; justify-content: space-between; border: 1px solid #dcdfe6; border-radius: 4px; padding: 0 15px; cursor: pointer; background-color: white; i { color: #c0c4cc; } } .searchBox { width: 200px; } .searchBox+.searchBox { margin-left: 8px; } ::v-deep.el-radio-button--medium .el-radio-button__inner { padding: 8px !important; } </style>