Przeglądaj źródła

feat(金融管理): 新增运费金融功能模块

添加运费金融功能页面,包括货主列表、可贷款航次展示和贷款申请流程
更新路由配置和菜单数据以支持新功能
添加leaflet地图依赖用于航次轨迹展示
优化环境配置和版本显示
wzg 4 miesięcy temu
rodzic
commit
0afd9077f0

+ 1 - 1
.env.dev

@@ -1,2 +1,2 @@
 VITE_PROJECT_ENV = 'dev'
-VITE_BASEURL = 'https://interface.huihenduo.com.cn/hhd-proxy-dev/'
+VITE_BASEURL = 'https://interface.huihenduo.cc/hhd-proxy/'

+ 1 - 0
package.json

@@ -17,6 +17,7 @@
     "dayjs": "^1.11.4",
     "echarts": "^5.3.3",
     "element-plus": "^1.1.0-beta.24",
+    "leaflet": "^1.9.4",
     "lodash": "^4.17.21",
     "md5": "^2.3.0",
     "vite-plugin-compression": "^0.3.5",

+ 18 - 6
src/auth/menuData.js

@@ -1,6 +1,6 @@
 let menuData = [
   {
-    icon: "el-icon-s-data",
+    icon: "el-icon-menu",
     title: "总台",
     code: "VOYAGELIST",
     items: [
@@ -12,7 +12,7 @@ let menuData = [
     ],
   },
   {
-    icon: "el-icon-s-data",
+    icon: "el-icon-ship",
     title: "航次管理",
     code: "VOYAGEMANAGE",
     items: [
@@ -51,7 +51,7 @@ let menuData = [
   //   ],
   // },
   {
-    icon: "el-icon-s-data",
+    icon: "el-icon-user",
     title: "船东管理",
     code: "SHIPOWNERMANAGE",
     items: [
@@ -63,7 +63,7 @@ let menuData = [
     ],
   },
   {
-    icon: "el-icon-s-data",
+    icon: "el-icon-document",
     title: "投标管理",
     code: "SHIPOWNERLIST",
     items: [
@@ -75,7 +75,7 @@ let menuData = [
     ],
   },
   {
-    icon: "el-icon-s-data",
+    icon: "el-icon-help",
     title: "账户管理",
     code: "ACCOUNTMANAGE",
     items: [
@@ -92,7 +92,7 @@ let menuData = [
     ],
   },
   {
-    icon: "el-icon-s-data",
+    icon: "el-icon-setting",
     title: "权限管理",
     code: "PERMISSIONMANAGE",
     items: [
@@ -108,6 +108,18 @@ let menuData = [
       },
     ],
   },
+  {
+    icon: "el-icon-money",
+    title: "金融管理",
+    code: "VOYAGELIST",
+    items: [
+      {
+        path: "/financeManage/freightFinance",
+        name: "运费金融",
+        code: "VOYAGELIST",
+      },
+    ],
+  },
 ];
 
 export default menuData;

+ 2 - 4
src/components/Header.vue

@@ -4,9 +4,7 @@
       <!-- <img class="first" src="../assets/three.png" alt="" />
       <div class="shu"></div> -->
       <img class="logo" src="../assets/white-logo.png" alt="" />
-      <div class="ml20" style="color: #fff; font-size: 18px">
-        version:{{ timelineData[0]?.version }}
-      </div>
+      <div class="ml20" style="color: #fff; font-size: 18px">version:1.0</div>
     </div>
     <div class="right">
       <el-alert
@@ -300,7 +298,7 @@ async function getCode() {
   }
 }
 onMounted(() => {
-  cloudLogin();
+  // cloudLogin();
 });
 </script>
 <style scoped>

+ 10 - 0
src/router/index.js

@@ -188,6 +188,16 @@ const router = createRouter({
       },
       component: () => import("../views/tenderManage/tenderDetail.vue"),
     },
+
+    {
+      path: "/financeManage/freightFinance",
+      name: "freightFinance",
+      meta: {
+        title: "运费金融",
+        code: "VOYAGELIST",
+      },
+      component: () => import("../views/financeManage/freightFinance.vue"),
+    },
   ],
 });
 

+ 899 - 0
src/views/financeManage/freightFinance.vue

@@ -0,0 +1,899 @@
+<template>
+  <div class="container">
+    <header class="header">
+      <div class="logo">运费金融</div>
+      <div class="user-info">
+        <span class="user-name">张三</span>
+        <span class="verified-icon" title="已认证">✓</span>
+      </div>
+    </header>
+
+    <section class="section">
+      <h2>认证货主列表</h2>
+      <div class="shipper-list">
+        <table>
+          <thead>
+            <tr>
+              <th>货主名称</th>
+              <th>认证有效期</th>
+              <th>贷款滚动额度(元)</th>
+              <th>已使用额度(元)</th>
+              <th>剩余额度(元)</th>
+            </tr>
+          </thead>
+          <tbody>
+            <tr v-for="shipper in shipperList" :key="shipper.id">
+              <td>{{ shipper.name }}</td>
+              <td>{{ shipper.validUntil }}</td>
+              <td>{{ formatCurrency(shipper.totalLimit) }}</td>
+              <td>{{ formatCurrency(shipper.usedLimit) }}</td>
+              <td>{{ formatCurrency(shipper.remainingLimit) }}</td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
+    </section>
+
+    <section class="section">
+      <h2>可申请贷款航次列表</h2>
+      <div class="voyage-list">
+        <table id="available-voyages">
+          <thead>
+            <tr>
+              <th>选择</th>
+              <th>航次编号</th>
+              <th>货主名称</th>
+              <th>货种</th>
+              <th>装载吨位(吨)</th>
+              <th>运价(元/吨)</th>
+              <th>航次总运费(元)</th>
+              <th>当前状态</th>
+            </tr>
+          </thead>
+          <tbody>
+            <tr v-for="voyage in availableVoyages" :key="voyage.id">
+              <td>
+                <input
+                  type="radio"
+                  name="voyage"
+                  :value="voyage.id"
+                  v-model="selectedVoyage"
+                />
+              </td>
+              <td>{{ voyage.voyageNumber }}</td>
+              <td>{{ voyage.shipperName }}</td>
+              <td>{{ voyage.cargoType }}</td>
+              <td>{{ voyage.weight.toLocaleString() }}</td>
+              <td>{{ voyage.rate }}</td>
+              <td>{{ formatCurrency(voyage.totalFreight) }}</td>
+              <td>{{ voyage.status }}</td>
+            </tr>
+          </tbody>
+        </table>
+        <div class="action-buttons">
+          <button @click="applyLoan" class="primary-btn">申请贷款</button>
+        </div>
+      </div>
+    </section>
+
+    <section class="section">
+      <h2>贷款中航次列表</h2>
+      <div class="loan-voyage-list">
+        <table>
+          <thead>
+            <tr>
+              <th>航次编号</th>
+              <th>货主名称</th>
+              <th>货种</th>
+              <th>装载吨位(吨)</th>
+              <th>运价(元/吨)</th>
+              <th>航次总运费(元)</th>
+              <th>贷款金额(元)</th>
+              <th>申请日期</th>
+              <th>贷款状态</th>
+              <th>还款状态</th>
+            </tr>
+          </thead>
+          <tbody>
+            <tr v-for="loanVoyage in loanVoyages" :key="loanVoyage.id">
+              <td>{{ loanVoyage.voyageNumber }}</td>
+              <td>{{ loanVoyage.shipperName }}</td>
+              <td>{{ loanVoyage.cargoType }}</td>
+              <td>{{ loanVoyage.weight.toLocaleString() }}</td>
+              <td>{{ loanVoyage.rate }}</td>
+              <td>{{ formatCurrency(loanVoyage.totalFreight) }}</td>
+              <td>{{ formatCurrency(loanVoyage.loanAmount) }}</td>
+              <td>{{ loanVoyage.applicationDate }}</td>
+              <td>{{ loanVoyage.loanStatus }}</td>
+              <td :class="getRepaymentStatusClass(loanVoyage.repaymentStatus)">
+                {{ loanVoyage.repaymentStatus }}
+              </td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
+    </section>
+
+    <section v-if="showVoyageDetail" class="section">
+      <h2>航次详情</h2>
+      <div class="voyage-info">
+        <div class="info-section">
+          <h3>航次基础信息</h3>
+          <div class="info-grid">
+            <div class="info-item">
+              <span class="label">航次编号:</span>
+              <span class="value">{{ voyageDetail.voyageNumber }}</span>
+            </div>
+            <div class="info-item">
+              <span class="label">货主公司名称:</span>
+              <span class="value">{{ voyageDetail.shipperName }}</span>
+            </div>
+            <div class="info-item">
+              <span class="label">航次发起日期:</span>
+              <span class="value">{{ voyageDetail.startDate }}</span>
+            </div>
+            <div class="info-item">
+              <span class="label">装货港:</span>
+              <span class="value">{{ voyageDetail.loadingPort }}</span>
+            </div>
+            <div class="info-item">
+              <span class="label">卸货港:</span>
+              <span class="value">{{ voyageDetail.unloadingPort }}</span>
+            </div>
+            <div class="info-item">
+              <span class="label">船名:</span>
+              <span class="value">{{ voyageDetail.shipName }}</span>
+            </div>
+            <div class="info-item">
+              <span class="label">船东:</span>
+              <span class="value">{{ voyageDetail.shipOwner }}</span>
+            </div>
+            <div class="info-item">
+              <span class="label">船舶MMSI:</span>
+              <span class="value">{{ voyageDetail.shipMMSI }}</span>
+            </div>
+            <div class="info-item">
+              <span class="label">货种:</span>
+              <span class="value">{{ voyageDetail.cargoType }}</span>
+            </div>
+            <div class="info-item">
+              <span class="label">实载吨位:</span>
+              <span class="value">
+                {{ voyageDetail.weight.toLocaleString() }}吨
+              </span>
+            </div>
+            <div class="info-item">
+              <span class="label">运价:</span>
+              <span class="value">{{ voyageDetail.rate }}元/吨</span>
+            </div>
+            <div class="info-item">
+              <span class="label">航次总运费:</span>
+              <span class="value">
+                {{ formatCurrency(voyageDetail.totalFreight) }}
+              </span>
+            </div>
+          </div>
+        </div>
+
+        <div class="map-container">
+          <h3>航次轨迹</h3>
+          <div id="voyage-map" ref="voyageMap"></div>
+        </div>
+
+        <div class="info-section">
+          <h3>装货信息</h3>
+          <div class="info-grid">
+            <div class="info-item">
+              <span class="label">到达装货港时间:</span>
+              <span class="value">{{ voyageDetail.arrivalTime }}</span>
+            </div>
+            <div class="info-item">
+              <span class="label">装货开始时间:</span>
+              <span class="value">{{ voyageDetail.loadingStart }}</span>
+            </div>
+            <div class="info-item">
+              <span class="label">装货结束时间:</span>
+              <span class="value">{{ voyageDetail.loadingEnd }}</span>
+            </div>
+            <div class="info-item">
+              <span class="label">航次开航时间:</span>
+              <span class="value">{{ voyageDetail.departureTime }}</span>
+            </div>
+          </div>
+        </div>
+
+        <div class="document-section">
+          <h3>航次文件确认</h3>
+          <div class="document-list">
+            <div
+              class="document-item"
+              v-for="doc in voyageDetail.documents"
+              :key="doc.id"
+            >
+              <span class="document-name">{{ doc.name }}</span>
+              <button class="view-btn">查看</button>
+              <span class="confirm-status">✓ 已确认</span>
+            </div>
+          </div>
+        </div>
+
+        <div class="loan-application">
+          <h3>贷款申请</h3>
+          <div class="loan-amount-container">
+            <div class="loan-info">
+              <span class="label">航次总运费:</span>
+              <span class="value">
+                {{ formatCurrency(voyageDetail.totalFreight) }}
+              </span>
+            </div>
+            <div class="loan-info">
+              <span class="label">最高可贷款金额(80%):</span>
+              <span class="value">{{ formatCurrency(maxLoanAmount) }}</span>
+            </div>
+            <div class="loan-slider-container">
+              <span class="label">申请贷款金额:</span>
+              <input
+                type="range"
+                v-model="loanAmount"
+                :min="0"
+                :max="maxLoanAmount"
+                :step="10000"
+                class="loan-slider"
+              />
+              <span class="value">{{ formatCurrency(loanAmount) }}</span>
+            </div>
+          </div>
+          <div class="action-buttons">
+            <button @click="submitApplication" class="primary-btn">
+              提交申请
+            </button>
+            <button @click="cancelApplication" class="secondary-btn">
+              取消
+            </button>
+          </div>
+        </div>
+      </div>
+    </section>
+
+    <!-- 弹窗组件 -->
+    <div v-if="showModal" class="modal">
+      <div class="modal-content">
+        <span class="close-btn" @click="closeModal">&times;</span>
+        <h2>{{ modalTitle }}</h2>
+        <p>{{ modalMessage }}</p>
+        <div class="modal-buttons">
+          <button @click="confirmModal" class="primary-btn">确认</button>
+          <button v-if="!hideCancel" @click="closeModal" class="secondary-btn">
+            取消
+          </button>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import L from "leaflet";
+import "leaflet/dist/leaflet.css";
+
+export default {
+  name: "FreightFinance",
+  data() {
+    return {
+      selectedVoyage: null,
+      showVoyageDetail: false,
+      showModal: false,
+      modalTitle: "",
+      modalMessage: "",
+      hideCancel: false,
+      confirmCallback: null,
+      loanAmount: 480000,
+      map: null,
+      shipperList: [
+        {
+          id: 1,
+          name: "上海海运有限公司",
+          validUntil: "2023-12-31",
+          totalLimit: 5000000,
+          usedLimit: 2300000,
+          remainingLimit: 2700000,
+        },
+        {
+          id: 2,
+          name: "江苏货运集团",
+          validUntil: "2024-06-30",
+          totalLimit: 3000000,
+          usedLimit: 1200000,
+          remainingLimit: 1800000,
+        },
+      ],
+      availableVoyages: [
+        {
+          id: "V20230001",
+          voyageNumber: "V20230001",
+          shipperName: "上海海运有限公司",
+          cargoType: "煤炭",
+          weight: 5000,
+          rate: 120,
+          totalFreight: 600000,
+          status: "运输中",
+        },
+        {
+          id: "V20230002",
+          voyageNumber: "V20230002",
+          shipperName: "上海海运有限公司",
+          cargoType: "铁矿石",
+          weight: 8000,
+          rate: 150,
+          totalFreight: 1200000,
+          status: "运输中",
+        },
+        {
+          id: "V20230003",
+          voyageNumber: "V20230003",
+          shipperName: "江苏货运集团",
+          cargoType: "粮食",
+          weight: 3000,
+          rate: 180,
+          totalFreight: 540000,
+          status: "运输中",
+        },
+      ],
+      loanVoyages: [
+        {
+          id: 1,
+          voyageNumber: "V20230004",
+          shipperName: "上海海运有限公司",
+          cargoType: "原油",
+          weight: 10000,
+          rate: 200,
+          totalFreight: 2000000,
+          loanAmount: 1600000,
+          applicationDate: "2023-09-15",
+          loanStatus: "审核中",
+          repaymentStatus: "未还款",
+        },
+        {
+          id: 2,
+          voyageNumber: "V20230005",
+          shipperName: "江苏货运集团",
+          cargoType: "钢材",
+          weight: 6000,
+          rate: 180,
+          totalFreight: 1080000,
+          loanAmount: 800000,
+          applicationDate: "2023-09-10",
+          loanStatus: "已放款",
+          repaymentStatus: "部分还款",
+        },
+        {
+          id: 3,
+          voyageNumber: "V20230006",
+          shipperName: "上海海运有限公司",
+          cargoType: "集装箱",
+          weight: 4500,
+          rate: 220,
+          totalFreight: 990000,
+          loanAmount: 750000,
+          applicationDate: "2023-09-01",
+          loanStatus: "已放款",
+          repaymentStatus: "已还清",
+        },
+      ],
+      voyageDetail: {
+        voyageNumber: "V20230001",
+        shipperName: "上海海运有限公司",
+        startDate: "2023-09-10",
+        loadingPort: "青岛港",
+        unloadingPort: "上海港",
+        shipName: "远洋号",
+        shipOwner: "中远海运",
+        shipMMSI: "123456789",
+        cargoType: "煤炭",
+        weight: 5000,
+        rate: 120,
+        totalFreight: 600000,
+        arrivalTime: "2023-09-10 08:00",
+        loadingStart: "2023-09-10 10:00",
+        loadingEnd: "2023-09-11 16:00",
+        departureTime: "2023-09-11 18:00",
+        documents: [
+          { id: 1, name: "当月运输合同" },
+          { id: 2, name: "航次装货运单" },
+        ],
+      },
+    };
+  },
+  computed: {
+    maxLoanAmount() {
+      return Math.floor(this.voyageDetail.totalFreight * 0.8);
+    },
+  },
+  mounted() {
+    this.$nextTick(() => {
+      if (this.showVoyageDetail) {
+        this.initMap();
+      }
+    });
+  },
+  methods: {
+    formatCurrency(value) {
+      return parseFloat(value).toLocaleString("zh-CN") + "元";
+    },
+    getRepaymentStatusClass(status) {
+      switch (status) {
+        case "未还款":
+          return "status-unpaid";
+        case "部分还款":
+          return "status-partial";
+        case "已还清":
+          return "status-paid";
+        default:
+          return "";
+      }
+    },
+    applyLoan() {
+      if (!this.selectedVoyage) {
+        this.showModalDialog("提示", "请先选择一个航次", true);
+        return;
+      }
+
+      this.showVoyageDetail = true;
+      this.$nextTick(() => {
+        this.initMap();
+        // 滚动到航次详情区域
+        const element = document.querySelector(".section:last-of-type");
+        if (element) {
+          element.scrollIntoView({ behavior: "smooth" });
+        }
+      });
+    },
+    submitApplication() {
+      this.showModalDialog(
+        "确认提交",
+        `您确定要申请 ${this.formatCurrency(this.loanAmount)} 的贷款吗?`,
+        false,
+        () => {
+          this.showModalDialog(
+            "提交成功",
+            "您的贷款申请已提交,请等待审核。",
+            true,
+            () => {
+              this.resetForm();
+            }
+          );
+        }
+      );
+    },
+    cancelApplication() {
+      this.showVoyageDetail = false;
+      this.selectedVoyage = null;
+    },
+    resetForm() {
+      this.showVoyageDetail = false;
+      this.selectedVoyage = null;
+      this.loanAmount = 480000;
+    },
+    showModalDialog(
+      title,
+      message,
+      hideCancel = false,
+      confirmCallback = null
+    ) {
+      this.modalTitle = title;
+      this.modalMessage = message;
+      this.hideCancel = hideCancel;
+      this.confirmCallback = confirmCallback;
+      this.showModal = true;
+    },
+    closeModal() {
+      this.showModal = false;
+    },
+    confirmModal() {
+      this.showModal = false;
+      if (this.confirmCallback) {
+        this.confirmCallback();
+      }
+    },
+    initMap() {
+      if (this.map) {
+        this.map.remove();
+      }
+
+      this.$nextTick(() => {
+        const mapElement = this.$refs.voyageMap;
+        if (!mapElement) return;
+
+        // 创建地图实例
+        this.map = L.map(mapElement).setView([35.5, 120], 6);
+
+        // 添加地图图层
+        L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
+          attribution:
+            '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
+        }).addTo(this.map);
+
+        // 示例航线数据
+        const routePoints = [
+          [36.0839, 120.3676], // 青岛港
+          [35.8, 121.5],
+          [34.7, 122.8],
+          [33.5, 123.5],
+          [32.0, 123.8],
+          [31.2304, 121.4737], // 上海港
+        ];
+
+        // 添加航线
+        const polyline = L.polyline(routePoints, {
+          color: "#1e88e5",
+          weight: 3,
+        }).addTo(this.map);
+
+        // 添加起点和终点标记
+        const startIcon = L.divIcon({
+          className: "start-marker",
+          html: '<div style="background-color:#4CAF50;width:12px;height:12px;border-radius:50%;"></div>',
+        });
+        const endIcon = L.divIcon({
+          className: "end-marker",
+          html: '<div style="background-color:#F44336;width:12px;height:12px;border-radius:50%;"></div>',
+        });
+
+        L.marker(routePoints[0], { icon: startIcon })
+          .addTo(this.map)
+          .bindPopup("青岛港 - 装货港");
+
+        L.marker(routePoints[routePoints.length - 1], { icon: endIcon })
+          .addTo(this.map)
+          .bindPopup("上海港 - 卸货港");
+
+        // 添加船舶当前位置
+        const shipIcon = L.divIcon({
+          className: "ship-marker",
+          html: '<div style="background-color:#1e88e5;width:16px;height:16px;border-radius:50%;border:2px solid white;"></div>',
+          iconSize: [16, 16],
+        });
+
+        // 假设船舶在航线中间位置
+        const currentPosition = routePoints[Math.floor(routePoints.length / 2)];
+        L.marker(currentPosition, { icon: shipIcon })
+          .addTo(this.map)
+          .bindPopup("远洋号 - 当前位置");
+
+        // 调整地图视图以适应航线
+        this.map.fitBounds(polyline.getBounds(), { padding: [50, 50] });
+      });
+    },
+  },
+  beforeUnmount() {
+    if (this.map) {
+      this.map.remove();
+    }
+  },
+};
+</script>
+
+<style scoped>
+/* 全局样式 */
+* {
+  margin: 0;
+  padding: 0;
+  box-sizing: border-box;
+  font-family: "PingFang SC", "Microsoft YaHei", sans-serif;
+}
+
+.container {
+  max-width: 1200px;
+  margin: 0 auto;
+  padding: 20px;
+  color: #333;
+  line-height: 1.6;
+}
+
+/* 头部样式 */
+.header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 15px 0;
+  border-bottom: 1px solid #e0e6ed;
+  margin-bottom: 20px;
+}
+
+.logo {
+  font-size: 24px;
+  font-weight: bold;
+  color: #1e88e5;
+}
+
+.user-info {
+  display: flex;
+  align-items: center;
+  gap: 10px;
+}
+
+.user-name {
+  font-weight: 500;
+}
+
+.verified-icon {
+  display: inline-block;
+  width: 20px;
+  height: 20px;
+  background-color: #4caf50;
+  color: white;
+  border-radius: 50%;
+  text-align: center;
+  line-height: 20px;
+  font-size: 12px;
+  cursor: pointer;
+}
+
+/* 区块样式 */
+.section {
+  background-color: #fff;
+  border-radius: 8px;
+  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
+  padding: 20px;
+  margin-bottom: 30px;
+}
+
+.section h2 {
+  font-size: 18px;
+  color: #333;
+  margin-bottom: 20px;
+  padding-bottom: 10px;
+  border-bottom: 1px solid #eee;
+}
+
+.section h3 {
+  font-size: 16px;
+  color: #555;
+  margin: 15px 0 10px;
+}
+
+/* 表格样式 */
+table {
+  width: 100%;
+  border-collapse: collapse;
+  margin-bottom: 20px;
+}
+
+table th,
+table td {
+  padding: 12px 15px;
+  text-align: left;
+  border-bottom: 1px solid #eee;
+}
+
+table th {
+  background-color: #f8f9fa;
+  font-weight: 500;
+  color: #555;
+}
+
+table tr:hover {
+  background-color: #f5f7fa;
+}
+
+/* 还款状态样式 */
+.status-unpaid {
+  color: #f44336;
+  font-weight: 500;
+}
+
+.status-partial {
+  color: #ff9800;
+  font-weight: 500;
+}
+
+.status-paid {
+  color: #4caf50;
+  font-weight: 500;
+}
+
+/* 按钮样式 */
+.action-buttons {
+  display: flex;
+  justify-content: flex-end;
+  gap: 15px;
+  margin-top: 20px;
+}
+
+.primary-btn,
+.secondary-btn,
+.view-btn {
+  padding: 8px 16px;
+  border-radius: 4px;
+  border: none;
+  cursor: pointer;
+  font-size: 14px;
+  transition: all 0.3s ease;
+}
+
+.primary-btn {
+  background-color: #1e88e5;
+  color: white;
+}
+
+.primary-btn:hover {
+  background-color: #1976d2;
+}
+
+.secondary-btn {
+  background-color: #f5f5f5;
+  color: #333;
+  border: 1px solid #ddd;
+}
+
+.secondary-btn:hover {
+  background-color: #e0e0e0;
+}
+
+.view-btn {
+  background-color: #f0f7ff;
+  color: #1e88e5;
+  border: 1px solid #d0e3ff;
+}
+
+.view-btn:hover {
+  background-color: #e1f0ff;
+}
+
+/* 航次详情样式 */
+.voyage-info {
+  display: flex;
+  flex-direction: column;
+  gap: 20px;
+}
+
+.info-section {
+  margin-bottom: 20px;
+}
+
+.info-grid {
+  display: grid;
+  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
+  gap: 15px;
+}
+
+.info-item {
+  display: flex;
+  flex-direction: column;
+  gap: 5px;
+}
+
+.label {
+  font-size: 14px;
+  color: #666;
+}
+
+.value {
+  font-size: 15px;
+  font-weight: 500;
+  color: #333;
+}
+
+/* 地图容器 */
+.map-container {
+  margin: 20px 0;
+}
+
+#voyage-map {
+  height: 300px;
+  border-radius: 8px;
+  border: 1px solid #eee;
+}
+
+/* 文档确认区域 */
+.document-list {
+  display: flex;
+  flex-direction: column;
+  gap: 15px;
+}
+
+.document-item {
+  display: flex;
+  align-items: center;
+  gap: 15px;
+  padding: 10px;
+  background-color: #f9f9f9;
+  border-radius: 4px;
+}
+
+.document-name {
+  flex: 1;
+}
+
+.confirm-status {
+  color: #4caf50;
+  font-weight: 500;
+}
+
+/* 贷款申请区域 */
+.loan-application {
+  background-color: #f8f9fa;
+  padding: 20px;
+  border-radius: 8px;
+  margin-top: 20px;
+}
+
+.loan-amount-container {
+  display: flex;
+  flex-direction: column;
+  gap: 15px;
+  margin-bottom: 20px;
+}
+
+.loan-info {
+  display: flex;
+  align-items: center;
+  gap: 10px;
+}
+
+.loan-slider-container {
+  display: flex;
+  align-items: center;
+  gap: 15px;
+  margin-top: 10px;
+}
+
+.loan-slider {
+  flex: 1;
+  height: 5px;
+  -webkit-appearance: none;
+  appearance: none;
+  background: #ddd;
+  outline: none;
+  border-radius: 5px;
+}
+
+.loan-slider::-webkit-slider-thumb {
+  -webkit-appearance: none;
+  appearance: none;
+  width: 20px;
+  height: 20px;
+  border-radius: 50%;
+  background: #1e88e5;
+  cursor: pointer;
+}
+
+/* 弹窗样式 */
+.modal {
+  position: fixed;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  background-color: rgba(0, 0, 0, 0.5);
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  z-index: 1000;
+}
+
+.modal-content {
+  background-color: #fff;
+  padding: 30px;
+  border-radius: 8px;
+  width: 90%;
+  max-width: 500px;
+  position: relative;
+}
+
+.close-btn {
+  position: absolute;
+  top: 15px;
+  right: 15px;
+  font-size: 24px;
+  cursor: pointer;
+  color: #999;
+}
+
+.modal-buttons {
+  display: flex;
+  justify-content: flex-end;
+  gap: 15px;
+  margin-top: 20px;
+}
+</style>