ShipInfo.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471
  1. <template>
  2. <div>
  3. <div class="container-title">船舶信息</div>
  4. <div
  5. class="pl50 pt30 bgf df jcsb pr20"
  6. v-if="route.name == 'shipOwnerDetail' || route.name == 'shipDetail'"
  7. style="max-width: 1200px"
  8. >
  9. <el-button-group class="mr20" v-if="route.name == 'shipOwnerDetail'">
  10. <el-button
  11. v-for="(item, index) in shipInfos"
  12. :key="item.code"
  13. @click="currentIndex = index"
  14. :disabled="!shipInfoDisabled"
  15. v-show="item.code"
  16. :type="index == currentIndex ? 'primary' : ''"
  17. >
  18. {{ item.shipname || "新增船舶" }}
  19. </el-button>
  20. </el-button-group>
  21. <div></div>
  22. <div class="df">
  23. <div class="df" v-if="shipInfos[currentIndex].code">
  24. <el-button v-if="shipInfoDisabled" type="primary" @click="showUpdate">
  25. 更新船舶基础信息
  26. </el-button>
  27. <el-button
  28. v-if="!shipInfoDisabled"
  29. type="primary"
  30. @click="confirmUpdate"
  31. >
  32. 确认更新
  33. </el-button>
  34. <el-button
  35. v-if="!shipInfoDisabled"
  36. type="primary"
  37. @click="cancelUpdate"
  38. >
  39. 取消更新
  40. </el-button>
  41. <el-button
  42. v-if="route.name == 'shipOwnerDetail'"
  43. @click="deleteShip(currentIndex)"
  44. type="primary"
  45. class="mr20"
  46. >
  47. 删除当前船舶
  48. </el-button>
  49. </div>
  50. <div class="df" v-if="route.name == 'shipOwnerDetail'">
  51. <el-button
  52. v-if="shipInfos.length == 0 || shipInfos[currentIndex].code"
  53. @click="addShip()"
  54. type="primary"
  55. >
  56. 新增船舶
  57. </el-button>
  58. <div v-else>
  59. <el-button
  60. v-if="shipInfos.length > 1"
  61. @click="cancelAdd()"
  62. type="primary"
  63. >
  64. 取消新增船舶
  65. </el-button>
  66. </div>
  67. </div>
  68. </div>
  69. </div>
  70. <div class="line-container-p24">
  71. <div class="line">
  72. <div class="info-line">
  73. <div class="info-line-title">
  74. <span class="red">*</span>
  75. 船名
  76. </div>
  77. <el-input
  78. class="info-line-text"
  79. v-model="shipInfos[currentIndex].shipname"
  80. :disabled="shipInfoDisabled"
  81. ></el-input>
  82. <view class="unit"></view>
  83. </div>
  84. <div class="info-line">
  85. <div class="info-line-title">MMSI</div>
  86. <el-input
  87. class="info-line-text"
  88. v-model="shipInfos[currentIndex].mmsi"
  89. :disabled="
  90. shipInfoDisabled ||
  91. !!shipInfos[currentIndex].code ||
  92. !!shipInfos[currentIndex].shipId
  93. "
  94. @blur="searchShip($event, currentIndex)"
  95. ></el-input>
  96. </div>
  97. </div>
  98. <div class="line">
  99. <div class="info-line">
  100. <div class="info-line-title">船长</div>
  101. <el-input
  102. class="info-line-text"
  103. v-model="shipInfos[currentIndex].length"
  104. :disabled="shipInfoDisabled"
  105. ></el-input>
  106. <view class="unit">米</view>
  107. </div>
  108. <div class="info-line">
  109. <div class="info-line-title">船宽</div>
  110. <el-input
  111. class="info-line-text"
  112. v-model="shipInfos[currentIndex].breadth"
  113. :disabled="shipInfoDisabled"
  114. ></el-input>
  115. <view class="unit">米</view>
  116. </div>
  117. </div>
  118. <div class="line">
  119. <div class="info-line">
  120. <div class="info-line-title">载货吨位</div>
  121. <el-input
  122. class="info-line-text"
  123. v-model="shipInfos[currentIndex].loadTons"
  124. :disabled="shipInfoDisabled"
  125. ></el-input>
  126. <view class="unit">吨</view>
  127. </div>
  128. <div class="info-line">
  129. <div class="info-line-title">船龄</div>
  130. <el-input
  131. class="info-line-text"
  132. v-model="shipInfos[currentIndex].age"
  133. :disabled="shipInfoDisabled"
  134. ></el-input>
  135. <view class="unit">年</view>
  136. </div>
  137. </div>
  138. <div class="line">
  139. <div class="info-line">
  140. <div class="info-line-title">满载吃水</div>
  141. <el-input
  142. class="info-line-text"
  143. v-model="shipInfos[currentIndex].draught"
  144. :disabled="shipInfoDisabled"
  145. ></el-input>
  146. <view class="unit">米</view>
  147. </div>
  148. <div class="info-line">
  149. <div class="info-line-title">吨位(总吨)</div>
  150. <el-input
  151. class="info-line-text"
  152. v-model="shipInfos[currentIndex].tonnage"
  153. :disabled="shipInfoDisabled"
  154. ></el-input>
  155. <view class="unit">吨</view>
  156. </div>
  157. </div>
  158. </div>
  159. <div style="max-width: 1200px">
  160. <div class="container-title">船舶证书</div>
  161. <div
  162. v-for="(item, index) in shipInfos[currentIndex].shipCerts"
  163. :key="item.title"
  164. style="background: #fff"
  165. class="pt20"
  166. >
  167. <div v-if="item.type == 5" class="container-title fs18 pt10 pb10">
  168. 船舶保险
  169. </div>
  170. <div class="df aic pl40 pb20">
  171. <div class="c6 fs16 mr30">{{ item.typeName }}</div>
  172. </div>
  173. <div class="ml50 mb20 c7 fs14" v-if="item.type != 0">
  174. <div
  175. class="df aic mb10"
  176. v-for="(item1, index1) in item.certValids"
  177. :key="item.id"
  178. >
  179. <div class="mr10">{{ item1.typeName }}</div>
  180. <el-date-picker
  181. style="width: 140px; font-size: 13px"
  182. v-model="item1.startValidTime"
  183. @change="changeDate($event, item, item1)"
  184. type="date"
  185. placeholder="有效期开始时间"
  186. value-format="YYYY/MM/DD"
  187. format="YYYY/MM/DD"
  188. />
  189. <div style="margin: 0 4px">-</div>
  190. <el-date-picker
  191. style="width: 140px; font-size: 13px"
  192. v-model="item1.endValidTime"
  193. @change="changeDate($event, item, item1)"
  194. type="date"
  195. placeholder="有效期结束时间"
  196. value-format="YYYY/MM/DD"
  197. format="YYYY/MM/DD"
  198. />
  199. </div>
  200. </div>
  201. <div class="df">
  202. <Uploader
  203. class="ml50 pb20"
  204. :uploaderId="'certsId' + 'country'"
  205. :params="
  206. shipInfos[currentIndex].code
  207. ? {
  208. ...updateParams,
  209. shipCode: shipInfos[currentIndex].code,
  210. type: item.type,
  211. }
  212. : addParams
  213. "
  214. :actionUrl="
  215. shipInfos[currentIndex].code
  216. ? store.state.updateCertsUrl
  217. : store.state.addCertsUrl
  218. "
  219. :disabled="disabled"
  220. :fileList="item.certs"
  221. @onUploadFileList="uploadSuccess($event, index)"
  222. @onRemoveFileList="removeSuccess($event, index)"
  223. ></Uploader>
  224. </div>
  225. </div>
  226. <div
  227. v-if="!shipInfos[currentIndex].code"
  228. class="p30 mb30 df jcfe"
  229. style="background: #fff"
  230. >
  231. <el-button :loading="isSubmitLoading" @click="submit" type="primary">
  232. {{ isSubmitLoading ? "正在添加" : "添加船舶" }}
  233. </el-button>
  234. </div>
  235. </div>
  236. </div>
  237. </template>
  238. <script setup>
  239. import { defineComponent, computed, ref, onMounted, watch } from "vue";
  240. import { ElMessage } from "element-plus";
  241. import api from "../apis/fetch";
  242. import _ from "lodash";
  243. import store from "../store";
  244. import { useRoute } from "vue-router";
  245. import router from "../router";
  246. const route = useRoute();
  247. const props = defineProps({
  248. certsId: {
  249. type: String,
  250. default: "cert",
  251. },
  252. disabled: {
  253. type: Boolean,
  254. default: false,
  255. },
  256. shipInfos: {
  257. type: Array,
  258. default: [{}],
  259. },
  260. shipOwnerId: [String, Number],
  261. });
  262. let currentIndex = ref(0);
  263. const emit = defineEmits(["submit"]);
  264. function initCerts(certs) {
  265. console.log(certs);
  266. }
  267. let updateParams = ref({
  268. loginAccountId: localStorage.loginAccountId,
  269. });
  270. let addParams = ref({
  271. loginAccountId: localStorage.loginAccountId,
  272. });
  273. // function uploadSuccess(list, index) {
  274. function uploadSuccess({ response, file, list }, index) {
  275. if (response.status == 0) {
  276. let { key, fileKey, viewUrl, downloadUrl, id } = response.result;
  277. props.shipInfos[currentIndex.value].shipCerts[index].certs.push({
  278. fileKey: fileKey || key,
  279. viewUrl,
  280. downloadUrl,
  281. id,
  282. url: viewUrl,
  283. });
  284. }
  285. }
  286. async function removeSuccess({ file, fileIndex }, index) {
  287. if (props.shipInfos[currentIndex.value].code) {
  288. let { data } = await api.deleteShipCert({ shipCertId: file.id });
  289. if (data.status == 0) {
  290. ElMessage({
  291. message: "删除成功!",
  292. type: "success",
  293. });
  294. props.shipInfos[currentIndex.value].shipCerts[index].certs.splice(
  295. fileIndex,
  296. 1
  297. );
  298. }
  299. } else {
  300. props.shipInfos[currentIndex.value].shipCerts[index].certs.splice(
  301. fileIndex,
  302. 1
  303. );
  304. }
  305. }
  306. async function changeDate(e, item, item1) {
  307. if (props.shipInfos[currentIndex.value].code) {
  308. let { data } = await api.updateShipCertValid({
  309. shipCode: props.shipInfos[currentIndex.value].code,
  310. type: item.type,
  311. validType: item1.type,
  312. startValidTime: item1.startValidTime,
  313. endValidTime: item1.endValidTime,
  314. });
  315. if (data.status == 0) {
  316. ElMessage({
  317. message: "更新成功!",
  318. type: "success",
  319. });
  320. }
  321. }
  322. }
  323. function getShipCerts() {
  324. return shipCerts.value;
  325. }
  326. async function searchShip(e) {
  327. if (e.target.value.length != 9) return;
  328. const loading = ElLoading.service({
  329. lock: true,
  330. text: "正在匹配船舶...",
  331. background: "rgba(0, 0, 0, 0.7)",
  332. });
  333. let { data } = await api.searchShip({
  334. mmsi: e.target.value,
  335. });
  336. loading.close();
  337. if (data.status == 0) {
  338. data.result.shipCerts[0].typeName = "船舶主要项目页";
  339. data.result.shipCerts[1].typeName = "船舶国籍证书";
  340. data.result.shipCerts[2].typeName = "内河船舶适航证书";
  341. data.result.shipCerts[3].typeName = "船舶营运证书";
  342. data.result.shipCerts[4].typeName = "内河船舶最低安全配员证书";
  343. data.result.shipCerts[5].typeName = "船舶保险";
  344. for (let i of data.result.shipCerts) {
  345. for (let j of i.certs) {
  346. j.url = j.viewUrl;
  347. }
  348. }
  349. data.result.disabled = false;
  350. if (props.shipInfos[currentIndex.value].shipname)
  351. data.result.shipname = props.shipInfos[currentIndex.value].shipname;
  352. props.shipInfos[currentIndex.value] = data.result;
  353. }
  354. }
  355. function deleteShip(index) {
  356. ElMessageBox.confirm("确认删除船舶?", "提示", {
  357. confirmButtonText: "确认",
  358. cancelButtonText: "取消",
  359. type: "warning",
  360. })
  361. .then(async () => {
  362. console.log(index);
  363. let { data } = await api.deleteShip({
  364. shipCode: props.shipInfos[index].code,
  365. });
  366. if (data.status == 0) {
  367. ElMessage({
  368. type: "success",
  369. message: "删除成功",
  370. });
  371. props.shipInfos.splice(index, 1);
  372. currentIndex.value = 0;
  373. }
  374. })
  375. .catch(() => {});
  376. }
  377. let cacheIndex = -1;
  378. async function addShip(item) {
  379. cacheIndex = _.cloneDeep(currentIndex.value);
  380. shipInfoDisabled.value = false;
  381. let { data } = await api.getAddShipCerts({});
  382. let initShipInfo = {
  383. shipId: 0,
  384. disabled: false,
  385. shipCerts: data.result,
  386. };
  387. if (
  388. props.shipInfos.length &&
  389. props.shipInfos[props.shipInfos.length - 1].code
  390. ) {
  391. props.shipInfos.push(initShipInfo);
  392. } else {
  393. props.shipInfos[props.shipInfos.length - 1] = initShipInfo;
  394. }
  395. currentIndex.value = props.shipInfos.length - 1;
  396. }
  397. function cancelAdd() {
  398. currentIndex.value = _.cloneDeep(cacheIndex);
  399. shipInfoDisabled.value = true;
  400. }
  401. let isSubmitLoading = ref(false);
  402. async function submit() {
  403. if (!props.shipInfos[currentIndex.value].shipname) {
  404. ElMessage({
  405. type: "warning",
  406. message: "请填写船舶名称",
  407. });
  408. return;
  409. }
  410. isSubmitLoading.value = true;
  411. let res = await api.addShip({
  412. ...props.shipInfos[currentIndex.value],
  413. shipOwnerId: props.shipOwnerId,
  414. });
  415. isSubmitLoading.value = false;
  416. store.commit("removeAlive", "shipOwnerList");
  417. router.replace("/shipOwnerManage/shipOwnerList");
  418. }
  419. let shipInfoDisabled = ref(true);
  420. let cacheInfo = ref({});
  421. function showUpdate() {
  422. cacheInfo.value = _.cloneDeep(props.shipInfos[currentIndex.value]);
  423. shipInfoDisabled.value = false;
  424. }
  425. async function confirmUpdate() {
  426. let postData = props.shipInfos[currentIndex.value];
  427. postData.shipCode = postData.code;
  428. let { data } = await api.updateShip(postData);
  429. if (data.status == 0) {
  430. ElMessage({
  431. message: data.msg,
  432. type: "success",
  433. });
  434. shipInfoDisabled.value = true;
  435. } else {
  436. ElMessage({
  437. message: data.msg,
  438. type: "error",
  439. });
  440. }
  441. }
  442. function cancelUpdate() {
  443. props.shipInfos[currentIndex.value] = _.cloneDeep(cacheInfo.value);
  444. shipInfoDisabled.value = true;
  445. }
  446. function changeDisable(b) {
  447. shipInfoDisabled.value = b;
  448. }
  449. defineExpose({
  450. initCerts,
  451. getShipCerts,
  452. changeDisable,
  453. });
  454. onMounted(() => {});
  455. </script>
  456. <style scoped>
  457. .unit {
  458. width: 40px;
  459. text-align: center;
  460. color: #555;
  461. }
  462. </style>