voyageList.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598
  1. <template>
  2. <div class="full-container-p24">
  3. <div style="display: flex; justify-content: space-between">
  4. <div class="df aic">
  5. <div
  6. @click="changeVoyageType(1)"
  7. :class="
  8. currentbtn == 1
  9. ? 'currentbtn radio-btns left-radius'
  10. : 'radio-btns left-radius'
  11. "
  12. >
  13. 装货中
  14. </div>
  15. <div
  16. style="border-left: none"
  17. @click="changeVoyageType(2)"
  18. :class="currentbtn == 2 ? 'currentbtn radio-btns' : 'radio-btns'"
  19. >
  20. 运输中
  21. </div>
  22. <div
  23. style="border-left: none"
  24. @click="changeVoyageType(3)"
  25. :class="currentbtn == 3 ? 'currentbtn radio-btns' : 'radio-btns'"
  26. >
  27. 卸货中
  28. </div>
  29. <div
  30. style="border-left: none"
  31. @click="changeVoyageType(4)"
  32. :class="currentbtn == 4 ? 'currentbtn radio-btns' : 'radio-btns'"
  33. >
  34. 未签单
  35. </div>
  36. <div
  37. @click="changeVoyageType(5)"
  38. :class="
  39. currentbtn == 5
  40. ? 'currentbtn radio-btns right-radius'
  41. : 'radio-btns right-radius '
  42. "
  43. style="margin-right: 40px; border-left: none"
  44. >
  45. 历史航次
  46. </div>
  47. <el-input
  48. placeholder="请输入货主名称/船名/MMSi"
  49. prefix-icon="el-icon-search"
  50. v-model="term"
  51. clearable
  52. style="width: 330px"
  53. ></el-input>
  54. <div class="search-btn" @click="getVoyageList()">查询</div>
  55. </div>
  56. <div class="cargo-owner-add" @click="voyageAddDialogVisible = true">
  57. 添加航次
  58. </div>
  59. </div>
  60. <el-dialog v-model="voyageAddDialogVisible" title="添加航次">
  61. <el-form
  62. :rules="rules"
  63. label-position="right"
  64. label-width="80px"
  65. ref="addVoyageForm"
  66. :model="voyageForm"
  67. :before-close="resetAddVoyageForm"
  68. >
  69. <div class="df ffw">
  70. <!-- <el-form-item prop="voyageName" label="航次名称">
  71. <el-input v-model="voyageForm.voyageName"></el-input>
  72. </el-form-item>
  73. <el-form-item label=""></el-form-item> -->
  74. <el-form-item prop="shipName" label="船舶">
  75. <!-- <el-input v-model="voyageForm.shipOwnerId"></el-input> -->
  76. <el-autocomplete
  77. v-model="voyageForm.shipName"
  78. :fetch-suggestions="searchShip"
  79. placeholder="选择船舶"
  80. @select="selectShip"
  81. />
  82. </el-form-item>
  83. <el-form-item prop="cargoOwnerId" label="货主">
  84. <el-autocomplete
  85. v-model="voyageForm.cargoOwnerName"
  86. :fetch-suggestions="searchCargoOwner"
  87. placeholder="选择货主"
  88. @select="selectCargoOwner"
  89. />
  90. </el-form-item>
  91. <el-form-item prop="startTime" label="开始时间">
  92. <el-date-picker
  93. v-model="voyageForm.startTime"
  94. type="date"
  95. value-format="YYYY/MM/DD"
  96. placeholder="航次开始时间"
  97. ></el-date-picker>
  98. </el-form-item>
  99. <el-form-item prop="endTime" label="结束时间">
  100. <el-date-picker
  101. v-model="voyageForm.endTime"
  102. type="date"
  103. value-format="YYYY/MM/DD"
  104. placeholder="航次结束时间"
  105. disabled
  106. ></el-date-picker>
  107. </el-form-item>
  108. <el-form-item prop="loadPort" label="装货港">
  109. <!-- <el-input v-model="voyageForm.loadPort"></el-input> -->
  110. <el-autocomplete
  111. v-model="voyageForm.loadPort"
  112. :fetch-suggestions="searchLoadPort"
  113. placeholder="选择装货港"
  114. @select="selectLoadPort"
  115. />
  116. </el-form-item>
  117. <el-form-item prop="dischargeProt" label="卸货港">
  118. <!-- <el-input v-model="voyageForm.dischargeProt"></el-input> -->
  119. <el-autocomplete
  120. v-model="voyageForm.dischargeProt"
  121. :fetch-suggestions="searchDischargeProt"
  122. placeholder="选择卸货港"
  123. @select="selectDischargeProt"
  124. />
  125. </el-form-item>
  126. <el-form-item prop="cargo" label="货种">
  127. <el-input v-model="voyageForm.cargo"></el-input>
  128. </el-form-item>
  129. <el-form-item prop="tons" label="吨位">
  130. <el-input v-model="voyageForm.tons"></el-input>
  131. </el-form-item>
  132. </div>
  133. </el-form>
  134. <template #footer>
  135. <span class="dialog-footer">
  136. <el-button @click="resetAddVoyageForm">取消</el-button>
  137. <el-button type="primary" @click="addVoyage">确定</el-button>
  138. </span>
  139. </template>
  140. </el-dialog>
  141. <el-table :data="tableData" stripe style="width: 100%; margin-top: 24px">
  142. <el-table-column
  143. type="index"
  144. label="序号"
  145. min-width="80"
  146. align="center"
  147. ></el-table-column>
  148. <el-table-column
  149. prop="voyageName"
  150. label="航次名称"
  151. min-width="120"
  152. align="center"
  153. ></el-table-column>
  154. <el-table-column
  155. prop="loadDiscPort"
  156. label="装货港-卸货港"
  157. min-width="200"
  158. align="center"
  159. ></el-table-column>
  160. <el-table-column
  161. prop="setSailTime"
  162. label="开航时间"
  163. min-width="180"
  164. align="center"
  165. ></el-table-column>
  166. <el-table-column
  167. prop="todayPhotoCount"
  168. label="今日照片"
  169. min-width="80"
  170. align="center"
  171. ></el-table-column>
  172. <el-table-column
  173. prop="cargo"
  174. label="货种"
  175. min-width="80"
  176. align="center"
  177. ></el-table-column>
  178. <el-table-column
  179. prop="tons"
  180. label="吨位(吨)"
  181. min-width="80"
  182. align="center"
  183. ></el-table-column>
  184. <el-table-column
  185. prop="transStatus"
  186. label="船舶状态"
  187. min-width="100"
  188. align="center"
  189. ></el-table-column>
  190. <el-table-column
  191. prop="remark"
  192. label="备注"
  193. min-width="100"
  194. align="center"
  195. ></el-table-column>
  196. <el-table-column label="操作" min-width="80" align="center">
  197. <template v-slot="scope">
  198. <el-button
  199. @click="voyageDetail(scope.row.id, tableData)"
  200. type="text"
  201. size="small"
  202. >
  203. 查看详情
  204. </el-button>
  205. </template>
  206. </el-table-column>
  207. </el-table>
  208. <div style="width: 100%; text-align: right; margin-top: 43px">
  209. <el-pagination
  210. background
  211. layout="prev, pager, next"
  212. :total="total"
  213. @current-change="pageChange"
  214. ></el-pagination>
  215. </div>
  216. </div>
  217. </template>
  218. <script>
  219. import { ref, h, reactive, toRefs, onMounted } from "vue";
  220. import { ElNotification, ElMessageBox, ElMessage } from "element-plus";
  221. import store from "../../store";
  222. import router from "../../router";
  223. import md5 from "md5";
  224. import api from "../../apis/fetch";
  225. export default {
  226. setup() {
  227. let currentbtn = ref(true);
  228. let currentPage = ref(1);
  229. let term = ref();
  230. let tableData = ref();
  231. let total = ref();
  232. let status = ref(1);
  233. async function getVoyageList() {
  234. tableData.value = [];
  235. let res = await api.getVoyageList({
  236. cargoOwnerId: 0,
  237. shipId: 0,
  238. status: status.value,
  239. term: term.value,
  240. currentPage: currentPage.value,
  241. size: 10,
  242. });
  243. term.value = "";
  244. if (res.data.status == 0) {
  245. tableData.value = res.data.result;
  246. } else {
  247. ElNotification({
  248. type: "error",
  249. title: res.data.msg,
  250. });
  251. }
  252. }
  253. function changeVoyageType(s) {
  254. term.value = "";
  255. currentPage.value = 1;
  256. currentbtn.value = s;
  257. status.value = s;
  258. getVoyageList();
  259. }
  260. async function voyageDetail(id) {
  261. router.push({
  262. path: "/voyage/voyageDetail",
  263. query: {
  264. id,
  265. },
  266. });
  267. }
  268. function pageChange(e) {
  269. currentPage.value = e;
  270. getVoyageList();
  271. }
  272. function goToVoyageAdd() {
  273. router.push({
  274. path: "/voyage/voyageAdd",
  275. });
  276. }
  277. let voyageAddDialogVisible = ref(false);
  278. const rules = reactive({
  279. rules: {
  280. voyageName: [
  281. { required: false, message: "请填写航次名称", trigger: "blur" },
  282. ],
  283. shipName: [{ required: true, message: "请选择船舶", trigger: "blur" }],
  284. cargoOwnerId: [
  285. { required: true, message: "请选择货主", trigger: "blur" },
  286. ],
  287. startTime: [
  288. { required: true, message: "请填写开始时间", trigger: "blur" },
  289. ],
  290. loadPort: [
  291. { required: true, message: "请填写装货港", trigger: "blur" },
  292. ],
  293. dischargeProt: [
  294. { required: true, message: "请填写卸货港", trigger: "blur" },
  295. ],
  296. cargo: [{ required: true, message: "请填写货种", trigger: "blur" }],
  297. tons: [{ required: true, message: "请填写吨位", trigger: "blur" }],
  298. // -----------
  299. shipOwnerName: [
  300. { required: true, message: "请选择船东", trigger: "blur" },
  301. ],
  302. cargoOwnerName: [
  303. { required: true, message: "请选择货主", trigger: "blur" },
  304. ],
  305. },
  306. });
  307. let voyageForm = reactive({
  308. voyageForm: {
  309. voyageName: "",
  310. cargoOwnerId: "",
  311. startTime: "",
  312. endTime: "",
  313. loadPort: "",
  314. dischargeProt: "",
  315. cargo: "",
  316. tons: "",
  317. // -----
  318. shipOwnerName: "",
  319. cargoOwnerName: "",
  320. },
  321. });
  322. let addVoyageForm = ref(null);
  323. async function addVoyage() {
  324. console.log("提交", voyageForm.voyageForm);
  325. return;
  326. addVoyageForm.value.validate(async (valid) => {
  327. if (valid) {
  328. // console.log("提交", voyageForm.voyageForm);
  329. let res = await api.addVoyage({
  330. ...voyageForm.voyageForm,
  331. });
  332. if (res.data.status == 0) {
  333. ElNotification({
  334. title: res.data.msg,
  335. type: "success",
  336. });
  337. resetAddVoyageForm();
  338. getVoyageList();
  339. } else {
  340. console.log(res);
  341. ElNotification({
  342. title: res.data.msg,
  343. type: "error",
  344. });
  345. }
  346. }
  347. });
  348. }
  349. async function searchShip(queryString, cb) {
  350. if (!queryString) return;
  351. let res = await api.searchShip({
  352. term: queryString,
  353. });
  354. let ships = [];
  355. if (res.data.status == 0) {
  356. ships = res.data.result;
  357. for (let i of ships) {
  358. i.value = `${i.shipName}`;
  359. }
  360. cb(ships);
  361. }
  362. }
  363. const selectShip = (item) => {
  364. voyageForm.voyageForm.shipOwnerId = item.shipOwnerId;
  365. voyageForm.voyageForm.shipId = item.shipId;
  366. };
  367. async function searchCargoOwner(queryString, cb) {
  368. if (!queryString) return;
  369. let res = await api.searchUser({
  370. term: queryString,
  371. identity: 2,
  372. });
  373. let cargoOwners = [];
  374. if (res.data.status == 0) {
  375. cargoOwners = res.data.result;
  376. for (let i of cargoOwners) {
  377. i.value = `${i.userName}`;
  378. }
  379. cb(cargoOwners);
  380. }
  381. }
  382. const selectCargoOwner = (item) => {
  383. voyageForm.voyageForm.cargoOwnerId = item.userId;
  384. };
  385. async function searchLoadPort(queryString, cb) {
  386. if (!queryString) return;
  387. let res = await api.getCol({
  388. term: queryString,
  389. });
  390. if (res.data.status == 0) {
  391. cb(res.data.result);
  392. }
  393. }
  394. const selectLoadPort = (item) => {
  395. voyageForm.voyageForm.loadPort = item.value;
  396. };
  397. async function searchDischargeProt(queryString, cb) {
  398. if (!queryString) return;
  399. let res = await api.getCol({
  400. term: queryString,
  401. });
  402. if (res.data.status == 0) {
  403. cb(res.data.result);
  404. }
  405. }
  406. const selectDischargeProt = (item) => {
  407. voyageForm.voyageForm.dischargeProt = item.value;
  408. };
  409. function resetAddVoyageForm() {
  410. voyageAddDialogVisible.value = false;
  411. voyageForm.voyageForm.shipOwnerName = "";
  412. voyageForm.voyageForm.cargoOwnerName = "";
  413. addVoyageForm.value.resetFields();
  414. }
  415. getVoyageList();
  416. onMounted(() => {});
  417. return {
  418. currentPage,
  419. term,
  420. tableData,
  421. total,
  422. currentbtn,
  423. changeVoyageType,
  424. getVoyageList,
  425. voyageDetail,
  426. pageChange,
  427. goToVoyageAdd,
  428. addVoyage,
  429. voyageAddDialogVisible,
  430. addVoyageForm,
  431. ...toRefs(rules),
  432. ...toRefs(voyageForm),
  433. searchShip,
  434. selectShip,
  435. searchCargoOwner,
  436. selectCargoOwner,
  437. resetAddVoyageForm,
  438. searchLoadPort,
  439. selectLoadPort,
  440. searchDischargeProt,
  441. selectDischargeProt,
  442. };
  443. },
  444. };
  445. </script>
  446. <style scoped>
  447. .search-btn {
  448. display: inline-block;
  449. width: 60px;
  450. height: 32px;
  451. background: #0094fe;
  452. border-radius: 2px;
  453. font-size: 14px;
  454. font-family: PingFangSC-Regular, PingFang SC;
  455. font-weight: 400;
  456. color: #ffffff;
  457. text-align: center;
  458. line-height: 32px;
  459. margin-left: 10px;
  460. cursor: pointer;
  461. }
  462. .cargo-owner-add {
  463. width: 80px;
  464. height: 32px;
  465. border-radius: 2px;
  466. border: 1px solid #0094fe;
  467. font-size: 14px;
  468. font-family: PingFangSC-Regular, PingFang SC;
  469. font-weight: 400;
  470. color: #0094fe;
  471. line-height: 32px;
  472. text-align: center;
  473. cursor: pointer;
  474. }
  475. :deep().el-dialog {
  476. width: 560px;
  477. padding: 20px 50px;
  478. border-radius: 6px;
  479. }
  480. :deep() .el-dialog__title {
  481. font-size: 18px;
  482. font-family: PingFangSC-Regular, PingFang SC;
  483. font-weight: 400;
  484. color: #0094fe;
  485. }
  486. .normal-label {
  487. font-size: 14px;
  488. font-family: PingFangSC-Regular, PingFang SC;
  489. font-weight: 400;
  490. color: #353a42;
  491. margin-right: 10px;
  492. }
  493. .show-input {
  494. width: 280px;
  495. height: 32px;
  496. background: #ffffff;
  497. border-radius: 2px;
  498. border: 1px solid #dee0e3;
  499. font-size: 14px;
  500. font-family: PingFangSC-Regular, PingFang SC;
  501. font-weight: 400;
  502. color: #333333;
  503. line-height: 32px;
  504. padding-left: 12px;
  505. margin-right: 40px;
  506. }
  507. .radio-btns {
  508. height: 38px;
  509. width: 103px;
  510. border: 1px solid #1486f9;
  511. line-height: 38px;
  512. text-align: center;
  513. font-size: 14px;
  514. font-family: PingFangSC-Regular, PingFang SC;
  515. font-weight: 400;
  516. color: #0094fe;
  517. cursor: pointer;
  518. }
  519. .left-radius {
  520. border-top-left-radius: 19px;
  521. border-bottom-left-radius: 19px;
  522. }
  523. .right-radius {
  524. border-top-right-radius: 19px;
  525. border-bottom-right-radius: 19px;
  526. }
  527. .currentbtn {
  528. background: #1486f9;
  529. color: #fff;
  530. }
  531. .search-btn {
  532. display: inline-block;
  533. width: 60px;
  534. height: 38px;
  535. background: #0094fe;
  536. border-radius: 2px;
  537. font-size: 14px;
  538. font-family: PingFangSC-Regular, PingFang SC;
  539. font-weight: 400;
  540. color: #ffffff;
  541. text-align: center;
  542. line-height: 38px;
  543. margin-left: 10px;
  544. cursor: pointer;
  545. }
  546. .voyage-add {
  547. width: 80px;
  548. height: 36px;
  549. border-radius: 2px;
  550. border: 1px solid #0094fe;
  551. font-size: 14px;
  552. font-family: PingFangSC-Regular, PingFang SC;
  553. font-weight: 400;
  554. color: #0094fe;
  555. line-height: 36px;
  556. text-align: center;
  557. cursor: pointer;
  558. }
  559. :deep() .el-dialog {
  560. width: 800px;
  561. }
  562. :deep() .el-form-item {
  563. margin-right: 22px;
  564. width: 300px;
  565. }
  566. :deep() .el-autocomplete {
  567. width: 220px;
  568. }
  569. </style>