You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

307 lines
8.9 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<view class="reservation-page" :class="{ 'wechat-browser': isWeixinBrowser }">
<view class="fixed-nav" v-if="!isWeixinBrowser">
<NavBar title="船只管理">
</NavBar>
</view>
<view class="content-area">
<view v-if="shipList.length === 0" class="empty-tip">
<image src="/static/empty.png" mode="aspectFit" class="empty-img" />
<text class="empty-text">暂无船只信息</text>
</view>
<view v-else>
<view v-for="item in shipList" :key="item.id" class="ship-cell" @click="goDetail(item)">
<view class="ship-card-header">
<view v-if="item.status === 'pending'" class="status pending"><span class="status-text">待审核</span></view>
<view v-else-if="item.status === 'rejected'" class="status rejected"><span class="status-text">已拒绝</span></view>
<view v-else-if="item.status === 'approved'" class="status approved"><span class="status-text">已通过</span></view>
</view>
<view class="ship-title">
船号: <text class="ship-no">{{ item.ship_number }}</text>
</view>
<view class="ship-row">所有人: {{ item.owner_name }}</view>
<view class="ship-row">联系电话: {{ item.phone }}</view>
<view class="ship-row">总吨位: {{ item.total_tonnage }} 吨</view>
</view>
</view>
</view>
<view class="fixed-bottom" v-if="shipList.length === 0">
<button class="add-cell-btn" @click="goAdd">添加</button>
</view>
<view class="fixed-bottom" v-if="shipList.length === 1">
<template v-if="shipList[0].status === 'pending'">
<button class="add-cell-btn" @click.stop="goEdit(shipList[0])">修改</button>
</template>
<template v-else-if="shipList[0].status === 'rejected'">
<button class="add-cell-btn" @click.stop="goEdit(shipList[0])">修改</button>
<button class="delete-cell-btn" @click.stop="onDelete(shipList[0])">删除</button>
</template>
<template v-else-if="shipList[0].status === 'approved'">
<button class="delete-cell-btn" @click.stop="onDelete(shipList[0])"></button>
</template>
</view>
</view>
</template>
<script>
import NavBar from '@/components/NavBar.vue'
import { API } from '@/config/index.js'
export default {
name: 'ShipManagePage',
components: { NavBar },
data() {
return {
isWeixinBrowser: false,
shipList: []
}
},
onLoad() {
// #ifdef H5
this.isWeixinBrowser = /MicroMessenger/i.test(navigator.userAgent)
// #endif
},
onShow() {
// 页面渲染完成后获取数据
this.fetchShipList();
},
methods: {
async fetchShipList() {
const token = uni.getStorageSync('token');
if (!token) {
uni.showToast({ title: '请先登录', icon: 'none' });
return;
}
uni.showLoading({ title: '加载中...' });
try {
console.log(API.SHIP_INDEX)
const res = await new Promise((resolve, reject) => {
uni.request({
url: API.SHIP_INDEX,
method: 'GET',
data: { token },
success: resolve,
fail: reject
});
});
uni.hideLoading();
if (res.data && res.data.errcode === 0) {
this.shipList = res.data.data || [];
} else {
uni.showToast({ title: res.data.errmsg || '获取失败', icon: 'none' });
}
} catch (error) {
uni.hideLoading();
uni.showToast({ title: error.message || '网络错误', icon: 'none' });
}
},
goAdd() {
uni.navigateTo({ url: '/pages/index/ship_add' })
},
goDetail(item) {
const itemStr = encodeURIComponent(JSON.stringify(item));
uni.navigateTo({
url: `/pages/index/ship_detail?id=${item.id}&item=${itemStr}`
})
},
getShipStatusText(status) {
if (status === 'pending') return '待审核';
if (status === 'rejected') return '已拒绝';
if (status === 'approved') return '已通过';
return '';
},
getShipStatusClass(status) {
if (status === 'pending') return 'pending';
if (status === 'rejected') return 'rejected';
if (status === 'approved') return 'approved';
return '';
},
goEdit(item) {
if (!item || !item.id) {
uni.showToast({ title: '无效的船舶信息', icon: 'none' });
return;
}
// 只传递船舶 id详情在 ship_add 页面通过接口获取
uni.navigateTo({
url: `/pages/index/ship_add?edit=1&id=${item.id}`
});
},
onDelete(item) {
const token = uni.getStorageSync('token');
if (!token) {
uni.showToast({ title: '请先登录', icon: 'none' });
return;
}
if (!item || !item.id) {
uni.showToast({ title: '无效的船舶信息', icon: 'none' });
return;
}
uni.showModal({
title: '提示',
content: '确定要删除该船舶吗?',
success: (res) => {
if (res.confirm) {
uni.showLoading({ title: '删除中...' });
uni.request({
url: `${API.SHIP_DELETE}/${item.id}?token=${token}`,
method: 'POST',
data: {},
header: { 'content-type': 'application/json' },
success: (res) => {
uni.hideLoading();
if (res.data && res.data.errcode === 0) {
uni.showToast({ title: '删除成功', icon: 'success' });
setTimeout(() => {
this.fetchShipList();
}, 1000);
} else {
uni.showToast({ title: res.data.errmsg || '删除失败', icon: 'none' });
}
},
fail: (err) => {
uni.hideLoading();
uni.showToast({ title: '网络错误', icon: 'none' });
}
});
}
}
});
}
}
}
</script>
<style lang="scss" scoped>
@import '@/styles/common.scss';
.reservation-page {
background: linear-gradient(180deg, #eaf3ff 0%, #f6faff 100%);
min-height: 100vh;
padding-bottom: 140rpx; // 为底部按钮留出空间
}
.wechat-browser {
padding-top: 20rpx;
}
.wechat-browser .content-area {
padding-top: 0;
}
.fixed-nav {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 100;
background: linear-gradient(180deg, #cbe6ff 0%, #f6faff 100%);
box-shadow: 0 2px 8px rgba(0,0,0,0.04);
}
.content-area {
padding: 220rpx 24rpx 24rpx 24rpx;
min-height: calc(100vh - 220rpx - 140rpx); // 减去顶部导航和底部按钮的高度
}
.ship-cell {
background: #fff;
border-radius: 16rpx;
box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.04);
padding: 32rpx 28rpx;
margin-bottom: 32rpx;
border: 1rpx solid #e5e5e5;
}
.ship-card-header {
display: flex;
align-items: center;
margin-bottom: 12rpx;
}
.status {
font-size: 24rpx;
border-radius: 8rpx;
padding: 2px 18rpx;
color: #fff;
font-weight: 500;
display: inline-block;
transform: skewX(-20deg);
border: none;
margin-right: 16rpx;
}
.status-text {
display: inline-block;
transform: skewX(20deg);
}
.status.pending { background: #ff9800; }
.status.rejected { background: #ff3b3b; }
.status.approved { background: #22c58b; }
.ship-title {
@include font-primary;
font-weight: $font-weight-bold;
margin-bottom: 18rpx;
color: $font-color-primary;
}
.ship-no {
color: $font-color-primary;
font-weight: $font-weight-bold;
@include font-primary;
}
.ship-row {
@include font-secondary;
color: $font-color-primary;
margin-bottom: 10rpx;
}
.fixed-bottom {
position: fixed;
left: 0;
right: 0;
bottom: 0;
background: #fcfcfc;
box-shadow: 0 -2rpx 16rpx rgba(59,124,255,0.08);
padding: 24rpx 24rpx 32rpx 24rpx;
z-index: 999;
display: flex;
justify-content: center;
}
.add-cell-btn {
min-width: 320rpx;
height: 80rpx;
border-radius: 40rpx;
background: #217aff;
color: #fff;
@include font-primary;
font-weight: $font-weight-medium;
border: none;
outline: none;
box-shadow: 0 4rpx 16rpx rgba(33,122,255,0.08);
transition: background 0.2s;
}
.empty-tip {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 120rpx 0;
}
.empty-img {
width: 240rpx;
height: 240rpx;
margin-bottom: 24rpx;
}
.empty-text {
@include font-secondary;
color: $font-color-secondary;
}
.delete-cell-btn {
min-width: 320rpx;
height: 80rpx;
border-radius: 40rpx;
background: #ff3b3b;
color: #fff;
@include font-primary;
font-weight: $font-weight-medium;
border: none;
outline: none;
box-shadow: 0 4rpx 16rpx rgba(255,59,59,0.12);
transition: background 0.2s;
}
.with-margin {
margin-left: 24rpx;
}
</style>