middle-admin-ant/src/application/mk/basic-pages/list.vue

590 lines
17 KiB
Vue

<template>
<div class="page-body">
<a-row type="flex">
<a-col :flex="$mk.config.ui.searchFlex">
<!-- 搜索区 -->
<vxe-form :data="options.searchFormData" :items="options.searchFormItems" titleColon @submit="onSearch2()">
<template #date="{}">
<a-form-item label="创建时间" :style="{ display: 'inline-block', width: 120 }">
</a-form-item>
<a-form-item :style="{ display: 'inline-block', width: 'calc(100% - 120px )' }">
<a-range-picker @change="onDateChange" />
</a-form-item>
</template>
</vxe-form>
</a-col>
<a-col :flex="$mk.config.ui.toolbarFlex">
<!-- 工具条 -->
<mk-toolbar @toolbarClick="toolbarClick"></mk-toolbar>
</a-col>
</a-row>
<vxe-toolbar ref="xToolbar" custom>
<template #buttons>
<a-button type="primary" icon="delete" @click="pageDelete()">批量删除</a-button>
<a-button type="primary" style="margin-left: 5px;" icon="export" v-if="options.enabledExport"
@click="pageExport()">导出</a-button>
<a-button type="primary" style="margin-left: 5px;" icon="import" v-if="options.enabledImport"
@click="pageImport()">导入</a-button>
<a-button type="default" style="margin-left: 5px;" v-if="options.enabledImportTemplate"
@click="pageImportTemplate()">下载导入模板</a-button>
</template>
</vxe-toolbar>
<!-- 表格区 -->
<div class="gridPanel">
<vxe-grid ref='xGrid' v-bind="options.gridOptions">
<template #op="{ row }">
<div class="oplinks">
<a @click.stop="pageEdit(row)" title="编辑"><a-icon type="edit" /></a>
<a @click.stop="pageDelete(row)" title="删除"><a-icon type="delete" /></a>
</div>
</template>
<template #column1="{ row }">
<slot name="column1" :row="row"></slot>
</template>
</vxe-grid>
</div>
<vxe-modal v-model="showSheetNameSelector" width="500" height="400" title="选择表名">
<template #default>
<div>
<vxe-select v-model="excelSheetName" placeholder="选择表名" style="width:100%">
<vxe-option v-for="n in excelSheetNames" :key="n" :value="n" :label="n"></vxe-option>
</vxe-select>
</div>
<div style="margin-top:10px;">
<vxe-button status="primary" content="确定" @click="importOk"></vxe-button>
</div>
</template>
</vxe-modal>
</div>
</template>
<script>
import FileSaver from 'file-saver'
import * as XLSX from 'xlsx'
import { read, utils } from "xlsx"; // 注意处理方法引入方式
export default {
name: 'BasicPageList',
props: {
options: {
type: Object
}
},
data() {
return {
showSheetNameSelector: false, excelSheetName: '', excelSheetNames: [],
bindSearchData: null
};
},
// 计算属性
computed: {
},
// 创建完成
created() {
let _this = this;
this.$nextTick(() => { // 在下次 DOM 更新循环结束之后执行延迟回调
// 将表格和工具栏进行关联
this.$refs.xGrid.connect(this.$refs.xToolbar) // 将表格和工具栏进行关联
});
this.options.gridOptions.proxyConfig = { // 配置代理
sort: true, // 启用排序代理,当点击排序时会自动触发 query 行为
filter: true, // 启用筛选代理,当点击筛选时会自动触发 query 行为
props: {
result: this.options.listFieldName, // 配置响应结果列表字段
total: 'total' // 配置响应结果总页数字段
},
// 接收Promise
ajax: {
// 当点击工具栏查询按钮或者手动提交指令 query或reload 时会被触发
query: (options) => { // options 为当前表格的配置项
const { page, sorts } = options; // 获取当前页码、每页条数、排序信息
var params = {}; // 定义请求参数
params.page = page.currentPage; // 当前页码
params.limit = page.pageSize; // 每页条数
params.order_bys = []; // 排序信息
params.search_rules = _this.getSearchParms(); // 搜索信息
if (sorts) { // 如果有排序信息
sorts.forEach((v) => { // 遍历排序信息
params.order_bys.push({ // 添加排序信息
column: v.property, // 字段名
order: v.order // 排序方式
})
});
}
return _this.loadData({ params }); // 返回请求结果
}
}
};
},
// 挂载完成
onLoad() {
},
// 动作
methods: {
pageExport() {
let jsonRows = [];
let headerCells = [];
for (let i = 0; i < this.options.exportColumns.length; i++) {
let item = this.options.exportColumns[i];
headerCells.push(item.title);
}
let details = JSON.parse(JSON.stringify(this.$refs.xGrid.getTableData().fullData));
details.forEach(row => {
let jsonRow = {
};
for (let i = 0; i < this.options.exportColumns.length; i++) {
let item = this.options.exportColumns[i];
var v = "";
if (item.valueGetter) {
v = item.valueGetter({ row: row, column: item });
}
else if (item.dataField) {
v = row[item.dataField];
if (item.textField && v) {
v = v[item.textField]
}
} else {
v = row[item.field] || '';
}
jsonRow[item.title] = v;
}
jsonRows.push(jsonRow);
});
var worksheet = XLSX.utils.json_to_sheet(jsonRows, { header: headerCells, skipHeader: false });
const workbook = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(workbook, worksheet, "Sheet1");
/* get binary string as output */
var wbout = XLSX.write(workbook, { bookType: 'xlsx', bookSST: true, type: 'array' })
try {
FileSaver.saveAs(new Blob([wbout], { type: 'application/octet-stream' }), (this.options.exportFileTitle || '导出数据') + '.xlsx')
} catch (e) {
if (typeof console !== 'undefined') {
console.log(e, wbout)
}
}
},
pageImportTemplate() {
let jsonRows = [];
let headerCells = [];
for (let i = 0; i < this.options.exportColumns.length; i++) {
let item = this.options.exportColumns[i];
headerCells.push(item.title);
}
var worksheet = XLSX.utils.json_to_sheet(jsonRows, { header: headerCells, skipHeader: false });
const workbook = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(workbook, worksheet, "Sheet1");
/* get binary string as output */
var wbout = XLSX.write(workbook, { bookType: 'xlsx', bookSST: true, type: 'array' })
try {
FileSaver.saveAs(new Blob([wbout], { type: 'application/octet-stream' }), '导入模板.xlsx')
} catch (e) {
if (typeof console !== 'undefined') {
console.log(e, wbout)
}
}
},
pageImport() {
let fileForm = document.createElement('form');
let fileInput = document.createElement('input');
fileForm.className = 'vxe-table--file-form';
fileInput.name = 'file';
fileInput.type = 'file';
fileForm.appendChild(fileInput);
document.body.appendChild(fileForm);
fileInput.multiple = false;
fileInput.accept = '';
fileInput.onchange = (evnt) => {
var files = evnt.target.files;
var file = files[0];
this.readExcel(file)
};
fileForm.reset();
fileInput.click();
},
readExcel(file) {
const fileReader = new FileReader();
this.$mk.loading("读取中...");
fileReader.onload = ev => {
try {
const data = ev.target.result;
const workbook = read(data, { type: "binary" });
this.workbook = workbook;
this.excelSheetNames = workbook.SheetNames;
this.showSheetNameSelector = true;
this.$mk.hideLoading();
} catch (e) {
console.log("error:" + e);
return false;
}
}
fileReader.readAsBinaryString(file);
},
importOk() {
this.showSheetNameSelector = false;
const { workbook, excelSheetName } = this;
if (!excelSheetName) {
return;
}
let tableData = utils.sheet_to_json(workbook.Sheets[excelSheetName]);
this.$emit("importData", { data: tableData });
},
// 修改日期
onDateChange(date) { // 日期选择器事件
if (date && date.length) { // 如果有值
date[0]._d.setHours(0, 0, 0, 0);
date[1]._d.setHours(23, 59, 59, 59);
this.start_time = parseInt(date[0]._d.getTime() / 1000); // 将日期转换为时间戳
this.end_time = parseInt(date[1]._d.getTime() / 1000); // 将日期转换为时间戳
} else { // 如果没有值
this.start_time = 0; // 将日期转换为时间戳
this.end_time = 0; // 将日期转换为时间戳
}
},
// 获取搜索参数
getSearchParms() { // 获取搜索参数
var rules = []; // 定义搜索参数
let findMode = k => { // 查找搜索模式
for (let i in this.options.searchRules) { // 遍历搜索规则
if (this.options.searchRules[i].key == k) return this.options.searchRules[i].mode; // 如果找到了就返回搜索模式
}
return "="; // 如果没有找到就返回等于
};
for (let key in this.options.searchFormData) { // 遍历搜索表单数据
let value = this.options.searchFormData[key]; // 获取值
if (value) { // 如果有值
let mode = findMode(key); // 获取搜索模式
if (mode == "like") { // 如果是模糊搜索
value = "%" + value + "%"; // 如果是模糊搜索就在两边加上%
}
if (typeof (value) == "object" && value.id) {
value = value.id;
}
rules.push({ // 添加搜索参数
column: key, // 字段名
mode: mode, // 搜索模式
value: value // 值
});
}
}
if (this.bindSearchData) {
for (let key in this.bindSearchData) { // 遍历搜索表单数据
let value = this.bindSearchData[key]; // 获取值
if (value) { // 如果有值
let mode = findMode(key); // 获取搜索模式
if (mode == "like") { // 如果是模糊搜索
value = "%" + value + "%"; // 如果是模糊搜索就在两边加上%
}
rules.push({ // 添加搜索参数
column: key, // 字段名
mode: mode, // 搜索模式
value: value // 值
});
}
}
}
return rules; // 返回搜索参数
},
// 获取选中行
getSelectdRow() { // 获取选中行
let row = this.$refs.xGrid.getCurrentRecord(); // 获取当前行
if (!row) { // 如果没有选中行
let rows = this.$refs.xGrid.getCheckboxRecords(); // 获取选中行
if (rows && rows.length) { row = rows[0]; } // 如果有选中行就取第一行
}
return row; // 返回选中行
},
// 加载数据
loadData({ params }) {
params.start_time = this.start_time; // 开始时间
params.end_time = this.end_time; // 结束时间
return this.$mk.getPagedData({
url: this.options.actions.getList,
data: params
});
},
// 工具栏点击事件 add / log / setting
toolbarClick(e) {
if (e.name == "add") { // 如果是添加
if (this.options.editPage) {
this.$mk.dialog.open({
page: this.options.editPage,
title: this.options.editPageTitle,
pageOptions: {
},
width: this.$mk.getWindowSize().width * 0.9,
height: this.$mk.getWindowSize().height * 0.9,
dataId: 0,
callback: ({ success }) => {
if (success) {
this.$refs.xGrid.commitProxy('query')
}
}
});
} else {
this.$openPage(this.options.addPageUrl); // 打开页面
}
}
},
getPageList() {
let target = [];
let find = (component) => {
if (component && component.pageList) {
target = component.pageList;
}
if (component.$parent) {
find(component.$parent)
}
}
find(this.$parent);
return target;
},
isEditPageOpen() {
let pageList = this.getPageList();
if (pageList.filter(a => a.keyPath && a.keyPath.indexOf(this.options.editPageUrl) == 0).length) {
return true;
}
return false;
},
getTabsViewPageComponent() {
let target = null;
let find = (component) => {
if (component && component.pageList) {
target = component;
}
if (component.$parent) {
find(component.$parent)
}
}
find(this.$parent);
return target;
},
//找到定义了beforeTabClose方法 的页面组件
findEditPageComponent(key) {
if (!key) {
return null;
}
let target = null;
let find = (children) => {
children.forEach(item => {
if (item.beforeTabClose && item.pageKeys && item.pageKeys.filter(a => key.indexOf(a) == 0).length) {
target = item;
return;
}
if (item.$children && item.$children.length) {
find(item.$children)
}
})
}
let tabsview = this.getTabsViewPageComponent();
if (tabsview == null) {
return null;
}
find(tabsview.$children);
return target;
},
// 编辑
pageEdit(row) {
if (!row) { // 如果没有选中行
this.$mk.msg("请选择行"); // 提示
return; // 返回
}
if (this.isEditPageOpen()) {
let editPage = this.findEditPageComponent(this.options.editPageUrl);
if (editPage != null) {
editPage.beforeTabClose().then(() => {
this.$closePage(this.options.editPageUrl);
this.showPageEdit(row[this.options.keyName]); // 打开页面
});
} else {
this.showPageEdit(row[this.options.keyName]); // 打开页面
}
} else {
this.showPageEdit(row[this.options.keyName]); // 打开页面
}
},
showPageEdit(dataId) {
if (this.options.editPage) {
this.$mk.dialog.open({
page: this.options.editPage,
title: this.options.editPageTitle,
pageOptions: {
},
width: this.$mk.getWindowSize().width * 0.9,
height: this.$mk.getWindowSize().height * 0.9,
dataId: dataId,
callback: ({ success }) => {
if (success) {
this.$refs.xGrid.commitProxy('query')
}
}
});
} else {
this.$openPage(this.options.editPageUrl + dataId);
}
},
// 删除
pageDelete(row) {
let rows = row ? [row] : this.$refs.xGrid.getCheckboxRecords(); // 获取选中行
let ids = []; // 定义id数组
rows.forEach((row) => { // 遍历选中行
ids.push(row[this.options.keyName]); // 将选择行的id添加到id数组
});
if (!ids.length) { // 如果没有选中行
this.$mk.error("请选择行"); // 提示
return;
}
let delParms = {};
let url = this.options.actions.delete;
if (url.indexOf('batchDelete') != -1) {
delParms = {
ids: ids
}
} else {
delParms = {
id: ids[0]
}
}
this.$mk.confirm('您确定要删除吗?').then(type => { // 确认删除
if (type == 'confirm') { // 如果确认删除
this.$mk.post({
url: url, // 请求删除数据地址
loading: "删除中...", // 加载提示
data: delParms,
useBigInt: true
}).then(() => { // 成功
this.$mk.success("删除成功"); // 提示成功
this.$refs.xGrid.commitProxy('query') // 提交搜索
}).catch((a) => { // 失败
this.$mk.error(a.data.msg); // 提示错误信息
});
}
});
},
// 搜索
onSearch2() {
this.$refs.xGrid.commitProxy('query') // 提交搜索
},
onSearch(arg) {
this.bindSearchData = arg;
this.$refs.xGrid.commitProxy('query') // 提交搜索
},
gridReload() {
this.$refs.xGrid.commitProxy('query')
},
getConfirmData() {
let rows = this.$refs.xGrid.getCheckboxRecords();
return rows;
},
},
// 监听属性
watch: {
}
};
</script>
<style scoped lang="less">
.page-body {
padding: 15px;
background: @base-bg-color;
}
.gridPanel {
height: calc(100vh - 220px);
}
.oplinks svg {
width: 22px;
height: 22px;
margin: 0 5px 0 0;
}
</style>