|
|
@@ -1,9 +1,510 @@
|
|
|
-<template>voyageDetail</template>
|
|
|
+<template>
|
|
|
+ <div class="line-container-p18">
|
|
|
+ <i class="el-icon-arrow-left"></i>
|
|
|
+ <div class="dib go-back ml8">返回航次列表</div>
|
|
|
+ <div class="line">
|
|
|
+ <div class="info-line">
|
|
|
+ <div class="info-line-title">航次名称</div>
|
|
|
+ <el-input
|
|
|
+ class="info-line-text"
|
|
|
+ v-model="voyage.voyageName"
|
|
|
+ disabled
|
|
|
+ ></el-input>
|
|
|
+ </div>
|
|
|
+ <div class="info-line">
|
|
|
+ <div class="info-line-title">货主</div>
|
|
|
+ <el-input
|
|
|
+ class="info-line-text"
|
|
|
+ v-model="voyage.cargoOwnerName"
|
|
|
+ disabled
|
|
|
+ ></el-input>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="line">
|
|
|
+ <div class="info-line">
|
|
|
+ <div class="info-line-title">船东</div>
|
|
|
+ <el-input
|
|
|
+ class="info-line-text"
|
|
|
+ v-model="voyage.shipOwnerName"
|
|
|
+ disabled
|
|
|
+ ></el-input>
|
|
|
+ </div>
|
|
|
+ <div class="info-line">
|
|
|
+ <div class="info-line-title">船东手机号</div>
|
|
|
+ <el-input
|
|
|
+ class="info-line-text"
|
|
|
+ v-model="voyage.shipOwnerPhone"
|
|
|
+ disabled
|
|
|
+ ></el-input>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="line">
|
|
|
+ <div class="info-line">
|
|
|
+ <div class="info-line-title">船舶</div>
|
|
|
+ <el-input
|
|
|
+ class="info-line-text"
|
|
|
+ v-model="voyage.shipName"
|
|
|
+ disabled
|
|
|
+ ></el-input>
|
|
|
+ </div>
|
|
|
+ <div class="info-line">
|
|
|
+ <div class="info-line-title">MMSI</div>
|
|
|
+ <el-input
|
|
|
+ class="info-line-text"
|
|
|
+ v-model="voyage.shipMmsi"
|
|
|
+ disabled
|
|
|
+ ></el-input>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div id="map-container" class="map-container"></div>
|
|
|
+ <div class="line" style="margin-top: 30px">
|
|
|
+ <div class="info-line">
|
|
|
+ <div class="info-line-title">开始时间</div>
|
|
|
+ <el-input
|
|
|
+ class="info-line-text"
|
|
|
+ v-model="voyage.startTime"
|
|
|
+ disabled
|
|
|
+ ></el-input>
|
|
|
+ </div>
|
|
|
+ <div class="info-line">
|
|
|
+ <div class="info-line-title">结束时间</div>
|
|
|
+ <el-input
|
|
|
+ class="info-line-text"
|
|
|
+ v-model="voyage.endTime"
|
|
|
+ disabled
|
|
|
+ ></el-input>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="line">
|
|
|
+ <div class="info-line">
|
|
|
+ <div class="info-line-title">装货港</div>
|
|
|
+ <el-input
|
|
|
+ class="info-line-text"
|
|
|
+ v-model="voyage.loadPort"
|
|
|
+ disabled
|
|
|
+ ></el-input>
|
|
|
+ </div>
|
|
|
+ <div class="info-line">
|
|
|
+ <div class="info-line-title">卸货港</div>
|
|
|
+ <el-input
|
|
|
+ class="info-line-text"
|
|
|
+ v-model="voyage.dischargeProt"
|
|
|
+ disabled
|
|
|
+ ></el-input>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="line">
|
|
|
+ <div class="info-line">
|
|
|
+ <div class="info-line-title">货种</div>
|
|
|
+ <el-input
|
|
|
+ class="info-line-text"
|
|
|
+ v-model="voyage.cargo"
|
|
|
+ disabled
|
|
|
+ ></el-input>
|
|
|
+ </div>
|
|
|
+ <div class="info-line">
|
|
|
+ <div class="info-line-title">吨位</div>
|
|
|
+ <el-input
|
|
|
+ class="info-line-text"
|
|
|
+ v-model="voyage.tons"
|
|
|
+ disabled
|
|
|
+ ></el-input>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="container-title">航次信息</div>
|
|
|
+ <div class="line-container-p18">
|
|
|
+ <div class="line">
|
|
|
+ <div class="info-line">
|
|
|
+ <div class="info-line-title">运输状态</div>
|
|
|
+ <el-select
|
|
|
+ v-model="voyage.transStatus"
|
|
|
+ placeholder="Select"
|
|
|
+ class="info-line-text"
|
|
|
+ :disabled="disabledStatus"
|
|
|
+ >
|
|
|
+ <el-option
|
|
|
+ v-for="item in options"
|
|
|
+ :key="item.value"
|
|
|
+ :label="item.label"
|
|
|
+ :value="item.value"
|
|
|
+ ></el-option>
|
|
|
+ </el-select>
|
|
|
+ </div>
|
|
|
+ <div class="info-line">
|
|
|
+ <div class="info-line-title">实际卸货吨位</div>
|
|
|
+ <el-input
|
|
|
+ class="info-line-text"
|
|
|
+ v-model="voyage.actualDischargeTons"
|
|
|
+ :disabled="disabledStatus"
|
|
|
+ ></el-input>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="line">
|
|
|
+ <div class="info-line">
|
|
|
+ <div class="info-line-title">装货开始时间</div>
|
|
|
+ <el-date-picker
|
|
|
+ class="info-line-text"
|
|
|
+ v-model="voyage.loadStartTime"
|
|
|
+ type="datetime"
|
|
|
+ format="YYYY/MM/DD HH:mm:ss"
|
|
|
+ value-format="YYYY/MM/DD HH:mm:ss"
|
|
|
+ placeholder="装货开始时间"
|
|
|
+ :disabled="disabledStatus"
|
|
|
+ ></el-date-picker>
|
|
|
+ </div>
|
|
|
+ <div class="info-line">
|
|
|
+ <div class="info-line-title">装货结束时间</div>
|
|
|
+ <el-date-picker
|
|
|
+ class="info-line-text"
|
|
|
+ v-model="voyage.loadEndTime"
|
|
|
+ type="datetime"
|
|
|
+ format="YYYY/MM/DD HH:mm:ss"
|
|
|
+ value-format="YYYY/MM/DD HH:mm:ss"
|
|
|
+ placeholder="装货开始时间"
|
|
|
+ :disabled="disabledStatus"
|
|
|
+ ></el-date-picker>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="line">
|
|
|
+ <div class="info-line">
|
|
|
+ <div class="info-line-title">卸货开始时间</div>
|
|
|
+ <el-date-picker
|
|
|
+ class="info-line-text"
|
|
|
+ v-model="voyage.dischargeStartTime"
|
|
|
+ type="datetime"
|
|
|
+ format="YYYY/MM/DD HH:mm:ss"
|
|
|
+ value-format="YYYY/MM/DD HH:mm:ss"
|
|
|
+ placeholder="装货开始时间"
|
|
|
+ :disabled="disabledStatus"
|
|
|
+ ></el-date-picker>
|
|
|
+ </div>
|
|
|
+ <div class="info-line">
|
|
|
+ <div class="info-line-title">卸货结束时间</div>
|
|
|
+ <el-date-picker
|
|
|
+ class="info-line-text"
|
|
|
+ v-model="voyage.dischargeEndTime"
|
|
|
+ type="datetime"
|
|
|
+ format="YYYY/MM/DD HH:mm:ss"
|
|
|
+ value-format="YYYY/MM/DD HH:mm:ss"
|
|
|
+ placeholder="装货开始时间"
|
|
|
+ :disabled="disabledStatus"
|
|
|
+ ></el-date-picker>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="line">
|
|
|
+ <div class="info-line">
|
|
|
+ <div class="info-line-title">备注</div>
|
|
|
+ <el-input
|
|
|
+ class="info-line-textarea"
|
|
|
+ v-model="voyage.remark"
|
|
|
+ autosize
|
|
|
+ type="textarea"
|
|
|
+ :disabled="disabledStatus"
|
|
|
+ ></el-input>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div
|
|
|
+ class="media-content df ffw"
|
|
|
+ style="
|
|
|
+ width: 100%;
|
|
|
+ height: 400px;
|
|
|
+ background: #f7f7f7;
|
|
|
+ border-radius: 2px;
|
|
|
+ "
|
|
|
+ >
|
|
|
+ <el-card
|
|
|
+ style="
|
|
|
+ width: 240px;
|
|
|
+ height: 360px;
|
|
|
+ margin-left: 20px;
|
|
|
+ margin-bottom: 15px;
|
|
|
+ "
|
|
|
+ v-for="item in medias"
|
|
|
+ :key="item"
|
|
|
+ shadow="hover"
|
|
|
+ >
|
|
|
+ <div class="card-note">
|
|
|
+ {{ item.note }}
|
|
|
+ </div>
|
|
|
+ <div class="media-box" style="position: relative">
|
|
|
+ <el-image
|
|
|
+ v-if="item.mediaType == 1"
|
|
|
+ style="width: 100%; height: 100%"
|
|
|
+ fit="contain"
|
|
|
+ :src="item.downloadUrl"
|
|
|
+ :preview-src-list="previewSrcList"
|
|
|
+ ></el-image>
|
|
|
+ <video
|
|
|
+ style="width: 100%; height: 100%"
|
|
|
+ v-else
|
|
|
+ :src="item.downloadUrl"
|
|
|
+ ></video>
|
|
|
+ <img
|
|
|
+ @click="openVideoModal(item.downloadUrl)"
|
|
|
+ v-if="item.mediaType == 2"
|
|
|
+ src="../../assets/icon-player.png"
|
|
|
+ style="
|
|
|
+ object-fit: contain;
|
|
|
+ width: 40px;
|
|
|
+ height: 40px;
|
|
|
+ position: absolute;
|
|
|
+ top: calc(50% - 20px);
|
|
|
+ left: calc(50% - 20px);
|
|
|
+ background: #fff;
|
|
|
+ border-radius: 50%;
|
|
|
+ "
|
|
|
+ alt=""
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </el-card>
|
|
|
+
|
|
|
+ <el-dialog
|
|
|
+ v-model="videoModal"
|
|
|
+ title="视频审核"
|
|
|
+ width="30%"
|
|
|
+ :before-close="videoClose"
|
|
|
+ >
|
|
|
+ <video
|
|
|
+ autoplay
|
|
|
+ controls
|
|
|
+ style="width: 100%; height: 100%"
|
|
|
+ :src="currentUrl"
|
|
|
+ ></video>
|
|
|
+ <template #footer>
|
|
|
+ <span class="dialog-footer">
|
|
|
+ <el-button type="primary" @click="dialogAuditVideo(1)">
|
|
|
+ 通过
|
|
|
+ </el-button>
|
|
|
+ <el-button type="warning" @click="dialogAuditVideo(2)">
|
|
|
+ 未通过
|
|
|
+ </el-button>
|
|
|
+ </span>
|
|
|
+ </template>
|
|
|
+ </el-dialog>
|
|
|
+ </div>
|
|
|
+ <div class="df aic acfe mt20" v-if="voyage.voyageStatus == 1">
|
|
|
+ <el-button v-if="disabledStatus" type="primary" @click="changeVoyageInfo">
|
|
|
+ 修改航次
|
|
|
+ </el-button>
|
|
|
+ <div v-else>
|
|
|
+ <div>
|
|
|
+ <el-button @click="cancelVoyageChange">取消修改</el-button>
|
|
|
+ <el-button type="primary" @click="submitVoyageChange">
|
|
|
+ 提交修改
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <el-button
|
|
|
+ v-if="voyage.dischargeEndTime && disabledStatus"
|
|
|
+ type="primary"
|
|
|
+ @click="finishVoyage"
|
|
|
+ >
|
|
|
+ 完成航次
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
<script>
|
|
|
+import { onMounted, reactive, ref, toRefs } from "_vue@3.2.20@vue";
|
|
|
+import api from "../../apis/fetch";
|
|
|
+import { useRoute } from "vue-router";
|
|
|
+import _ from "lodash";
|
|
|
+import { ElNotification } from "element-plus";
|
|
|
+
|
|
|
export default {
|
|
|
setup() {
|
|
|
- return {};
|
|
|
+ const route = useRoute();
|
|
|
+ let map = ref();
|
|
|
+ let voyage = ref({});
|
|
|
+ let medias = ref();
|
|
|
+ let coordinates = ref();
|
|
|
+ let previewSrcList = ref([]);
|
|
|
+
|
|
|
+ async function getVoyageDetail() {
|
|
|
+ let res = await api.getVoyageDetail({
|
|
|
+ type: 2,
|
|
|
+ voyageId: route.query.id,
|
|
|
+ });
|
|
|
+
|
|
|
+ coordinates.value = res.data.result.coordinates;
|
|
|
+ voyage.value = res.data.result.voyage;
|
|
|
+ medias.value = res.data.result.medias;
|
|
|
+ for (let i of medias.value) {
|
|
|
+ previewSrcList.value.push(i.downloadUrl);
|
|
|
+ }
|
|
|
+ setShipMarker();
|
|
|
+ }
|
|
|
+
|
|
|
+ function initMap() {
|
|
|
+ var center = new TMap.LatLng(31.228721, 121.524761);
|
|
|
+ //初始化地图
|
|
|
+ map.value = new TMap.Map("map-container", {
|
|
|
+ zoom: 12, //设置地图缩放级别
|
|
|
+ center: center, //设置地图中心点坐标
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ function setShipMarker(longitude, latitude) {
|
|
|
+ var marker = new TMap.MultiMarker({
|
|
|
+ id: "marker-layer", //图层id
|
|
|
+ map: map.value,
|
|
|
+ styles: {
|
|
|
+ //点标注的相关样式
|
|
|
+ marker: new TMap.MarkerStyle({
|
|
|
+ width: 25,
|
|
|
+ height: 35,
|
|
|
+ anchor: { x: 16, y: 32 },
|
|
|
+ src: "https://hhd-pat-1255802371.cos.ap-shanghai.myqcloud.com/frontend/ship-red-icon.png",
|
|
|
+ }),
|
|
|
+ },
|
|
|
+ geometries: [
|
|
|
+ {
|
|
|
+ //点标注数据数组
|
|
|
+ id: "demo",
|
|
|
+ styleId: "marker",
|
|
|
+ position: new TMap.LatLng(31.228721, 121.524761),
|
|
|
+ properties: {
|
|
|
+ title: "marker",
|
|
|
+ },
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ let disabledStatus = ref(true);
|
|
|
+ let updateCache = {};
|
|
|
+ function changeVoyageInfo() {
|
|
|
+ updateCache = _.cloneDeep(voyage.value);
|
|
|
+ disabledStatus.value = false;
|
|
|
+ }
|
|
|
+ function cancelVoyageChange() {
|
|
|
+ voyage.value = updateCache;
|
|
|
+ disabledStatus.value = true;
|
|
|
+ }
|
|
|
+ async function submitVoyageChange() {
|
|
|
+ let {
|
|
|
+ id,
|
|
|
+ transStatus,
|
|
|
+ loadStartTime,
|
|
|
+ loadEndTime,
|
|
|
+ dischargeStartTime,
|
|
|
+ dischargeEndTime,
|
|
|
+ actualDischargeTons,
|
|
|
+ remark,
|
|
|
+ } = voyage.value;
|
|
|
+ let res = await api.updateVoyage({
|
|
|
+ id,
|
|
|
+ transStatus,
|
|
|
+ loadStartTime,
|
|
|
+ loadEndTime,
|
|
|
+ dischargeStartTime,
|
|
|
+ dischargeEndTime,
|
|
|
+ actualDischargeTons,
|
|
|
+ remark,
|
|
|
+ });
|
|
|
+ if (res.data.status == 0) {
|
|
|
+ ElNotification({
|
|
|
+ type: "success",
|
|
|
+ title: res.data.msg,
|
|
|
+ });
|
|
|
+ disabledStatus.value = true;
|
|
|
+ } else {
|
|
|
+ ElNotification({
|
|
|
+ type: "error",
|
|
|
+ title: res.data.msg,
|
|
|
+ });
|
|
|
+ console.log(res);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ let options = ref([
|
|
|
+ {
|
|
|
+ value: 1,
|
|
|
+ label: "航行",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 2,
|
|
|
+ label: "停泊",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 3,
|
|
|
+ label: "装货",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 4,
|
|
|
+ label: "运输中",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 5,
|
|
|
+ label: "卸货",
|
|
|
+ },
|
|
|
+ ]);
|
|
|
+
|
|
|
+ async function finishVoyage() {
|
|
|
+ if (!voyage.value.dischargeEndTime) return;
|
|
|
+ let res = await api.finishVoyage({
|
|
|
+ voyageId: route.query.id,
|
|
|
+ });
|
|
|
+
|
|
|
+ if (res.data.status == 0) {
|
|
|
+ voyage.value.voyageStatus = 2;
|
|
|
+ ElNotification({
|
|
|
+ type: "success",
|
|
|
+ title: res.data.msg,
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ ElNotification({
|
|
|
+ type: "error",
|
|
|
+ title: res.data.msg,
|
|
|
+ });
|
|
|
+ console.log(res);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ function openVideoModal(url) {
|
|
|
+ currentUrl.value = url;
|
|
|
+ videoModal.value = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ onMounted(() => {
|
|
|
+ initMap();
|
|
|
+ getVoyageDetail();
|
|
|
+ });
|
|
|
+ return {
|
|
|
+ options,
|
|
|
+ voyage,
|
|
|
+ coordinates,
|
|
|
+ medias,
|
|
|
+ disabledStatus,
|
|
|
+ changeVoyageInfo,
|
|
|
+ cancelVoyageChange,
|
|
|
+ submitVoyageChange,
|
|
|
+ finishVoyage,
|
|
|
+ openVideoModal,
|
|
|
+ previewSrcList,
|
|
|
+ };
|
|
|
},
|
|
|
};
|
|
|
</script>
|
|
|
-<style scoped></style>
|
|
|
+<style scoped>
|
|
|
+.map-container {
|
|
|
+ width: 100%;
|
|
|
+ height: 500px;
|
|
|
+}
|
|
|
+:deep().el-input__inner {
|
|
|
+ color: #333 !important;
|
|
|
+}
|
|
|
+.card-note {
|
|
|
+ height: 30px;
|
|
|
+ font-size: 12px;
|
|
|
+ font-family: PingFangSC-Regular, PingFang SC;
|
|
|
+ font-weight: 400;
|
|
|
+ color: #777777;
|
|
|
+}
|
|
|
+
|
|
|
+.media-box {
|
|
|
+ width: 200px;
|
|
|
+ height: 200px;
|
|
|
+ margin-top: 20px;
|
|
|
+}
|
|
|
+</style>
|