From fa821ce7a7755dd0e13897cefc57071d4596431b Mon Sep 17 00:00:00 2001
From: jhzh <1628036192@qq.com>
Date: Wed, 14 Jan 2026 17:51:42 +0800
Subject: [PATCH] 1

---
 dist.rar                                      |    0 
 src/components/ImageViewer.vue                |  187 ++++
 src/page/newUser/smrz.vue                     |   21 
 .gitignore                                    |    1 
 src/assets/img/wancheng.png                   |    0 
 src/axios/api.js                              |   32 
 src/locales/zh.js                             |   51 +
 src/page/home/listcomponents/dazongjiaoyi.vue |    2 
 src/page/user/agreement.vue                   |  137 ++
 src/assets/img/chicang.png                    |    0 
 src/page/user/Warehouse.vue                   |   53 
 src/page/login/login.vue                      |    4 
 src/page/newUser/about.vue                    |  788 ++++++++++++++++++--
 src/page/authentication/index.vue             |   14 
 src/page/newUser/index.vue                    |   37 
 src/components/PdfViewer.vue                  |  395 ++++++++++
 src/page/login/register.vue                   |   94 +-
 src/locales/tw.js                             |   43 
 src/page/home/home.vue                        |    4 
 src/components/PdfViewerModern.vue            |  197 +++++
 src/router/index.js                           |    8 
 src/locales/en.js                             |   49 +
 src/assets/img/guadan.png                     |    0 
 src/page/kline/buyStock.vue                   |    2 
 src/page/user/Warehouse-detail.vue            |  121 ++
 25 files changed, 1,976 insertions(+), 264 deletions(-)

diff --git a/.gitignore b/.gitignore
index 541a820..efaa890 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,3 +12,4 @@
 *.ntvs*
 *.njsproj
 *.sln
+qd_ym.rar
diff --git a/dist.rar b/dist.rar
index 5b1b2cc..f0fe47c 100644
--- a/dist.rar
+++ b/dist.rar
Binary files differ
diff --git a/src/assets/img/chicang.png b/src/assets/img/chicang.png
new file mode 100644
index 0000000..3135fc8
--- /dev/null
+++ b/src/assets/img/chicang.png
Binary files differ
diff --git a/src/assets/img/guadan.png b/src/assets/img/guadan.png
new file mode 100644
index 0000000..88e6c6f
--- /dev/null
+++ b/src/assets/img/guadan.png
Binary files differ
diff --git a/src/assets/img/wancheng.png b/src/assets/img/wancheng.png
new file mode 100644
index 0000000..31c3ee0
--- /dev/null
+++ b/src/assets/img/wancheng.png
Binary files differ
diff --git a/src/axios/api.js b/src/axios/api.js
index 4d49a42..67e7f41 100644
--- a/src/axios/api.js
+++ b/src/axios/api.js
@@ -422,6 +422,38 @@
 }
 
 // 获取网站设置信息
+export function generateAgreementPdf(options) {
+  return post('/user/generateAgreementPdf.do', options)
+}
+
+export function viewAgreementPdf() {
+  return get('/user/viewAgreementPdf.do')
+}
+
+export function saveAgreementSignature(formData) {
+  return post('/user/saveAgreementSignature.do', formData, {
+    headers: {
+      'Content-Type': 'multipart/form-data'
+    }
+  })
+}
+
+export function generateAgreementContractPdf(options) {
+  return post('/user/generateAgreementContractPdf.do', options)
+}
+
+export function viewAgreementContractPdf() {
+  return get('/user/viewAgreementContractPdf.do')
+}
+
+export function saveAgreementContractSignature(formData) {
+  return post('/user/saveAgreementContractSignature.do', formData, {
+    headers: {
+      'Content-Type': 'multipart/form-data'
+    }
+  })
+}
+
 export function getInfoSite(options) {
   return post('/api/site/getInfo.do', options)
 }
diff --git a/src/components/ImageViewer.vue b/src/components/ImageViewer.vue
new file mode 100644
index 0000000..1c8ba27
--- /dev/null
+++ b/src/components/ImageViewer.vue
@@ -0,0 +1,187 @@
+<template>
+  <div class="image-viewer-wrapper">
+    <div class="image-toolbar">
+      <button @click="zoomOut" class="toolbar-btn" :disabled="scale <= 0.5">
+        <span class="icon">−</span>
+      </button>
+      <span class="zoom-info">{{ Math.round(scale * 100) }}%</span>
+      <button @click="zoomIn" class="toolbar-btn" :disabled="scale >= 3">
+        <span class="icon">+</span>
+      </button>
+      <div class="toolbar-divider"></div>
+      <button @click="prevPage" class="toolbar-btn" :disabled="currentPage <= 1">
+        <span class="icon">‹</span>
+      </button>
+      <span class="page-info">{{ currentPage }} / {{ totalPages }}</span>
+      <button @click="nextPage" class="toolbar-btn" :disabled="currentPage >= totalPages">
+        <span class="icon">›</span>
+      </button>
+    </div>
+    <div class="image-content" ref="imageContainer">
+      <img
+        :src="currentImageUrl"
+        :style="{ transform: `scale(${scale})`, transformOrigin: 'top left' }"
+        class="viewer-image"
+        @load="onImageLoad"
+        @error="onImageError"
+      />
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'ImageViewer',
+  props: {
+    imageUrls: {
+      type: Array,
+      required: true,
+      default: () => []
+    }
+  },
+  data() {
+    return {
+      currentPage: 1,
+      scale: 1.0,
+      loading: false,
+      error: null
+    }
+  },
+  computed: {
+    totalPages() {
+      return this.imageUrls.length
+    },
+    currentImageUrl() {
+      if (this.imageUrls.length === 0) return ''
+      const url = this.imageUrls[this.currentPage - 1]
+      // 添加token
+      const token = typeof window !== 'undefined' && window.localStorage ? window.localStorage.getItem('USERTOKEN') || '' : ''
+      if (url && url.indexOf('token=') === -1) {
+        return url + (url.indexOf('?') > -1 ? '&' : '?') + 'token=' + encodeURIComponent(token)
+      }
+      return url
+    }
+  },
+  methods: {
+    zoomIn() {
+      this.scale = Math.min(this.scale + 0.2, 3)
+    },
+    zoomOut() {
+      this.scale = Math.max(this.scale - 0.2, 0.5)
+    },
+    prevPage() {
+      if (this.currentPage > 1) {
+        this.currentPage--
+        this.scale = 1.0
+      }
+    },
+    nextPage() {
+      if (this.currentPage < this.totalPages) {
+        this.currentPage++
+        this.scale = 1.0
+      }
+    },
+    onImageLoad() {
+      this.loading = false
+      this.error = null
+    },
+    onImageError() {
+      this.loading = false
+      this.error = '图片加载失败'
+    }
+  }
+}
+</script>
+
+<style scoped>
+.image-viewer-wrapper {
+  width: 100%;
+  height: 80%;
+  background: #f5f5f5;
+  display: flex;
+  flex-direction: column;
+}
+
+.image-toolbar {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  padding: 10px;
+  background: #fff;
+  border-bottom: 1px solid #e0e0e0;
+  gap: 10px;
+}
+
+.toolbar-btn {
+  width: 36px;
+  height: 36px;
+  border: 1px solid rgb(50, 145, 113);
+  background: linear-gradient(-55deg, rgb(50, 145, 113), rgb(50, 145, 113));
+  border-radius: 4px;
+  cursor: pointer;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  font-size: 18px;
+  color: #fff;
+  font-weight: bold;
+  box-shadow: 0 2px 4px rgba(241, 22, 20, 0.3);
+  transition: all 0.3s ease;
+}
+
+.toolbar-btn:disabled {
+  opacity: 0.5;
+  cursor: not-allowed;
+  background: #ccc;
+  border-color: #999;
+  box-shadow: none;
+}
+
+.toolbar-btn:not(:disabled):hover {
+  background: linear-gradient(-55deg, rgb(50, 145, 113), rgb(50, 145, 113));
+  box-shadow: 0 2px 8px rgba(241, 22, 20, 0.5);
+  transform: translateY(-1px);
+}
+
+.toolbar-btn:not(:disabled):active {
+  transform: translateY(0);
+  box-shadow: 0 1px 3px rgba(241, 22, 20, 0.4);
+}
+
+.zoom-info {
+  min-width: 50px;
+  text-align: center;
+  font-size: 14px;
+  color: #666;
+}
+
+.toolbar-divider {
+  width: 1px;
+  height: 24px;
+  background: #e0e0e0;
+  margin: 0 5px;
+}
+
+.page-info {
+  min-width: 60px;
+  text-align: center;
+  font-size: 14px;
+  color: #666;
+}
+
+.image-content {
+  flex: 1;
+  overflow: auto;
+  display: flex;
+  align-items: flex-start;
+  justify-content: center;
+  padding: 20px;
+}
+
+.viewer-image {
+  max-width: 100%;
+  height: auto;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+  transition: transform 0.2s;
+}
+</style>
diff --git a/src/components/PdfViewer.vue b/src/components/PdfViewer.vue
new file mode 100644
index 0000000..984ee8a
--- /dev/null
+++ b/src/components/PdfViewer.vue
@@ -0,0 +1,395 @@
+<template>
+  <div class="pdf-viewer-wrapper">
+    <div v-if="loading" class="pdf-loading">
+      <div class="loading-spinner"></div>
+      <p>加载中...</p>
+    </div>
+    <div v-else-if="error" class="pdf-error">
+      <p>{{ error }}</p>
+      <button @click="loadPdf" class="retry-btn">重试</button>
+    </div>
+    <div v-else class="pdf-container">
+      <div class="pdf-toolbar">
+        <button @click="zoomOut" class="toolbar-btn" :disabled="scale <= 0.5">
+          <span class="icon">−</span>
+        </button>
+        <span class="zoom-info">{{ Math.round(scale * 100) }}%</span>
+        <button @click="zoomIn" class="toolbar-btn" :disabled="scale >= 3">
+          <span class="icon">+</span>
+        </button>
+        <div class="toolbar-divider"></div>
+        <button @click="prevPage" class="toolbar-btn" :disabled="currentPage <= 1">
+          <span class="icon">‹</span>
+        </button>
+        <span class="page-info">{{ currentPage }} / {{ totalPages }}</span>
+        <button @click="nextPage" class="toolbar-btn" :disabled="currentPage >= totalPages">
+          <span class="icon">›</span>
+        </button>
+      </div>
+      <div class="pdf-content" ref="pdfContainer">
+        <canvas ref="pdfCanvas" class="pdf-canvas"></canvas>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import PDFJS from 'pdfjs-dist'
+
+// 使用本地worker
+PDFJS.GlobalWorkerOptions.workerSrc = require('pdfjs-dist/build/pdf.worker.min.js')
+
+export default {
+  name: 'PdfViewer',
+  props: {
+    pdfUrl: {
+      type: String,
+      required: true,
+      default: ''
+    }
+  },
+  data() {
+    return {
+      loading: true,
+      error: null,
+      pdfDoc: null,
+      currentPage: 1,
+      totalPages: 0,
+      scale: 1.0,
+      renderTask: null
+    }
+  },
+  mounted() {
+    this.loadPdf()
+  },
+  watch: {
+    pdfUrl() {
+      this.loadPdf()
+    }
+  },
+  methods: {
+    async loadPdf() {
+      if (!this.pdfUrl) {
+        this.error = 'PDF地址为空'
+        this.loading = false
+        return
+      }
+
+      this.loading = true
+      this.error = null
+
+      try {
+        console.log('开始加载PDF,URL:', this.pdfUrl)
+
+        // 获取PDF数据,确保携带认证信息
+        const token = typeof window !== 'undefined' && window.localStorage ? window.localStorage.getItem('USERTOKEN') || '' : ''
+        const url = this.pdfUrl + (this.pdfUrl.indexOf('?') > -1 ? '&' : '?') + 'token=' + encodeURIComponent(token)
+
+        console.log('请求URL:', url)
+
+        const response = await fetch(url, {
+          credentials: 'include',
+          headers: {
+            'USERTOKEN': token
+          }
+        })
+
+        if (!response.ok) {
+          throw new Error('加载PDF失败: ' + response.status)
+        }
+
+        const arrayBuffer = await response.arrayBuffer()
+        console.log('PDF数据大小:', arrayBuffer.byteLength)
+
+        if (arrayBuffer.byteLength === 0) {
+          throw new Error('PDF文件为空')
+        }
+
+        // 加载PDF文档
+        const loadingTask = PDFJS.getDocument({
+          data: arrayBuffer,
+          verbosity: 0
+        })
+
+        this.pdfDoc = await loadingTask.promise
+        this.totalPages = this.pdfDoc.numPages
+        console.log('PDF加载成功,总页数:', this.totalPages)
+
+        // 计算适合H5的初始缩放比例
+        await this.calculateInitialScale()
+
+        await this.renderPage(this.currentPage)
+        this.loading = false
+      } catch (error) {
+        console.error('加载PDF失败:', error)
+        this.error = '加载PDF失败,请稍后重试'
+        this.loading = false
+      }
+    },
+    async calculateInitialScale() {
+      if (!this.pdfDoc) return
+
+      try {
+        const page = await this.pdfDoc.getPage(1)
+        const viewport = page.getViewport({ scale: 1.0 })
+
+        // 获取容器宽度(H5适配)
+        const containerWidth = this.$refs.pdfContainer ? this.$refs.pdfContainer.clientWidth : window.innerWidth - 40
+        const containerHeight = window.innerHeight - 200
+
+        // 计算适合的缩放比例
+        const scaleX = containerWidth / viewport.width
+        const scaleY = containerHeight / viewport.height
+        this.scale = Math.min(scaleX, scaleY, 1.2) // 初始缩放不超过1.2倍
+        console.log('计算初始缩放比例:', this.scale)
+      } catch (error) {
+        console.error('计算缩放比例失败:', error)
+        this.scale = 1.0
+      }
+    },
+    async renderPage(pageNum) {
+      if (!this.pdfDoc || !this.$refs.pdfCanvas) return
+
+      // 取消之前的渲染任务
+      if (this.renderTask) {
+        this.renderTask.cancel()
+      }
+
+      try {
+        const page = await this.pdfDoc.getPage(pageNum)
+        const canvas = this.$refs.pdfCanvas
+        const context = canvas.getContext('2d')
+
+        const viewport = page.getViewport({ scale: this.scale })
+
+        // 设置canvas尺寸(H5高清适配)
+        const dpr = window.devicePixelRatio || 1
+        canvas.width = viewport.width * dpr
+        canvas.height = viewport.height * dpr
+        canvas.style.width = viewport.width + 'px'
+        canvas.style.height = viewport.height + 'px'
+
+        context.scale(dpr, dpr)
+
+        const renderContext = {
+          canvasContext: context,
+          viewport: viewport
+        }
+
+        this.renderTask = page.render(renderContext)
+        await this.renderTask.promise
+        this.currentPage = pageNum
+        console.log('渲染第', pageNum, '页完成,缩放比例:', this.scale)
+      } catch (error) {
+        if (error.name !== 'RenderingCancelledException') {
+          console.error('渲染PDF页面失败:', error)
+        }
+      }
+    },
+    zoomIn() {
+      this.scale = Math.min(this.scale + 0.2, 3)
+      this.renderPage(this.currentPage)
+    },
+    zoomOut() {
+      this.scale = Math.max(this.scale - 0.2, 0.5)
+      this.renderPage(this.currentPage)
+    },
+    prevPage() {
+      if (this.currentPage > 1) {
+        this.renderPage(this.currentPage - 1)
+      }
+    },
+    nextPage() {
+      if (this.currentPage < this.totalPages) {
+        this.renderPage(this.currentPage + 1)
+      }
+    }
+  },
+  beforeDestroy() {
+    if (this.renderTask) {
+      this.renderTask.cancel()
+    }
+  }
+}
+</script>
+
+<style scoped>
+.pdf-viewer-wrapper {
+  width: 100%;
+  height: 100%;
+  background: #f5f5f5;
+}
+
+.pdf-loading {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  height: 60vh;
+  color: #666;
+}
+
+.loading-spinner {
+  width: 40px;
+  height: 40px;
+  border: 4px solid #f3f3f3;
+  border-top: 4px solid #f11514;
+  border-radius: 50%;
+  animation: spin 1s linear infinite;
+  margin-bottom: 15px;
+}
+
+@keyframes spin {
+  0% { transform: rotate(0deg); }
+  100% { transform: rotate(360deg); }
+}
+
+.pdf-error {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  height: 60vh;
+  color: #f56c6c;
+  padding: 20px;
+  text-align: center;
+}
+
+.retry-btn {
+  margin-top: 15px;
+  padding: 10px 20px;
+  background: linear-gradient(-55deg, rgb(241, 22, 20), rgb(240, 40, 37));
+  color: #fff;
+  border: none;
+  border-radius: 5px;
+  font-size: 14px;
+  cursor: pointer;
+}
+
+.pdf-container {
+  width: 100%;
+  height: 100%;
+  display: flex;
+  flex-direction: column;
+  background: #525252;
+}
+
+.pdf-toolbar {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  padding: 10px 5px;
+  background: #fff;
+  border-bottom: 1px solid #e0e0e0;
+  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
+  position: sticky;
+  top: 0;
+  z-index: 10;
+  flex-shrink: 0;
+}
+
+.toolbar-btn {
+  width: 36px;
+  height: 36px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  background: #f5f5f5;
+  border: 1px solid #e0e0e0;
+  border-radius: 4px;
+  margin: 0 3px;
+  cursor: pointer;
+  font-size: 20px;
+  color: #333;
+  transition: all 0.2s;
+  -webkit-tap-highlight-color: transparent;
+}
+
+.toolbar-btn:active {
+  background: #e0e0e0;
+  transform: scale(0.95);
+}
+
+.toolbar-btn:disabled {
+  opacity: 0.4;
+  cursor: not-allowed;
+}
+
+.toolbar-btn .icon {
+  line-height: 1;
+  font-weight: bold;
+  user-select: none;
+}
+
+.zoom-info,
+.page-info {
+  min-width: 55px;
+  text-align: center;
+  font-size: 13px;
+  color: #666;
+  margin: 0 6px;
+  user-select: none;
+}
+
+.toolbar-divider {
+  width: 1px;
+  height: 24px;
+  background: #e0e0e0;
+  margin: 0 6px;
+}
+
+.pdf-content {
+  flex: 1;
+  overflow: auto;
+  -webkit-overflow-scrolling: touch;
+  background: #525252;
+  display: flex;
+  align-items: flex-start;
+  justify-content: center;
+  padding: 15px 10px;
+  min-height: calc(100vh - 280px);
+}
+
+.pdf-canvas {
+  display: block;
+  margin: 0 auto;
+  background: #fff;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.3);
+  max-width: 100%;
+  height: auto;
+  touch-action: pan-x pan-y pinch-zoom;
+}
+
+/* H5移动端优化 */
+@media (max-width: 768px) {
+  .pdf-toolbar {
+    padding: 8px 3px;
+  }
+
+  .toolbar-btn {
+    width: 32px;
+    height: 32px;
+    margin: 0 2px;
+    font-size: 18px;
+  }
+
+  .zoom-info,
+  .page-info {
+    font-size: 12px;
+    margin: 0 4px;
+    min-width: 50px;
+  }
+
+  .pdf-content {
+    padding: 10px 5px;
+    min-height: calc(100vh - 160px);
+  }
+}
+
+/* 横屏适配 */
+@media (orientation: landscape) {
+  .pdf-content {
+    min-height: calc(100vh - 140px);
+  }
+}
+</style>
diff --git a/src/components/PdfViewerModern.vue b/src/components/PdfViewerModern.vue
new file mode 100644
index 0000000..ffa8005
--- /dev/null
+++ b/src/components/PdfViewerModern.vue
@@ -0,0 +1,197 @@
+<template>
+  <div class="pdf-viewer-modern">
+    <div v-if="loading" class="loading-wrapper">
+      <div class="loading-content">
+        <div class="spinner"></div>
+        <p class="loading-text">正在加载PDF...</p>
+      </div>
+    </div>
+    <div v-else-if="error" class="error-wrapper">
+      <div class="error-content">
+        <div class="error-icon">⚠️</div>
+        <p class="error-text">{{ error }}</p>
+        <button @click="loadPdf" class="retry-button">重新加载</button>
+      </div>
+    </div>
+    <div v-else class="viewer-container">
+      <iframe
+        :src="pdfSrc"
+        class="pdf-iframe"
+        frameborder="0"
+        @load="onPdfLoad"
+        @error="onPdfError"
+      ></iframe>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'PdfViewerModern',
+  props: {
+    pdfUrl: {
+      type: String,
+      required: true,
+      default: ''
+    }
+  },
+  data() {
+    return {
+      loading: true,
+      error: null,
+      pdfSrc: ''
+    }
+  },
+  mounted() {
+    this.loadPdf()
+  },
+  watch: {
+    pdfUrl() {
+      this.loadPdf()
+    }
+  },
+  computed: {
+    finalPdfUrl() {
+      if (!this.pdfUrl) return ''
+
+      let url = this.pdfUrl
+
+      // 如果URL不包含http,需要添加基础URL
+      if (!url.startsWith('http')) {
+        const APIUrl = require('@/axios/api.url').default
+        url = APIUrl.baseURL + (url.startsWith('/') ? url : '/' + url)
+      }
+
+      // 添加token
+      const token = typeof window !== 'undefined' && window.localStorage ? window.localStorage.getItem('USERTOKEN') || '' : ''
+      url = url + (url.indexOf('?') > -1 ? '&' : '?') + 'token=' + encodeURIComponent(token)
+      
+      // 保留工具栏(包含缩放工具),但隐藏导航面板
+      url = url + '#toolbar=1&navpanes=0'
+
+      return url
+    }
+  },
+  methods: {
+    loadPdf() {
+      if (!this.pdfUrl) {
+        this.error = 'PDF地址为空'
+        this.loading = false
+        return
+      }
+
+      this.loading = true
+      this.error = null
+
+      // 设置iframe的src,浏览器会自动加载
+      this.pdfSrc = this.finalPdfUrl
+
+      // 延迟隐藏loading,给iframe一些加载时间
+      setTimeout(() => {
+        this.loading = false
+      }, 500)
+    },
+    onPdfLoad() {
+      this.loading = false
+      this.error = null
+    },
+    onPdfError() {
+      this.loading = false
+      this.error = 'PDF加载失败,请检查文件是否存在'
+    }
+  }
+}
+</script>
+
+<style scoped>
+.pdf-viewer-modern {
+  width: 100%;
+  height: 100%;
+  max-height: calc(100vh - 400px);
+  background: #f5f5f5;
+  display: flex;
+  flex-direction: column;
+}
+
+.loading-wrapper,
+.error-wrapper {
+  flex: 1;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  background: #f8f9fa;
+}
+
+.loading-content,
+.error-content {
+  text-align: center;
+  padding: 40px;
+}
+
+.spinner {
+  width: 50px;
+  height: 50px;
+  margin: 0 auto 20px;
+  border: 4px solid rgba(102, 126, 234, 0.1);
+  border-top-color: #667eea;
+  border-radius: 50%;
+  animation: spin 0.8s linear infinite;
+}
+
+@keyframes spin {
+  to { transform: rotate(360deg); }
+}
+
+.loading-text {
+  color: #667eea;
+  font-size: 16px;
+  font-weight: 500;
+}
+
+.error-icon {
+  font-size: 48px;
+  margin-bottom: 16px;
+}
+
+.error-text {
+  color: #e74c3c;
+  font-size: 16px;
+  margin-bottom: 20px;
+}
+
+.retry-button {
+  padding: 12px 24px;
+  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+  color: #fff;
+  border: none;
+  border-radius: 8px;
+  font-size: 14px;
+  font-weight: 500;
+  cursor: pointer;
+  transition: transform 0.2s, box-shadow 0.2s;
+  box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
+}
+
+.retry-button:active {
+  transform: scale(0.95);
+}
+
+.viewer-container {
+  flex: 1;
+  display: flex;
+  flex-direction: column;
+  background: #f5f5f5;
+  overflow: hidden;
+  position: relative;
+  max-height: calc(100vh - 200px);
+    height: calc(100vh - 200px);
+}
+
+.pdf-iframe {
+  width: 100%;
+  height: 100%;
+  border: none;
+  background: #fff;
+  min-height: 0;
+}
+</style>
diff --git a/src/locales/en.js b/src/locales/en.js
index 5e73c28..a98c0ea 100644
--- a/src/locales/en.js
+++ b/src/locales/en.js
@@ -127,6 +127,7 @@
   "hj21": "Invitation code",
   "hj210": "Submitted successfully!",
   "hj211": "Bind bank card",
+  "hj2111": "Address",
   "hj212": "bank card information",
   "hj213": "Bank name",
   "hj214": "Account opening branch",
@@ -729,9 +730,9 @@
   "jy80": "Baiyun Airport",
   "jy81": "Dongfeng Motor",
   "jy82": "China International Trade",
-  "jy83": "deep",
-  "jy84": "Shanghai",
-  "jy85": "north",
+  "jy83": "sz",
+  "jy84": "sh",
+  "jy85": "bj",
   "jy86": "Large transactions",
   "jy87": "Please enter the quantity",
   "jy88": "purchasing price",
@@ -793,7 +794,8 @@
   jy517: "ID card front",
   jy518: "Upload the front of your ID",
   jy519: "Please type in your name",
-  jy520: "Please enter ID number",
+  jy520: "My Commission",
+  jy561: "Please enter ID number",
   jy521: "deposit funds",
   // jy521: "Mobile banking deposit",
   jy522: "withdraw funds",
@@ -801,11 +803,11 @@
   jy523: "Account number",
   jy524: "Under certification",
   jy525: "Number of winning shares",
-  jy526: "Payment date",
-  jy527: "Bank securities transfer",
-  jy528: "Mobile banking deposit",
-  jy529: "UnionPay deduction",
-  jy530: "Maintaining and updating",
+  jy526: "Generating contract, please wait...",
+  jy527: "Please complete the electronic signature",
+  jy528: "Clear signature",
+  jy529: "Confirm signature",
+  jy530: "You have completed the signature",
   jy531: "Leverage ratio",
   jy532: "Margin leverage",
   jy533: "Buy/Sell handling fee",
@@ -821,6 +823,28 @@
   jy543: "Failed to get platform transfer information",
   jy544: "Please enter transfer user name",
   jy545: "Please upload transfer screenshot",
+  jy546: "Online contract",
+  jy547: "Non-Disclosure Agreement",
+  jy548: "Margin Trading and Securities Lending Account",
+  jy549: "Margin Trading Withdrawable Funds",
+  jy550: "Margin Trading Available Funds",
+  jy551: "Please verify your identity first",
+  jy552: "Shareholder Reduction",
+  jy553: "Profit Calendar",
+  jy554: "Please complete the electronic signature first!",
+  jy555: "Signature component not initialized, please try again later!",
+  jy556: "Signature saved successfully",
+  jy557: "Signature save failed",
+  jy558: "Contract generated successfully",
+  jy559: "Generation failed: No image data returned",
+  jy560: "Generation failed",
+  jy565: "Profit and Loss Ratio",
+  jy566: "Bank securities transfer",
+  jy567: "Mobile banking deposit",
+  jy568: "UnionPay deduction",
+  jy569: "Maintaining and updating",
+  jy570: "Payment date",
+
   // Profit Calendar
   profitCalendar_title: "General Asset Analysis",
   profitCalendar_monthProfit: "Monthly Account Profit①",
@@ -844,7 +868,7 @@
   dz_share: "Share",
   dz_completed: "Completed",
   dz_buySuccess: "Buy Success",
-  
+
   // Login and Register page new keys
   login_phoneNumber: "Phone Number",
   login_loginPassword: "Login Password",
@@ -868,7 +892,10 @@
   register_professionalService: "Professional Service",
   register_investmentAdvisor: "Investment Advisor",
   register_verificationCodeSentSuccess: "Verification code sent successfully",
-  
+  jy562: "Position Details",
+  jy563: "Commission Details",
+  jy564: "Close Position Details",
+
 }
 
 
diff --git a/src/locales/tw.js b/src/locales/tw.js
index 098065d..891ee4e 100644
--- a/src/locales/tw.js
+++ b/src/locales/tw.js
@@ -128,6 +128,7 @@
   "hj21": "邀請碼",
   "hj210": "提交成功!",
   "hj211": "綁定銀行卡",
+  "hj2111": "地址",
   "hj212": "銀行卡信息",
   "hj213": "銀行名稱",
   "hj214": "開戶支行",
@@ -795,7 +796,8 @@
   jy517: "身份證正面",
   jy518: "上傳您的身份證正面",
   jy519: "請輸入姓名",
-  jy520: "請輸入身份證號碼",
+  jy520: "我的委託",
+  jy561: "請輸入身份證號碼",
   jy521: "銀轉證",
   // jy521: "手機銀行入款",
   jy522: "證轉銀",
@@ -803,12 +805,11 @@
   jy523: "帳戶號碼",
   jy524: "認證中",
   jy525: "中簽股數",
-  jy526: "繳費日期",
-  jy527: "維護更新中",
-  jy527: "銀證轉帳",
-  jy528: "手機銀行入款",
-  jy529: "銀聯劃扣",
-  jy530: "維護更新中",
+  jy526: "正在生成合同,請稍候...",
+  jy527: "請完成電子簽名",
+  jy528: "清空簽名",
+  jy529: "確認簽名",
+  jy530: "您已完成簽名",
   jy531: "槓桿倍數",
   jy532: "選擇融資倍數",
   jy533: "買入/賣出手續費",
@@ -824,6 +825,27 @@
   jy543: "平台轉賬信息獲取失敗",
   jy544: "請輸入轉賬用戶名",
   jy545: "請上傳轉賬截圖",
+  jy546: "線上契约",
+  jy547: "保密協定",
+  jy548: "融資融券賬戶",
+  jy549: "兩融可取資金",
+  jy550: "兩融可用資金",
+  jy551: "請先實名認證",
+  jy552: "股東減持",
+  jy553: "收益日曆",
+  jy554: "請先完成電子簽名!",
+  jy555: "簽名組件未初始化,請稍候再試!",
+  jy556: "簽名保存成功",
+  jy557: "簽名保存失敗",
+  jy558: "合同生成成功",
+  jy559: "生成失敗:未返回圖片數據",
+  jy560: "生成失敗",
+  jy565: "盈虧比例",
+  jy566: "銀證轉帳",
+  jy567: "手機銀行入款",
+  jy568: "銀聯劃扣",
+  jy569: "維護更新中",
+  jy570: "繳費日期",
   // 收益日曆
   profitCalendar_title: "普通資產分析",
   profitCalendar_monthProfit: "本月帳戶收益①",
@@ -847,7 +869,7 @@
   dz_share: "份額",
   dz_completed: "已完成",
   dz_buySuccess: "買入成功",
-  
+
   // 登錄註冊頁面新增
   login_phoneNumber: "手機號",
   login_loginPassword: "登錄密碼",
@@ -871,5 +893,8 @@
   register_professionalService: "專業服務",
   register_investmentAdvisor: "投資顧問",
   register_verificationCodeSentSuccess: "驗證碼發送成功",
-  
+  jy562: "持倉詳情",
+  jy563: "委託詳情",
+  jy564: "平倉詳情",
+
 }
diff --git a/src/locales/zh.js b/src/locales/zh.js
index 31329b4..fc94e4a 100644
--- a/src/locales/zh.js
+++ b/src/locales/zh.js
@@ -212,6 +212,7 @@
   hj209: "请上传您的身份证照片",
   hj210: "提交成功!",
   hj211: "绑定银行卡",
+  hj2111: "地址",
   hj212: "银行卡信息",
   hj213: "银行名称",
   hj214: "开户支行",
@@ -592,7 +593,7 @@
   jy310: "点击注册",
   jy311: "请输入手机号",
   jy312: "请再次输入密码",
-  jy313: "机构码",
+  jy313: "两融邀请码",
   jy314: "关于我们",
   jy315: "暂未开放",
   jy316: "隐私协议",
@@ -782,6 +783,19 @@
   jy498: "请输入转换数量",
   jy499: "转换",
   jy500: "港币",
+  jy520: "我的委托",
+  jy521: "挂单时间",
+  jy522: "平仓数量",
+  jy523: "部分平仓",
+  jy524: "格式错误",
+  jy525: "超过最大数量",
+  jy526: "正在生成合同,请稍候...",
+  jy527: "请完成电子签名",
+  jy528: "清空签名",
+  jy529: "确认签名",
+  jy530: "您已完成签名",
+  jy531: "生成用户合同",
+  jy532: "请输入价格",
   jy501: "英文",
   jy502: "简体中文",
   jy503: "简体中文",
@@ -802,17 +816,17 @@
   jy517: "身份证正面",
   jy518: "上传您的身份证正面",
   jy519: "请输入姓名",
-  jy520: "请输入身份证号码",
+  jy561: "请输入身份证号码",
   jy521: "证转银",
   jy522: "银转证",
   jy523: "账户号码",
   jy524: "认证中",
   jy525: "中签股数",
-  jy526: "缴费日期",
-  jy527: "银证转账",
-  jy528: "手机银行入款",
-  jy529: "银联划扣",
-  jy530: "维护更新中",
+  jy570: "缴费日期",
+  jy566: "银证转账",
+  jy567: "手机银行入款",
+  jy568: "银联划扣",
+  jy569: "维护更新中",
   jy531: "杠杆倍数",
   jy532: "选择融资倍数",
   jy533: "买入/卖出手续费",
@@ -828,6 +842,29 @@
   jy543: "平台转账信息获取失败",
   jy544: "请输入转账用户名",
   jy545: "请上传转账截图",
+  jy546: "线上合同",
+  jy547: "保密协议",
+  jy548: "融资融券账户",
+  jy549: "两融可取资金",
+  jy550: "两融可用资金",
+  jy551: "请先实名认证",
+  jy552: "股东减持",
+  jy553: "收益日历",
+  jy554: "请先完成电子签名!",
+  jy555: "签名组件未初始化,请稍候再试!",
+  jy556: "签名保存成功",
+  jy557: "签名保存失败",
+  jy558: "合同生成成功",
+  jy559: "生成失败:未返回图片数据",
+  jy560: "生成失败",
+  jy562: "持仓详情",
+  jy563: "委托详情",
+  jy564: "平仓详情",
+  jy565: "盈亏比例",
+  jy566: "银证转账",
+  jy567: "手机银行入款",
+  jy568: "银联划扣",
+  jy569: "维护更新中",
   // 收益日历
   profitCalendar_title: "普通资产分析",
   profitCalendar_monthProfit: "本月账户收益①",
diff --git a/src/page/authentication/index.vue b/src/page/authentication/index.vue
index 79cd473..c192bf9 100644
--- a/src/page/authentication/index.vue
+++ b/src/page/authentication/index.vue
@@ -28,6 +28,15 @@
           <input v-if="!showBtn" type="text" v-model="form.idCard" readonly />
         </div>
       </div>
+      <div class="bank_name">
+        <div class="lefts">
+          <span>{{ $t('hj2111') + ':' }}</span>
+        </div>
+        <div class="rights">
+          <input v-if="showBtn" type="text" v-model="form.address" :placeholder="$t('hj2111')" />
+          <input v-if="!showBtn" type="text" v-model="form.address" readonly />
+        </div>
+      </div>
       <div class="uploads">
         <div class="lefts">
           <el-upload :with-credentials="true" class="avatar-uploader" :action="admin + '/user/upload.do'"
@@ -88,6 +97,7 @@
         phone: "",
         name: "",
         idCard: "",
+        address: "",
         img1key: "",
         img2key: "",
         img3key: ""
@@ -170,6 +180,7 @@
       ) {
         this.form.idCard = this.$store.state.userInfo.idCard;
         this.form.name = this.$store.state.userInfo.realName;
+        this.form.address = this.$store.state.userInfo.regAddress || "";
         this.form.img1key = this.$store.state.userInfo.img1Key;
         this.form.img2key = this.$store.state.userInfo.img2Key;
         //   this.form.img3key = this.$store.state.userInfo.img3Key
@@ -215,6 +226,8 @@
         Toast(this.$t('hj207'));
       } else if (isNull(this.form.idCard) || !idCardReg(this.form.idCard)) {
         Toast(this.$t('hj208'));
+      } else if (isNull(this.form.address)) {
+        Toast('请输入' + this.$t('hj2111'));
       } else if (isNull(this.form.img1key) || isNull(this.form.img2key)) {
         Toast(this.$t('hj209'));
       } else {
@@ -226,6 +239,7 @@
       let opts = {
         realName: this.form.name,
         idCard: this.form.idCard,
+        address: this.form.address,
         img1key: this.form.img1key,
         img2key: this.form.img2key,
         img3key: this.form.img3key
diff --git a/src/page/home/home.vue b/src/page/home/home.vue
index c3f3f1b..02352ec 100644
--- a/src/page/home/home.vue
+++ b/src/page/home/home.vue
@@ -97,7 +97,7 @@
         <img
           src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADoAAAA6CAYAAADhu0ooAAAAAXNSR0IArs4c6QAABWpJREFUaEPtWl1sFFUU/s7spluVH6m1y8xssDYEDcaAhCBsl5b+PIhoYkiA4Is/iUFRQR/EaDAYiA8mPmhAIRKivhCFaIwi8gCldtsCCmIwEkkqNs3u3S4tIDFgO9mZY+6GNrvD1s7uztKp7H2953zn++bcmbnn3Eu4RQbdIjpRFvp/y3Q5oyMZDQaDdwQCgQqvZnh4eNhIJpNXx+OXM6O6rrcw85MAlgNQxwPxwHwCwPdEtDcejx/JxSdLaDAYrPP5fB8DaPEA+UIpHDZNc10ymTyfCTAqNBQKLbIs6xCAGYVG8JDfJUVRlsdisR9HOKWF6roeYuafAdztIbLFUrloWdbC/v7+XgmUFqqq6ndE9OgYyNcAJImIi43stj8zS/5BALfnwmbmg4lEYkVaqKZpEQDRHIbnmHljIpE4DMB0m6SLeD5VVVuJ6AMA9+XAXSqE6JRCtwN4KdOAmf8IBAILe3t7/3KRUEmhamtr7zQM4ycAs22BdgghXpZCf8/xJNYKIT4vKbMSgGuatgaAnfc5IcT9Uug/ACoz4/r9/qq+vr7LJeBSUshZs2bNSKVSl2xBhoQQt0mhN3xkhBCTdms4lp6y0JKusRKClzNafkdLuLxKCV1euvksXU3TNgHYCEBzmJU+AFuFEHvGso9GIjN8FYosKGodYkqzAWbeHT4a3UxA1u+x6Izqur6CmQ/kQWbElBVFWZxZMo1OAHSsufErgJ8oABcMera+7YdPMn2LFqqq6jYi2lwIIbmXFkJ8aPftamrcQMRyM17o2BVu63jBVaGapj0O4JtCGCmK8rA9o53Lli1UFKsLQMH9KAI/s6Qt+qmrQiWYqqpvEtGrAKodCu4H8I4QYkem/cnW1umGZcj3ss4hjt3sCjPviVfP3LR6//6sErLopVsgoZxu3c0N+wCsyjH5Xrit47ViYnlGaFdT43oivuF9JcLxaVWDjQ/sP2tMeqHdrQ0PwUK3vSwEcJksZcGS9vZ0f6eYMeEZ7ayvn0oB30kC5tiEMIhXho9Evy5G4IjvhAvtbl66F6C1djEM3l7fFt3ghkiJ4YpQBuh4U2QRFP/UfIhZbC0mYNuNPnRq+l0DYflehkKhBy3Lkh09J+OaEEL2bFN246KF/rZqbsWVi9UHXeziXzHJWrD0SOd5TdPkx2m9E4UZNqcMw2gaHBz829X/aHdLwzowduVJZkxzYqxZcrRj33+0W52E2iKE2Oqq0GPNDVsYeNtJ9PFsGLyzvi2azqCqqiuJ6MvxfMaY/0gI8aKrQk+0ROaYrJweqyueB9HTw5YSbmpvH5I+VVVV0yorK88AuCcPDGlqKopSH4vFTrgqVIJFmyLz/EQbGTQlT1Kj5habb0WOdp3L9A+FQrplWW8AqHGIK49Jdgsh5F45axT9MXJIYMLNykLz6TBMeLocEChn9FbK6IC9kE6lUjMvXLiQdLBSPGVSU1MT9Pv9stjPHFeFEFPk2Yv8N87PnCGi9fF4fKenVDggo+v688xs531GCDGPdF1/X55s23AGFEUJx2KxHgf4njAJhUKzLcuStW7WPQx5Eh6Px1+h61XDLwAUG+OLALYA+FYIEffo8b5P0zQdgGzcye2pvZdlKYoyPxaL/Zo+B9U0TXbSnvJEatwl8ZkQ4mkJmRZaV1c3fWhoSO4Zc112cDf0zUPrud5mTZ+Aj55sB4PBe30+n+zEz715XEoW6axpmo8lk8k/RyJkHeFXV1dPraioeBfAcwD8JaNROmDZcdhtGMbr9oI8512F63cCVxPRI8wsr7PkvLBUOr55IV8joh5mPmSa5heZWcz6ZeYFOYmNJ+3tk3yfeVlovk/M6/bljHo9Q/ny+xcuWZRZFpiovgAAAABJRU5ErkJggg=="
         />
-        <p>股东减持</p>
+        <p>{{ $t("jy552") }}</p>
       </div>
       <div class="xbox" @click="getHeaderlink(4)">
 		<img
@@ -128,7 +128,7 @@
         <img
           src="data:image/png;base64,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"
         />
-        <p>收益日历</p>
+        <p>{{ $t("jy553") }}</p>
       </div>
 	  
       <!-- <div class="xbox" @click="getHeaderlink1(6)">
diff --git a/src/page/home/listcomponents/dazongjiaoyi.vue b/src/page/home/listcomponents/dazongjiaoyi.vue
index 5a93270..41b41e6 100644
--- a/src/page/home/listcomponents/dazongjiaoyi.vue
+++ b/src/page/home/listcomponents/dazongjiaoyi.vue
@@ -198,7 +198,7 @@
         },
         async getxiadan() {
             if (!this.price) {
-                this.$toast('请输入价格')
+                this.$toast(this.$t('jy532'))
                 return
             }
             if (!this.num) {
diff --git a/src/page/kline/buyStock.vue b/src/page/kline/buyStock.vue
index 07b43e8..e756c91 100644
--- a/src/page/kline/buyStock.vue
+++ b/src/page/kline/buyStock.vue
@@ -236,7 +236,7 @@
         return
       }
       if (!this.buyPrice) {
-        Toast('请输入价格')
+        Toast(this.$t('jy532'))
         return
       }
       if (this.buyNum * 100 < this.settingdetail.buyMinNum) {
diff --git a/src/page/login/login.vue b/src/page/login/login.vue
index 6157d0e..7bf223c 100644
--- a/src/page/login/login.vue
+++ b/src/page/login/login.vue
@@ -91,7 +91,7 @@
           class="agreement_checkbox"
         />
         <label for="agreement" class="agreement_label">
-          {{ $t('login_agreeToTerms') }}<span class="agreement_link" @click.stop="viewAgreement">《{{ $t('login_userAgreement') }}》</span>
+          {{ $t('login_agreeToTerms') }}<span class="agreement_link" @click.stop="viewAgreement">{{ $t('login_userAgreement') }}</span>
         </label>
       </div>
 
@@ -184,7 +184,7 @@
     },
     viewAgreement() {
       // 跳转到用户协议页面
-      this.$router.push('/about?e=2');
+      this.$router.push('/about?e=3');
     },
     async loginIN() {
       if (!this.agreedToTerms) {
diff --git a/src/page/login/register.vue b/src/page/login/register.vue
index 59b7f2d..ccffe35 100644
--- a/src/page/login/register.vue
+++ b/src/page/login/register.vue
@@ -65,7 +65,7 @@
             <input :placeholder="$t('jy311')" v-model="phone" class="field-input" />
           </div>
         </div>
-        
+
         <div class="form-field">
           <label class="field-label">{{ $t('login_loginPassword') }}</label>
           <input
@@ -75,7 +75,7 @@
             class="field-input"
           />
         </div>
-        
+
         <div class="form-field">
           <label class="field-label">{{ $t('register_confirmPassword') }}</label>
           <input
@@ -85,23 +85,23 @@
             class="field-input"
           />
         </div>
-        
+
         <div class="form-field">
           <label class="field-label">{{ $t('register_inviteCode') }}</label>
           <input :placeholder="$t('jy313')" v-model="userName" class="field-input" />
         </div>
-        
+
         <div class="agreement">
           <input type="checkbox" id="agreement" v-model="agree" />
           <label for="agreement">
             {{ $t('login_agreeToTerms') }} <span class="agreement-link" @click.stop="viewAgreement">{{ $t('login_userAgreement') }}</span>
           </label>
         </div>
-        
+
         <div class="loginBtn" v-loading="loginBtn" @click="gook">
           {{ $t('register_openAccountNow') }}
         </div>
-        
+
         <div class="login-link">
           <span @click="$router.push('/login')">{{ $t('register_haveAccountLoginNow') }}</span>
         </div>
@@ -119,7 +119,7 @@
           <div class="feature-title">{{ $t('register_fastAccountOpening') }}</div>
           <div class="feature-desc">{{ $t('register_completedIn3Minutes') }}</div>
         </div>
-        
+
         <div class="feature-item">
           <div class="feature-icon">
             <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
@@ -129,7 +129,7 @@
           <div class="feature-title">{{ $t('register_bankLevelSecurity') }}</div>
           <div class="feature-desc">{{ $t('register_fundProtection') }}</div>
         </div>
-        
+
         <div class="feature-item">
           <div class="feature-icon">
             <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
@@ -141,8 +141,8 @@
         </div>
       </div>
       </div>
-      
-      
+
+
     </div>
   </div>
 </template>
@@ -209,7 +209,7 @@
     },
     viewAgreement() {
       // 跳转到用户协议页面
-      this.$router.push('/about?e=2');
+      this.$router.push('/about?e=3');
     },
 	getCodeRandom(){
 		const code = Math.floor(1000 + Math.random() * 9000).toString();
@@ -357,15 +357,17 @@
         // }, 2000)
         Toast(this.$t("hj28"));
         this.loginBtn = false;
-      } else if (isNull(this.yzmCode)) {
-        // this.texts = this.$t('hj30')
-        // this.alertShow = true
-        // setTimeout(() => {
-        //   this.alertShow = false
-        // }, 2000)
-        Toast(this.$t("jy459"));
-        this.loginBtn = false;
-      } else if (isNull(this.userPassword)) {
+      }
+      // else if (isNull(this.yzmCode)) {
+      //   // this.texts = this.$t('hj30')
+      //   // this.alertShow = true
+      //   // setTimeout(() => {
+      //   //   this.alertShow = false
+      //   // }, 2000)
+      //   Toast(this.$t("jy459"));
+      //   this.loginBtn = false;
+      // }
+      else if (isNull(this.userPassword)) {
         // this.texts = this.$t('hj30')
         // this.alertShow = true
         // setTimeout(() => {
@@ -752,7 +754,7 @@
 
 .header-content {
   padding-top: 1rem;
-  
+
   .page-title {
     font-size: 0.65rem;
     font-weight: 600;
@@ -760,20 +762,20 @@
     margin: 0 0 0.5rem 0;
     padding-left: 0.5rem;
   }
-  
+
   .features {
     display: flex;
     flex-wrap: wrap;
     gap: 0.3rem;
     padding-left: 0.5rem;
-    
+
     .feature-item {
       display: flex;
       align-items: center;
       gap: 0.2rem;
       font-size: 0.28rem;
       color: #666;
-      
+
       .check-icon {
         width: 0.4rem;
         height: 0.4rem;
@@ -804,7 +806,7 @@
 
 .form-field {
   margin-bottom: 1rem;
-  
+
   .field-label {
     display: block;
     font-size: 0.32rem;
@@ -812,7 +814,7 @@
     color: #333;
     margin-bottom: 0.3rem;
   }
-  
+
   .input-wrapper {
     display: flex;
     align-items: center;
@@ -820,13 +822,13 @@
     border-radius: 0.2rem;
     overflow: hidden;
     background: #F5F7FA;
-    
+
     .area-select {
       width: 2rem;
       border: none;
       border-right: 1px solid #e0e0e0;
       background: #F5F7FA;
-      
+
       /deep/ .el-input__inner {
         border: none;
         height: 1.3rem;
@@ -835,7 +837,7 @@
         background: #F5F7FA;
       }
     }
-    
+
     .field-input {
       flex: 1;
       border: none;
@@ -845,7 +847,7 @@
       background: #F5F7FA;
     }
   }
-  
+
   .field-input {
     width: 100%;
     height: 1.3rem;
@@ -854,7 +856,7 @@
     padding: 0 0.3rem;
     font-size: 0.32rem;
     background: #F5F7FA;
-    
+
     &:focus {
       outline: none;
       border-color: #1890ff;
@@ -941,7 +943,7 @@
   margin: 0.5rem 0;
   font-size: 0.28rem;
   color: #666;
-  
+
   input[type="checkbox"] {
     width: 0.45rem;
     height: 0.45rem;
@@ -955,11 +957,11 @@
     position: relative;
     flex-shrink: 0;
     transition: all 0.3s ease;
-    
+
     &:checked {
       background-color: #1890ff;
       border-color: #1890ff;
-      
+
       &::after {
         content: '✓';
         position: absolute;
@@ -972,28 +974,28 @@
         line-height: 1;
       }
     }
-    
+
     &:hover {
       border-color: #1890ff;
     }
-    
+
     &:focus {
       outline: none;
       box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
     }
   }
-  
+
   label {
     display: flex;
     align-items: center;
     cursor: pointer;
     user-select: none;
   }
-  
+
   .agreement-link {
     color: #1890ff;
     text-decoration: none;
-    
+
     &:hover {
       text-decoration: underline;
     }
@@ -1018,12 +1020,12 @@
 .login-link {
   text-align: center;
   margin-top: 0.5rem;
-  
+
   span {
     font-size: 0.28rem;
     color: #999;
     cursor: pointer;
-    
+
     &:hover {
       color: #1890ff;
     }
@@ -1036,13 +1038,13 @@
   align-items: center;
   padding: 1rem 0.5rem;
   background: #fff;
-  
+
   .feature-item {
     display: flex;
     flex-direction: column;
     align-items: center;
     flex: 1;
-    
+
     .feature-icon {
       width: 1rem;
       height: 1rem;
@@ -1052,21 +1054,21 @@
       align-items: center;
       justify-content: center;
       margin-bottom: 0.3rem;
-      
+
       svg {
         width: 0.6rem;
         height: 0.6rem;
         color: #fff;
       }
     }
-    
+
     .feature-title {
       font-size: 0.28rem;
       font-weight: 600;
       color: #333;
       margin-bottom: 0.15rem;
     }
-    
+
     .feature-desc {
       font-size: 0.24rem;
       color: #999;
diff --git a/src/page/newUser/about.vue b/src/page/newUser/about.vue
index 31737ab..97f65d5 100644
--- a/src/page/newUser/about.vue
+++ b/src/page/newUser/about.vue
@@ -11,68 +11,98 @@
     <div class="hezi" v-show="type == '1'">
       <img src="@/assets/img/yyzz.png" />
       <h6>{{ $t("jy321") }}</h6>
-      <p>{{ $t("jy320") }}:V1.1.2</p>
+      <p>{{ $t("jy320") }}: V1.1.2</p>
     </div>
     <div v-show="type != '1'" class="hezi" style="line-height: 0.5rem;">
-      <div v-if="type == 2" v-html="userInfo.companyInfo"></div>
+      <div v-if="type == 2">
+        <div v-if="generating" class="loading-container">
+          <div class="loading-spinner"></div>
+          <p class="loading-text">{{ $t('jy526') }}</p>
+        </div>
+        <div v-else-if="!hasAgreementPdf" style="text-align: center; padding: 20px;">
+          <!-- <button @click="handleGeneratePdf" class="btn-generate" :disabled="generating">
+            生成用户合同
+          </button> -->
+        </div>
+        <div v-else class="agreement-container">
+          <ImageViewer :imageUrls="imageUrls" v-if="imageUrls && imageUrls.length > 0" />
+          <div class="signature-section" v-if="showSignature && !isSigned">
+            <h4>{{ $t('jy527') }}</h4>
+            <vue-signature-pad
+              ref="mySignaturePad"
+              class="signature-canvas"
+              :options="signatureOptions"
+            ></vue-signature-pad>
+            <div class="signature-btns">
+              <button @click="clearSignature" class="btn-clear" :disabled="submittingSignature">{{ $t('jy528') }}</button>
+              <button @click="confirmSignature" class="btn-confirm" :disabled="submittingSignature">{{ $t('jy529') }}</button>
+            </div>
+          </div>
+          <div v-else-if="!isSigned" class="signature-action">
+            <button @click="showSignature = true" class="btn-signature">{{ $t('jy529') }}</button>
+          </div>
+          <div v-if="isSigned" class="signature-tip">
+            <p>{{ $t('jy530') }}</p>
+          </div>
+        </div>
+      </div>
       <div v-else-if="type == 3" v-html="userInfo.certImg1"></div>
       <div v-else-if="type == 4" v-html="userInfo.certImg2"></div>
       <div v-else-if="type == 5" v-html="userInfo.tradeAgreeText"></div>
       <div v-else-if="type == 6">{{ $t("jy319") }}</div>
+      <div v-else-if="type == 7">
+        <div v-if="generatingContract" class="loading-container">
+          <div class="loading-spinner"></div>
+          <p class="loading-text">{{ $t('jy526') }}</p>
+        </div>
+        <div v-else-if="!hasContractPdf" style="text-align: center; padding: 20px;">
+          <!-- <button @click="handleGenerateContractPdf" class="btn-generate" :disabled="generatingContract">
+            生成用户合同
+          </button> -->
+        </div>
+        <div v-else class="agreement-container">
+          <ImageViewer :imageUrls="contractImageUrls" v-if="contractImageUrls && contractImageUrls.length > 0" />
+          <div class="signature-section" v-if="showContractSignature && !isContractSigned">
+            <h4>{{ $t('jy527') }}</h4>
+            <vue-signature-pad
+              ref="contractSignaturePad"
+              class="signature-canvas"
+              :options="signatureOptions"
+            ></vue-signature-pad>
+            <div class="signature-btns">
+              <button @click="clearContractSignature" class="btn-clear" :disabled="submittingContractSignature">{{ $t('jy528') }}</button>
+              <button @click="confirmContractSignature" class="btn-confirm" :disabled="submittingContractSignature">{{ $t('jy529') }}</button>
+            </div>
+          </div>
+          <div v-else-if="!isContractSigned" class="signature-action">
+            <button @click="showContractSignature = true" class="btn-signature">{{ $t('jy529') }}</button>
+          </div>
+          <div v-if="isContractSigned" class="signature-tip">
+            <p>{{ $t('jy530') }}</p>
+          </div>
+        </div>
+      </div>
       <div v-else></div>
 	  <!-- <img src="@/assets/img/yyzz.png" style="width: 100%;" /> -->
-	  
-    </div>
-	<div>
-	    <!-- 原始图片,点击可放大 -->
-	    <img 
-	      src="@/assets/img/yyzz.png" 
-	      style="width: 100%; cursor: pointer;" 
-	      @click="showModal = true"
-	    />
 
-<!-- <div class="signature-area">
-      <h4>请完成电子签名</h4>
-      <vue-signature-pad
-        ref="mySignaturePad"
-        class="signature-canvas"
-        :options="signatureOptions"
-      ></vue-signature-pad>
-      <div class="signature-btns">
-        <button @click="clearSignature" class="btn-clear">清空签名</button>
-        <button @click="confirmSignature" class="btn-confirm" :disabled="!isAgree || !hasSignature">确认签名</button>
-      </div>
     </div>
-
-    <div class="signature-preview" v-if="signatureImg">
-      <h4>签名预览</h4>
-      <img :src="signatureImg" alt="电子签名" />
-    </div> -->
-      
-	
-	    <!-- 模态框,用于显示放大的图片 -->
-	    <div 
-	      v-if="showModal" 
-	      class="modal" 
-	      @click.self="showModal = false"
-	    >
-	      <div class="modal-content">
-	        <img 
-	          :src="require('@/assets/img/yyzz.png')" 
-	          class="enlarged-image"
-	        />
-	      </div>
-	    </div>
-	  </div>
   </div>
 </template>
 <script>
 import * as api from "@/axios/api";
 import VueSignaturePad from 'vue-signature-pad'
+import PdfViewerModern from '@/components/PdfViewerModern.vue'
+import ImageViewer from '@/components/ImageViewer.vue'
+import axios from '@/axios/index'
+import APIUrl from '@/axios/api.url'
+import { Toast } from 'mint-ui'
+
 export default {
   name: "about",
   components: {
-    VueSignaturePad
+    VueSignaturePad,
+    PdfViewerModern,
+    ImageViewer
   },
   created() {
     var that = this;
@@ -84,7 +114,7 @@
           this.title = this.$t("jy318");
           break;
         case "2":
-          this.title = this.$t("jy317");
+          this.title = this.$t("jy546");
           break;
         case "3":
           this.title = this.$t("jy316");
@@ -98,6 +128,9 @@
         case "6":
           this.title = this.$t("jy315");
           break;
+        case "7":
+          this.title = this.$t("jy547");
+          break;
         default:
           break;
       }
@@ -109,75 +142,513 @@
       title: this.$t("jy314"),
       type: 0,
       userInfo: {},
-	  showModal: false,
-	  signatureImg: '',
-	  isAgree: false,
-	  hasSignature: false,
-	  signatureOptions: {
-		penColor: '#000000',
-		penWidth: 2,
-	  },
-    signatureInstance: null
+      signatureImg: '',
+      hasSignature: false,
+      signatureOptions: {
+        penColor: '#000000',
+        penWidth: 2,
+      },
+      signatureInstance: null,
+      hasAgreementPdf: false,
+      generating: false,
+      pdfUrl: '',
+      imageUrls: [],
+      showSignature: false,
+      currentUser: null,
+      hasContractPdf: false,
+      generatingContract: false,
+      contractPdfUrl: '',
+      contractImageUrls: [],
+      showContractSignature: false,
+      contractSignatureInstance: null,
+      submittingSignature: false,
+      submittingContractSignature: false
     };
   },
-  mounted() {
-    this.getUserInfo();
-    // vue-signature-pad@2.x 的实例在 this.$refs.xxx.signaturePad 里
-    this.signatureInstance = this.$refs.mySignaturePad.signaturePad
-    // 监听签名变化,更新 hasSignature 状态
-    this.$refs.mySignaturePad.$on('signatureChanged', (isEmpty) => {
-      this.hasSignature = !isEmpty
-    })
+  computed: {
+    isSigned() {
+      // 判断是否已签名:检查isSignedContract字段是否不为空
+      return this.currentUser && this.currentUser.isSignedContract && this.currentUser.isSignedContract.trim() !== '';
+    },
+    isContractSigned() {
+      // 判断保密协议是否已签名:检查isSignedAgreement字段是否等于'Y'
+      return this.currentUser && this.currentUser.isSignedAgreement === 'Y';
+    },
+    pdfIframeSrc() {
+      if (!this.pdfUrl) return '';
+      const token = typeof window !== 'undefined' && window.localStorage ? window.localStorage.getItem('USERTOKEN') || '' : '';
+      return this.pdfUrl + '?token=' + token;
+    }
+  },
+  async mounted() {
+    if(this.type != 3) {
+    await this.getUserInfo();
+    }else{
+      let data = await api.getInfoSite();
+      if (data.status === 0) {
+        this.userInfo = data.data;
+      }
+    }
+    if (this.type == 2) {
+      this.checkAgreementPdf();
+    } else if (this.type == 7) {
+      this.checkContractPdf();
+    }
+  },
+  watch: {
+    showSignature(newVal) {
+      if (newVal) {
+        // 当显示签名区域时,初始化签名组件
+        this.$nextTick(() => {
+          this.initSignaturePad();
+        });
+      }
+    },
+    showContractSignature(newVal) {
+      if (newVal) {
+        // 当显示合同签名区域时,初始化签名组件
+        this.$nextTick(() => {
+          this.initContractSignaturePad();
+        });
+      }
+    }
   },
   methods: {
+    isAuthenticated() {
+      // 判断是否已实名认证:isActive === 1 (审核中) 或 isActive === 2 (已通过)
+      const userInfo = this.currentUser || this.$store.state.userInfo;
+      return userInfo && (userInfo.isActive === 1 || userInfo.isActive === 2);
+    },
     async getUserInfo() {
       // 获取用户信息
       let data = await api.getInfoSite();
       if (data.status === 0) {
         this.userInfo = data.data;
-      } else {
+      }
+      // 获取当前登录用户信息
+      let userData = await api.getUserInfo();
+      if (userData.status === 0) {
+        this.currentUser = userData.data;
+        this.$store.state.userInfo = userData.data;
       }
     },
-    // 清空签名(调用真实实例的方法)
-    clearSignature() {
-      if (this.signatureInstance) {
-        this.signatureInstance.clear()
-        this.signatureImg = ''
-        this.hasSignature = false
-      } else {
-        alert('签名组件未初始化!')
-      }
-    },
-    // 确认签名(调用真实实例的方法)
-    confirmSignature() {
-      if (!this.isAgree) {
-        alert('请先阅读并同意用户协议!')
-        return
-      }
-      if (this.signatureInstance) {
-        // 检查是否有签名
-        if (!this.signatureInstance.isEmpty()) {
-          // 导出 Base64 图片
-          this.signatureImg = this.signatureInstance.toDataURL('image/png')
-          this.hasSignature = true
-          this.submitAgreement()
-        } else {
-          alert('请先完成电子签名!')
+    initSignaturePad() {
+      this.$nextTick(() => {
+        if (this.$refs.mySignaturePad) {
+          this.signatureInstance = this.$refs.mySignaturePad.signaturePad;
         }
-      } else {
-        alert('签名组件未初始化!')
+      });
+    },
+    clearSignature() {
+      this.$nextTick(() => {
+        if (!this.signatureInstance && this.$refs.mySignaturePad) {
+          this.signatureInstance = this.$refs.mySignaturePad.signaturePad;
+        }
+        if (this.signatureInstance) {
+          this.signatureInstance.clear();
+          this.signatureImg = '';
+          this.hasSignature = false;
+        }
+      });
+    },
+    confirmSignature() {
+      // 防止重复点击
+      if (this.submittingSignature) {
+        return;
+      }
+      this.$nextTick(() => {
+        if (!this.signatureInstance && this.$refs.mySignaturePad) {
+          this.signatureInstance = this.$refs.mySignaturePad.signaturePad;
+        }
+        if (this.signatureInstance) {
+          if (!this.signatureInstance.isEmpty()) {
+            this.signatureImg = this.signatureInstance.toDataURL('image/png');
+            this.hasSignature = true;
+            this.submitAgreement();
+          } else {
+          this.$message.error(this.$t('jy554'));
+          }
+        } else {
+          this.$message.error(this.$t('jy555'));
+
+        }
+      });
+    },
+    async submitAgreement() {
+      // 防止重复提交
+      if (this.submittingSignature) {
+        return;
+      }
+      this.submittingSignature = true;
+      try {
+        const blob = await this.dataURLtoBlob(this.signatureImg);
+        const formData = new FormData();
+        formData.append('signature', blob, 'signature.png');
+
+        const config = {
+          headers: {
+            'Content-Type': 'multipart/form-data'
+          }
+        };
+
+        if (window.localStorage.getItem("USERTOKEN")) {
+          config.headers["USERTOKEN"] = window.localStorage.getItem("USERTOKEN");
+        }
+
+        const result = await axios.post(APIUrl.baseURL + '/user/saveAgreementSignature.do', formData, config);
+
+        if (result.data.status === 0) {
+          this.$message.success(this.$t('jy556'));
+          this.showSignature = false;
+          // 重新获取用户信息,更新签名状态
+          let userData = await api.getUserInfo();
+          if (userData.status === 0) {
+            this.currentUser = userData.data;
+            this.$store.state.userInfo = userData.data;
+          }
+          // 延迟跳转,让用户看到成功提示
+          setTimeout(() => {
+            this.$router.push('/User');
+          }, 1500);
+        } else {
+          this.$message.error(result.data.msg || this.$t('jy557'));
+          this.submittingSignature = false;
+        }
+      } catch (error) {
+        console.error('提交签名失败:', error);
+        this.$message.error(this.$t('jy557'));
+        this.submittingSignature = false;
       }
     },
-    // 提交协议
-    submitAgreement() {
-      const submitData = {
-        userId: '当前用户ID',
-        isAgree: this.isAgree,
-        signature: this.signatureImg,
-        agreeTime: new Date().getTime()
+    dataURLtoBlob(dataurl) {
+      const arr = dataurl.split(',');
+      const mime = arr[0].match(/:(.*?);/)[1];
+      const bstr = atob(arr[1]);
+      let n = bstr.length;
+      const u8arr = new Uint8Array(n);
+      while (n--) {
+        u8arr[n] = bstr.charCodeAt(n);
       }
-      console.log('提交数据:', submitData)
-      alert('签名成功,协议已提交!')
+      return new Blob([u8arr], { type: mime });
+    },
+    async checkAgreementPdf() {
+      try {
+        // type == 2 是线上合同
+        if (this.type == 2) {
+          const APIUrl = require('@/axios/api.url').default;
+          
+          // 如果已签名(isSignedContract === 'Y'),调用viewAgreementPdf接口获取已签名的图片
+          if (this.currentUser && this.currentUser.isSignedContract === 'Y') {
+            this.generating = true;
+            let result = await api.viewAgreementPdf();
+            console.log('viewAgreementPdf返回结果:', result);
+            if (result.status === 0) {
+              this.hasAgreementPdf = true;
+              // result.data 现在是图片数组
+              if (Array.isArray(result.data) && result.data.length > 0) {
+                this.imageUrls = result.data.map(url => {
+                  if (!url.startsWith('http')) {
+                    return APIUrl.baseURL + (url.startsWith('/') ? url : '/' + url);
+                  }
+                  return url;
+                });
+                console.log('处理后的图片URLs:', this.imageUrls);
+              } else {
+                console.warn('未返回图片数据或数据为空');
+                this.hasAgreementPdf = false;
+              }
+            } else {
+              console.error('接口返回错误:', result.msg);
+              this.hasAgreementPdf = false;
+            }
+            this.generating = false;
+            return;
+          }
+          
+          // 如果未签名(isSignedContract为空),调用generateAgreementPdf接口生成并渲染图片
+          this.generating = true;
+          let result = await api.generateAgreementPdf();
+          if (result.status === 0) {
+            this.hasAgreementPdf = true;
+            // result.data 现在是图片数组
+            if (Array.isArray(result.data) && result.data.length > 0) {
+              this.imageUrls = result.data.map(url => {
+                if (!url.startsWith('http')) {
+                  return APIUrl.baseURL + (url.startsWith('/') ? url : '/' + url);
+                }
+                return url;
+              });
+            } else {
+              this.hasAgreementPdf = false;
+            }
+          } else {
+            this.hasAgreementPdf = false;
+          }
+          this.generating = false;
+          return;
+        }
+
+        // 其他type的处理逻辑
+        // 如果已签名,直接使用已签名的PDF
+        if (this.isSigned && this.currentUser && this.currentUser.isSignedContract) {
+          this.hasAgreementPdf = true;
+          let url = this.currentUser.isSignedContract;
+          if (!url.startsWith('http')) {
+            url = APIUrl.baseURL + (url.startsWith('/') ? url : '/' + url);
+          }
+          this.pdfUrl = url;
+          return;
+        }
+
+        // 未签名,生成新的PDF
+        this.generating = true;
+        let result = await api.generateAgreementPdf();
+        if (result.status === 0) {
+          this.hasAgreementPdf = true;
+          // result.data 现在是图片数组
+          if (Array.isArray(result.data) && result.data.length > 0) {
+            this.imageUrls = result.data.map(url => {
+              if (!url.startsWith('http')) {
+                return APIUrl.baseURL + (url.startsWith('/') ? url : '/' + url);
+              }
+              return url;
+            });
+          } else {
+            this.hasAgreementPdf = false;
+          }
+        } else {
+          this.hasAgreementPdf = false;
+        }
+      } catch (e) {
+        this.hasAgreementPdf = false;
+      } finally {
+        this.generating = false;
+      }
+    },
+    async handleGeneratePdf() {
+      this.generating = true;
+      try {
+        let result = await api.generateAgreementPdf();
+        if (result.status === 0) {
+          this.hasAgreementPdf = true;
+          // result.data 现在是图片数组
+          if (Array.isArray(result.data) && result.data.length > 0) {
+            this.imageUrls = result.data.map(url => {
+              if (!url.startsWith('http')) {
+                return APIUrl.baseURL + (url.startsWith('/') ? url : '/' + url);
+              }
+              return url;
+            });
+            this.$message.success(this.$t('jy558'));
+          } else {
+            this.$message.error(this.$t('jy559'));
+          }
+        } else {
+          this.$message.error(result.msg || this.$t('jy560'));
+        }
+      } catch (e) {
+        this.$message.error(this.$t('jy560') + ': ' + e.message);
+      } finally {
+        this.generating = false;
+      }
+    },
+    initContractSignaturePad() {
+      this.$nextTick(() => {
+        if (this.$refs.contractSignaturePad) {
+          this.contractSignatureInstance = this.$refs.contractSignaturePad.signaturePad;
+        }
+      });
+    },
+    clearContractSignature() {
+      this.$nextTick(() => {
+        if (!this.contractSignatureInstance && this.$refs.contractSignaturePad) {
+          this.contractSignatureInstance = this.$refs.contractSignaturePad.signaturePad;
+        }
+        if (this.contractSignatureInstance) {
+          this.contractSignatureInstance.clear();
+        }
+      });
+    },
+    confirmContractSignature() {
+      // 防止重复点击
+      if (this.submittingContractSignature) {
+        return;
+      }
+      this.$nextTick(() => {
+        if (!this.contractSignatureInstance && this.$refs.contractSignaturePad) {
+          this.contractSignatureInstance = this.$refs.contractSignaturePad.signaturePad;
+        }
+        if (this.contractSignatureInstance) {
+          if (!this.contractSignatureInstance.isEmpty()) {
+            const signatureImg = this.contractSignatureInstance.toDataURL('image/png');
+            this.submitContractAgreement(signatureImg);
+          } else {
+            this.$message.error(this.$t('jy554'));
+          }
+        } else {
+          this.$message.error(this.$t('jy555'));
+        }
+      });
+    },
+    async submitContractAgreement(signatureImg) {
+      // 防止重复提交
+      if (this.submittingContractSignature) {
+        return;
+      }
+      this.submittingContractSignature = true;
+      try {
+        const blob = await this.dataURLtoBlob(signatureImg);
+        const formData = new FormData();
+        formData.append('signature', blob, 'signature.png');
+
+        const config = {
+          headers: {
+            'Content-Type': 'multipart/form-data'
+          }
+        };
+
+        if (window.localStorage.getItem("USERTOKEN")) {
+          config.headers["USERTOKEN"] = window.localStorage.getItem("USERTOKEN");
+        }
+
+        const result = await axios.post(APIUrl.baseURL + '/user/saveAgreementContractSignature.do', formData, config);
+
+        if (result.data.status === 0) {
+          this.$message.success(this.$t('jy556'));
+          this.showContractSignature = false;
+          // 重新获取用户信息,更新签名状态
+          let userData = await api.getUserInfo();
+          if (userData.status === 0) {
+            this.currentUser = userData.data;
+            this.$store.state.userInfo = userData.data;
+          }
+          // 延迟跳转,让用户看到成功提示
+          setTimeout(() => {
+            this.$router.push('/User');
+          }, 1500);
+        } else {
+          this.$message.error(result.data.msg || this.$t('jy557'));
+          this.submittingContractSignature = false;
+        }
+      } catch (error) {
+        console.error('提交合同签名失败:', error);
+        this.$message.error(this.$t('jy557'));
+        this.submittingContractSignature = false;
+      }
+    },
+    async checkContractPdf() {
+      try {
+        // type == 7 是保密协议
+        if (this.type == 7) {
+          const APIUrl = require('@/axios/api.url').default;
+          
+          // 判断是否已签名:isSignedAgreement === 'Y'
+          const isSigned = this.currentUser && this.currentUser.isSignedAgreement === 'Y';
+          
+          if (isSigned) {
+            // 如果已签名,调用viewAgreementContractPdf接口获取已签名的图片(从数据库查询)
+            this.generatingContract = true;
+            let result = await api.viewAgreementContractPdf();
+            console.log('viewAgreementContractPdf返回结果:', result);
+            if (result.status === 0) {
+              this.hasContractPdf = true;
+              // result.data 现在是图片数组
+              if (Array.isArray(result.data) && result.data.length > 0) {
+                this.contractImageUrls = result.data.map(url => {
+                  if (!url.startsWith('http')) {
+                    return APIUrl.baseURL + (url.startsWith('/') ? url : '/' + url);
+                  }
+                  return url;
+                });
+                console.log('处理后的图片URLs:', this.contractImageUrls);
+              } else {
+                console.warn('未返回图片数据或数据为空');
+                this.hasContractPdf = false;
+              }
+            } else {
+              console.error('接口返回错误:', result.msg);
+              this.hasContractPdf = false;
+            }
+            this.generatingContract = false;
+            return;
+          }
+          
+          // 如果未签名(isSignedAgreement为空),调用generateAgreementContractPdf接口生成并渲染图片
+          this.generatingContract = true;
+          let result = await api.generateAgreementContractPdf();
+          if (result.status === 0) {
+            this.hasContractPdf = true;
+            // result.data 现在是图片数组
+            if (Array.isArray(result.data) && result.data.length > 0) {
+              this.contractImageUrls = result.data.map(url => {
+                if (!url.startsWith('http')) {
+                  return APIUrl.baseURL + (url.startsWith('/') ? url : '/' + url);
+                }
+                return url;
+              });
+            } else {
+              this.hasContractPdf = false;
+            }
+          } else {
+            this.hasContractPdf = false;
+          }
+          this.generatingContract = false;
+          return;
+        }
+      } catch (e) {
+        console.error('checkContractPdf错误:', e);
+        this.hasContractPdf = false;
+      } finally {
+        this.generatingContract = false;
+      }
+    },
+    async handleGenerateContractPdf() {
+      this.generatingContract = true;
+      try {
+        let result = await api.generateAgreementContractPdf();
+        if (result.status === 0) {
+          this.hasContractPdf = true;
+          // result.data 现在是图片数组
+          if (Array.isArray(result.data) && result.data.length > 0) {
+            this.contractImageUrls = result.data.map(url => {
+              if (!url.startsWith('http')) {
+                return APIUrl.baseURL + (url.startsWith('/') ? url : '/' + url);
+              }
+              return url;
+            });
+            this.$message.success(this.$t('jy558'));
+          } else {
+            this.$message.error(this.$t('jy559'));
+          }
+        } else {
+          this.$message.error(result.msg || this.$t('jy560'));
+        }
+      } catch (e) {
+        this.$message.error(this.$t('jy560') + ': ' + e.message);
+      } finally {
+        this.generatingContract = false;
+      }
+    },
+    async handleGenerateContractPdfOld() {
+      this.generatingContract = true;
+      try {
+        let result = await api.generateAgreementContractPdf();
+        if (result.status === 0) {
+          this.hasContractPdf = true;
+          let url = result.data || '/user/viewAgreementContractPdf.do';
+          if (!url.startsWith('http')) {
+            url = APIUrl.baseURL + url;
+          }
+          this.contractPdfUrl = url;
+          this.$message.success(this.$t('jy558'));
+        } else {
+          this.$message.error(result.msg || this.$t('jy560'));
+        }
+      } catch (e) {
+        this.$message.error(this.$t('jy560') + ': ' + e.message);
+      } finally {
+        this.generatingContract = false;
+      }
     }
   }
 };
@@ -270,6 +741,9 @@
 .bijnm {
   background: #fff;
   min-height: 100vh;
+  width: 100%;
+  max-width: 100%;
+  box-sizing: border-box;
 }
 
 .headf {
@@ -311,14 +785,128 @@
 }
 
 .hezi {
-  width: 9.2115rem;
+  width: 100%;
+  max-width: 100%;
+  padding: 0 20px;
   border-bottom: 0.0267rem solid #e0e0e0;
   margin: 0 auto;
   margin-top: 1.1748rem;
   padding-bottom: 0.534rem;
+  box-sizing: border-box;
 }
 
 .hezi img {
   width: 5rem;
 }
+
+.btn-generate, .btn-view {
+  padding: 10px 20px;
+  background: linear-gradient(-55deg, rgb(241, 22, 20), rgb(240, 40, 37));
+  color: #fff;
+  border: none;
+  border-radius: 5px;
+  font-size: 16px;
+  cursor: pointer;
+}
+
+.btn-generate:disabled {
+  background: #ccc;
+  cursor: not-allowed;
+}
+
+.agreement-container {
+  padding: 0;
+  width: 100%;
+  max-width: 100%;
+  box-sizing: border-box;
+  height: calc(100vh - 1.1748rem - 100px);
+  max-height: calc(100vh - 1.1748rem - 100px);
+  margin-top: -20px;
+}
+
+
+.signature-section {
+  margin-top: 20px;
+  padding: 20px;
+  background: #f9f9f9;
+  border-radius: 5px;
+}
+
+.signature-section h4 {
+  margin-bottom: 15px;
+  font-size: 18px;
+  font-weight: bold;
+}
+
+.signature-canvas {
+  width: 100%;
+  height: 300px;
+  border: 2px dashed #ccc;
+  margin: 15px 0;
+  background: #fff;
+  border-radius: 5px;
+}
+
+.signature-btns {
+  display: flex;
+  gap: 10px;
+  margin-top: 10px;
+}
+
+.btn-signature {
+  padding: 10px 20px;
+  background: linear-gradient(-55deg, rgb(241, 22, 20), rgb(240, 40, 37));
+  color: #fff;
+  border: none;
+  border-radius: 5px;
+  font-size: 16px;
+  cursor: pointer;
+  width: 100%;
+  margin-top: 20px;
+}
+
+.signature-tip {
+  margin-top: 20px;
+  padding: 15px;
+  background: #e8f5e9;
+  border-radius: 5px;
+  text-align: center;
+}
+
+.signature-tip p {
+  margin: 0;
+  color: #4caf50;
+  font-size: 16px;
+  font-weight: bold;
+}
+
+.loading-container {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  padding: 60px 20px;
+  min-height: 300px;
+}
+
+.loading-spinner {
+  width: 50px;
+  height: 50px;
+  border: 4px solid #f3f3f3;
+  border-top: 4px solid rgb(241, 22, 20);
+  border-radius: 50%;
+  animation: spin 1s linear infinite;
+  margin-bottom: 20px;
+}
+
+@keyframes spin {
+  0% { transform: rotate(0deg); }
+  100% { transform: rotate(360deg); }
+}
+
+.loading-text {
+  color: #666;
+  font-size: 16px;
+  margin-top: 10px;
+}
 </style>
diff --git a/src/page/newUser/index.vue b/src/page/newUser/index.vue
index fb335c5..81dd076 100644
--- a/src/page/newUser/index.vue
+++ b/src/page/newUser/index.vue
@@ -238,7 +238,7 @@
       </div>
     </div>
     <div class="zijk">
-      <h5>{{ $t("jy334") }}(融资融券账户)</h5>
+      <h5>{{ $t("jy334") }}({{ $t("jy548") }})</h5>
       <div class="kunk">
         <van-circle
           v-model="currentRate"
@@ -306,7 +306,7 @@
               src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAABVVJREFUWEfFl2tsk2UUx3/Pu7Zrd2FjwNaNSwYbasAAKsotYKYSEUk0GAKSoEZGApKYaKKSGMOInyYfQINfQESjYUrw8gGMCmQagqiJiiMgchsXGYONiVvbbe3Wx5w+79Z27dsVQ+JJlqXt85zzf87lf85RZCmaEwWQ9zhEa0DNACYCRfb1f4Bm0MfAaoTQfsXUQDaq1XCHNGerwXoNeBrIH+68/XsQaIBovaL6bKY7jgA0zV6I1oF6CfBkaXjosTDorWBtVEzsSacjLQDNmSrI2QuIq2+HHIPosnTeSAGguXAvRL8Cym6H5QQd18BarKj8NVFvEgA73j8AY26z8QF1bRCdm+iJQQCayz6IHAWmpxif4IIn82C+F6Z6wJ8DIyzQGjo1XO2D4xE43ANfBqGlPxP+JnDPVozvlkMJAM7Vg3o16WaVGzaXwBN5YAFX+uH3XrjcDzej5uhoC8a6YIYNTGx/HoRXOuBinwMQ/ZaiSirLALCT7g/APXhjZi586wefgnc6YWcXnI5kjswUN6wuhHUjIKRhQQucTHsnAtEpEgobwPkdQG2S9p8rjKsfboUzwxgeCusuN3xfDk1hWNjqBHqnYlKt0pwqBM/VFJIJVcKHAVjX/t/ycW8pLPBC6SWn+0EIlytN83LQn6Sc+qIMHvVBbTvszopVjQrx6foRsHUUNARgVVuGB6gVSnN+O7Am5dRDPjjkN18fDxtvNHbDiQj06uTjXmWSUO48UwB32qk0swV+6c3kwR0C4EdgVsqpoxVQ5YK3O2FVglJJ/pY+6NbmtT4LKnLi9SRx3xuEDcWmLBc55oCY/EkAiI9GpwDoqYT3u+CFG+YneZXE9A43jHdBgZLygYCGS31wKgJHeuKVIjnwoBfGOOaAaG0XAOKj1GZzwA8P5MLS63AoxhmZRQA+WwDTPCAhmes17p8v+e0oYWcAs3NBwiCv/KYbPgoYINfSsFzdSHi9CJSCE2HDAXe7ocCC/SFY2QadNnElY4kBSB8C8YC8YkcXLMs3cY45rd8wYUc/WArKckAI6NMgvHwjTsN5Cl4sgjeL4Ts7F1Kxx0KQPgklB4T91t8Al4I5uTA3N54D0guEhoWu9wRhxXXjLXF/oQVttrU1hbB9NDzfDru6hsYiloTpy3CgCoQJpQzTycZieGMkTLhkXl5kwUG/ASUMKDkglXJynAG0ICUfpAwdiGiAB8LaxF/+jvaCfB6QfWUwThrRFchVcLgcpnugPQoSgnl2L9g2Cp4rhIILQ54RIyIHKhYmfMwH+0KwJM8YkNr/MwIXhAeiUOMzHW92CxRbcHqcMSC9Y5bXcMDBbtgyCtYWgi8JQAjC/oFm9B6wOglebyXsCsDadiix4BGfmQek3OTVEmtpViJjLkJQm1mh0Q8lOVDbBh/YFH6kHPIt46m4mGYkn+1J6GRSO/5trDEscXPq61Ilorzub9h006iuFoA5JvNFBLhU1IYOqJfpPSYR0FMVVWecB5J5Xvi6DGSm2NYJHweM+4fKnlJYmm9KUM4llvtCHzSUmpK954rxkpHNikmx4WfoSCYlOW3QxmQ3bC2BRfZE9Jc9esn/jqjhzwoXLLfXBYn9ge7Y+7jfY3hEQC9uhfOD01ETeOcoKkJJABJCkTqUTnKZREzMASm5fg1d2oToVNiAuc9jeEOmJ2nj73ZBYNAtzkPpwKv/17E8DiK2jn2WFI7U6N/KN00QfSqrxSQOIraabbJXs/iweitmTbZvueXVLNGG5txke1xfCeRlaV/6927Q9VJqme4Mux3HPRJbz5eArrF3RlnPi+3fhQSagWOgZD3fl+16/i91NuTW6o8hHwAAAABJRU5ErkJggg=="
               style="width: 0.4272rem; height: 0.4272rem; margin-right: 0.1602rem;"
             />
-            两融可取资金
+            {{ $t("jy549") }}
           </p>
           <h6>
             ¥
@@ -324,7 +324,7 @@
               src="data:image/png;base64,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"
               style="width: 0.4272rem; height: 0.4272rem; margin-right: 0.1602rem;"
             />
-            两融可用资金
+            {{ $t("jy550") }}
           </p>
           <h6 style="margin-left: 0.534rem;">
             <span class="bzz" v-if="!selectUserFlag">{{
@@ -434,12 +434,21 @@
         </div>
         <span></span>
       </li>
-      <li @click="$router.push('/about?e=2')">
+      <li @click="goToUserAgreement">
         <div class="le">
           <img
             src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAD6klEQVRYhc2YTWhVRxTH/3NfFm5sNxVFdxakhaL4xYuIduPKNqGbQnEhWHDZrWRbCqIrF7oTFBWxha7is4t007SV1iR+YIpgXUmycSM0RZPcOTNH5n5l3ryZefP0EfOH5H7P+d1zzzlz5gk4OvzFH5cBfAsgs69w/U+ItWNzCNHs19viHnaO68eL+7nnfs2sBcSVuc7oadtuF0TxEPOp9YYz+5nIMgZOuTwj7gkhRKsCfQFgpguOuRl4x/YdxzVzca8256trrLk41lqXntG6OH796vW0JLnUA8dswEdZYEttOwpogc7dvXNkPHT90nVeJoWWUoAkQGlASkCqtW2eEyQRFCmsrK58d/PCR/O+sfZ/+fevAjjGnmtBQN/NtgxQChxJs5Ugouh4IXtewOazRmTsuXB5DuSEAsaFkxHAMj79JnsA3YQIyYbLZXkcgsvlMD2YAAeE4QyMiTkDJ6UsYRM96LPbU2bcUhLSIHCkVBSwsesxGo7BPlrJyySx4cxnJUVeOAPeF87jQX8MVkU1JgO3KjkYc6oCM4AGztTCoMpK7b3q9aA9Q4TkSwif57TS5b6JiZgHU7M4BQ5FDMq+MVfD1edi4oHKTEqSVHGVAqe0Lqa0kGK2erM4MUlkbjyYu3B/kVI/a6XZ9pyJx5gHG6eklBm3CwkCkpRNDBI9J6VOLCwuHp66tutrUuooEc0aqLpZyLIsj41XwqXUQYRrki0iOieJnimlJpTWn/5y5eNb81OfF09N//jZn/8tLbW11ic180MA11dWV//tB5fWLLj9XEA/Xdx2FsDZ0PV/po6aIW5Uf30k0pMkBW7YioXVW8fgMMVY66z7Aq43XG0v/RMnNgvDVGx6DTYL7s37j9/dmbVaP2jmzb7Fkrtosl/UrnNCZAuSaOLJnfb/tr0sNYvd1VetrNWaYOBEJrKuDtjeNnCZu/qr4CqI1sjIIwCXm3eKZHFPDPrgUK7cJgXE0tt6ziolCwz87jqlTpQEDzrr1kr3O4c6AD70vOQ7q3yvAbJ4vevgQFkcqoPtr+Y2SaJvhBAfhD5rsWBnfvS40+76hP0Uc4h/XexxNyn1vRDiTCzmUCQC9O7x2U8eTx58NghgOUrioslXZpj5ZWJCLDNjORXOMpy+JvF11Q86o+f3jd37zdRBaO76rcbJ1qfztw8uDgPOCxhr+R/cbt8bzHCiIrNXsFl4bx2Now1RZgZak7wvD4a0MQp1RBuiYY0pXKg1H9g7NjOJ+MTfNU2JwPlq0Fi27gkx+uqgEoyWyLKtAMZCLROcCd7u5+zzzQzR9WO6X8zcs3j2tVtXIYReJ8+tOYbZ2LzadRLAG2TYR+L1rz8MAAAAAElFTkSuQmCC"
           />
-          <p>{{ $t("jy317") }}</p>
+          <p>{{ $t("jy546") }}</p>
+        </div>
+        <span></span>
+      </li>
+      <li @click="goToUserContract">
+        <div class="le">
+          <img
+            src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAD6klEQVRYhc2YTWhVRxTH/3NfFm5sNxVFdxakhaL4xYuIduPKNqGbQnEhWHDZrWRbCqIrF7oTFBWxha7is4t007SV1iR+YIpgXUmycSM0RZPcOTNH5n5l3ryZefP0EfOH5H7P+d1zzzlz5gk4OvzFH5cBfAsgs69w/U+ItWNzCNHs19viHnaO68eL+7nnfs2sBcSVuc7oadtuF0TxEPOp9YYz+5nIMgZOuTwj7gkhRKsCfQFgpguOuRl4x/YdxzVzca8256trrLk41lqXntG6OH796vW0JLnUA8dswEdZYEttOwpogc7dvXNkPHT90nVeJoWWUoAkQGlASkCqtW2eEyQRFCmsrK58d/PCR/O+sfZ/+fevAjjGnmtBQN/NtgxQChxJs5Ugouh4IXtewOazRmTsuXB5DuSEAsaFkxHAMj79JnsA3YQIyYbLZXkcgsvlMD2YAAeE4QyMiTkDJ6UsYRM96LPbU2bcUhLSIHCkVBSwsesxGo7BPlrJyySx4cxnJUVeOAPeF87jQX8MVkU1JgO3KjkYc6oCM4AGztTCoMpK7b3q9aA9Q4TkSwif57TS5b6JiZgHU7M4BQ5FDMq+MVfD1edi4oHKTEqSVHGVAqe0Lqa0kGK2erM4MUlkbjyYu3B/kVI/a6XZ9pyJx5gHG6eklBm3CwkCkpRNDBI9J6VOLCwuHp66tutrUuooEc0aqLpZyLIsj41XwqXUQYRrki0iOieJnimlJpTWn/5y5eNb81OfF09N//jZn/8tLbW11ic180MA11dWV//tB5fWLLj9XEA/Xdx2FsDZ0PV/po6aIW5Uf30k0pMkBW7YioXVW8fgMMVY66z7Aq43XG0v/RMnNgvDVGx6DTYL7s37j9/dmbVaP2jmzb7Fkrtosl/UrnNCZAuSaOLJnfb/tr0sNYvd1VetrNWaYOBEJrKuDtjeNnCZu/qr4CqI1sjIIwCXm3eKZHFPDPrgUK7cJgXE0tt6ziolCwz87jqlTpQEDzrr1kr3O4c6AD70vOQ7q3yvAbJ4vevgQFkcqoPtr+Y2SaJvhBAfhD5rsWBnfvS40+76hP0Uc4h/XexxNyn1vRDiTCzmUCQC9O7x2U8eTx58NghgOUrioslXZpj5ZWJCLDNjORXOMpy+JvF11Q86o+f3jd37zdRBaO76rcbJ1qfztw8uDgPOCxhr+R/cbt8bzHCiIrNXsFl4bx2Now1RZgZak7wvD4a0MQp1RBuiYY0pXKg1H9g7NjOJ+MTfNU2JwPlq0Fi27gkx+uqgEoyWyLKtAMZCLROcCd7u5+zzzQzR9WO6X8zcs3j2tVtXIYReJ8+tOYbZ2LzadRLAG2TYR+L1rz8MAAAAAElFTkSuQmCC"
+          />
+          <p>{{ $t("jy547") }}</p>
         </div>
         <span></span>
       </li>
@@ -513,6 +522,24 @@
     this.getInfoSite();
   },
   methods: {
+    goToUserAgreement() {
+      // 判断是否已实名认证
+      const userInfo = this.userInfo && this.userInfo.length > 0 ? this.userInfo : this.$store.state.userInfo;
+      if (!userInfo || userInfo.isActive !== 2) {
+        Toast(this.$t('jy551'));
+        return;
+      }
+      this.$router.push('/about?e=2');
+    },
+    goToUserContract() {
+      // 判断是否已实名认证
+      const userInfo = this.userInfo && this.userInfo.length > 0 ? this.userInfo : this.$store.state.userInfo;
+      if (!userInfo || userInfo.isActive !== 2) {
+        Toast(this.$t('jy551'));
+        return;
+      }
+      this.$router.push('/about?e=7');
+    },
 	rechargeMsg(msg){
 		Toast(this.$t("jy527"));
 	},
diff --git a/src/page/newUser/smrz.vue b/src/page/newUser/smrz.vue
index 34f4d01..5aaaf71 100644
--- a/src/page/newUser/smrz.vue
+++ b/src/page/newUser/smrz.vue
@@ -29,12 +29,24 @@
       </li>
       <li class="verli">
         <input
-          :placeholder="$t('jy520')"
+          :placeholder="$t('jy561')"
           v-model="form.idCard"
           v-if="showBtn"
         /><input
-          :placeholder="$t('jy520')"
+          :placeholder="$t('jy561')"
           v-model="form.idCard"
+          v-if="!showBtn"
+          readonly
+        />
+      </li>
+      <li class="verli">
+        <input
+          :placeholder="$t('hj2111')"
+          v-model="form.address"
+          v-if="showBtn"
+        /><input
+          :placeholder="$t('hj2111')"
+          v-model="form.address"
           v-if="!showBtn"
           readonly
         />
@@ -127,6 +139,7 @@
         phone: "",
         name: "",
         idCard: "",
+        address: "",
         img1key: "",
         img2key: "",
         img3key: ""
@@ -220,6 +233,7 @@
         ) {
           this.form.idCard = this.$store.state.userInfo.idCard;
           this.form.name = this.$store.state.userInfo.realName;
+          this.form.address = this.$store.state.userInfo.regAddress || "";
           this.form.img1key = this.$store.state.userInfo.img1Key;
           this.form.img2key = this.$store.state.userInfo.img2Key;
           //   this.form.img3key = this.$store.state.userInfo.img3Key
@@ -265,6 +279,8 @@
         Toast(this.$t("hj207"));
       } else if (isNull(this.form.idCard) || !idCardReg(this.form.idCard)) {
         Toast(this.$t("hj208"));
+      } else if (isNull(this.form.address)) {
+        Toast('请输入' + this.$t('hj2111'));
       } else if (isNull(this.form.img1key)) {
         Toast(this.$t("jy516"));
       } else if (isNull(this.form.img2key)) {
@@ -278,6 +294,7 @@
       let opts = {
         realName: this.form.name,
         idCard: this.form.idCard,
+        address: this.form.address,
         img1key: this.form.img1key,
         img2key: this.form.img2key,
         img3key: this.form.img3key
diff --git a/src/page/user/Warehouse-detail.vue b/src/page/user/Warehouse-detail.vue
index 68a83e1..343f1de 100644
--- a/src/page/user/Warehouse-detail.vue
+++ b/src/page/user/Warehouse-detail.vue
@@ -3,33 +3,46 @@
 		<div class="trade-record-detail">
 			<div class="headf">
             <div>
-                <h2><span class="hbnh"><a class="fan" @click="$router.back()"></a></span>{{ $t('jy453') }}</h2>
+                <h2 v-if="this.$route.query.type == 'pingcang'"><span class="hbnh"><a class="fan" @click="$router.back()"></a></span>{{ $t('jy564') }}</h2>
+                <h2 v-if="this.$route.query.type == 'weituo'"><span class="hbnh"><a class="fan" @click="$router.back()"></a></span>{{ $t('jy563') }}</h2>
+                <h2 v-if="this.$route.query.type == 'chicang'"><span class="hbnh"><a class="fan" @click="$router.back()"></a></span>{{ $t('jy562') }}</h2>
             </div>
         </div>
 			<!-- 新内容 -->
 			<div class="stock">
-				<div class="stock-name PingFang-Regular-crude">{{detail.stockName}}</div>
+				<!-- <div class="stock-name PingFang-Regular-crude">{{detail.stockName}}</div>
 				<div class="stock-code PingFang-Regular-crude">({{detail.stockCode}})</div>
 				<div class="stock-order-price PingFang-Regular">{{detail.orderTotalPrice}}</div>
 				<div class="stock-price PingFang-Regular">
 					<div class="stock-price-item">{{ $t('hj85') }}: {{detail.buyOrderPrice}}</div>
 					<div class="stock-price-item">{{ $t('hj84') }}: {{detail.sellOrderPrice}}</div>
-				</div>
+				</div> -->
 				<div class="stock-jywc">
-					<img v-if="detail.allProfitAndLose > 0" style="width: 60px;" src="@/assets/img/jywc.png" />
-					<img v-else style="width: 60px;" src="@/assets/img/jywc-d.png" />
+					<img v-if="this.$route.query.type == 'pingcang'" style="width: 150px;" src="@/assets/img/wancheng.png" />
+					<img v-if="this.$route.query.type == 'weituo'" style="width: 150px;" src="@/assets/img/guadan.png" />
+					<img v-if="this.$route.query.type == 'chicang'" style="width: 150px;" src="@/assets/img/chicang.png" />
+
 				</div>
 			</div>
-			<div class="partition">
+			<div class="partition" style="display: none;">
 				<div class="partition-item" v-for="item in 15" :key="item">
 					<div class="partition-point"></div>
 				</div>
 			</div>
-			<div class="detail-con PingFang-Regular-crude">
+			<div class="detail-con">
 				<div class="detail-item flex col-center row-between page-warper">
-					<div class="name">{{ $t('jy24') }}</div>
-					<div class="value">{{detail.buyOrderTime}}</div>
+					<div class="name">{{ $t('jy161') }}</div>
+					<div class="value">
+						<span class="sz" v-show="(detail.stockGid.indexOf('sz')>=0)">{{ $t('jy83') }}</span>
+                            <span class="sh"  v-show="(detail.stockGid.indexOf('sh')>=0)">{{ $t('jy84') }}</span>
+                            <span class="bj"  v-show="(detail.stockGid.indexOf('bj')>=0)">{{ $t('jy85') }}</span>
+						{{detail.stockCode}}</div>
 				</div>
+				<div class="detail-item flex col-center row-between page-warper">
+					<div class="name">{{ $t('jy160') }}</div>
+					<div class="value">{{detail.stockName}}</div>
+				</div>
+
 				<div class="detail-item flex col-center row-between page-warper">
 					<div class="name">{{ $t('jy19') }}</div>
 					<div class="value">{{detail.buyOrderPrice}}</div>
@@ -46,11 +59,7 @@
 					<div class="name">{{ $t('jy450') }}</div>
 					<div class="value">{{detail.orderNum}}</div>
 				</div>
-				<div class="detail-item flex col-center row-between page-warper">
-					<div class="name">{{ $t('jy449') }}</div>
-					<div class="value">{{detail.sellOrderTime}}</div>
-				</div>
-				<div class="detail-item flex col-center row-between page-warper">
+				<div class="detail-item flex col-center row-between page-warper" v-if="this.$route.query.type == 'pingcang' ">
 					<div class="name">{{ $t('jy25') }}</div>
 					<div class="value">{{detail.sellOrderPrice}}</div>
 				</div>
@@ -62,13 +71,25 @@
 					<div class="name">{{ $t('jy16') }}</div>
 					<div class="value">{{detail.orderSpread}}</div>
 				</div>
-				<div class="detail-item flex col-center row-between page-warper">
+				<div class="detail-item flex col-center row-between page-warper" v-if="this.$route.query.type == 'pingcang'">
 					<div class="name">{{ $t('jy448') }}</div>
 					<div class="value">{{detail.profitAndLose}}</div>
 				</div>
-				<div class="detail-item flex col-center row-between page-warper">
+				<div class="detail-item flex col-center row-between page-warper" v-if="this.$route.query.type !== 'weituo'">
 					<div class="name">{{ $t('jy12') }}</div>
-					<div class="value" style="color: #098C26;">{{detail.allProfitAndLose}}</div>
+					<div class="value" :class="{'profit-red': parseFloat(detail.allProfitAndLose) > 0, 'profit-green': parseFloat(detail.allProfitAndLose) < 0}">{{detail.allProfitAndLose}}</div>
+				</div>
+				<div class="detail-item flex col-center row-between page-warper" v-if="this.$route.query.type == 'chicang'">
+					<div class="name">{{ $t('jy565') }}</div>
+					<div class="value" :class="{'profit-red': parseFloat(detail.allProfitAndLoseStr) > 0, 'profit-green': parseFloat(detail.allProfitAndLoseStr) < 0}">{{detail.allProfitAndLoseStr}}</div>
+				</div>
+				<div class="detail-item flex col-center row-between page-warper">
+					<div class="name">{{ $t('jy24') }}</div>
+					<div class="value">{{detail.buyOrderTime}}</div>
+				</div>
+				<div class="detail-item flex col-center row-between page-warper" v-if="this.$route.query.type == 'pingcang' ">
+					<div class="name">{{ $t('jy449') }}</div>
+					<div class="value">{{detail.sellOrderTime}}</div>
 				</div>
 			</div>
 		</div>
@@ -81,10 +102,13 @@
 	export default {
 		data() {
 			return {
-				detail: {}
+				detail: {},
+				fromType: '' // 接收来源类型:chicang-持仓, pingcang-平仓, weituo-委托
 			}
 		},
 		mounted() {
+			// 接收来源类型参数
+			this.fromType = this.$route.query.type || '';
 			this.getDetail()
 		},
 		methods: {
@@ -103,6 +127,34 @@
 </script>
 
 <style lang="less" scoped>
+.sz {
+	color: #fff;
+	padding: 3px;
+	background: #3b4fde;
+}
+.bj {
+	color: #fff;
+	padding: 3px;
+	background: #ea6248;
+}
+
+.sh {
+	color: #fff;
+    padding: 3px;
+	background: #aa3bde;
+}
+
+.shbg {
+	color: #aa3bde;
+	padding: 3px;
+	background: rgba(170, 59, 222, .1);
+}
+
+.bjbg {
+	padding: 3px;
+	color: #ea6248;
+	background: rgba(234, 98, 72, .1);
+}
 .partition{
 	width: 100%;
 	height: 20rpx;
@@ -206,8 +258,8 @@
 			}
 			.stock-jywc{
 				position: absolute;
-				right: 50px;
-				top: 50px;
+				right: 142px;
+				top: 130px;
 				color: #11183C;
 			}
 			
@@ -250,17 +302,34 @@
 			}
 		}
 		.detail-con{
-			padding: 20px;
+			background-color: #fff;
+			border-radius: 12px;
+			overflow: hidden;
+			margin: 16px;
 			.detail-item{
-				padding-top: 10px;
-				padding-bottom: 10px;
+				display: flex;
+				align-items: center;
+				justify-content: space-between;
+				padding: 20px 16px;
+				border-bottom: 1px solid #E5E5E5;
 				.name{
-					font-size: 14px;
-					color: #11183C;
+					font-size: 18px;
+					color: #999999;
+					font-weight: 400;
 				}
 				.value{
-					font-size: 14px;
+					font-size: 18px;
 					color: #11183C;
+					font-weight: 500;
+					&.profit-red{
+						color: #F11614;
+					}
+					&.profit-green{
+						color: #09A028;
+					}
+				}
+				&:last-child{
+					border-bottom: none;
 				}
 			}
 		}
diff --git a/src/page/user/Warehouse.vue b/src/page/user/Warehouse.vue
index 15616ba..654c88a 100644
--- a/src/page/user/Warehouse.vue
+++ b/src/page/user/Warehouse.vue
@@ -8,7 +8,7 @@
             <div class="sert">
                 <span v-for="(item, index) in chicangList" :key="index" @click="chicangidx = index"
                     :class="chicangidx == index ? 'sdpl' : ''">{{ item.name }}</span>
-                <a :style="{ left: getIndicatorLeft() + 'rem' }"></a>
+                <a :style="{ left: getIndicatorLeft() }"></a>
             </div>
             <div class="bnm"></div>
         </div>
@@ -17,7 +17,7 @@
         <van-list v-model="loading" :finished="finished" :finished-text="$t('hj43')"
                 v-show="chicangidx === 0" @load="onLoad" :immediate-check="immediate">
             <!-- <div class="cichang" v-for="(item,index) in tabsPositionNumArr" :key="item.buyOrderId"> -->
-			<div class="cichang" v-for="(item, key) in tabsPositionObj" :key="item.buyOrderId">
+			<div class="cichang" v-for="(item, key) in tabsPositionObj" :key="item.buyOrderId" @click="goDetail(item)">
                 <div class="dingbu">
                     <div class="dl">
                         <h6>{{ item.stockName ? item.stockName : item.indexName }}</h6>
@@ -31,7 +31,7 @@
                   <div class="button-container">
                     <!-- <div class="dr" style="margin-right: 16px" v-if="chicangidx == 0" @click="goBuyDetail(item)">买入</div>
                     <div class="dr-blue" style="margin-right: 16px"  v-if="chicangidx == 0" @click="getpingcangbf(item.positionSn,item.orderNum)"> 部分平仓 </div> -->
-					<div class="dr-blue" style="margin-right: 16px"  v-if="chicangidx == 0" @click="getpingcang(item.positionSn)"> {{ $t('hj121') }} </div>
+					<div class="dr-blue" style="margin-right: 16px"  v-if="chicangidx == 0" @click.stop="getpingcang(item.positionSn)"> {{ $t('hj121') }} </div>
 
                   </div>
                          </div>
@@ -58,7 +58,7 @@
                     <!-- <p v-if="chicangidx == 1"><span>{{ $t('jy19') }}</span><a class="red">5.49/{{ $t('jy96') }}</a></p>
                     <p v-if="chicangidx == 1"><span>{{ $t('jy15') }}</span><a class="red">49959.00</a></p> -->
 					<!-- <p><span>{{ $t('jy531') }}</span><a class="red">{{item.orderLever}}</a></p> -->
-					<p><span>{{ $t('jy37') }}</span><a class="red">{{item.buyAmtAutual}}</a></p>
+					<!-- <p><span>{{ $t('jy37') }}</span><a class="red">{{item.buyAmtAutual}}</a></p> -->
                 </div>
             </div>
         </van-list>
@@ -99,7 +99,7 @@
                     <p><span>{{ $t('jy533') }}</span><a class="red">{{item.orderFee}}</a></p>
                     <p><span>{{ $t('jy17') }}</span><a class="red">{{item.orderTotalPrice}}</a></p>
 					<p><span>{{ $t('jy153') }}</span><a class="red">{{item.orderSpread}}</a></p>
-                    <p v-if="chicangidx == 1"><span>{{ $t('jy15') }}</span><a class="red">{{item.orderStayFee}}</a></p>
+                    <!-- <p v-if="chicangidx == 1"><span>{{ $t('jy15') }}</span><a class="red">{{item.orderStayFee}}</a></p> -->
                 </div>
             </div>
         </van-list>
@@ -137,7 +137,7 @@
                     <p><span>{{ $t('jy19') }}</span><a class="red">{{item.buyOrderPrice}}/{{ $t('jy96') }}</a></p>
 					<p v-if="chicangidx == 1"><span>{{ $t('jy25') }}</span><a class="red">{{item.sellOrderPrice}}/{{ $t('jy96') }}</a></p>
                     <p><span>{{ $t('jy18') }}</span><a class="red">{{item.orderNum}}</a></p>
-                    <p><span>挂单时间</span><a class="red">{{ item.buyOrderTime | gettime }}</a></p>
+                    <p><span>{{ $t('jy521') }}</span><a class="red">{{ item.buyOrderTime | gettime }}</a></p>
                     <p><span>{{ $t('jy17') }}</span><a class="red">{{item.orderTotalPrice}}</a></p>
 					<!-- <p><span>{{ $t('jy153') }}</span><a class="red">{{item.orderSpread}}</a></p> -->
                     <p v-if="chicangidx == 1"><span>{{ $t('jy15') }}</span><a class="red">{{item.orderStayFee}}</a></p>
@@ -170,7 +170,7 @@
                     name: this.$t('jy410')
                 },
                 {
-                    name: '我的委托'
+                    name: this.$t('jy520')
                 }
             ],
             chicangidx: 0,
@@ -206,19 +206,22 @@
     methods: {
         // 计算滑动指示器的位置
         getIndicatorLeft() {
-            const totalWidth = 5.34 // .sert 的总宽度(rem)
             const tabCount = this.chicangList.length
-            const indicatorWidth = 0.53 // 指示器宽度(rem)
             
-            // 计算每个标签的中心位置
-            const tabWidth = totalWidth / tabCount
-            const centerPosition = (this.chicangidx + 0.7) * tabWidth
+            // 每个标签占的百分比
+            const tabWidthPercent = 100 / tabCount
             
-            // 减去指示器宽度的一半,使其居中
-            return centerPosition - indicatorWidth / 2
+            // 当前选中标签的中心位置(百分比)
+            const centerPositionPercent = (this.chicangidx + 0.5) * tabWidthPercent
+            
+            // 返回百分比,指示器会自动居中
+            return centerPositionPercent + '%'
         },
         goDetail(item) {
-            this.$router.push(`/WarehouseDetail?positionSn=${item.positionSn}`)
+            // 根据当前的tab索引传递不同的类型值
+            // chicangidx: 0-持仓, 1-平仓, 2-委托
+            const type = this.chicangidx === 1 ? 'pingcang' : this.chicangidx === 2 ? 'weituo' : 'chicang';
+            this.$router.push(`/WarehouseDetail?positionSn=${item.positionSn}&type=${type}`)
         },
         onLoad() {
       //持仓
@@ -308,20 +311,20 @@
 	    // 如果 chicangidx 为 0,表示是沪深京市场(可能是股票市场的不同板块)
 	    if (this.chicangidx == 0) {
 	        // 先弹出一个选择平仓数量的输入框
-	        this.$prompt('平仓数量', '部分平仓', {
+	        this.$prompt(this.$t('jy522'), this.$t('jy523'), {
 	            confirmButtonText: this.$t('hj161'),
 	            cancelButtonText: this.$t('hj106'),
 	            inputPattern: /^[0-9]*[1-9][0-9]*$/, // 限制输入为正整数
-	            inputErrorMessage: '格式错误' // 输入不合法时的错误提示
+	            inputErrorMessage: this.$t('jy524') // 输入不合法时的错误提示
 	        }).then(async ({ value }) => {
 	            const selectedQuantity = Number(value);  // 用户选择的平仓数量
 	            
 	            if (selectedQuantity <= 0) {
-	                Toast('格式错误');  // 如果输入无效数量,提示错误
+	                Toast(this.$t('jy524'));  // 如果输入无效数量,提示错误
 	                return;
 	            }
 				if(selectedQuantity > orderNum){
-					Toast('超过最大数量'+orderNum);  // 如果输入无效数量,提示错误
+					Toast(this.$t('jy525') + orderNum);  // 如果输入无效数量,提示错误
 					return;
 				}
 	            // 弹出确认框,询问用户是否确认平仓
@@ -580,14 +583,17 @@
     border-radius: 0.4rem 0.4rem 0 0;
     margin-top: -0.4rem;
     background: #fff;
+    padding: 0 0.4rem;
+    box-sizing: border-box;
 
     .sert {
-        width: 5.34rem;
+        width: 100%;
         margin: 0 auto;
         display: flex;
         justify-content: space-between;
         position: relative;
         height: 1.07rem;
+        box-sizing: border-box;
 
         span {
             text-align: center;
@@ -595,6 +601,11 @@
             font-size: .4rem;
             font-weight: 550;
             line-height: 1.07rem;
+            flex: 1;
+            white-space: nowrap;
+            overflow: hidden;
+            text-overflow: ellipsis;
+            min-width: 0;
         }
 
         .sdpl {
@@ -608,7 +619,7 @@
             border-radius: 0.05rem;
             position: absolute;
             bottom: 0;
-            margin-left: -0.266rem;
+            transform: translateX(-50%);
             transition: all .5s;
         }
     }
diff --git a/src/page/user/agreement.vue b/src/page/user/agreement.vue
index c31a494..dc6d02d 100644
--- a/src/page/user/agreement.vue
+++ b/src/page/user/agreement.vue
@@ -5,57 +5,140 @@
         <router-link to="" slot="left">
           <mt-button @click="goBack" icon="back"></mt-button>
         </router-link>
-        <!-- <mt-button icon="more" slot="right"></mt-button> -->
       </mt-header>
     </div>
-    <div style="margin:12px 20px;">
-      <div class="risk_text">
-        <p v-for="item in siteInfo.tradeAgreeText.split('。')" :key="item">{{item}}。</p>
+    <div class="agreement-content">
+      <div v-if="loading" class="loading-container">
+        <div class="loading-spinner"></div>
+        <p>加载中...</p>
       </div>
-
+      <div v-else-if="error" class="error-container">
+        <p>{{ error }}</p>
+        <button @click="loadPdf" class="retry-btn">重试</button>
+      </div>
+      <div v-else class="pdf-wrapper">
+        <ImageViewer :imageUrls="imageUrls" v-if="imageUrls && imageUrls.length > 0" />
+      </div>
     </div>
   </div>
-
 </template>
 <script>
+import * as api from '@/axios/api'
+import ImageViewer from '@/components/ImageViewer.vue'
+
 export default {
+  components: {
+    ImageViewer
+  },
   data () {
-    return {siteInfo: {}}
+    return {
+      loading: true,
+      error: null,
+      imageUrls: []
+    }
   },
   mounted () {
-    this.getInfoSite()
+    this.loadPdf()
   },
   methods: {
     goBack () {
       this.$router.back(-1)
     },
-    async getInfoSite () {
-        // 获取网站信息
-        let result = await api.getInfoSite()
+    async loadPdf () {
+      this.loading = true
+      this.error = null
+      try {
+        const result = await api.viewAgreementPdf()
         if (result.status === 0) {
-          this.siteInfo = result.data
+          // result.data 现在是图片数组
+          if (Array.isArray(result.data) && result.data.length > 0) {
+            const APIUrl = require('@/axios/api.url').default
+            this.imageUrls = result.data.map(url => {
+              if (!url.startsWith('http')) {
+                return APIUrl.baseURL + (url.startsWith('/') ? url : '/' + url)
+              }
+              return url
+            })
+            this.loading = false
+          } else {
+            this.error = '未返回图片数据'
+            this.loading = false
+          }
         } else {
-          this.$message.error(result.msg)
+          this.error = result.msg || '加载合同失败'
+          this.loading = false
         }
+      } catch (e) {
+        console.error('加载PDF失败:', e)
+        this.error = e.message || '加载失败,请稍后重试'
+        this.loading = false
+      }
     }
   }
 }
 </script>
 <style lang="css" scoped>
-  h1 {
-    font-size: 0.25rem;
-    text-align: center;
-  }
+.wrapper {
+  height: 100vh;
+  display: flex;
+  flex-direction: column;
+  background: #f5f5f5;
+}
 
-  h4 {
-    font-size: 13px;
-    line-height: 25px;
-    margin: 25px 0;
-  }
+.header {
+  flex-shrink: 0;
+}
 
-  p {
-    font-size: 12px;
-    line-height: 25px;
-    text-indent: 2em;
-  }
+.agreement-content {
+  flex: 1;
+  overflow: hidden;
+  position: relative;
+}
+
+.loading-container,
+.error-container {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  height: 100%;
+  color: #666;
+}
+
+.loading-spinner {
+  width: 40px;
+  height: 40px;
+  border: 4px solid #f3f3f3;
+  border-top: 4px solid #f11514;
+  border-radius: 50%;
+  animation: spin 1s linear infinite;
+  margin-bottom: 15px;
+}
+
+@keyframes spin {
+  0% { transform: rotate(0deg); }
+  100% { transform: rotate(360deg); }
+}
+
+.error-container {
+  color: #f56c6c;
+  padding: 20px;
+  text-align: center;
+}
+
+.retry-btn {
+  margin-top: 15px;
+  padding: 10px 20px;
+  background: linear-gradient(-55deg, rgb(241, 22, 20), rgb(240, 40, 37));
+  color: #fff;
+  border: none;
+  border-radius: 5px;
+  font-size: 14px;
+  cursor: pointer;
+}
+
+.pdf-wrapper {
+  height: 100%;
+  width: 100%;
+}
 </style>
diff --git a/src/router/index.js b/src/router/index.js
index 5605a97..daca248 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -269,7 +269,7 @@
       name: 'about',
       meta: {
         title: '详情',
-        requireAuth: true,
+        requireAuth: false,
         hasHeader: false,
         show: true,
         index: 1
@@ -625,7 +625,7 @@
       name: 'aggre',
       meta: {
         title: '合作协议',
-        requireAuth: true,
+        requireAuth: false,
         index: 30
       },
       component: Aggre
@@ -709,7 +709,7 @@
       name: 'agree',
       meta: {
         title: '注册协议',
-        requireAuth: true,
+        requireAuth: false,
         index: 38
       },
       component: Agree
@@ -718,7 +718,7 @@
       name: 'trade',
       meta: {
         title: '交易⻛险揭示书',
-        requireAuth: true,
+        requireAuth: false,
         index: 39
       },
       component: Trage

--
Gitblit v1.9.3