|
|
@@ -1,15 +1,231 @@
|
|
|
<template>
|
|
|
<div class="df">
|
|
|
- <div id="map-container" class="map-container"></div>
|
|
|
- <div
|
|
|
- style="width: 200px; height: calc(100vh - 256px); border: 1px solid grey"
|
|
|
- ></div>
|
|
|
+ <div class="left-top">
|
|
|
+ <div id="map-container" class="map-container"></div>
|
|
|
+ <div class="df aic tabs">
|
|
|
+ <div
|
|
|
+ @click="changeVoyageType(0)"
|
|
|
+ :class="
|
|
|
+ status == 0
|
|
|
+ ? 'currentbtn radio-btns left-radius'
|
|
|
+ : 'radio-btns left-radius'
|
|
|
+ "
|
|
|
+ >
|
|
|
+ 全部航次
|
|
|
+ </div>
|
|
|
+ <div
|
|
|
+ style="border-left: none"
|
|
|
+ @click="changeVoyageType(1)"
|
|
|
+ :class="status == 1 ? 'currentbtn radio-btns' : 'radio-btns'"
|
|
|
+ >
|
|
|
+ 装货中
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div
|
|
|
+ style="border-left: none"
|
|
|
+ @click="changeVoyageType(2)"
|
|
|
+ :class="status == 2 ? 'currentbtn radio-btns' : 'radio-btns'"
|
|
|
+ >
|
|
|
+ 运输中
|
|
|
+ </div>
|
|
|
+ <div
|
|
|
+ style="border-left: none"
|
|
|
+ @click="changeVoyageType(3)"
|
|
|
+ :class="
|
|
|
+ status == 3
|
|
|
+ ? 'currentbtn radio-btns right-radius'
|
|
|
+ : 'radio-btns right-radius '
|
|
|
+ "
|
|
|
+ >
|
|
|
+ 卸货中
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="right-top"></div>
|
|
|
</div>
|
|
|
<div class="df">
|
|
|
- <div
|
|
|
- style="width: calc(100% - 200px); height: 118px; border: 1px solid green"
|
|
|
- ></div>
|
|
|
- <div style="width: 200px; height: 118px; border: 1px solid blue"></div>
|
|
|
+ <div class="left-bottom">
|
|
|
+ <div
|
|
|
+ class="df aic jcfs mt20"
|
|
|
+ style="
|
|
|
+ font-size: 14px;
|
|
|
+ color: #333;
|
|
|
+ width: calc(100vw - 300px);
|
|
|
+ flex-wrap: wrap;
|
|
|
+ "
|
|
|
+ >
|
|
|
+ <div class="df jcsb aic mb10 mr20 ml20">
|
|
|
+ <div class="mr10">装货港:</div>
|
|
|
+ <el-select
|
|
|
+ style="width: 120px"
|
|
|
+ v-model="postData.loadPortId"
|
|
|
+ placeholder="装货港"
|
|
|
+ size="small"
|
|
|
+ @change="getIndexData(1)"
|
|
|
+ @focus="getPortSelect"
|
|
|
+ filterable
|
|
|
+ clearable
|
|
|
+ >
|
|
|
+ <el-option
|
|
|
+ v-for="item in portOptions"
|
|
|
+ :key="item"
|
|
|
+ :label="item.value"
|
|
|
+ :value="item.key"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+ </div>
|
|
|
+ <div class="df jcsb aic mb10 mr20">
|
|
|
+ <div class="mr10">卸货港:</div>
|
|
|
+ <el-select
|
|
|
+ style="width: 120px"
|
|
|
+ v-model="postData.discPortId"
|
|
|
+ placeholder="卸货港"
|
|
|
+ size="small"
|
|
|
+ @change="getIndexData(1)"
|
|
|
+ @focus="getPortSelect"
|
|
|
+ filterable
|
|
|
+ clearable
|
|
|
+ >
|
|
|
+ <el-option
|
|
|
+ v-for="item in portOptions"
|
|
|
+ :key="item"
|
|
|
+ :label="item.value"
|
|
|
+ :value="item.key"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+ </div>
|
|
|
+ <div class="df jcsb aic mb10 mr20">
|
|
|
+ <div class="mr10">到港状态:</div>
|
|
|
+ <el-select
|
|
|
+ style="width: 120px"
|
|
|
+ v-model="postData.isArrived"
|
|
|
+ placeholder="到港状态"
|
|
|
+ size="small"
|
|
|
+ @change="getIndexData(1)"
|
|
|
+ >
|
|
|
+ <el-option label="已到港" :value="0" />
|
|
|
+ <el-option label="未到港" :value="1" />
|
|
|
+ </el-select>
|
|
|
+ </div>
|
|
|
+ <div class="df jcsb aic mb10 mr20">
|
|
|
+ <div class="mr10">航次状态:</div>
|
|
|
+ <el-select
|
|
|
+ style="width: 120px"
|
|
|
+ v-model="postData.abnormalStatus"
|
|
|
+ placeholder="航次状态"
|
|
|
+ size="small"
|
|
|
+ @change="getIndexData(1)"
|
|
|
+ >
|
|
|
+ <el-option label="正常" :value="0" />
|
|
|
+ <el-option label="异常" :value="1" />
|
|
|
+ </el-select>
|
|
|
+ </div>
|
|
|
+ <div class="df jcsb aic mb10 mr20">
|
|
|
+ <div class="mr10">货种:</div>
|
|
|
+ <el-select
|
|
|
+ style="width: 100px"
|
|
|
+ v-model="postData.cargoId"
|
|
|
+ placeholder="货种"
|
|
|
+ size="small"
|
|
|
+ @change="getIndexData(1)"
|
|
|
+ @focus="getCargoSelect"
|
|
|
+ filterable
|
|
|
+ clearable
|
|
|
+ >
|
|
|
+ <el-option
|
|
|
+ v-for="item in cargoOptions"
|
|
|
+ :key="item"
|
|
|
+ :label="item.value"
|
|
|
+ :value="item.key"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+ </div>
|
|
|
+ <el-button
|
|
|
+ @click="resetFilter"
|
|
|
+ class="mb10"
|
|
|
+ size="small"
|
|
|
+ type="primary"
|
|
|
+ >
|
|
|
+ 重置
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="right-bottom">
|
|
|
+ <el-popover placement="top" :width="100" trigger="hover">
|
|
|
+ <template #reference>
|
|
|
+ <el-button size="large" type="primary">导出报告</el-button>
|
|
|
+ </template>
|
|
|
+ <div
|
|
|
+ style="
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ height: 180px;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ "
|
|
|
+ >
|
|
|
+ <el-button
|
|
|
+ type="primary"
|
|
|
+ size="medium"
|
|
|
+ v-auth="'DOWNLOADVOYAGELIST'"
|
|
|
+ @click="showExportModal('航次列表')"
|
|
|
+ >
|
|
|
+ 导出航次列表
|
|
|
+ </el-button>
|
|
|
+ <el-button
|
|
|
+ type="primary"
|
|
|
+ size="medium"
|
|
|
+ v-auth="'MULTDOWNLOADSHIPTRACK'"
|
|
|
+ @click="showExportModal('航次跟踪')"
|
|
|
+ >
|
|
|
+ 导出航次跟踪
|
|
|
+ </el-button>
|
|
|
+ <el-button
|
|
|
+ type="primary"
|
|
|
+ size="medium"
|
|
|
+ @click="showExportModal('卸货记录')"
|
|
|
+ v-auth="'MULTDOWNLOADDISCHARGE'"
|
|
|
+ >
|
|
|
+ 导出卸货记录
|
|
|
+ </el-button>
|
|
|
+ <el-button
|
|
|
+ v-auth="'DOWNLOADFYDI'"
|
|
|
+ type="primary"
|
|
|
+ size="medium"
|
|
|
+ @click="downloadFYDI"
|
|
|
+ >
|
|
|
+ 下载FYDI指数
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
+ </el-popover>
|
|
|
+ <el-dialog
|
|
|
+ v-model="exportModalVisable"
|
|
|
+ :title="exportModalTitle"
|
|
|
+ :close-on-click-modal="false"
|
|
|
+ @close="isLoadingZip = false"
|
|
|
+ width="200px"
|
|
|
+ >
|
|
|
+ <div class="df aic jcsb">
|
|
|
+ <div
|
|
|
+ v-if="exportModalTitle != '航次列表' || cargoOwnerId == 7"
|
|
|
+ class="df aic"
|
|
|
+ >
|
|
|
+ <div class="mr20">请选择月份:</div>
|
|
|
+ <el-date-picker
|
|
|
+ v-model="currentMonth"
|
|
|
+ type="month"
|
|
|
+ placeholder="请选择年月"
|
|
|
+ value-format="YYYYMM"
|
|
|
+ :disabled="isLoadingZip"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div></div>
|
|
|
+ <el-button type="primary" @click="exportZip" :loading="isLoadingZip">
|
|
|
+ 导出{{ exportModalTitle }}
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</template>
|
|
|
<script setup>
|
|
|
@@ -20,7 +236,10 @@ import router from "../../router";
|
|
|
|
|
|
import md5 from "md5";
|
|
|
import api from "../../apis/fetch";
|
|
|
+import downloadBlobFile from "../../utils/downloadBlobFile";
|
|
|
+import url from "../../apis/config";
|
|
|
let map = ref({});
|
|
|
+let cargoOwnerId = localStorage.userId;
|
|
|
|
|
|
function initMap() {
|
|
|
map.value = new AMap.Map("map-container", {
|
|
|
@@ -76,14 +295,241 @@ function initMap() {
|
|
|
}, 2000);
|
|
|
});
|
|
|
}
|
|
|
+let status = ref(0);
|
|
|
+function changeVoyageType(s) {
|
|
|
+ status.value = s;
|
|
|
+ getIndexData();
|
|
|
+}
|
|
|
+
|
|
|
+let postData = ref({
|
|
|
+ status: 0,
|
|
|
+ loadPortId: "",
|
|
|
+ discPortId: "",
|
|
|
+ isArrived: "",
|
|
|
+ abnormalStatus: "",
|
|
|
+ cargoId: "",
|
|
|
+});
|
|
|
+async function getIndexData() {
|
|
|
+ postData.value.status = status.value;
|
|
|
+ let res = await api.getIndexData({
|
|
|
+ ...postData.value,
|
|
|
+ });
|
|
|
+ console.log(res);
|
|
|
+}
|
|
|
+
|
|
|
+let portOptions = ref([]);
|
|
|
+async function getPortSelect() {
|
|
|
+ if (portOptions.value.length) return;
|
|
|
+ let res = await api.getCol({
|
|
|
+ term: "",
|
|
|
+ });
|
|
|
+ portOptions.value = res.data.result;
|
|
|
+}
|
|
|
+
|
|
|
+let cargoOptions = ref([]);
|
|
|
+async function getCargoSelect() {
|
|
|
+ if (cargoOptions.value.length) return;
|
|
|
+ let res = await api.getCargoSelect({
|
|
|
+ status: 2,
|
|
|
+ term: "",
|
|
|
+ });
|
|
|
+ cargoOptions.value = res.data.result;
|
|
|
+}
|
|
|
+
|
|
|
+async function downloadFYDI() {
|
|
|
+ let res0 = await api.getFYFIDownloadUrl({
|
|
|
+ loginAccountId: localStorage.loginAccountId,
|
|
|
+ });
|
|
|
+
|
|
|
+ if (res0.data.result == 1) {
|
|
|
+ ElNotification({
|
|
|
+ type: "info",
|
|
|
+ title: "更新中",
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ let url = res0.data.result;
|
|
|
+ let a = document.createElement("a");
|
|
|
+ a.setAttribute("href", url);
|
|
|
+ a.click();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+let exportModalVisable = ref(false);
|
|
|
+let exportModalTitle = ref("");
|
|
|
+let currentMonth = ref("");
|
|
|
+
|
|
|
+function showExportModal(type) {
|
|
|
+ exportModalVisable.value = true;
|
|
|
+ exportModalTitle.value = type;
|
|
|
+}
|
|
|
+
|
|
|
+let isLoadingZip = ref(false);
|
|
|
+
|
|
|
+async function exportZip() {
|
|
|
+ if (!currentMonth.value && exportModalTitle.value != "航次列表") return;
|
|
|
+
|
|
|
+ isLoadingZip.value = true;
|
|
|
+ let path = "";
|
|
|
+ let type = "";
|
|
|
+ let postData = {
|
|
|
+ loginAccountId: localStorage.loginAccountId,
|
|
|
+ };
|
|
|
+ let title = "";
|
|
|
+ switch (exportModalTitle.value) {
|
|
|
+ case "航次列表": {
|
|
|
+ if (localStorage.userId == 7) {
|
|
|
+ path = "/voyage/exportVoyageReportExcel";
|
|
|
+ postData.loginAccountId = localStorage.loginAccountId;
|
|
|
+ postData.date = currentMonth.value;
|
|
|
+ } else {
|
|
|
+ path = "/voyage/exportListExcel";
|
|
|
+ let arr = [];
|
|
|
+ for (let i of tableData.value) {
|
|
|
+ arr.push(i.id);
|
|
|
+ }
|
|
|
+ postData.voyageIds = arr.join(",");
|
|
|
+ }
|
|
|
+ type =
|
|
|
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8";
|
|
|
+ title = `${exportModalTitle.value}`;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case "航次跟踪": {
|
|
|
+ path = "/voyage/exportMultExcel";
|
|
|
+ type = "application/zip";
|
|
|
+ postData.date = currentMonth.value;
|
|
|
+ title = `${exportModalTitle.value}${currentMonth.value}`;
|
|
|
+
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case "卸货记录": {
|
|
|
+ path = "/voyage/exportMultDischargeExcel";
|
|
|
+ type = "application/zip";
|
|
|
+ postData.date = currentMonth.value;
|
|
|
+ title = `${exportModalTitle.value}${currentMonth.value}`;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ let res = await downloadBlobFile(
|
|
|
+ `${url.baseurl}${path}`,
|
|
|
+ postData,
|
|
|
+ title,
|
|
|
+ "post",
|
|
|
+ type
|
|
|
+ );
|
|
|
+ if (res.status == 0) {
|
|
|
+ ElNotification({
|
|
|
+ title: "导出成功!",
|
|
|
+ type: "success",
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ ElNotification({
|
|
|
+ title: "暂无数据",
|
|
|
+ });
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ ElNotification({
|
|
|
+ title: "暂无数据",
|
|
|
+ });
|
|
|
+ } finally {
|
|
|
+ isLoadingZip.value = false;
|
|
|
+ currentMonth.value = "";
|
|
|
+ exportModalVisable.value = false;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function resetFilter() {
|
|
|
+ postData.value = {
|
|
|
+ status: 0,
|
|
|
+ loadPortId: "",
|
|
|
+ discPortId: "",
|
|
|
+ isArrived: "",
|
|
|
+ abnormalStatus: "",
|
|
|
+ cargoId: "",
|
|
|
+ };
|
|
|
+ getIndexData();
|
|
|
+}
|
|
|
onMounted(() => {
|
|
|
initMap();
|
|
|
+ getPortSelect();
|
|
|
+ getCargoSelect();
|
|
|
+ getIndexData();
|
|
|
});
|
|
|
</script>
|
|
|
|
|
|
<style scoped>
|
|
|
-.map-container {
|
|
|
+.left-top {
|
|
|
width: calc(100% - 200px);
|
|
|
height: calc(100vh - 256px);
|
|
|
+ position: relative;
|
|
|
+}
|
|
|
+
|
|
|
+.map-container {
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+}
|
|
|
+
|
|
|
+.tabs {
|
|
|
+ position: absolute;
|
|
|
+ top: 20px;
|
|
|
+ left: 30px;
|
|
|
+}
|
|
|
+
|
|
|
+.radio-btns {
|
|
|
+ height: 38px;
|
|
|
+ width: 70px;
|
|
|
+ border: 1px solid #1486f9;
|
|
|
+ line-height: 38px;
|
|
|
+ text-align: center;
|
|
|
+ font-size: 14px;
|
|
|
+ font-family: PingFangSC-Regular, PingFang SC;
|
|
|
+ font-weight: 400;
|
|
|
+ color: #0094fe;
|
|
|
+ cursor: pointer;
|
|
|
+ background: #fff;
|
|
|
+}
|
|
|
+
|
|
|
+.left-radius {
|
|
|
+ border-top-left-radius: 19px;
|
|
|
+ border-bottom-left-radius: 19px;
|
|
|
+ width: 80px;
|
|
|
+}
|
|
|
+
|
|
|
+.right-radius {
|
|
|
+ border-top-right-radius: 19px;
|
|
|
+ border-bottom-right-radius: 19px;
|
|
|
+ width: 80px;
|
|
|
+}
|
|
|
+.currentbtn {
|
|
|
+ background: #1486f9;
|
|
|
+ color: #fff;
|
|
|
+}
|
|
|
+
|
|
|
+.right-top {
|
|
|
+ width: 200px;
|
|
|
+ height: calc(100vh - 256px);
|
|
|
+ border: 1px solid grey;
|
|
|
+}
|
|
|
+
|
|
|
+.left-bottom {
|
|
|
+ width: calc(100% - 200px);
|
|
|
+ height: 118px;
|
|
|
+ background: #fff;
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+}
|
|
|
+
|
|
|
+.right-bottom {
|
|
|
+ width: 200px;
|
|
|
+ height: 118px;
|
|
|
+ text-align: center;
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-around;
|
|
|
+ align-items: center;
|
|
|
+}
|
|
|
+
|
|
|
+:deep() .el-dialog {
|
|
|
+ width: 800px;
|
|
|
}
|
|
|
</style>
|