voyageList.vue 13 KB

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