Files
tms-erp-web/src/views/business/common-route.vue

1044 lines
33 KiB
Vue
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<basic-container class="common-route-page">
<avue-crud
:option="option"
:table-loading="loading"
:data="data"
v-model:page="page"
v-model="form"
ref="crud"
:permission="permissionList"
:before-open="beforeOpen"
@row-save="rowSave"
@row-update="rowUpdate"
@row-del="rowDel"
@search-change="searchChange"
@search-reset="searchReset"
@selection-change="selectionChange"
@current-change="currentChange"
@size-change="sizeChange"
@refresh-change="refreshChange"
@on-load="onLoad"
>
<template #menu-left>
<el-button
type="primary"
icon="el-icon-plus"
v-if="hasPermission('common_route_add')"
@click="$refs.crud.rowAdd()"
>新建路线
</el-button>
<el-button
type="primary"
icon="el-icon-upload"
plain
v-if="config.importUrl && hasPermission('common_route_import')"
@click="handleImport"
>批量导入
</el-button>
<el-button
type="primary"
icon="el-icon-download"
plain
v-if="config.templateUrl && hasPermission('common_route_template')"
@click="handleTemplate"
>下载模板
</el-button>
<el-button
type="primary"
icon="el-icon-download"
plain
v-if="config.exportUrl && hasPermission('common_route_export')"
@click="handleExport"
>批量导出
</el-button>
<el-button
type="danger"
icon="el-icon-delete"
plain
v-if="hasPermission('common_route_delete')"
@click="handleDelete"
>批量删除
</el-button>
</template>
<template #departureAddress-form>
<div class="common-route-page__route-address">
<el-input
v-model="form.departureName"
readonly
placeholder="自动带出"
:disabled="dialogReadonly"
/>
<el-input
v-model="form.departureAddress"
placeholder="请输入并选择地址"
suffix-icon="el-icon-location"
:disabled="dialogReadonly"
@click="openRouteMapDialog('departure')"
/>
<el-tooltip content="选择常用地址" placement="top">
<el-button
type="primary"
:icon="List"
link
:disabled="dialogReadonly"
@click="openAddressDialog('departure')"
/>
</el-tooltip>
</div>
</template>
<template #arrivalAddress-form>
<div class="common-route-page__route-address">
<el-input
v-model="form.arrivalName"
readonly
placeholder="自动带出"
:disabled="dialogReadonly"
/>
<el-input
v-model="form.arrivalAddress"
placeholder="请输入并选择地址"
suffix-icon="el-icon-location"
:disabled="dialogReadonly"
@click="openRouteMapDialog('arrival')"
/>
<el-tooltip content="选择常用地址" placement="top">
<el-button
type="primary"
:icon="List"
link
:disabled="dialogReadonly"
@click="openAddressDialog('arrival')"
/>
</el-tooltip>
</div>
</template>
<template #menu="{ row, index }">
<el-link
type="primary"
v-if="hasPermission('common_route_view')"
@click="$refs.crud.rowView(row, index)"
>
查看
</el-link>
<el-link
type="primary"
v-if="hasPermission('common_route_edit') && !row.readonly"
@click="$refs.crud.rowEdit(row, index)"
>
编辑
</el-link>
<el-link
type="primary"
v-if="hasPermission('common_route_delete') && !row.readonly"
@click="rowDel(row)"
>
删除
</el-link>
</template>
</avue-crud>
<empty-pagination
:page="page"
@size-change="sizeChange"
@current-change="currentChange"
@load="onLoad(page, query)"
/>
<el-dialog :title="`${config.title}导入`" append-to-body v-model="excelBox" width="555px">
<avue-form :option="excelOptionConfig" v-model="excelForm">
<template #excelTemplate>
<el-button type="primary" @click="handleTemplate">
点击下载<i class="el-icon-download el-icon--right"></i>
</el-button>
</template>
</avue-form>
</el-dialog>
<el-dialog
title="选择常用地址"
append-to-body
v-model="addressDialogVisible"
width="1080px"
class="common-route-page__address-dialog"
@opened="loadAddressList"
>
<section-card title="查询条件">
<div class="common-route-page__address-search">
<el-form :model="addressQuery" label-position="right" label-width="86px">
<el-row :gutter="16">
<el-col :span="6">
<el-form-item label="地址名称">
<el-input v-model="addressQuery.addressName" clearable placeholder="请输入" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="地址类型">
<el-select
v-model="addressQuery.addressType"
clearable
placeholder="请选择"
style="width: 100%"
>
<el-option
v-for="item in addressTypeOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="详细地址">
<el-input v-model="addressQuery.detailAddress" clearable placeholder="请输入" />
</el-form-item>
</el-col>
<el-col :span="6" class="common-route-page__address-search-actions">
<el-button type="primary" @click="handleAddressSearch">查询</el-button>
<el-button @click="handleAddressReset">重置</el-button>
</el-col>
<el-col :span="6">
<el-form-item label="组织">
<el-select
v-model="addressQuery.deptId"
clearable
filterable
placeholder="请选择"
style="width: 100%"
>
<el-option
v-for="item in deptOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
</section-card>
<section-card title="常用地址">
<el-table
border
:data="addressData"
v-loading="addressLoading"
height="310"
highlight-current-row
@row-click="selectAddressRow"
>
<el-table-column type="index" label="序号" width="80" align="center" />
<el-table-column prop="addressName" label="地址名称" min-width="150" />
<el-table-column prop="addressCode" label="地址编号" min-width="150" />
<el-table-column prop="addressType" label="类型" min-width="150" />
<el-table-column label="站点编码" min-width="170">
<template #default="{ row }">
{{ row.addressType === '常规地址' ? '/' : row.siteCodeDisplay || row.siteCode || '' }}
</template>
</el-table-column>
<el-table-column prop="detailAddress" label="详细地址" min-width="220" />
<el-table-column label="操作" width="120" fixed="right">
<template #default="{ row }">
<el-link type="primary" @click.stop="selectAddressRow(row)">选择</el-link>
</template>
</el-table-column>
</el-table>
<div class="common-route-page__address-pagination">
<el-pagination
v-model:current-page="addressPage.currentPage"
v-model:page-size="addressPage.pageSize"
:page-sizes="[10, 20, 50, 100]"
layout="total, prev, pager, next, sizes"
:total="addressPage.total"
@size-change="handleAddressSizeChange"
@current-change="handleAddressCurrentChange"
/>
</div>
</section-card>
<template #footer>
<el-button @click="addressDialogVisible = false">关闭</el-button>
</template>
</el-dialog>
<el-dialog
title="地图选择地址"
append-to-body
v-model="routeMapVisible"
width="920px"
@opened="initRouteAmap"
>
<div class="common-route-page__map-toolbar">
<el-input
v-model="routeMapKeyword"
clearable
placeholder="输入地址关键词"
@keyup.enter="searchRouteMapKeyword"
/>
<el-button
type="primary"
:icon="Search"
:loading="routeMapLoading"
@click="searchRouteMapKeyword"
>
搜索
</el-button>
</div>
<div ref="routeAmap" class="common-route-page__map"></div>
<div class="common-route-page__map-info">
<span>{{ routeMapStatus }}</span>
<span v-if="routeMapSelected.regionName"
>发货/收货地{{ routeMapSelected.regionName }}</span
>
</div>
<template #footer>
<el-button @click="routeMapVisible = false">取消</el-button>
<el-button
type="primary"
:disabled="!routeMapSelected.longitude"
@click="confirmRouteMapPick"
>
确定
</el-button>
</template>
</el-dialog>
</basic-container>
</template>
<script>
import * as api from '@/api/business/common-route';
import { getList as getCommonAddressList } from '@/api/base/common-address';
import { exportBlob } from '@/api/common';
import { getDeptTree } from '@/api/system/dept';
import { addressTypeOptions } from '@/option/base/common-address';
import { config, excelOption, option } from '@/option/business/common-route';
import { getToken } from '@/utils/auth';
import { openImportDialog } from '@/utils/import-excel';
import { downloadXls } from '@/utils/util';
import { List, Search } from '@element-plus/icons-vue';
import { mapGetters } from 'vuex';
import NProgress from 'nprogress';
import 'nprogress/nprogress.css';
const AMAP_KEY = '653b7cf105ad7fb8ec9b2f5198ade315';
const AMAP_SECURITY_CODE = '5aab65c632e48ebae0d0e28f5b28e21a';
let amapLoader;
export default {
data() {
return {
List,
Search,
config,
option,
form: {},
query: {},
loading: true,
data: [],
dialogReadonly: false,
excelBox: false,
excelForm: {},
excelOptionConfig: excelOption,
addressTypeOptions,
addressDialogVisible: false,
addressTarget: '',
addressQuery: {},
addressData: [],
addressLoading: false,
routeMapVisible: false,
routeMapTarget: '',
routeMapLoading: false,
routeMapKeyword: '',
routeMapStatus: '可搜索地址或点击地图选点',
routeMapSelected: {},
routeAmap: null,
routeAmapMarker: null,
routeAmapGeocoder: null,
deptOptions: [],
page: {
pageSize: 10,
pageSizes: [10, 20, 50, 100],
currentPage: 1,
total: 0,
},
addressPage: {
pageSize: 10,
currentPage: 1,
total: 0,
},
selectionList: [],
};
},
computed: {
...mapGetters(['permission', 'userInfo']),
permissionList() {
return {
addBtn: this.hasPermission('common_route_add'),
};
},
isAdmin() {
const authority = this.userInfo && this.userInfo.authority;
return Array.isArray(authority)
? authority.includes('admin')
: String(authority || '').includes('admin');
},
ids() {
return this.selectionList.map(item => item.id).join(',');
},
},
created() {
this.initDeptTree();
},
methods: {
hasPermission(code) {
return this.isAdmin || this.validData(this.permission && this.permission[code], false);
},
initDeptTree() {
getDeptTree(this.userInfo.tenantId).then(res => {
const deptTree = res.data.data || [];
this.deptOptions = this.flattenDept(deptTree);
const deptColumn = this.findColumn(this.option.column, 'searchDeptId');
if (deptColumn) {
deptColumn.dicData = this.buildDeptTree(deptTree);
}
});
},
buildDeptTree(tree) {
return tree.map(item => ({
label: item.title || item.deptName || item.name,
value: item.id,
children:
item.children && item.children.length ? this.buildDeptTree(item.children) : undefined,
}));
},
flattenDept(tree, level = 0) {
const result = [];
tree.forEach(item => {
result.push({
label: `${' '.repeat(level)}${item.title || item.deptName || item.name}`,
value: item.id,
});
if (item.children && item.children.length) {
result.push(...this.flattenDept(item.children, level + 1));
}
});
return result;
},
defaultDeptId() {
return (this.userInfo && (this.userInfo.deptId || this.userInfo.dept_id)) || '';
},
resetAddressQuery() {
this.addressQuery = {
addressName: '',
addressType: '',
detailAddress: '',
deptId: this.defaultDeptId(),
};
},
openAddressDialog(target) {
if (this.dialogReadonly) return;
this.addressTarget = target;
this.addressPage.currentPage = 1;
this.resetAddressQuery();
this.addressDialogVisible = true;
},
handleAddressSearch() {
this.addressPage.currentPage = 1;
this.loadAddressList();
},
handleAddressReset() {
this.addressPage.currentPage = 1;
this.resetAddressQuery();
this.loadAddressList();
},
handleAddressSizeChange(pageSize) {
this.addressPage.pageSize = pageSize;
this.addressPage.currentPage = 1;
this.loadAddressList();
},
handleAddressCurrentChange(currentPage) {
this.addressPage.currentPage = currentPage;
this.loadAddressList();
},
loadAddressList() {
this.addressLoading = true;
getCommonAddressList(this.addressPage.currentPage, this.addressPage.pageSize, {
...this.addressQuery,
allDept: 0,
})
.then(res => {
const data = res.data.data || {};
this.addressPage.total = data.total || 0;
this.addressData = data.records || [];
})
.finally(() => {
this.addressLoading = false;
});
},
selectAddressRow(row) {
if (!row) return;
this.applyAddress(this.addressTarget, row);
this.addressDialogVisible = false;
},
applyAddress(target, address) {
if (!target || !address) return;
const prefix = target === 'departure' ? 'departure' : 'arrival';
this.form[`${prefix}Name`] = address.addressName || '';
this.form[`${prefix}Address`] = address.detailAddress || '';
this.form[`${prefix}AddressCode`] = address.addressCode || '';
this.form[`${prefix}SiteCode`] =
address.addressType === '常规地址'
? '/'
: address.siteCodeDisplay || address.siteCode || '';
this.form[`${prefix}Longitude`] = address.longitude || '';
this.form[`${prefix}Latitude`] = address.latitude || '';
this.form[`${prefix}Contact`] = address.contactName || this.form[`${prefix}Contact`] || '';
this.form[`${prefix}Phone`] = address.contactPhone || this.form[`${prefix}Phone`] || '';
},
openRouteMapDialog(target) {
if (this.dialogReadonly) return;
const prefix = target === 'departure' ? 'departure' : 'arrival';
this.routeMapTarget = prefix;
this.routeMapKeyword = this.form[`${prefix}Address`] || this.form[`${prefix}Name`] || '';
this.routeMapSelected = this.buildRouteMapSelection({
lng: this.form[`${prefix}Longitude`],
lat: this.form[`${prefix}Latitude`],
address: this.form[`${prefix}Address`],
regionName: this.form[`${prefix}Name`],
});
this.routeMapStatus = this.routeMapSelected.longitude
? '已加载当前选点,可重新选点'
: '可搜索地址或点击地图选点';
this.routeMapVisible = true;
},
loadAmap() {
if (window.AMap && window.AMap.Map) {
return Promise.resolve();
}
if (!amapLoader) {
amapLoader = new Promise((resolve, reject) => {
window._AMapSecurityConfig = {
securityJsCode: AMAP_SECURITY_CODE,
};
const script = document.createElement('script');
script.src = `https://webapi.amap.com/maps?v=2.0&key=${AMAP_KEY}`;
script.async = true;
script.onload = resolve;
script.onerror = () => reject(new Error('高德地图组件加载失败'));
document.body.appendChild(script);
});
}
return amapLoader;
},
initRouteAmap() {
this.loadAmap()
.then(() => {
this.$nextTick(() => {
if (!this.routeAmap) {
const center = this.toLngLat(
this.routeMapSelected.longitude || 116.40769,
this.routeMapSelected.latitude || 39.89945
);
this.routeAmap = new window.AMap.Map(this.$refs.routeAmap, {
center,
zoom: this.routeMapSelected.longitude ? 14 : 11,
});
window.AMap.plugin(['AMap.ToolBar', 'AMap.Geocoder'], () => {
this.routeAmap.addControl(new window.AMap.ToolBar());
if (!this.routeAmapGeocoder) {
this.routeAmapGeocoder = new window.AMap.Geocoder();
}
});
this.routeAmap.on('click', event => this.pickRouteMapPoint(event.lnglat));
} else if (typeof this.routeAmap.resize === 'function') {
this.routeAmap.resize();
}
if (this.routeMapSelected.longitude) {
this.renderRouteMapMarker(
this.toLngLat(this.routeMapSelected.longitude, this.routeMapSelected.latitude)
);
}
});
})
.catch(() => {
this.$message.error('高德地图组件加载失败,请稍后重试或重新打开弹窗');
this.routeMapVisible = false;
});
},
searchRouteMapKeyword() {
const keyword = String(this.routeMapKeyword || '').trim();
if (!keyword) {
this.$message.warning('请输入地址关键词');
return;
}
this.loadAmap()
.then(() => {
this.routeMapLoading = true;
return this.ensureRouteAmapGeocoder();
})
.then(() => this.runAmapGeocode('location', keyword))
.then(result => {
const point = this.resolveMapPoint(result);
if (!point) {
this.routeMapStatus = '未找到匹配地址';
this.$message.warning('地图搜索无匹配地址');
return;
}
this.pickRouteMapPoint(point, keyword);
})
.catch(() => {
this.routeMapStatus = '地图搜索失败';
this.$message.error('地图搜索失败,请稍后重试');
})
.finally(() => {
this.routeMapLoading = false;
});
},
pickRouteMapPoint(lnglat, keyword) {
const longitude = this.getPointLng(lnglat);
const latitude = this.getPointLat(lnglat);
if (longitude === undefined || latitude === undefined) {
this.$message.warning('选点坐标无效');
return;
}
const point = this.toLngLat(longitude, latitude);
this.renderRouteMapMarker(point);
this.routeMapSelected = this.buildRouteMapSelection({
lng: longitude,
lat: latitude,
address: keyword,
});
this.routeMapStatus = '正在反查地址...';
this.ensureRouteAmapGeocoder()
.then(() => this.runAmapGeocode('address', point))
.then(result => {
const address = this.resolveMapAddress(result);
this.routeMapSelected = {
...this.routeMapSelected,
detailAddress: address.detailAddress || this.routeMapSelected.detailAddress,
regionName: address.regionName || this.routeMapSelected.regionName,
};
this.routeMapKeyword = this.routeMapSelected.detailAddress || this.routeMapKeyword;
this.routeMapStatus = this.routeMapSelected.detailAddress || '已选点,可确认回填';
})
.catch(() => {
this.routeMapStatus = '反查地址失败';
this.$message.error('反查地址失败,请重新选点');
});
},
renderRouteMapMarker(point) {
if (!this.routeAmap || !window.AMap) return;
if (this.routeAmapMarker) {
this.routeAmapMarker.setMap(null);
}
this.routeAmapMarker = new window.AMap.Marker({ position: point });
this.routeAmapMarker.setMap(this.routeAmap);
this.routeAmap.setCenter(point);
},
confirmRouteMapPick() {
if (!this.routeMapSelected.longitude) {
this.$message.warning('请先搜索或点击地图完成选点');
return;
}
const prefix = this.routeMapTarget;
this.form[`${prefix}Address`] =
this.routeMapSelected.detailAddress || this.form[`${prefix}Address`];
this.form[`${prefix}Name`] = this.routeMapSelected.regionName || this.form[`${prefix}Name`];
this.form[`${prefix}Longitude`] = this.routeMapSelected.longitude;
this.form[`${prefix}Latitude`] = this.routeMapSelected.latitude;
this.routeMapVisible = false;
this.$refs.crud?.validateField?.(`${prefix}Address`);
},
buildRouteMapSelection({ lng, lat, address, regionName }) {
return {
longitude: this.formatCoordinate(lng),
latitude: this.formatCoordinate(lat),
detailAddress: address || '',
regionName: regionName || '',
};
},
formatCoordinate(value) {
if (value === undefined || value === null || value === '') return '';
const numberValue = Number(value);
return Number.isFinite(numberValue) ? numberValue.toFixed(6) : '';
},
toLngLat(lng, lat) {
return new window.AMap.LngLat(Number(lng), Number(lat));
},
getPointLng(point) {
if (!point) return undefined;
if (typeof point.getLng === 'function') return point.getLng();
return point.lng ?? point.lon;
},
getPointLat(point) {
if (!point) return undefined;
if (typeof point.getLat === 'function') return point.getLat();
return point.lat;
},
ensureRouteAmapGeocoder() {
if (this.routeAmapGeocoder) return Promise.resolve(this.routeAmapGeocoder);
return new Promise((resolve, reject) => {
if (!window.AMap || !window.AMap.plugin) {
reject(new Error('高德地图组件未就绪'));
return;
}
window.AMap.plugin(['AMap.Geocoder'], () => {
try {
this.routeAmapGeocoder = new window.AMap.Geocoder();
resolve(this.routeAmapGeocoder);
} catch (error) {
reject(error);
}
});
});
},
runAmapGeocode(action, input) {
return new Promise((resolve, reject) => {
const timer = window.setTimeout(() => {
reject(new Error('高德地图请求超时'));
}, 10000);
const done = (status, result) => {
window.clearTimeout(timer);
if (status === 'complete' && result) {
resolve(result);
return;
}
reject(new Error('高德地图请求失败'));
};
try {
if (action === 'location') {
this.routeAmapGeocoder.getLocation(input, done);
} else {
this.routeAmapGeocoder.getAddress(input, done);
}
} catch (error) {
window.clearTimeout(timer);
reject(error);
}
});
},
resolveMapPoint(result) {
if (!result) return null;
const geocode = Array.isArray(result.geocodes) ? result.geocodes[0] : null;
if (geocode && geocode.location) return geocode.location;
if (result.location) return result.location;
if (result.lnglat) return result.lnglat;
if (result.getLng || result.lng || result.lon) return result;
return null;
},
resolveMapAddress(result = {}) {
const regeocode = result.regeocode || {};
const component = regeocode.addressComponent || {};
const city = Array.isArray(component.city) ? '' : component.city;
return {
detailAddress: regeocode.formattedAddress || '',
regionName: [component.province, city, component.district].filter(Boolean).join(''),
};
},
normalizeRow(row) {
const submitRow = { ...row };
Object.keys(submitRow).forEach(key => {
if (typeof submitRow[key] === 'string') {
submitRow[key] = submitRow[key].trim();
}
});
return submitRow;
},
validateRow(row) {
if (!row.routeName) {
this.$message.warning('请输入线路名称');
return false;
}
if (row.routeName.length > 100) {
this.$message.warning('线路名称不能超过100个字符');
return false;
}
if (!row.departureName || !row.departureAddress) {
this.$message.warning('请选择发货地址');
return false;
}
if (!row.arrivalName || !row.arrivalAddress) {
this.$message.warning('请选择收货地址');
return false;
}
if (row.departureAddress.length > 255) {
this.$message.warning('发货地址不能超过255个字符');
return false;
}
if (row.arrivalAddress.length > 255) {
this.$message.warning('收货地址不能超过255个字符');
return false;
}
if (row.remark && row.remark.length > 500) {
this.$message.warning('备注不能超过500个字符');
return false;
}
return true;
},
stopSubmitLoading(loading) {
if (typeof loading === 'function') {
loading();
}
},
rowSave(row, done, loading) {
const submitRow = this.normalizeRow(row);
if (!this.validateRow(submitRow)) {
this.stopSubmitLoading(loading);
return;
}
api.submit(submitRow).then(
() => {
this.onLoad(this.page);
this.$message({ type: 'success', message: '操作成功!' });
done();
},
error => {
window.console.log(error);
this.stopSubmitLoading(loading);
}
);
},
rowUpdate(row, index, done, loading) {
const submitRow = this.normalizeRow(row);
if (!this.validateRow(submitRow)) {
this.stopSubmitLoading(loading);
return;
}
api.submit(submitRow).then(
() => {
this.onLoad(this.page);
this.$message({ type: 'success', message: '操作成功!' });
done();
},
error => {
window.console.log(error);
this.stopSubmitLoading(loading);
}
);
},
rowDel(row) {
this.$confirm('确定将选择数据删除?', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(() => api.remove(row.id))
.then(res => {
this.afterRemove(res.data.data);
});
},
handleDelete() {
if (this.selectionList.length === 0) {
this.$message.warning('请选择至少一条数据');
return;
}
const selection = this.selectionList.filter(item => !item.readonly);
if (!selection.length) {
this.$message.warning('所选数据均为只读数据');
return;
}
this.$confirm('确定将选择数据删除?', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(() => api.remove(selection.map(item => item.id).join(',')))
.then(res => {
this.afterRemove(res.data.data);
});
},
afterRemove(result = {}) {
this.onLoad(this.page);
const successCount = result.successCount || 0;
const skippedCount = result.skippedCount || 0;
if (skippedCount) {
this.$message.warning(`成功删除${successCount}条,因业务引用跳过${skippedCount}`);
} else {
this.$message({ type: 'success', message: '删除成功!' });
}
this.selectionClear();
},
beforeOpen(done, type) {
this.dialogReadonly = type === 'view';
if (type === 'add') {
this.form = {};
done();
return;
}
if (['edit', 'view'].includes(type)) {
api.getDetail(this.form.id).then(res => {
this.form = res.data.data || {};
done();
});
return;
}
done();
},
searchReset() {
this.query = {};
this.page.currentPage = 1;
this.onLoad(this.page);
},
searchChange(params, done) {
this.query = params;
this.page.currentPage = 1;
this.onLoad(this.page, params);
done();
},
selectionChange(list) {
this.selectionList = list;
},
selectionClear() {
this.selectionList = [];
if (this.$refs.crud) {
this.$refs.crud.toggleSelection();
}
},
currentChange(currentPage) {
this.page.currentPage = currentPage;
},
sizeChange(pageSize) {
this.page.pageSize = pageSize;
},
refreshChange() {
this.onLoad(this.page, this.query);
},
onLoad(page, params = {}) {
this.loading = true;
api
.getList(page.currentPage, page.pageSize, { ...params, ...this.query, allDept: 0 })
.then(res => {
const result = res.data.data;
this.page.total = result.total;
this.data = result.records;
this.selectionClear();
})
.finally(() => {
this.loading = false;
});
},
buildExportParams() {
return {
...this.query,
allDept: 0,
ids: this.ids,
[this.website.tokenHeader]: getToken(),
};
},
handleExport() {
this.$confirm(`是否导出${config.exportName}?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}).then(() => {
NProgress.start();
exportBlob(config.exportUrl, this.buildExportParams(), { feedback: true })
.then(res => {
downloadXls(
res.data,
`${config.exportName}${this.$dayjs().format('YYYY-MM-DD HH:mm:ss')}.xlsx`
);
})
.finally(() => {
NProgress.done();
});
});
},
handleTemplate() {
NProgress.start();
exportBlob(
config.templateUrl,
{
[this.website.tokenHeader]: getToken(),
},
{ feedback: true }
)
.then(res => {
downloadXls(res.data, `${config.title}模板.xlsx`);
})
.finally(() => {
NProgress.done();
});
},
handleImport() {
const column = this.excelOptionConfig.column.find(item => item.prop === 'excelFile');
column.action = config.importUrl;
openImportDialog(this, config.title, () => this.onLoad(this.page, this.query));
},
},
};
</script>
<style lang="scss" scoped>
.common-route-page {
&__route-address {
display: flex;
gap: 10px;
align-items: center;
.el-input {
flex: 1;
min-width: 0;
}
.el-input:first-child {
flex: 0 0 34%;
}
.el-button {
flex: 0 0 40px;
font-size: 30px;
}
}
&__address-search {
padding: 4px 8px 10px;
}
&__address-search-actions {
display: flex;
align-items: flex-start;
justify-content: flex-end;
}
&__address-pagination {
display: flex;
justify-content: flex-end;
margin-top: 14px;
}
&__map-toolbar {
display: flex;
gap: 8px;
margin-bottom: 12px;
.el-input {
flex: 1;
min-width: 0;
}
}
&__map {
width: 100%;
height: 420px;
border: 1px solid #eff1f7;
}
&__map-info {
display: flex;
flex-wrap: wrap;
gap: 12px;
margin-top: 10px;
color: #606266;
line-height: 1.6;
}
}
</style>