middleground_code_v2/src/components/base/baseLayout/index.vue

683 lines
19 KiB
Vue
Raw Normal View History

2024-03-26 11:18:19 +08:00
<!--
* @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() {
this.$emit("onQuery", this.mergeParam(true));
},
// 页数或每页条数更改时触发
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({}, "");
},
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>