voyageList.vue 15 KB

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