feat: 完善订阅和历史记录,修复一些bug

main
sankeyangshu 2024-12-04 17:02:48 +08:00
parent c82c62232e
commit 9813ae3c79
24 changed files with 1651 additions and 477 deletions

View File

@ -9,4 +9,4 @@ NODE_ENV = 'development'
# 如果没有跨域问题,直接在这里配置即可
# VITE_APP_BASE_API = 'http://192.168.1.116:8080'
# VITE_APP_BASE_API = 'http://121.41.36.72:8080'
VITE_APP_BASE_API = 'http://www.cvlip.com'
VITE_APP_BASE_API = 'http://www.cvlip.com:8080'

View File

@ -15,6 +15,8 @@ const api = {
receiveHistoryList: '/cargo/sail_schedule/history/receive/page', // 我接受的历史数据
vinSearch: '/cargo/sail_schedule/vin/query', // 车架号查询
shipList: '/cargo/sail_schedule/ship/list', // 订阅的船期列表
sailScheduleUpdate: '/cargo/sail_schedule/status/update', // 更新船期状态
subscribePage: '/cargo/sail_schedule/subscribe/page', // 订阅的船期列表-船舶信息里
};
/**
@ -122,3 +124,21 @@ export function getVinSearchAPI(data: { vin: string }) {
export function postSaleShipListAPI(data: dictionaryType) {
return http.get<dictionaryListType[]>(api.shipList, data);
}
/**
*
* @param {BoatInfoPageType} data
* @return
*/
export function getSailScheduleUpdateAPI(data: { id: number; status: string }) {
return http.postParams<string>(api.sailScheduleUpdate, data);
}
/**
* -
* @param {BoatInfoPageType} data
* @return
*/
export function getSubscribePageAPI(data: Partial<BoatInfoPageType>) {
return http.post<PageRowsResult<BoatInfoType>>(api.subscribePage, data);
}

View File

@ -7,9 +7,11 @@ const api = {
manifestDel: '/cargo/manifest/detail/delete', // 删除
manifestGet: '/cargo/manifest/detail/get', // 获取
manifestPage: '/cargo/manifest/detail/page', // 分页列表
manifestList: '/cargo/manifest/detail/list', // 非分页列表
manifestSave: '/cargo/manifest/detail/save', // 保存
manifestImport: '/cargo/manifest/detail/import', // 舱单导入
manifestExport: '/cargo/manifest/detail/tmp/export', // 下载模版
manifestFileExport: '/cargo/manifest/detail/export', // 舱单导出
};
/**
@ -39,6 +41,15 @@ export function getManifestDetailPageAPI(data: Partial<ManifestDetailPageType>)
return http.post<PageRowsResult<ManifestDetailType>>(api.manifestPage, data);
}
/**
*
* @param {ManifestDetailPageType} data
* @return
*/
export function getManifestDetailListAPI(data: Partial<ManifestDetailPageType>) {
return http.post<ManifestDetailType[]>(api.manifestList, data);
}
/**
*
* @param {ManifestDetailType} data
@ -70,3 +81,13 @@ export function getManifestDetailTmpExportAPI() {
}
);
}
/**
*
* @return
*/
export function getManifestDetailFileExportAPI(data: Partial<ManifestDetailPageType>) {
return http.get<ArrayBuffer>(api.manifestFileExport, data, {
responseType: 'arraybuffer',
});
}

View File

@ -11,6 +11,7 @@ const api = {
receivePage: '/cargo/subscribe/receive/page', // 我接受订阅分页列表
subscriptionSave: '/cargo/subscribe/save', // 保存
editStatus: '/cargo/subscribe/update', // 修改状态
subscriptionCount: '/cargo/subscribe/count', // 待处理的订阅数
};
/**
@ -75,3 +76,11 @@ export function subscriptionSaveAPI(data: SubscriptionType) {
export function editStatusAPI(data: { id: string | number; status: string }) {
return http.get<string>(api.editStatus, data);
}
/**
*
* @return
*/
export function subscriptionCountAPI() {
return http.get<string>(api.subscriptionCount);
}

View File

@ -2,6 +2,7 @@ import { defineStore } from 'pinia';
interface settingsStateType {
noticeCount: number;
receiveCount: number;
}
export const useSettingStore = defineStore({
@ -11,6 +12,7 @@ export const useSettingStore = defineStore({
// state: 返回对象的函数
state: (): settingsStateType => ({
noticeCount: 0,
receiveCount: 0,
}),
// actions: 可以同步 也可以异步
@ -19,5 +21,9 @@ export const useSettingStore = defineStore({
setNoticeCount(value: number) {
this.noticeCount = value;
},
// 设置未读消息数量
setReceiveCount(value: number) {
this.receiveCount = value;
},
},
});

View File

@ -22,7 +22,7 @@ export interface PageRowsResult<T> {
*/
export interface dictionaryType {
q?: string;
ref?: string;
ref?: string | number;
}
/**

View File

@ -91,7 +91,7 @@ export interface ManifestDetailType {
*
*/
export interface ManifestDetailPageType extends PageRowsType {
manifestId: number;
manifestId: number[];
billNo: string;
}

View File

@ -37,8 +37,10 @@ export interface userInfoType {
openId: string;
enterpriseId: string | number;
enterpriseName: string;
wharfId: string;
wharfId: string | number;
wharfName: string | number;
portId: string | number;
portName: string;
}
/**

View File

@ -69,7 +69,7 @@
import dayjs from 'dayjs';
import { ElMessage, ElMessageBox } from 'element-plus';
import { computed, ref } from 'vue';
import { getSailScheduleExportAPI, getSailSchedulePageAPI } from '@/api/Boat/info';
import { getSailScheduleExportAPI, getSubscribePageAPI } from '@/api/Boat/info';
import { BoatInfoType } from '@/types/boatInfo';
import BoatDialog from './BoatDialog.vue';
@ -97,7 +97,7 @@ const disabled = computed(() => loadMoreState.value === 'finished');
const getTableDataList = async () => {
loadMoreState.value = 'loading';
const { data } = await getSailSchedulePageAPI({
const { data } = await getSubscribePageAPI({
page: currentPage.value,
rows: 10,
});

View File

@ -0,0 +1,172 @@
<template>
<div class="historyTable">
<el-table :data="historyData">
<el-table-column prop="ship.name" label="船名" align="center" width="150" />
<el-table-column prop="voyage" label="航次" align="center" width="180" />
<el-table-column prop="loadPort.name" label="装货港" align="center" width="150" />
<el-table-column prop="dischargePort.name" label="卸货港" align="center" width="150" />
<el-table-column prop="carNumActual" label="商品车数量" align="center" width="180" />
<el-table-column prop="spareNumActual" label="件杂货数量" align="center" width="180" />
<el-table-column prop="departureDatePlan" label="计划离港时间" align="center" width="200" />
<el-table-column prop="departureDateActual" label="实际离港时间" align="center" width="200" />
<el-table-column prop="createDate" label="发布日期时间" align="center" width="200" />
</el-table>
<div class="table-content">
<div class="table-header">
<div style="width: 36px"></div>
<div class="table-header-title">历史舱单信息</div>
<div style="width: 320px"></div>
</div>
<el-table
:data="manifestTable"
style="width: 100%"
max-height="400px"
@row-click="onClickOpenManifestDetail"
>
<el-table-column type="index" label="No." width="50" />
<el-table-column prop="schedule.ship.name" label="船名" align="center" width="120" />
<el-table-column prop="schedule.voyage" label="航次" align="center" width="120" />
<el-table-column prop="deck" label="舱层" align="center" width="80" />
<el-table-column prop="cabin" label="舱段" align="center" width="80" />
<el-table-column prop="billNo" label="贸易类型" align="center" width="160" />
<el-table-column prop="billNo" label="提单号" align="center" width="160" />
<el-table-column label="货名/品牌/型号" align="center" width="200">
<template #default="scope">
<div class="goods-name">
{{ scope.row.goodsName }}/{{ scope.row.brand.name }}/{{ scope.row.model }}
</div>
</template>
</el-table-column>
<el-table-column prop="shippingMark" label="唛头" align="center" width="180" />
<el-table-column prop="carNum" label="商品车" align="center" width="100" />
<el-table-column prop="spareNum" label="件杂货" align="center" width="100" />
<el-table-column prop="weight" label="重量 (kg)" align="center" width="100" />
<el-table-column prop="volume" label="体积 (m3)" align="center" width="100" />
<!-- TODO:港口没有 -->
<el-table-column prop="consigner" label="发货人" align="center" width="180" />
<el-table-column prop="consignee" label="收货人" align="center" width="180" />
<el-table-column prop="goodsStatus" label="货物状态" align="center" width="150" />
</el-table>
</div>
<div class="table-content">
<div class="table-header">
<div style="width: 36px"></div>
<div class="table-header-title">历史舱单明细</div>
<div style="width: 320px"></div>
</div>
<el-table v-loading="tableLoading" :data="manifestDetail" max-height="400px">
<el-table-column type="index" label="No." width="50" />
<el-table-column prop="billNo" label="提单号" align="center" width="150" />
<el-table-column prop="brand.name" label="品牌" align="center" width="150" />
<el-table-column prop="vehicleType.name" label="车型" align="center" width="150" />
<el-table-column
prop="vehicleTypeDetail.name"
label="车型明细"
align="center"
width="180"
/>
<el-table-column prop="model" label="型号" align="center" width="150" />
<el-table-column prop="vin" label="VIN" align="center" width="200" />
<el-table-column prop="weight" label="重量(kg)" align="center" width="150" />
<el-table-column prop="volume" label="体积(m3)" align="center" width="150" />
<el-table-column prop="length" label="长 mm" align="center" width="150" />
<el-table-column prop="width" label="宽 mm" align="center" width="150" />
<el-table-column prop="height" label="高 mm" align="center" width="150" />
<el-table-column prop="bamm" label="BAmm" align="center" width="150" />
<el-table-column prop="lrmm" label="LRmm" align="center" width="150" />
<el-table-column prop="damage" label="有无质损" align="center" width="150" />
<el-table-column prop="damageDesc" label="质损描述" align="center" width="200" />
<el-table-column prop="updateDate" label="更新时间" align="center" width="180" />
</el-table>
</div>
</div>
</template>
<script lang="ts" setup>
import dayjs from 'dayjs';
import { onMounted, ref } from 'vue';
import { getManifestListAPI } from '@/api/Manifest';
import { getManifestDetailListAPI } from '@/api/Manifest/detail';
import { BoatInfoType } from '@/types/boatInfo';
import { ManifestDetailType, ManifestType } from '@/types/manifest';
//
const props = defineProps<{
historyData: BoatInfoType[];
}>();
//
const manifestTable = ref<ManifestType[]>([]);
//
const getManifestTable = async () => {
const scheduleId = props.historyData[0].shipId;
const { data } = await getManifestListAPI({
scheduleId,
});
manifestTable.value = data;
};
onMounted(async () => {
await getManifestTable();
});
//
const tableLoading = ref(false);
//
const manifestDetail = ref<ManifestDetailType[]>([]);
//
const onClickOpenManifestDetail = async (row: ManifestType) => {
tableLoading.value = true;
const { data } = await getManifestDetailListAPI({
manifestId: [row.id],
});
manifestDetail.value = data.map((item) => {
item.createDate = dayjs(item.createDate).format('YYYY-MM-DD HH:mm');
item.updateDate = dayjs(item.updateDate).format('YYYY-MM-DD HH:mm');
return item;
});
tableLoading.value = false;
};
</script>
<style lang="scss" scoped>
.historyTable {
display: flex;
flex: 1;
flex-direction: column;
width: 100%;
.table-content {
width: 100%;
.table-header {
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: space-between;
padding: 16px 16px 0;
margin-bottom: 15px;
color: #fff;
.table-header-title {
font-size: 28px;
font-weight: 700;
}
.sort {
display: flex;
align-items: flex-end;
height: 100%;
font-family: 'Arial Normal', Arial;
font-size: 15px;
font-style: normal;
font-weight: 400;
color: #aaa;
}
}
}
}
</style>

View File

@ -16,37 +16,31 @@
max-height="400px"
v-el-table-infinite-scroll="tableDataLoad"
:infinite-scroll-disabled="disabled"
@row-click="onClickCellOpenDetail"
>
<!-- <el-table-column prop="enterprise.name" label="企业" align="center" width="150" /> -->
<el-table-column prop="ship.name" label="船名" align="center" width="150" />
<el-table-column prop="voyage" label="航次" align="center" width="180" />
<el-table-column prop="loadPort.name" label="装货港口" align="center" width="150" />
<el-table-column prop="loadWharf.name" label="装货码头" align="center" width="150" />
<el-table-column prop="dischargePort.name" label="卸货港口" align="center" width="150" />
<el-table-column prop="dischargeWharf.name" label="卸货码头" align="center" width="150" />
<el-table-column prop="carNumPlan" label="计划商品车数量" align="center" width="180" />
<el-table-column prop="carNumActual" label="实际商品车数量" align="center" width="180" />
<el-table-column prop="spareNumPlan" label="计划件杂货数量" align="center" width="180" />
<el-table-column
prop="spareNumActual"
label="实际件杂货数量"
align="center"
width="180"
/>
<el-table-column prop="loadPort.name" label="装货港" align="center" width="150" />
<!-- <el-table-column prop="loadWharf.name" label="装货码头" align="center" width="150" /> -->
<el-table-column prop="dischargePort.name" label="卸货港" align="center" width="150" />
<!-- <el-table-column prop="dischargeWharf.name" label="卸货码头" align="center" width="150" /> -->
<!-- <el-table-column prop="carNumPlan" label="计划商品车数量" align="center" width="180" /> -->
<el-table-column prop="carNumActual" label="商品车数量" align="center" width="180" />
<!-- <el-table-column prop="spareNumPlan" label="计划件杂货数量" align="center" width="180" /> -->
<el-table-column prop="spareNumActual" label="件杂货数量" align="center" width="180" />
<el-table-column
prop="departureDatePlan"
label="计划离时间"
label="计划离港时间"
align="center"
width="200"
/>
<el-table-column
prop="departureDateActual"
label="实际离时间"
label="实际离时间"
align="center"
width="200"
/>
<el-table-column prop="tradeType" label="贸易类型" align="center" width="150" />
<el-table-column prop="shipStatus" label="当前状态" align="center" width="150" />
<el-table-column prop="createDate" label="发布日期时间" align="center" width="200" />
</el-table>
</div>
<!-- 分页 -->
@ -67,6 +61,7 @@ const handleTableData = (data: BoatInfoType[]) => {
for (const item of data) {
item.departureDatePlan = dayjs(item.departureDatePlan).format('YYYY-MM-DD HH:mm');
item.departureDateActual = dayjs(item.departureDateActual).format('YYYY-MM-DD HH:mm');
item.createDate = dayjs(item.createDate).format('YYYY-MM-DD HH:mm');
}
return data;
};
@ -105,6 +100,14 @@ const getTableDataList = async () => {
const tableDataLoad = async () => {
await getTableDataList();
};
//
const emits = defineEmits(['openDetail']);
//
const onClickCellOpenDetail = (row: BoatInfoType) => {
emits('openDetail', row);
};
</script>
<style lang="scss" scoped>

View File

@ -16,37 +16,31 @@
max-height="400px"
v-el-table-infinite-scroll="tableDataLoad"
:infinite-scroll-disabled="disabled"
@row-click="onClickCellOpenDetail"
>
<!-- <el-table-column prop="enterprise.name" label="企业" align="center" width="150" /> -->
<el-table-column prop="ship.name" label="船名" align="center" width="150" />
<el-table-column prop="voyage" label="航次" align="center" width="180" />
<el-table-column prop="loadPort.name" label="装货港口" align="center" width="150" />
<el-table-column prop="loadWharf.name" label="装货码头" align="center" width="150" />
<el-table-column prop="dischargePort.name" label="卸货港口" align="center" width="150" />
<el-table-column prop="dischargeWharf.name" label="卸货码头" align="center" width="150" />
<el-table-column prop="carNumPlan" label="计划商品车数量" align="center" width="180" />
<el-table-column prop="carNumActual" label="实际商品车数量" align="center" width="180" />
<el-table-column prop="spareNumPlan" label="计划件杂货数量" align="center" width="180" />
<el-table-column
prop="spareNumActual"
label="实际件杂货数量"
align="center"
width="180"
/>
<el-table-column prop="loadPort.name" label="装货港" align="center" width="150" />
<!-- <el-table-column prop="loadWharf.name" label="装货码头" align="center" width="150" /> -->
<el-table-column prop="dischargePort.name" label="卸货港" align="center" width="150" />
<!-- <el-table-column prop="dischargeWharf.name" label="卸货码头" align="center" width="150" /> -->
<!-- <el-table-column prop="carNumPlan" label="计划商品车数量" align="center" width="180" /> -->
<el-table-column prop="carNumActual" label="商品车数量" align="center" width="180" />
<!-- <el-table-column prop="spareNumPlan" label="计划件杂货数量" align="center" width="180" /> -->
<el-table-column prop="spareNumActual" label="件杂货数量" align="center" width="180" />
<el-table-column
prop="departureDatePlan"
label="计划离时间"
label="计划离港时间"
align="center"
width="200"
/>
<el-table-column
prop="departureDateActual"
label="实际离时间"
label="实际离时间"
align="center"
width="200"
/>
<el-table-column prop="tradeType" label="贸易类型" align="center" width="150" />
<el-table-column prop="shipStatus" label="当前状态" align="center" width="150" />
<el-table-column prop="createDate" label="发布日期时间" align="center" width="200" />
</el-table>
</div>
<!-- 分页 -->
@ -67,6 +61,7 @@ const handleTableData = (data: BoatInfoType[]) => {
for (const item of data) {
item.departureDatePlan = dayjs(item.departureDatePlan).format('YYYY-MM-DD HH:mm');
item.departureDateActual = dayjs(item.departureDateActual).format('YYYY-MM-DD HH:mm');
item.createDate = dayjs(item.createDate).format('YYYY-MM-DD HH:mm');
}
return data;
};
@ -105,6 +100,14 @@ const getTableDataList = async () => {
const tableDataLoad = async () => {
await getTableDataList();
};
//
const emits = defineEmits(['openDetail']);
//
const onClickCellOpenDetail = (row: BoatInfoType) => {
emits('openDetail', row);
};
</script>
<style lang="scss" scoped>

View File

@ -17,8 +17,11 @@
</div>
<div class="content">
<PublishTable v-if="currentHistoryNav === ''" />
<ReceiveTable v-if="currentHistoryNav === ''" />
<div class="content-wrap" v-if="!isViewHistory">
<PublishTable v-if="currentHistoryNav === ''" @openDetail="onClickOpenDetail" />
<ReceiveTable v-if="currentHistoryNav === ''" @openDetail="onClickOpenDetail" />
</div>
<HistoryTable v-else :historyData="historyData!" />
</div>
</div>
</template>
@ -26,6 +29,8 @@
<script lang="ts" setup>
import { ref } from 'vue';
import { useRouter } from 'vue-router';
import { BoatInfoType } from '@/types/boatInfo';
import HistoryTable from './components/HistoryTable.vue';
import PublishTable from './components/PublishTable.vue';
import ReceiveTable from './components/ReceiveTable.vue';
@ -33,7 +38,12 @@ const router = useRouter();
//
const onClickReturn = () => {
//
if (isViewHistory.value) {
isViewHistory.value = false;
} else {
router.back();
}
};
//
@ -42,6 +52,17 @@ const currentHistoryNav = ref('我发布的');
const onClickChangeHistoryNav = (item: string) => {
if (currentHistoryNav.value === item) return;
currentHistoryNav.value = item;
isViewHistory.value = false;
};
//
const isViewHistory = ref(false);
const historyData = ref<BoatInfoType[]>([]);
//
const onClickOpenDetail = (row: BoatInfoType) => {
historyData.value = [row];
isViewHistory.value = true;
};
</script>
@ -101,6 +122,10 @@ const onClickChangeHistoryNav = (item: string) => {
box-sizing: border-box;
flex: 1;
padding: 16px;
.content-wrap {
width: 100%;
height: 100%;
}
}
}
</style>

View File

@ -1,29 +1,44 @@
<template>
<div class="table">
<div class="manifestDetail">
<div class="header">
<el-form :inline="true" :model="searchTableForm" ref="tableFormRef">
<el-form-item prop="name">
<el-input
v-model="searchTableForm.billNo"
placeholder="请输入提单号"
style="width: 120px"
/>
</el-form-item>
<div class="header-left">
<svg-icon icon="return" className="side-icon" @click="onClickReturn"></svg-icon>
<div class="search">
<el-form :model="searchTableForm">
<el-form-item>
<el-button type="primary" icon="Search" @click="onClickSearch"></el-button>
<el-button icon="Refresh" @click="onClickResetForm(tableFormRef)"></el-button>
<div class="search-top">
<div class="card-title">请输入提单号</div>
<div class="card-text">
<el-input v-model="searchTableForm.billNo" placeholder="" />
</div>
</div>
</el-form-item>
</el-form>
<div class="bottom-one" @click="onClickSearch"></div>
</div>
</div>
<div class="title">提单明细</div>
<div class="api-btn">
<div
class="btn"
:class="{ 'btn-active': '提单明细' === item }"
v-for="item in subscribeNavList"
:key="item"
@click="onClickChangeSubscribeType(item)"
>
{{ item }}
</div>
</div>
</div>
<div class="content">
<div class="footer">
<!-- 表格 -->
<div class="footer-table">
<el-table
v-loading="tableLoading"
:data="tableState.tableData"
style="width: 100%; height: 100%"
>
<el-table-column prop="manifest.name" label="舱单" align="center" width="150" />
<el-table v-loading="tableLoading" :data="tableData" max-height="400px">
<el-table-column type="index" label="No." width="50" />
<el-table-column prop="billNo" label="提单号" align="center" width="150" />
<el-table-column prop="brand.name" label="品牌" align="center" width="150" />
<el-table-column prop="vehicleType.name" label="车型" align="center" width="150" />
<el-table-column
prop="vehicleTypeDetail.name"
@ -31,59 +46,86 @@
align="center"
width="180"
/>
<el-table-column prop="model" label="型号" align="center" width="150" />
<el-table-column prop="vin" label="VIN" align="center" width="200" />
<el-table-column prop="weight" label="重量" align="center" width="150" />
<el-table-column prop="volume" label="体积" align="center" width="150" />
<el-table-column prop="length" label="长" align="center" width="150" />
<el-table-column prop="width" label="宽" align="center" width="150" />
<el-table-column prop="height" label="高" align="center" width="150" />
<el-table-column prop="weight" label="重量(kg)" align="center" width="150" />
<el-table-column prop="volume" label="体积(m3)" align="center" width="150" />
<el-table-column prop="length" label="长 mm" align="center" width="150" />
<el-table-column prop="width" label="宽 mm" align="center" width="150" />
<el-table-column prop="height" label="高 mm" align="center" width="150" />
<el-table-column prop="bamm" label="BAmm" align="center" width="150" />
<el-table-column prop="lrmm" label="LRmm" align="center" width="150" />
<el-table-column prop="damage" label="有无质损" align="center" width="150" />
<el-table-column prop="damageDesc" label="质损描述" align="center" width="200" />
<el-table-column prop="createDate" label="创建时间" align="center" width="180" />
<el-table-column prop="updateDate" label="更新时间" align="center" width="180" />
</el-table>
</div>
<!-- 分页 -->
<div class="footer-pagination">
<Pagination
:pageAble="tableState.pageAble"
:handle-size-change="handleSizeChange"
:handle-current-change="handleCurrentChange"
/>
<div class="btn-export" @click="onClickExport">
<svg-icon icon="Export" className="icon"></svg-icon>
导出全部提单明细
</div>
</div>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { FormInstance } from 'element-plus';
import dayjs from 'dayjs';
import { ElMessage, ElMessageBox } from 'element-plus';
import { onMounted, reactive, ref } from 'vue';
import { getManifestDetailPageAPI } from '@/api/Manifest/detail';
import Pagination from '@/components/Pagination/Pagination.vue';
import { useTable } from '@/hooks/useTable';
import { getManifestDetailFileExportAPI, getManifestDetailListAPI } from '@/api/Manifest/detail';
import { ManifestDetailPageType, ManifestDetailType } from '@/types/manifest';
const emits = defineEmits(['ReturnRouter', 'CurrentNav']);
const onClickReturn = () => {
emits('ReturnRouter');
};
const subscribeNavList = ref(['舱单信息', '提单明细', '积载图']);
const onClickChangeSubscribeType = (item: string) => {
emits('CurrentNav', item);
};
//
const props = withDefaults(
defineProps<{
manifestId: string;
manifestId: number;
}>(),
{
manifestId: '',
manifestId: 0,
}
);
//
const tableData = ref<ManifestDetailType[]>([]);
//
const { getTableList, tableState, searchTable, resetTable, tableChangeCurrent, tableChangeSize } =
useTable({
api: getManifestDetailPageAPI,
const getManifestList = async (params: Partial<ManifestDetailPageType>) => {
tableLoading.value = true;
const { data } = await getManifestDetailListAPI(params);
tableData.value = data.map((item) => {
item.createDate = dayjs(item.createDate).format('YYYY-MM-DD HH:mm');
item.updateDate = dayjs(item.updateDate).format('YYYY-MM-DD HH:mm');
return item;
});
tableLoading.value = false;
};
onMounted(async () => {
if (props.manifestId) {
tableState.value.searchInitParam = {
await getManifestList({
manifestId: [props.manifestId],
};
});
} else {
await getManifestList({});
}
await getTableList();
});
//
@ -94,46 +136,180 @@ const searchTableForm = reactive({
//
const tableLoading = ref(false);
//
const tableFormRef = ref<FormInstance>();
//
const onClickSearch = async () => {
if (searchTableForm.billNo === '') {
ElMessage({
message: '请输入提单号',
type: 'warning',
});
return;
}
tableLoading.value = true;
//
tableState.value.searchParam = searchTableForm;
let params: Partial<ManifestDetailPageType> = {
billNo: searchTableForm.billNo,
};
//
await searchTable();
// ID
if (props.manifestId) {
params.manifestId = [props.manifestId];
}
await getManifestList(params);
tableLoading.value = false;
};
//
const onClickResetForm = async (formEl: FormInstance | undefined) => {
if (!formEl) return;
await resetTable();
formEl.resetFields();
};
//
const handleSizeChange = async (val: number) => {
await tableChangeSize(val);
};
//
const handleCurrentChange = async (val: number) => {
await tableChangeCurrent(val);
//
const onClickExport = () => {
ElMessageBox.confirm(`你确定要导出提单明细吗?`, '温馨提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
draggable: true,
})
.then(async () => {
try {
let params: any = {};
if (searchTableForm.billNo) {
params.billNo = searchTableForm.billNo;
}
const { data } = await getManifestDetailFileExportAPI(params);
const blob = new Blob([data], {
type: 'application/vnd.ms-excel;charset=utf-8',
});
const downloadUrl = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = downloadUrl;
link.download = '提单明细.xlsx';
link.click();
ElMessage({
message: '导出成功',
type: 'success',
});
} catch (error) {
ElMessage({
message: '导出失败',
type: 'error',
});
}
})
.catch(() => {
console.log('用户点击了取消');
});
};
</script>
<style lang="scss" scoped>
.table {
.manifestDetail {
width: 100%;
height: 100%;
.header {
box-sizing: border-box;
display: flex;
flex-shrink: 0;
align-items: center;
justify-content: space-between;
padding: 16px 16px 0;
margin-bottom: 15px;
color: #fff;
.header-left {
display: flex;
.side-icon {
width: 36px;
height: 32px;
font-weight: 400;
line-height: normal;
color: #b4b4b4;
}
.search {
display: flex;
align-items: center;
justify-content: space-between;
height: 50px;
margin: 0 20px;
:deep(.el-form-item) {
margin: 0;
}
.search-top {
position: relative;
box-sizing: border-box;
width: 215px;
height: 45px;
margin-bottom: 5px;
border: 3px solid #d7d7d7;
border-radius: 7px;
.card-title {
position: absolute;
top: -18px; /* 使标题悬浮在边框上方 */
left: 20px; /* 根据需要调整水平位置 */
padding: 0 8px; /* 增加一点内边距 */
font-size: 15px;
color: #fff;
background-color: #555;
}
.card-text {
display: flex;
align-items: center;
width: 100%;
height: 100%;
:deep(.el-input__wrapper) {
background-color: transparent;
box-shadow: none;
}
:deep(.el-input__inner) {
font-size: 21px;
color: #ff0;
}
}
}
.bottom-one {
width: 90px;
height: 40px;
margin-left: 20px;
font-size: 18px;
line-height: 40px; /* 让文字垂直居中 */
text-align: center;
background-color: rgb(22 155 213 / 100%);
border-radius: 5px;
}
}
}
.title {
font-size: 32px;
font-weight: 700;
}
.api-btn {
display: flex;
align-items: center;
justify-content: flex-end;
.btn {
display: flex;
align-items: center;
justify-content: center;
width: 150px;
height: 50px;
margin-left: 10px;
font-size: 18px;
color: #d7d7d7;
background-color: rgb(51 51 51 / 100%);
border-radius: 75px;
box-shadow: 5px 5px 5px rgb(0 0 0 / 34.9%);
}
.btn-active {
color: #000;
background-color: #f2f2f2;
box-shadow: none;
}
}
}
.content {
box-sizing: border-box;
display: flex;
flex: 1;
flex-direction: column;
width: 100%;
padding: 16px;
.header {
display: flex;
justify-content: space-between;
@ -150,8 +326,7 @@ const handleCurrentChange = async (val: number) => {
.footer-util {
display: flex;
flex-shrink: 0;
align-items: center;
justify-content: center;
justify-content: flex-end;
margin-bottom: 15px;
}
.footer-table {
@ -161,10 +336,28 @@ const handleCurrentChange = async (val: number) => {
.footer-pagination {
box-sizing: border-box;
display: flex;
flex-shrink: 0;
justify-content: flex-end;
align-items: center;
width: 100%;
padding-top: 20px;
.btn-export {
display: flex;
align-items: center;
justify-content: center;
width: 300px;
height: 60px;
font-size: 21px;
color: #fff;
background-color: rgb(0 128 128 / 100%);
border-radius: 5px;
box-shadow: 5px 5px 5px rgb(0 0 0 / 34.9%);
.icon {
width: 32px;
height: 32px;
margin-right: 10px;
color: #80fffe;
}
}
}
}
}
}

View File

@ -56,43 +56,31 @@
v-loading="tableLoading"
:data="tableState.tableData"
style="width: 100%; height: 100%"
@row-click="onClickOpenDetail"
>
<el-table-column type="index" label="No." width="50" />
<el-table-column prop="schedule.name" label="船期" align="center" width="120" />
<el-table-column prop="schedule.ship.name" label="船名" align="center" width="120" />
<el-table-column prop="schedule.voyage" label="航次" align="center" width="120" />
<el-table-column prop="deck" label="舱层" align="center" width="80" />
<el-table-column prop="cabin" label="舱段" align="center" width="80" />
<el-table-column prop="billNo" label="贸易类型" align="center" width="160" />
<el-table-column prop="billNo" label="提单号" align="center" width="160" />
<el-table-column prop="goodsName" label="货名" align="center" width="120" />
<el-table-column prop="brand.name" label="品牌" align="center" width="120" />
<el-table-column prop="model" label="型号" align="center" width="120" />
<el-table-column label="货名/品牌/型号" align="center" width="200">
<template #default="scope">
<div class="goods-name">
{{ scope.row.goodsName }}/{{ scope.row.brand.name }}/{{ scope.row.model }}
</div>
</template>
</el-table-column>
<el-table-column prop="shippingMark" label="唛头" align="center" width="180" />
<el-table-column prop="carNum" label="车数量" align="center" width="100" />
<el-table-column prop="spareNum" label="件杂货数" align="center" width="100" />
<el-table-column prop="weight" label="重量" align="center" width="100" />
<el-table-column prop="volume" label="体积" align="center" width="100" />
<el-table-column prop="carNum" label="商品车" align="center" width="100" />
<el-table-column prop="spareNum" label="件杂货" align="center" width="100" />
<el-table-column prop="weight" label="重量 (kg)" align="center" width="100" />
<el-table-column prop="volume" label="体积 (m3)" align="center" width="100" />
<!-- TODO:港口没有 -->
<el-table-column prop="consigner" label="发货人" align="center" width="180" />
<el-table-column prop="consignee" label="收货人" align="center" width="180" />
<el-table-column prop="goodsStatus" label="货物状态" align="center" width="150" />
<el-table-column prop="createDate" label="创建时间" align="center" width="180" />
<el-table-column
prop="operator"
label="操作"
width="200px"
align="center"
fixed="right"
>
<template #default="scope">
<el-button
type="primary"
size="small"
icon="View"
link
@click="onClickOpenDetail(scope.row)"
>
查看明细
</el-button>
</template>
</el-table-column>
</el-table>
</div>
@ -318,6 +306,10 @@ const handleCurrentChange = async (val: number) => {
background-color: transparent;
box-shadow: none;
}
:deep(.el-select__selection) {
font-size: 21px;
color: #ff0;
}
}
}
.search-bottom {

View File

@ -21,10 +21,13 @@
@ReturnRouter="onClickReturn"
@CurrentNav="onClickChangeSubscribeType"
/>
<!-- <div class="content">
<ManifestDetailTable :manifestId="manifestID" v-if="currentSubscribeNav === ''" />
</div> -->
<ManifestDetailTable
:manifestId="manifestID"
v-if="currentSubscribeNav === '提单明细'"
@ReturnRouter="onClickReturn"
@CurrentNav="onClickChangeSubscribeType"
/>
</div>
</template>
@ -32,7 +35,7 @@
import { ref } from 'vue';
import { useRouter } from 'vue-router';
import { ManifestType } from '@/types/manifest';
// import ManifestDetailTable from './components/ManifestDetailTable.vue';
import ManifestDetailTable from './components/ManifestDetailTable.vue';
import ManifestTable from './components/ManifestTable.vue';
const router = useRouter();

View File

@ -0,0 +1,174 @@
<template>
<div class="historyTable">
<el-table :data="historyData">
<el-table-column prop="ship.name" label="船名" align="center" width="150" />
<el-table-column prop="voyage" label="航次" align="center" width="180" />
<el-table-column label="装货港 / 装货码头" align="center" width="300">
<template #default="scope">
<div class="goods-name">
{{ scope.row.loadPort.name }} / {{ scope.row.loadWharf.name }}
</div>
</template>
</el-table-column>
<el-table-column label="卸货港 / 卸货码头" align="center" width="300">
<template #default="scope">
<div class="goods-name">
{{ scope.row.dischargePort.name }} / {{ scope.row.dischargeWharf.name }}
</div>
</template>
</el-table-column>
<el-table-column prop="carNumActual" label="商品车数量" align="center" width="180" />
<el-table-column prop="spareNumActual" label="件杂货数量" align="center" width="180" />
<el-table-column prop="departureDatePlan" label="计划离港时间" align="center" width="200" />
<el-table-column prop="departureDateActual" label="实际离港时间" align="center" width="200" />
<el-table-column prop="shipStatus" label="当前状态" align="center" width="150" />
</el-table>
<div class="table-content">
<div class="table-header">
<div style="width: 36px"></div>
<div class="table-header-title">舱单信息</div>
<div></div>
</div>
<el-table
:data="manifestTable"
style="width: 100%"
max-height="400px"
@row-click="onClickOpenManifestDetail"
>
<el-table-column type="index" label="No." width="50" />
<el-table-column prop="schedule.ship.name" label="船名" align="center" width="120" />
<el-table-column prop="schedule.voyage" label="航次" align="center" width="120" />
<el-table-column prop="deck" label="舱层" align="center" width="80" />
<el-table-column prop="cabin" label="舱段" align="center" width="80" />
<el-table-column prop="billNo" label="贸易类型" align="center" width="160" />
<el-table-column prop="billNo" label="提单号" align="center" width="160" />
<el-table-column label="货名/品牌/型号" align="center" width="200">
<template #default="scope">
<div class="goods-name">
{{ scope.row.goodsName }}/{{ scope.row.brand.name }}/{{ scope.row.model }}
</div>
</template>
</el-table-column>
<el-table-column prop="shippingMark" label="唛头" align="center" width="180" />
<el-table-column prop="carNum" label="商品车" align="center" width="100" />
<el-table-column prop="spareNum" label="件杂货" align="center" width="100" />
<el-table-column prop="weight" label="重量 (kg)" align="center" width="100" />
<el-table-column prop="volume" label="体积 (m3)" align="center" width="100" />
<!-- TODO:港口没有 -->
<el-table-column prop="consigner" label="发货人" align="center" width="180" />
<el-table-column prop="consignee" label="收货人" align="center" width="180" />
<el-table-column prop="goodsStatus" label="货物状态" align="center" width="150" />
</el-table>
</div>
<div class="table-content">
<div class="table-header">
<div style="width: 36px"></div>
<div class="table-header-title">舱单明细</div>
<div></div>
</div>
<el-table v-loading="tableLoading" :data="manifestDetail" max-height="400px">
<el-table-column type="index" label="No." width="50" />
<el-table-column prop="billNo" label="提单号" align="center" width="150" />
<el-table-column prop="brand.name" label="品牌" align="center" width="150" />
<el-table-column prop="vehicleType.name" label="车型" align="center" width="150" />
<el-table-column
prop="vehicleTypeDetail.name"
label="车型明细"
align="center"
width="180"
/>
<el-table-column prop="model" label="型号" align="center" width="150" />
<el-table-column prop="vin" label="VIN" align="center" width="200" />
<el-table-column prop="weight" label="重量(kg)" align="center" width="150" />
<el-table-column prop="volume" label="体积(m3)" align="center" width="150" />
<el-table-column prop="length" label="长 mm" align="center" width="150" />
<el-table-column prop="width" label="宽 mm" align="center" width="150" />
<el-table-column prop="height" label="高 mm" align="center" width="150" />
<el-table-column prop="bamm" label="BAmm" align="center" width="150" />
<el-table-column prop="lrmm" label="LRmm" align="center" width="150" />
<el-table-column prop="damage" label="有无质损" align="center" width="150" />
<el-table-column prop="damageDesc" label="质损描述" align="center" width="200" />
<el-table-column prop="updateDate" label="更新时间" align="center" width="180" />
</el-table>
</div>
</div>
</template>
<script lang="ts" setup>
import dayjs from 'dayjs';
import { onMounted, ref } from 'vue';
import { getManifestListAPI } from '@/api/Manifest';
import { getManifestDetailListAPI } from '@/api/Manifest/detail';
import { BoatInfoType } from '@/types/boatInfo';
import { ManifestDetailType, ManifestType } from '@/types/manifest';
//
const props = defineProps<{
historyData: BoatInfoType[];
}>();
//
const manifestTable = ref<ManifestType[]>([]);
//
const getManifestTable = async () => {
const scheduleId = props.historyData[0].shipId;
const { data } = await getManifestListAPI({
scheduleId,
});
manifestTable.value = data;
};
onMounted(async () => {
await getManifestTable();
});
//
const tableLoading = ref(false);
//
const manifestDetail = ref<ManifestDetailType[]>([]);
//
const onClickOpenManifestDetail = async (row: ManifestType) => {
tableLoading.value = true;
const { data } = await getManifestDetailListAPI({
manifestId: [row.id],
});
manifestDetail.value = data.map((item) => {
item.createDate = dayjs(item.createDate).format('YYYY-MM-DD HH:mm');
item.updateDate = dayjs(item.updateDate).format('YYYY-MM-DD HH:mm');
return item;
});
tableLoading.value = false;
};
</script>
<style lang="scss" scoped>
.historyTable {
display: flex;
flex: 1;
flex-direction: column;
width: 100%;
.table-content {
width: 100%;
.table-header {
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: space-between;
padding: 16px 16px 0;
margin-bottom: 15px;
color: #fff;
.table-header-title {
font-size: 28px;
font-weight: 700;
}
}
}
}
</style>

View File

@ -0,0 +1,251 @@
<template>
<el-dialog v-model="dialogVisible" width="866px" style="padding: 0" :show-close="false">
<template #header>
<div class="header">我发布的船货信息</div>
</template>
<div class="content">
<div class="content-left">
<div class="item">
<div class="title">起运港</div>
<div class="text">{{ dialogProps.row.loadPort?.name }}</div>
</div>
<div class="item">
<div class="title">目的港:</div>
<div class="text">{{ dialogProps.row.dischargePort?.name }}</div>
</div>
<div class="item">
<div class="title">船名:</div>
<div class="text">{{ dialogProps.row.ship?.name }}</div>
</div>
<div class="item">
<div class="title">航次:</div>
<div class="text">{{ dialogProps.row.voyage }}</div>
</div>
<div class="item">
<div class="title">计划装载:</div>
<div class="text">{{ dialogProps.row.carNumPlan }}()</div>
</div>
<div class="item">
<div class="title">实际装载:</div>
<div class="text">{{ dialogProps.row.carNumActual }}()</div>
</div>
<div class="item">
<div class="title">计划离港时间:</div>
<div class="text">{{ dialogProps.row.departureDatePlan }}</div>
</div>
<div class="item">
<div class="title">实际离港时间:</div>
<div class="text">{{ dialogProps.row.departureDateActual }}</div>
</div>
<div class="item">
<div class="title">当前状态:</div>
<div class="text">
<el-select v-model="dialogProps.row.shipStatus" placeholder="" style="width: 100%">
<el-option label="有计划" value="PLAN" />
<el-option label="已靠港" value="REACH" />
<el-option label="作业中" value="WORK" />
<el-option label="已离港" value="LEAVE" />
</el-select>
</div>
</div>
</div>
<div class="content-right">
<!-- <div class="btn-img">查看船图</div>
<div class="btn-address">查看船位</div> -->
<div class="info">
<div class="info-item">
<div class="info-title">发布单位</div>
<div class="info-text">{{ userInfo.enterpriseName }}</div>
</div>
<div class="info-item">
<div class="info-title">发布人</div>
<div class="info-text">{{ userInfo.username }}</div>
</div>
<div class="info-item">
<div class="info-title">发布时间</div>
<div class="info-text">{{ dialogProps.row.createDate }}</div>
</div>
<div class="info-item">
<div class="info-title">更新时间</div>
<div class="info-text">{{ dialogProps.row.updateDate }}</div>
</div>
<div class="info-item">
<div class="info-title">联系电话</div>
<div class="info-text">暂无</div>
</div>
</div>
</div>
</div>
<template #footer>
<div class="footer">
<div class="btn" @click="onClickUpdateStatus"></div>
</div>
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import { ElMessage } from 'element-plus';
import { storeToRefs } from 'pinia';
import { ref } from 'vue';
import { getSailScheduleUpdateAPI } from '@/api/Boat/info';
import { useUserStore } from '@/store/modules/user';
import { BoatInfoType } from '@/types/boatInfo';
interface DialogPropsType {
row: Partial<BoatInfoType>;
getTableList?: () => void;
}
// dialog
const dialogVisible = ref(false);
//
const dialogProps = ref<DialogPropsType>({
row: {},
});
// dialog/
const isShowDialog = (params: DialogPropsType) => {
dialogProps.value = params;
dialogVisible.value = true;
};
//
defineExpose({ isShowDialog });
//
const userState = useUserStore();
const { userInfo } = storeToRefs(userState);
//
const onClickUpdateStatus = async () => {
try {
await getSailScheduleUpdateAPI({
id: dialogProps.value.row.id!,
status: dialogProps.value.row.shipStatus!,
});
ElMessage({
message: `更新状态成功`,
type: 'success',
});
dialogProps.value.getTableList!();
} finally {
dialogVisible.value = false;
}
};
</script>
<style lang="scss" scoped>
.header {
width: 100%;
height: 50px;
font-size: 18px;
line-height: 50px;
color: #fff;
text-align: center;
background-color: #a30014;
}
.content {
box-sizing: border-box;
display: flex;
justify-content: space-between;
width: 100%;
padding: 30px 60px;
.content-left {
width: 319px;
height: 342px;
font-size: 21px;
font-weight: 400;
color: #333;
.item {
display: flex;
width: 100%;
line-height: 38px;
.title {
width: 147px;
}
.text {
flex: 1;
color: #027db4;
}
}
}
.content-right {
display: flex;
flex-direction: column;
justify-content: space-between;
width: 238px;
height: 342px;
// margin-left: 160px;
.btn-img {
width: 120px;
height: 40px;
font-size: 15px;
line-height: 40px;
color: #fff;
text-align: center;
background-color: rgb(0 128 128 / 100%);
border-radius: 5px;
}
.btn-address {
width: 120px;
height: 40px;
font-size: 15px;
line-height: 40px;
color: #fff;
text-align: center;
background-color: rgb(22 155 213 / 100%);
border-radius: 5px;
}
.info {
box-sizing: border-box;
width: 238px;
height: 180px;
padding: 15px 20px;
font-family: 'Arial Normal', Arial;
font-size: 15px;
font-style: normal;
font-weight: 400;
line-height: 30px;
color: #333;
background-color: rgb(242 242 242 / 100%);
border-radius: 7px;
.info-item {
display: flex;
width: 100%;
line-height: 30px;
.info-title {
width: 75px;
}
.info-text {
flex: 1;
color: #027db4;
}
}
}
}
}
.footer {
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: center;
width: 100%;
padding-bottom: 40px;
background-color: #fff;
.btn {
width: 170px;
height: 55px;
font-size: 18px;
line-height: 55px;
color: #fff;
text-align: center;
background-color: #027db4;
border-radius: 5px;
box-shadow: 5px 5px 5px rgb(0 0 0 / 34.9%);
}
}
</style>

View File

@ -12,48 +12,46 @@
max-height="400px"
v-el-table-infinite-scroll="tableDataLoad"
:infinite-scroll-disabled="disabled"
@row-click="onClickCellOpenDetail"
>
<!-- <el-table-column prop="enterprise.name" label="企业" align="center" width="150" /> -->
<el-table-column prop="ship.name" label="船名" align="center" width="150" />
<el-table-column prop="voyage" label="航次" align="center" width="180" />
<el-table-column prop="loadPort.name" label="装货港口" align="center" width="150" />
<el-table-column prop="loadWharf.name" label="装货码头" align="center" width="150" />
<el-table-column prop="dischargePort.name" label="卸货港口" align="center" width="150" />
<el-table-column prop="dischargeWharf.name" label="卸货码头" align="center" width="150" />
<el-table-column prop="carNumPlan" label="计划商品车数量" align="center" width="180" />
<el-table-column prop="carNumActual" label="实际商品车数量" align="center" width="180" />
<el-table-column prop="spareNumPlan" label="计划件杂货数量" align="center" width="180" />
<el-table-column
prop="spareNumActual"
label="实际件杂货数量"
align="center"
width="180"
/>
<el-table-column label="装货港 / 装货码头" align="center" width="300">
<template #default="scope">
<div class="goods-name">
{{ scope.row.loadPort.name }} / {{ scope.row.loadWharf.name }}
</div>
</template>
</el-table-column>
<el-table-column label="卸货港 / 卸货码头" align="center" width="300">
<template #default="scope">
<div class="goods-name">
{{ scope.row.dischargePort.name }} / {{ scope.row.dischargeWharf.name }}
</div>
</template>
</el-table-column>
<!-- <el-table-column prop="carNumPlan" label="计划商品车数量" align="center" width="180" /> -->
<el-table-column prop="carNumActual" label="商品车数量" align="center" width="180" />
<!-- <el-table-column prop="spareNumPlan" label="计划件杂货数量" align="center" width="180" /> -->
<el-table-column prop="spareNumActual" label="件杂货数量" align="center" width="180" />
<el-table-column
prop="departureDatePlan"
label="计划离泊时间"
label="计划离时间"
align="center"
width="200"
/>
<el-table-column
prop="departureDateActual"
label="实际离时间"
label="实际离时间"
align="center"
width="200"
/>
<el-table-column prop="tradeType" label="贸易类型" align="center" width="150" />
<el-table-column prop="shipStatus" label="当前状态" align="center" width="150" />
<el-table-column prop="operator" label="操作" width="200px" align="center" fixed="right">
<template #default="scope">
<el-button
type="primary"
size="small"
icon="View"
link
@click="onClickOpenDetail(scope.row)"
>
查看
</el-button>
<div class="update-btn">
<div class="btn" @click.stop="onClickOpenDetail(scope.row)">更新状态</div>
</div>
</template>
</el-table-column>
</el-table>
@ -66,19 +64,24 @@
</div>
</div>
</div>
<SendDialog ref="sendDialogRef" />
</div>
</template>
<script lang="ts" setup>
import dayjs from 'dayjs';
import { computed, ref } from 'vue';
import { getSailScheduleGetAPI, getSailSchedulePageAPI } from '@/api/Boat/info';
import { getSailSchedulePageAPI } from '@/api/Boat/info';
import { BoatInfoType } from '@/types/boatInfo';
import SendDialog from './SendDialog.vue';
const handleTableData = (data: BoatInfoType[]) => {
for (const item of data) {
item.departureDatePlan = dayjs(item.departureDatePlan).format('YYYY-MM-DD HH:mm');
item.departureDateActual = dayjs(item.departureDateActual).format('YYYY-MM-DD HH:mm');
item.createDate = dayjs(item.createDate).format('YYYY-MM-DD HH:mm');
item.updateDate = dayjs(item.updateDate).format('YYYY-MM-DD HH:mm');
}
return data;
};
@ -118,17 +121,33 @@ const tableDataLoad = async () => {
await getTableDataList();
};
const emits = defineEmits(['sendInfo']);
const emits = defineEmits(['sendInfo', 'openDetail']);
//
const onClickSendInfo = () => {
emits('sendInfo');
};
//
const onClickCellOpenDetail = (row: BoatInfoType) => {
emits('openDetail', row);
};
//
const getTableList = async () => {
currentPage.value = 1;
tableData.value = [];
await getTableDataList();
};
//
const sendDialogRef = ref<InstanceType<typeof SendDialog> | null>(null);
const onClickOpenDetail = async (row: BoatInfoType) => {
const { data } = await getSailScheduleGetAPI({ id: row.id });
console.log('🚀 ~ file: BoatTable.vue:146 ~ onClickOpenDetail ~ data:', data);
const params = {
row,
getTableList,
};
sendDialogRef.value?.isShowDialog(params);
};
</script>
@ -167,6 +186,25 @@ const onClickOpenDetail = async (row: BoatInfoType) => {
.footer-table {
position: relative;
flex: 1;
.update-btn {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
.btn {
width: 135px;
height: 40px;
font-size: 18px;
line-height: 40px;
background-color: rgb(0 191 191 / 100%);
border-radius: 26px;
}
.btn:hover {
color: #fff;
background-color: rgb(109 0 14 / 100%);
}
}
}
.footer-pagination {
box-sizing: border-box;

View File

@ -2,12 +2,17 @@
<div class="table">
<div class="header">
<svg-icon icon="return" className="side-icon" @click="onClickReturn"></svg-icon>
<div class="title">发布船货信息</div>
<div class="title">{{ isViewHistory ? '船期信息' : '发布船货信息' }}</div>
<div></div>
</div>
<div class="content">
<SendTable v-if="currentSubscribeNav === ''" @sendInfo="onClickSendInfo" />
<SendTable
v-if="currentSubscribeNav === '船货信息' && !isViewHistory"
@sendInfo="onClickSendInfo"
@openDetail="onClickOpenDetail"
/>
<HistoryTable v-if="isViewHistory" :historyData="historyData!" />
<Send v-if="currentSubscribeNav === ''" />
</div>
</div>
@ -16,6 +21,8 @@
<script lang="ts" setup>
import { ref } from 'vue';
import { useRouter } from 'vue-router';
import { BoatInfoType } from '@/types/boatInfo';
import HistoryTable from './components/HistoryTable.vue';
import Send from './components/Send.vue';
import SendTable from './components/SendTable.vue';
@ -23,7 +30,12 @@ const router = useRouter();
//
const onClickReturn = () => {
//
if (isViewHistory.value) {
isViewHistory.value = false;
} else {
router.back();
}
};
//
@ -33,6 +45,16 @@ const currentSubscribeNav = ref('船货信息');
const onClickSendInfo = () => {
currentSubscribeNav.value = '发布信息';
};
//
const isViewHistory = ref(false);
const historyData = ref<BoatInfoType[]>([]);
//
const onClickOpenDetail = (row: BoatInfoType) => {
historyData.value = [row];
isViewHistory.value = true;
};
</script>
<style lang="scss" scoped>
@ -63,30 +85,6 @@ const onClickSendInfo = () => {
font-size: 28px;
font-weight: 700;
}
.api-btn {
display: flex;
flex: 1;
align-items: center;
justify-content: flex-end;
.btn {
display: flex;
align-items: center;
justify-content: center;
width: 150px;
height: 50px;
margin-left: 10px;
font-size: 18px;
color: #d7d7d7;
background-color: rgb(51 51 51 / 100%);
border-radius: 75px;
box-shadow: 5px 5px 5px rgb(0 0 0 / 34.9%);
}
.btn-active {
color: #000;
background-color: #f2f2f2;
box-shadow: none;
}
}
}
.content {
box-sizing: border-box;

View File

@ -1,10 +1,8 @@
<template>
<el-dialog
v-model="dialogVisible"
:title="`${dialogProps.title}`"
width="80%"
@close="onCloseDialog"
>
<el-dialog v-model="dialogVisible" width="866px" style="padding: 40px" :show-close="false">
<template #header>
<div class="header">{{ dialogProps.title }}我的订阅</div>
</template>
<el-form
ref="ruleFormRef"
label-width="auto"
@ -13,102 +11,87 @@
:model="dialogProps.row"
:hide-required-asterisk="dialogProps.isView"
>
<!-- <el-form-item label="订阅企业" prop="enterpriseId">
<el-input v-model="dialogProps.row!.enterpriseId" placeholder="请输入订阅企业ID" />
</el-form-item> -->
<el-form-item label="订阅港口" prop="portId">
<RemoteSelect
v-model:value="dialogProps.row!.portId"
placeholder="请选择订阅港口"
:api="postPortListAPI"
/>
</el-form-item>
<el-form-item label="订阅码头" prop="wharfId">
<RemoteSelect
v-model:value="dialogProps.row!.wharfId"
placeholder="请选择订阅码头"
:api="postWharfListAPI"
/>
</el-form-item>
<el-form-item label="订阅的企业" prop="subEnterpriseId">
<el-form-item label="订阅企业" prop="subEnterpriseId">
<RemoteSelect
v-model:value="dialogProps.row!.subEnterpriseId"
placeholder="请选择订阅的企业"
:api="postEnterpriseListAPI"
/>
</el-form-item>
<el-form-item label="订阅的航线" prop="subShipRouteId">
<el-row :gutter="30">
<el-col :span="12">
<el-form-item label="起运港口" prop="subShipRouteId">
<RemoteSelect
v-model:value="dialogProps.row!.subShipRouteId"
placeholder="请选择订阅的航线"
placeholder="请选择上游港口航线"
:api="postRouteListAPI"
/>
</el-form-item>
<el-form-item label="订阅的港口" prop="subPortId">
</el-col>
<el-col :span="12">
<el-form-item prop="subPortId">
<RemoteSelect
v-model:value="dialogProps.row!.subPortId"
placeholder="请选择订阅的港口"
placeholder="请选择上游港口"
:api="postPortListAPI"
:disabled="true"
/>
</el-form-item>
<el-form-item label="订阅的码头" prop="subWharfId">
</el-col>
</el-row>
<el-form-item label="装货码头" prop="subWharfId">
<RemoteSelect
v-model:value="dialogProps.row!.subWharfId"
placeholder="请选择订阅的码头"
:api="postWharfListAPI"
placeholder="请选择港口码头"
:api="() => postWharfListAPI({ ref: dialogProps.row!.subPortId })"
:disabled="!dialogProps.row.subPortId"
/>
</el-form-item>
<el-form-item label="订阅类型" prop="subInfo">
<el-select v-model="dialogProps.row!.subInfo" placeholder="请选择订阅类型">
<el-form-item label="订阅信息" prop="subInfo">
<el-select v-model="dialogProps.row!.subInfo" placeholder="请选择订阅信息">
<el-option label="船期信息" value="船期信息" />
<el-option label="舱单信息" value="舱单信息" />
<el-option label="舱单明细" value="舱单明细" />
</el-select>
</el-form-item>
<el-form-item label="阅开始日期" prop="beginDate">
<el-form-item label="订日期" prop="beginDate">
<el-date-picker
v-model="dialogProps.row!.beginDate"
type="date"
placeholder="请选择阅开始日期"
placeholder="请选择订日期"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD HH:mm"
/>
</el-form-item>
<el-form-item label="订阅结束日期" prop="endDate">
<el-form-item label="截止日期" prop="endDate">
<el-date-picker
v-model="dialogProps.row!.endDate"
type="date"
placeholder="请选择订阅结束日期"
placeholder="请选择截止日期"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD HH:mm"
/>
</el-form-item>
<el-form-item label="订阅状态" prop="subStatus">
<el-select v-model="dialogProps.row!.subStatus" placeholder="请选择订阅状态">
<el-option label="待接受" value="NO_ACCEPTED" />
<el-option label="已关闭" value="CLOSED" />
<el-option label="订阅中" value="SUBSCRIBE" />
<el-option label="已取消" value="CANCELLED" />
</el-select>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button v-show="!dialogProps.isView" type="primary" @click="onClickConfirm(ruleFormRef)">
确认
</el-button>
</span>
<div class="footer">
<div class="btn-send" @click="onClickConfirm(ruleFormRef)"></div>
<div class="btn" @click="onCloseDialog"></div>
</div>
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import { ElMessage, FormInstance, FormRules } from 'element-plus';
import { reactive, ref } from 'vue';
import { storeToRefs } from 'pinia';
import { reactive, ref, watch } from 'vue';
import { postRouteListAPI } from '@/api/BoatRoute';
import { postEnterpriseListAPI } from '@/api/Enterprise/company';
import { postEnterpriseGetAPI, postEnterpriseListAPI } from '@/api/Enterprise/company';
import { postPortListAPI } from '@/api/Port';
import { postWharfListAPI } from '@/api/Wharf';
import RemoteSelect from '@/components/RemoteSelect/index.vue';
import { useUserStore } from '@/store/modules/user';
import { SubscriptionType } from '@/types/subscription';
interface DialogPropsType {
@ -129,6 +112,21 @@ const dialogProps = ref<DialogPropsType>({
row: {},
});
//
watch(
() => dialogProps.value.row.subEnterpriseId ?? undefined,
async (newValue) => {
if (newValue) {
const { data } = await postEnterpriseGetAPI({ id: newValue as number });
if (data) {
dialogProps.value.row.subPortId = data.portId;
}
} else {
dialogProps.value.row.subPortId = undefined;
}
}
);
// dialog/
const isShowDialog = (params: DialogPropsType) => {
dialogProps.value = params;
@ -144,7 +142,7 @@ const formRules = reactive<FormRules>({
subEnterpriseId: [{ required: true, message: '请输入订阅的企业', trigger: 'blur' }],
subShipRouteId: [{ required: true, message: '请输入订阅的航线', trigger: 'blur' }],
subPortId: [{ required: true, message: '请输入订阅的港口', trigger: 'blur' }],
subWharfId: [{ required: true, message: '请输入订阅的码头', trigger: 'blur' }],
subWharfId: [{ required: true, message: '请输入订阅的码头', trigger: 'change' }],
subInfo: [{ required: true, message: '请选择订阅类型', trigger: 'change' }],
beginDate: [{ required: true, message: '请选择订阅开始日期', trigger: 'change' }],
endDate: [{ required: true, message: '请选择订阅结束日期', trigger: 'change' }],
@ -157,17 +155,30 @@ const ruleFormRef = ref<FormInstance>();
const onCloseDialog = () => {
//
ruleFormRef.value?.resetFields();
dialogVisible.value = false;
};
// ID
const userState = useUserStore();
const { userInfo } = storeToRefs(userState);
// /
const onClickConfirm = (formEl: FormInstance | undefined) => {
if (!formEl) return;
formEl.validate(async (valid) => {
if (!valid) return;
try {
// ID
if (dialogProps.value.title === '新增') {
dialogProps.value.row.portId = userInfo.value.portId as number;
dialogProps.value.row.wharfId = userInfo.value.wharfId as number;
}
await dialogProps.value.api!(dialogProps.value.row);
ElMessage({
message: `${dialogProps.value.title}成功`,
message:
dialogProps.value.title === '编辑'
? `编辑成功`
: '发送成功,请关注目标港口的接收反馈信息',
type: 'success',
});
dialogProps.value.getTableList!();
@ -178,4 +189,45 @@ const onClickConfirm = (formEl: FormInstance | undefined) => {
};
</script>
<style lang="scss" scoped></style>
<style lang="scss" scoped>
.header {
height: 30px;
font-size: 27px;
font-style: normal;
font-weight: 700;
line-height: 30px;
color: #a30014;
}
.footer {
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: center;
width: 100%;
padding-bottom: 40px;
background-color: #fff;
.btn-send {
width: 160px;
height: 50px;
font-size: 18px;
line-height: 50px;
color: #fff;
text-align: center;
background-color: rgb(163 0 20 / 100%);
border-radius: 5px;
box-shadow: 5px 5px 5px rgb(0 0 0 / 34.9%);
}
.btn {
width: 120px;
height: 50px;
margin-left: 20px;
font-size: 18px;
line-height: 50px;
color: #fff;
text-align: center;
background-color: rgb(1 84 120 / 100%);
border-radius: 5px;
box-shadow: 5px 5px 5px rgb(0 0 0 / 34.9%);
}
}
</style>

View File

@ -6,62 +6,64 @@
<div class="footer">
<!-- 表格 -->
<div class="footer-table">
<el-table v-loading="tableLoading" :data="tableState.tableData" max-height="100%">
<el-table-column prop="enterprise.name" label="订阅企业" align="center" width="150" />
<el-table-column prop="port.name" label="订阅港口" align="center" width="150" />
<el-table-column prop="wharf.name" label="订阅码头" align="center" width="150" />
<el-table-column
prop="subEnterprise.name"
label="订阅的企业"
align="center"
width="150"
/>
<el-table-column prop="subShipRoute.name" label="订阅的航线" align="center" width="150" />
<el-table-column prop="subPort.name" label="订阅的港口" align="center" width="150" />
<el-table-column prop="subWharf.name" label="订阅的码头" align="center" width="150" />
<el-table-column prop="subInfo" label="订阅类型" align="center" width="200" />
<el-table-column prop="beginDate" label="订阅开始日期" align="center" width="180" />
<el-table-column prop="endDate" label="订阅结束日期" align="center" width="180" />
<el-table-column prop="subStatus" label="订阅状态" align="center" width="150" />
<el-table-column prop="createDate" label="创建时间" align="center" width="180" />
<el-table-column prop="operator" label="操作" width="200px" align="center" fixed="right">
<el-table
v-loading="loadMoreState === 'loading'"
:data="tableData"
max-height="100%"
v-el-table-infinite-scroll="tableDataLoad"
:infinite-scroll-disabled="disabled"
>
<el-table-column type="index" label="序号" width="60" />
<el-table-column prop="subPort.name" label="上游港口" align="center" width="150" />
<el-table-column prop="subWharf.name" label="装货码头" align="center" width="150" />
<el-table-column prop="subInfo" label="订阅信息" align="center" width="200" />
<el-table-column prop="beginDate" label="订阅日期" align="center" width="180" />
<el-table-column prop="endDate" label="截止日期" align="center" width="180" />
<el-table-column prop="scheduleNum" label="收到船期" align="center" width="150" />
<el-table-column prop="billNoNum" label="收到舱单" align="center" width="150" />
<el-table-column prop="billNoDetailNum" label="舱单明细" align="center" width="150" />
<el-table-column prop="subStatus" label="状态" align="center" width="150">
<template #default="scope">
<el-button
type="primary"
size="small"
icon="View"
link
@click="onClickOpenDialog('查看', scope.row)"
<div style="color: #caf982" v-if="scope.row.subStatus === '待接受'">
{{ scope.row.subStatus }}
</div>
<div style="color: #f59a23" v-else-if="scope.row.subStatus === ''">
{{ scope.row.subStatus }}
</div>
<div style="color: #facd91" v-else-if="scope.row.subStatus === ''">
{{ scope.row.subStatus }}
</div>
<div style="color: #ffff80" v-else-if="scope.row.subStatus === ''">
{{ scope.row.subStatus }}
</div>
<div v-else>{{ scope.row.subStatus }}</div>
</template>
</el-table-column>
<el-table-column prop="operator" label="操作" width="240px" align="center" fixed="right">
<template #default="scope">
<div class="btn-wrap">
<div class="btn edit-btn" @click="onClickOpenDialog('编辑', scope.row)">修订</div>
<div>
<div
class="btn reset-btn"
v-if="scope.row.subStatus === '已取消'"
@click="onClickOpenStatusDialog(scope.row, 'SUBSCRIBE')"
>
查看
</el-button>
<el-button
type="primary"
size="small"
icon="Edit"
link
@click="onClickOpenDialog('编辑', scope.row)"
重启
</div>
<div
class="btn cancel-btn"
v-else
@click="onClickOpenStatusDialog(scope.row, 'CANCELLED')"
>
编辑
</el-button>
<el-button
type="primary"
size="small"
icon="Edit"
link
@click="onClickOpenStatusDialog(scope.row)"
>
状态
</el-button>
<el-button
type="danger"
size="small"
icon="Delete"
link
@click="onClickDel(scope.row)"
>
删除
</el-button>
取消
</div>
</div>
<div>
<div class="btn del-disable" v-if="scope.row.subStatus === '订阅中'"></div>
<div class="btn del-btn" v-else @click="onClickDel(scope.row)"></div>
</div>
</div>
</template>
</el-table-column>
</el-table>
@ -75,78 +77,72 @@
</div>
</div>
<PublishDialog ref="publishDialogRef" />
<el-dialog v-model="isShowStatusDialog" width="70%" top="50px">
<el-form ref="statusRuleFormRef" label-width="auto" :model="statusForm">
<!-- <el-form-item label="订阅企业" prop="enterpriseId">
<el-input v-model="dialogProps.row!.enterpriseId" placeholder="请输入订阅企业ID" />
</el-form-item> -->
<el-form-item
label="订阅状态"
:rules="[{ required: true, message: '请选择订阅类型', trigger: 'change' }]"
prop="status"
>
<el-select v-model="statusForm.status" placeholder="请选择订阅状态">
<el-option label="待接受" value="NO_ACCEPTED" />
<el-option label="已关闭" value="CLOSED" />
<el-option label="订阅中" value="SUBSCRIBE" />
<el-option label="已取消" value="CANCELLED" />
</el-select>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="isShowStatusDialog = false">取消</el-button>
<el-button type="primary" @click="onClickConfirm(statusRuleFormRef)"> </el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script lang="ts" setup>
import dayjs from 'dayjs';
import { ElMessage, ElMessageBox, FormInstance } from 'element-plus';
import { onMounted, reactive, ref } from 'vue';
import { ElMessage, ElMessageBox } from 'element-plus';
import { computed, ref } from 'vue';
import {
editStatusAPI,
publishPageAPI,
subscriptionDeleteAPI,
subscriptionSaveAPI,
} from '@/api/Subscription';
import { useTable } from '@/hooks/useTable';
import { PageRowsResult } from '@/types';
import { SubscriptionType } from '@/types/subscription';
import PublishDialog from './PublishDialog.vue';
//
const handleTableData = (data: PageRowsResult<SubscriptionType>) => {
const { records } = data;
for (const item of records) {
item.beginDate = dayjs(item.beginDate).format('YYYY-MM-DD HH:mm:ss');
item.endDate = dayjs(item.endDate).format('YYYY-MM-DD HH:mm:ss');
const handleTableData = (data: SubscriptionType[]) => {
for (const item of data) {
item.beginDate = dayjs(item.beginDate).format('YYYY-MM-DD HH:mm');
item.endDate = dayjs(item.endDate).format('YYYY-MM-DD HH:mm');
}
return data;
};
//
const tableData = ref<SubscriptionType[]>([]);
// -
const currentPage = ref(1);
//
const loadMoreState = ref('loading');
const disabled = computed(() => loadMoreState.value === 'finished');
//
const { getTableList, tableState } = useTable({
api: publishPageAPI,
dataCallBack: handleTableData,
});
const getTableDataList = async () => {
const { data } = await publishPageAPI({
page: currentPage.value,
rows: 10,
});
onMounted(async () => {
await getTableList();
});
//
const dataRecords = handleTableData(data.records);
//
// const searchTableForm = reactive({
// enterpriseId: '',
// portId: '',
// wharfId: '',
// });
tableData.value = [...tableData.value, ...dataRecords];
//
const tableLoading = ref(false);
currentPage.value++;
//
if (currentPage.value > Number(data.pages) || data.records.length < 10) {
loadMoreState.value = 'finished';
} else {
loadMoreState.value = 'load';
}
};
const tableDataLoad = async () => {
await getTableDataList();
};
//
const getTableList = async () => {
currentPage.value = 1;
tableData.value = [];
await getTableDataList();
};
const publishDialogRef = ref<InstanceType<typeof PublishDialog> | null>(null);
const onClickOpenDialog = (title: string, row: Partial<SubscriptionType> = {}) => {
@ -161,32 +157,16 @@ const onClickOpenDialog = (title: string, row: Partial<SubscriptionType> = {}) =
};
//
const isShowStatusDialog = ref(false);
const statusRuleFormRef = ref();
const statusForm = reactive({
id: 0,
status: '',
});
const onClickOpenStatusDialog = (row: SubscriptionType) => {
statusForm.id = row.id;
statusForm.status = row.subStatus;
isShowStatusDialog.value = true;
};
const onClickConfirm = (formEl: FormInstance | undefined) => {
if (!formEl) return;
formEl.validate(async (valid) => {
if (!valid) return;
try {
await editStatusAPI(statusForm);
const onClickOpenStatusDialog = async (row: SubscriptionType, status: string) => {
await editStatusAPI({
id: row.id,
status,
});
ElMessage({
message: `修改状态成功`,
type: 'success',
});
getTableList();
} finally {
isShowStatusDialog.value = false;
}
});
};
//
@ -248,6 +228,50 @@ const onClickDel = (row: SubscriptionType) => {
.footer-table {
position: relative;
flex: 1;
.btn-wrap {
display: flex;
flex-direction: row;
justify-content: space-between;
width: 100%;
height: 100%;
.btn {
width: 60px;
height: 32px;
font-size: 13px;
line-height: 32px;
color: #fff;
text-align: center;
border-radius: 5px;
box-shadow: 5px 5px 5px rgb(0 0 0 / 34.9%);
}
.edit-btn {
background-color: rgb(109 0 14 / 100%);
}
.edit-btn:hover {
background: rgb(163 0 20 / 100%);
}
.cancel-btn {
background-color: rgb(1 84 120 / 100%);
}
.cancel-btn:hover {
background: rgb(2 125 180 / 100%);
}
.reset-btn {
background-color: #4b7902;
}
.reset-btn:hover {
background: rgb(112 182 3 / 100%);
}
.del-btn {
background-color: #333;
}
.del-disable {
background-color: #7f7f7f;
}
.del-btn:hover {
background: rgb(0 0 0 / 100%);
}
}
}
.footer-pagination {
box-sizing: border-box;

View File

@ -6,24 +6,74 @@
<div class="footer">
<!-- 表格 -->
<div class="footer-table">
<el-table v-loading="tableLoading" :data="tableState.tableData" max-height="100%">
<el-table-column prop="enterprise.name" label="订阅企业" align="center" width="150" />
<el-table-column prop="port.name" label="订阅港口" align="center" width="150" />
<el-table-column prop="wharf.name" label="订阅码头" align="center" width="150" />
<el-table-column
prop="subEnterprise.name"
label="订阅的企业"
align="center"
width="150"
/>
<el-table-column prop="subShipRoute.name" label="订阅的航线" align="center" width="150" />
<el-table-column prop="subPort.name" label="订阅的港口" align="center" width="150" />
<el-table-column prop="subWharf.name" label="订阅的码头" align="center" width="150" />
<el-table-column prop="subInfo" label="订阅类型" align="center" width="200" />
<el-table-column prop="beginDate" label="订阅开始日期" align="center" width="180" />
<el-table-column prop="endDate" label="订阅结束日期" align="center" width="180" />
<el-table-column prop="subStatus" label="订阅状态" align="center" width="150" />
<el-table-column prop="createDate" label="创建时间" align="center" width="180" />
<el-table
v-loading="loadMoreState === 'loading'"
:data="tableData"
max-height="100%"
v-el-table-infinite-scroll="tableDataLoad"
:infinite-scroll-disabled="disabled"
>
<el-table-column prop="port.name" label="下游港口" align="center" width="150" />
<el-table-column prop="wharf.name" label="卸货码头" align="center" width="150" />
<el-table-column prop="subInfo" label="订阅信息" align="center" width="200" />
<el-table-column prop="beginDate" label="订阅日期" align="center" width="180" />
<el-table-column prop="endDate" label="截止日期" align="center" width="180" />
<el-table-column prop="scheduleNum" label="已发船期" align="center" width="150" />
<el-table-column prop="billNoNum" label="已发舱单" align="center" width="150" />
<el-table-column prop="billNoDetailNum" label="舱单明细" align="center" width="150" />
<el-table-column prop="subStatus" label="状态" align="center" width="150">
<template #default="scope">
<div style="color: #caf982" v-if="scope.row.subStatus === '待接受'">
{{ scope.row.subStatus }}
</div>
<div style="color: #f59a23" v-else-if="scope.row.subStatus === ''">
{{ scope.row.subStatus }}
</div>
<div style="color: #facd91" v-else-if="scope.row.subStatus === ''">
{{ scope.row.subStatus }}
</div>
<div style="color: #ffff80" v-else-if="scope.row.subStatus === ''">
{{ scope.row.subStatus }}
</div>
<div v-else>{{ scope.row.subStatus }}</div>
</template>
</el-table-column>
<el-table-column prop="operator" label="操作" width="240px" align="center" fixed="right">
<template #default="scope">
<div class="btn-wrap">
<div>
<div
class="btn edit-btn"
@click="onClickOpenStatusDialog(scope.row, 'SUBSCRIBE')"
v-if="scope.row.subStatus === '待接受'"
>
接受
</div>
<div class="btn del-disable" v-else></div>
</div>
<div>
<div
class="btn del-disable"
v-if="scope.row.subStatus === '已关闭'"
@click="onClickOpenStatusDialog(scope.row, 'SUBSCRIBE')"
>
开启
</div>
<div
class="btn cancel-btn"
v-else
@click="onClickOpenStatusDialog(scope.row, 'CLOSED')"
>
关闭
</div>
</div>
<div>
<div class="btn del-disable" v-if="scope.row.subStatus === '订阅中'"></div>
<div class="btn del-btn" v-else @click="onClickDel(scope.row)"></div>
</div>
</div>
</template>
</el-table-column>
</el-table>
</div>
<!-- 分页 -->
@ -33,36 +83,110 @@
<script lang="ts" setup>
import dayjs from 'dayjs';
import { onMounted, ref } from 'vue';
import { receivePageAPI } from '@/api/Subscription';
import { useTable } from '@/hooks/useTable';
import { PageRowsResult } from '@/types';
import { ElMessage, ElMessageBox } from 'element-plus';
import { computed, ref } from 'vue';
import {
editStatusAPI,
receivePageAPI,
subscriptionCountAPI,
subscriptionDeleteAPI,
} from '@/api/Subscription';
import { useSettingStore } from '@/store/modules/setting';
import { SubscriptionType } from '@/types/subscription';
//
const handleTableData = (data: PageRowsResult<SubscriptionType>) => {
const { records } = data;
for (const item of records) {
item.beginDate = dayjs(item.beginDate).format('YYYY-MM-DD HH:mm:ss');
item.endDate = dayjs(item.endDate).format('YYYY-MM-DD HH:mm:ss');
const handleTableData = (data: SubscriptionType[]) => {
for (const item of data) {
item.beginDate = dayjs(item.beginDate).format('YYYY-MM-DD HH:mm');
item.endDate = dayjs(item.endDate).format('YYYY-MM-DD HH:mm');
}
return data;
};
//
const tableData = ref<SubscriptionType[]>([]);
// -
const currentPage = ref(1);
//
const loadMoreState = ref('loading');
const disabled = computed(() => loadMoreState.value === 'finished');
//
const { getTableList, tableState } = useTable({
api: receivePageAPI,
dataCallBack: handleTableData,
});
const getTableDataList = async () => {
const { data } = await receivePageAPI({
page: currentPage.value,
rows: 10,
});
onMounted(async () => {
//
const dataRecords = handleTableData(data.records);
tableData.value = [...tableData.value, ...dataRecords];
currentPage.value++;
//
if (currentPage.value > Number(data.pages) || data.records.length < 10) {
loadMoreState.value = 'finished';
} else {
loadMoreState.value = 'load';
}
};
const tableDataLoad = async () => {
await getTableDataList();
};
//
const getTableList = async () => {
currentPage.value = 1;
tableData.value = [];
await getTableDataList();
await getReceiveCount();
};
//
const settingState = useSettingStore();
const getReceiveCount = async () => {
const { data } = await subscriptionCountAPI();
settingState.setReceiveCount(Number(data));
};
//
const onClickOpenStatusDialog = async (row: SubscriptionType, status: string) => {
await editStatusAPI({
id: row.id,
status,
});
ElMessage({
message: `修改状态成功`,
type: 'success',
});
getTableList();
};
//
const onClickDel = (row: SubscriptionType) => {
ElMessageBox.confirm(`你确定要删除该订阅吗?`, '温馨提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
draggable: true,
})
.then(async () => {
await subscriptionDeleteAPI([row.id]);
//
await getTableList();
});
//
//
const tableLoading = ref(false);
ElMessage({
message: '删除成功',
type: 'success',
});
})
.catch(() => {
console.log('用户点击了取消');
});
};
</script>
<style lang="scss" scoped>
@ -101,6 +225,44 @@ const tableLoading = ref(false);
.footer-table {
position: relative;
flex: 1;
.btn-wrap {
display: flex;
flex-direction: row;
justify-content: space-between;
width: 100%;
height: 100%;
.btn {
width: 60px;
height: 32px;
font-size: 13px;
line-height: 32px;
color: #fff;
text-align: center;
border-radius: 5px;
box-shadow: 5px 5px 5px rgb(0 0 0 / 34.9%);
}
.edit-btn {
background-color: rgb(109 0 14 / 100%);
}
.edit-btn:hover {
background: rgb(163 0 20 / 100%);
}
.cancel-btn {
background-color: rgb(1 84 120 / 100%);
}
.cancel-btn:hover {
background: rgb(2 125 180 / 100%);
}
.del-btn {
background-color: #333;
}
.del-disable {
background-color: #7f7f7f;
}
.del-btn:hover {
background: rgb(0 0 0 / 100%);
}
}
}
.footer-pagination {
box-sizing: border-box;

View File

@ -6,13 +6,25 @@
<div class="api-btn">
<div
class="btn"
:class="{ 'btn-active': currentSubscribeNav === item }"
v-for="item in subscribeNavList"
:key="item"
@click="onClickChangeSubscribeType(item)"
:class="{ 'btn-active': currentSubscribeNav === '我的订阅' }"
@click="onClickChangeSubscribeType('我的订阅')"
>
{{ item }}
我的订阅
</div>
<el-badge
:value="receiveCount"
:show-zero="false"
:offset="[-10, 0]"
badge-style="background-color: #D9001C;color: #fff;"
>
<div
class="btn"
:class="{ 'btn-active': currentSubscribeNav === '收到订阅' }"
@click="onClickChangeSubscribeType('收到订阅')"
>
收到订阅
</div>
</el-badge>
</div>
</div>
@ -24,8 +36,10 @@
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { computed, onMounted, ref } from 'vue';
import { useRouter } from 'vue-router';
import { subscriptionCountAPI } from '@/api/Subscription';
import { useSettingStore } from '@/store/modules/setting';
import PublishTable from './components/PublishTable.vue';
import ReceiveTable from './components/ReceiveTable.vue';
@ -37,12 +51,24 @@ const onClickReturn = () => {
};
//
const subscribeNavList = ref(['我的订阅', '收到订阅']);
const currentSubscribeNav = ref('我的订阅');
const onClickChangeSubscribeType = async (item: string) => {
if (item === currentSubscribeNav.value) return;
currentSubscribeNav.value = item;
};
//
const settingState = useSettingStore();
const receiveCount = computed(() => settingState.receiveCount);
//
const getReceiveCount = async () => {
const { data } = await subscriptionCountAPI();
settingState.setReceiveCount(Number(data));
};
onMounted(async () => {
await getReceiveCount();
});
</script>
<style lang="scss" scoped>