Sfoglia il codice sorgente

项目静态页面

jianggs 5 giorni fa
parent
commit
52771c7e3c

+ 2 - 1
web/.gitignore

@@ -1,7 +1,8 @@
 .DS_Store
 node_modules/
 node_modules_qt/
-dist/
+dist
+dist.zip
 npm-debug.log*
 yarn-debug.log*
 yarn-error.log*

+ 1 - 6
web/package.json

@@ -37,12 +37,10 @@
     "url": "http://192.168.254.128/YUFP/xy-web/issues"
   },
   "dependencies": {
-    "@babel/polyfill": "^7.6.0",
     "@popperjs/core": "^2.11.8",
     "clipboard": "2.0.4",
     "codemirror": "5.45.0",
     "crypto-js": "^4.1.1",
-    "date-range-picker": "^0.3.5",
     "driver.js": "0.9.5",
     "el-table-infinite-scroll": "^2.0.0",
     "file-saver": "2.0.1",
@@ -80,9 +78,7 @@
     "@vue/cli-plugin-eslint": "5.0.8",
     "@vue/cli-plugin-unit-jest": "5.0.8",
     "@vue/cli-service": "5.0.8",
-    "@vue/test-utils": "2.4.6",
     "@wchbrad/vue-easy-tree": "1.0.12",
-    "babel-core": "7.0.0-bridge.0",
     "babel-eslint": "10.0.1",
     "babel-jest": "29.7.0",
     "browserslist": "^4.23.0",
@@ -92,7 +88,7 @@
     "connect": "3.7.0",
     "eslint": "^8.57.0",
     "eslint-plugin-html": "^7.1.0",
-    "eslint-plugin-vue": "^9.26.0",
+    "eslint-plugin-vue": "^8.0.0",
     "glob": "^10.4.1",
     "gulp": "4.0.2",
     "gulp-autoprefixer": "^8.0.0",
@@ -112,7 +108,6 @@
     "runjs": "^4.4.1",
     "sass": "^1.62.1",
     "sass-loader": "^13.2.2",
-    "script-ext-html-webpack-plugin": "2.1.5",
     "script-loader": "0.7.2",
     "serve-static": "^1.15.0",
     "svg-sprite-loader": "6.0.11",

+ 1 - 1
web/public/index.html

@@ -53,7 +53,7 @@
     <script src="<%= BASE_URL %>static/libs/x6-plugin-selection/main/index.js"></script> -->
     <!-- <script src="<%= BASE_URL %>static/libs/g2plot_2.4.23.min.js"></script>
     <script src="<%= BASE_URL %>static/libs/g2_4.2.7.min.js"></script> -->
-    <!-- <script src="<%= BASE_URL %>static/echarts/echarts.5.4.1.min.js"></script> -->
+    <script src="<%= BASE_URL %>static/echarts/echarts.5.4.1.min.js"></script>
     <!-- <script src="<%= BASE_URL %>static/libs/jspdf.debug.js"></script> -->
     <!-- <script src="<%= BASE_URL %>static/libs/element-ui-patch@1.2/index.js"></script> -->
     <!-- <script src="<%= BASE_URL %>static/libs/popperjs@2.11.8/index.js"></script> -->

+ 14 - 0
web/src/router/constant-routes.js

@@ -127,6 +127,20 @@ let constantRoutes = [
         meta: { title: '标签列表', noCache: false },
         hidden: true,
       },
+      {
+        path: "/tag-system-edit",
+        component: () => import("@/views/content/aiTagging/taggingSystemManage/TagSystemEdit.vue"),
+        name: "tag-system-edit",
+        meta: { title: '标签列表', noCache: false },
+        hidden: true,
+      },
+      {
+        path: '/taggingDetail',
+        component: () => import('@/views/content/aiTagging/taggingDetail/index'),
+        name: 'taggingDetail',
+        meta: { title: '打标详情', noCache: true },
+        hidden: true
+      }
     ],
   },
 

+ 612 - 0
web/src/views/content/aiTagging/appAuthManage/index.vue

@@ -0,0 +1,612 @@
+<template>
+  <div class="app-auth-manage">
+    <!-- 搜索栏 -->
+    <div class="search-bar">
+      <el-form :inline="true" :model="searchForm" class="demo-form-inline">
+        <el-form-item label="应用名称:">
+          <el-input v-model="searchForm.appName" placeholder="请输入" style="width: 200px;"></el-input>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="handleSearch">查询</el-button>
+        </el-form-item>
+        <el-form-item>
+          <el-button @click="handleReset">重置</el-button>
+        </el-form-item>
+      </el-form>
+    </div>
+    
+    <!-- 应用列表表格和分页容器 -->
+    <div class="table-container">
+      <!-- 表格头部操作区 -->
+      <div class="table-header">
+        <el-button type="primary" @click="handleCreate">新建</el-button>
+      </div>
+      <!-- 应用列表表格 -->
+      <el-table :data="appList" style="width: 100%" border stripe>
+        <el-table-column prop="appName" label="应用名称" min-width="150"></el-table-column>
+        <el-table-column label="应用ID" min-width="280">
+          <template slot-scope="scope">
+            <div class="app-id-container">
+              <span class="app-id">{{ scope.row.appId }}</span>
+              <el-button type="text" size="mini" @click="handleCopy(scope.row.appId)" class="copy-btn">
+                <i class="el-icon-document-copy"></i>
+              </el-button>
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column label="应用密钥" min-width="200">
+          <template slot-scope="scope">
+            <span>************************</span>
+          </template>
+        </el-table-column>
+        <el-table-column prop="expiryTime" label="有效时间" min-width="180">
+          <template slot-scope="scope">
+            <span>{{ scope.row.expiryTime || '--' }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="操作" min-width="160">
+          <template slot-scope="scope">
+            <el-button type="text" @click="handleResetSecret(scope.row)" class="action-btn">重置密钥</el-button>
+            <el-button type="text" @click="handleExtend(scope.row)" class="action-btn">延期</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      
+      <!-- 分页 -->
+      <div class="pagination">
+        <el-pagination
+          @size-change="handleSizeChange"
+          @current-change="handleCurrentChange"
+          :current-page="currentPage"
+          :page-sizes="[10, 20, 50, 100]"
+          :page-size="pageSize"
+          layout="total,sizes, prev, pager, next, jumper"
+          :total="totalCount"
+        >
+        </el-pagination>
+      </div>
+    </div>
+    
+    <!-- 新建应用弹框 -->
+    <el-dialog
+      title="新增应用"
+      :visible.sync="dialogVisible"
+      width="300px"
+      :close-on-click-modal="false"
+    >
+      <el-form :model="newAppForm" label-width="100px">
+        <el-form-item label="应用名称:">
+          <el-input v-model="newAppForm.appName" placeholder="请输入" style="width: 250px;"></el-input>
+        </el-form-item>
+      </el-form>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="dialogVisible = false">取消</el-button>
+        <el-button type="primary" @click="handleCreateApp">创建并生成密钥</el-button>
+      </span>
+    </el-dialog>
+    
+    <!-- 重置密钥确认弹框 -->
+    <el-dialog
+      title="提示"
+      :visible.sync="resetConfirmVisible"
+      width="400px"
+      :close-on-click-modal="false"
+    >
+      <div class="reset-confirm">
+        <div class="confirm-icon">
+          <i class="el-icon-info"></i>
+        </div>
+        <div class="confirm-content">
+          <p>您确定要重置密钥吗?</p>
+          <p class="confirm-tip">重置后,原密钥将会失效,请保存好新密钥并及时更换</p>
+        </div>
+      </div>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="resetConfirmVisible = false">取消</el-button>
+        <el-button type="primary" @click="handleConfirmReset">确定</el-button>
+      </span>
+    </el-dialog>
+    
+    <!-- 延期确认弹框 -->
+    <el-dialog
+      title="密钥延期确认"
+      :visible.sync="extendConfirmVisible"
+      width="400px"
+      :close-on-click-modal="false"
+    >
+      <div class="extend-confirm">
+        <div class="confirm-icon">
+          <i class="el-icon-info"></i>
+        </div>
+        <div class="confirm-content">
+          <p>密钥延期为敏感操作,确定要将该密钥延期 180 天?</p>
+        </div>
+      </div>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="extendConfirmVisible = false">取消</el-button>
+        <el-button type="primary" @click="handleConfirmExtend">确定</el-button>
+      </span>
+    </el-dialog>
+    
+    <!-- 无需延期提示 -->
+    <el-dialog
+      title="提示"
+      :visible.sync="noExtendVisible"
+      width="400px"
+      :close-on-click-modal="false"
+      :show-close="false"
+    >
+      <div class="no-extend">
+        <div class="warning-icon">
+          <i class="el-icon-warning"></i>
+        </div>
+        <div class="warning-content">
+          <p>该密钥尚未过期,无需延期</p>
+        </div>
+      </div>
+      <span slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="noExtendVisible = false">确定</el-button>
+      </span>
+    </el-dialog>
+    
+    <!-- 密钥生成成功弹框 -->
+    <el-dialog
+      title="密钥已生成!"
+      :visible.sync="secretDialogVisible"
+      width="400px"
+      :close-on-click-modal="false"
+      :show-close="false"
+    >
+      <div class="secret-success">
+        <div class="success-icon">
+          <i class="el-icon-check"></i>
+        </div>
+        <div class="secret-info">
+          <p>应用密钥:{{ generatedSecret }}</p>
+        </div>
+        <el-button type="primary" @click="handleCopySecret" style="margin-top: 20px;">复制密钥</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'AppAuthManage',
+  data() {
+    return {
+      // 搜索表单
+      searchForm: {
+        appName: ''
+      },
+      // 新建应用表单
+      newAppForm: {
+        appName: ''
+      },
+      // 应用列表数据
+      appList: [
+        {
+          id: 1,
+          appName: '应用A',
+          appId: 'YY20260203001098791241241',
+          appSecret: 'secret1234567890',
+          expiryTime: ''
+        },
+        {
+          id: 2,
+          appName: '应用B',
+          appId: 'YY2026020300123124441241',
+          appSecret: 'secret1234567890',
+          expiryTime: ''
+        },
+        {
+          id: 3,
+          appName: '应用C',
+          appId: 'YY20260203001321321321567',
+          appSecret: 'secret1234567890',
+          expiryTime: ''
+        },
+        {
+          id: 4,
+          appName: '应用D',
+          appId: 'YY2026020300109879124167',
+          appSecret: 'secret1234567890',
+          expiryTime: ''
+        },
+        {
+          id: 5,
+          appName: '应用E',
+          appId: 'YY2026020300109879890786',
+          appSecret: 'secret1234567890',
+          expiryTime: ''
+        },
+        {
+          id: 6,
+          appName: '应用F',
+          appId: 'YY2026020300105567876671',
+          appSecret: 'secret1234567890',
+          expiryTime: ''
+        },
+        {
+          id: 7,
+          appName: '应用G',
+          appId: 'YY20260203001098791242241',
+          appSecret: 'secret1234567890',
+          expiryTime: ''
+        },
+        {
+          id: 8,
+          appName: '应用H',
+          appId: 'YY20260203001098791241232',
+          appSecret: 'secret1234567890',
+          expiryTime: ''
+        },
+        {
+          id: 9,
+          appName: '应用I',
+          appId: 'YY20260203001098791245545',
+          appSecret: 'secret1234567890',
+          expiryTime: ''
+        },
+        {
+          id: 10,
+          appName: '应用J',
+          appId: 'YY20260203001098791241980',
+          appSecret: 'secret1234567890',
+          expiryTime: ''
+        }
+      ],
+      // 分页数据
+      currentPage: 1,
+      pageSize: 10,
+      totalCount: 120,
+      // 弹框状态
+      dialogVisible: false,
+      secretDialogVisible: false,
+      resetConfirmVisible: false,
+      extendConfirmVisible: false,
+      noExtendVisible: false,
+      // 生成的密钥
+      generatedSecret: '',
+      // 当前操作的应用
+      currentApp: null
+    }
+  },
+  methods: {
+    // 查询
+    handleSearch() {
+      console.log('查询应用:', this.searchForm.appName);
+      // 这里可以添加查询逻辑
+    },
+    
+    // 重置
+    handleReset() {
+      this.searchForm.appName = '';
+      console.log('重置搜索条件');
+    },
+    
+    // 新建
+    handleCreate() {
+      // 重置表单
+      this.newAppForm = {
+        appName: ''
+      };
+      // 打开新建应用弹框
+      this.dialogVisible = true;
+    },
+    
+    // 创建应用并生成密钥
+    handleCreateApp() {
+      if (!this.newAppForm.appName) {
+        this.$message.warning('请输入应用名称');
+        return;
+      }
+      
+      // 生成随机密钥
+      this.generatedSecret = this.generateRandomSecret();
+      
+      // 模拟创建应用
+      console.log('创建应用:', this.newAppForm.appName);
+      console.log('生成密钥:', this.generatedSecret);
+      
+      // 关闭新建应用弹框
+      this.dialogVisible = false;
+      
+      // 打开密钥生成成功弹框
+      this.secretDialogVisible = true;
+    },
+    
+    // 生成随机密钥
+    generateRandomSecret() {
+      const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
+      let secret = '';
+      for (let i = 0; i < 20; i++) {
+        secret += chars.charAt(Math.floor(Math.random() * chars.length));
+      }
+      return secret;
+    },
+    
+    // 复制生成的密钥
+    handleCopySecret() {
+      // 模拟复制到剪贴板
+      console.log('复制密钥:', this.generatedSecret);
+      this.$message.success('复制成功');
+      // 关闭密钥生成成功弹框
+      this.secretDialogVisible = false;
+    },
+    
+    // 复制应用ID
+    handleCopy(appId) {
+      console.log('复制应用ID:', appId);
+      // 这里可以添加复制到剪贴板的逻辑
+      this.$message.success('复制成功');
+    },
+    
+    // 重置密钥
+    handleResetSecret(row) {
+      // 保存当前操作的应用
+      this.currentApp = row;
+      // 打开重置密钥确认弹框
+      this.resetConfirmVisible = true;
+    },
+    
+    // 确认重置密钥
+    handleConfirmReset() {
+      if (!this.currentApp) return;
+      
+      // 生成随机密钥
+      this.generatedSecret = this.generateRandomSecret();
+      
+      // 模拟重置密钥
+      console.log('重置密钥:', this.currentApp.appName);
+      console.log('生成新密钥:', this.generatedSecret);
+      
+      // 关闭确认弹框
+      this.resetConfirmVisible = false;
+      
+      // 打开密钥生成成功弹框
+      this.secretDialogVisible = true;
+    },
+    
+    // 延期
+    handleExtend(row) {
+      // 保存当前操作的应用
+      this.currentApp = row;
+      
+      // 模拟检查密钥是否过期
+      // 这里可以根据实际的expiryTime来判断
+      // 为了演示,我们假设前5个应用需要延期,后5个不需要
+      const needExtend = row.id <= 5;
+      
+      if (needExtend) {
+        // 显示延期确认弹框
+        this.extendConfirmVisible = true;
+      } else {
+        // 显示无需延期提示
+        this.noExtendVisible = true;
+      }
+    },
+    
+    // 确认延期
+    handleConfirmExtend() {
+      if (!this.currentApp) return;
+      
+      // 模拟延期操作
+      console.log('延期:', this.currentApp.appName);
+      console.log('延期180天');
+      
+      // 关闭确认弹框
+      this.extendConfirmVisible = false;
+      
+      // 显示成功提示
+      this.$message.success('延期成功');
+    },
+    
+    // 分页大小变化
+    handleSizeChange(val) {
+      console.log(`每页 ${val} 条`);
+      this.pageSize = val;
+      // 这里可以添加分页逻辑
+    },
+    
+    // 当前页码变化
+    handleCurrentChange(val) {
+      console.log(`当前页: ${val}`);
+      this.currentPage = val;
+      // 这里可以添加分页逻辑
+    }
+  }
+}
+</script>
+
+<style scoped>
+.app-auth-manage {
+  padding: 0;
+  background-color: transparent;
+  min-height: 100vh;
+}
+
+/* 搜索栏 */
+.search-bar {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  background: #fff;
+  padding: 20px;
+  border-radius: 8px;
+  margin-bottom: 20px;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.08);
+}
+
+/* 表格和分页容器 */
+.table-container {
+  padding: 15px;
+  background: #fff;
+  border-radius: 8px;
+  overflow: hidden;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.08);
+}
+
+/* 表格头部操作区 */
+.table-header {
+  display: flex;
+  justify-content: flex-start;
+  align-items: center;
+  margin-bottom: 10px;
+
+}
+
+/* 表格样式 */
+:deep(.el-table) {
+  border: none;
+  border-top: 1px solid #ebeef5;
+  border-bottom: 1px solid #ebeef5;
+}
+
+/* 应用ID容器 */
+.app-id-container {
+  display: flex;
+  align-items: center;
+  gap: 8px;
+}
+
+/* 应用ID文本 */
+.app-id {
+  flex: 1;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
+/* 复制按钮 */
+.copy-btn {
+  color: #409EFF;
+  font-size: 14px;
+  padding: 0 4px;
+}
+
+.copy-btn:hover {
+  color: #66B1FF;
+}
+
+/* 操作按钮 */
+.action-btn {
+  color: #409EFF;
+  font-size: 14px;
+  padding: 0 8px;
+}
+
+.action-btn:hover {
+  color: #66B1FF;
+}
+
+/* 有效时间为空时的样式 */
+:deep(.el-table__row .el-table__cell) {
+  padding: 12px;
+}
+
+/* 分页 */
+.pagination {
+  display: flex;
+  justify-content: flex-end;
+  align-items: center;
+  padding: 0 20px;
+  border-top: 1px solid #ebeef5;
+}
+
+/* 重置密钥确认弹框样式 */
+.reset-confirm {
+  display: flex;
+  padding: 20px 0;
+}
+
+.confirm-icon {
+  color: #E6A23C;
+  font-size: 24px;
+  margin-right: 16px;
+  flex-shrink: 0;
+  margin-top: 4px;
+}
+
+.confirm-content {
+  flex: 1;
+}
+
+.confirm-content p {
+  margin: 8px 0;
+  font-size: 14px;
+  color: #606266;
+}
+
+.confirm-tip {
+  font-size: 12px !important;
+  color: #909399 !important;
+  line-height: 1.5;
+}
+
+/* 延期确认弹框样式 */
+.extend-confirm {
+  display: flex;
+  padding: 20px 0;
+}
+
+/* 无需延期提示样式 */
+.no-extend {
+  display: flex;
+  padding: 20px 0;
+}
+
+.warning-icon {
+  color: #F56C6C;
+  font-size: 24px;
+  margin-right: 16px;
+  flex-shrink: 0;
+  margin-top: 4px;
+}
+
+.warning-content {
+  flex: 1;
+}
+
+.warning-content p {
+  margin: 8px 0;
+  font-size: 14px;
+  color: #606266;
+}
+
+/* 密钥生成成功弹框样式 */
+.secret-success {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  padding: 20px 0;
+}
+
+.success-icon {
+  width: 60px;
+  height: 60px;
+  border-radius: 50%;
+  background-color: #67C23A;
+  color: white;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  font-size: 32px;
+  margin-bottom: 20px;
+}
+
+.secret-info {
+  text-align: center;
+  margin-bottom: 20px;
+}
+
+.secret-info p {
+  margin: 10px 0;
+  font-size: 14px;
+  color: #606266;
+}
+
+.secret-info p span {
+  font-weight: 500;
+}
+</style>

+ 277 - 0
web/src/views/content/aiTagging/externalPage/index.vue

@@ -0,0 +1,277 @@
+<template>
+  <div class="intelligent-tagging">
+    <!-- 标题和提示 -->
+    <div class="header">
+      <h2 class="title">智能打标</h2>
+      <div class="close-btn" @click="handleClose">
+        <i class="el-icon-close"></i>
+      </div>
+    </div>
+    
+    <!-- 系统提示 -->
+    <div class="system-tip">
+      <i class="el-icon-info"></i>
+      <span>系统已自动生成标签推荐结果,请您勾选确认准确标签,针对不符合标签可提交反馈内容以优化后续推荐服务;若无适用标签,可通过手动选标完成打标操作。</span>
+    </div>
+    
+    <!-- 标签推荐列表 -->
+    <div class="tag-list">
+      <div 
+        v-for="(tag, index) in tagRecommendations" 
+        :key="index"
+        class="tag-item"
+        :class="{ 'selected': tag.selected }"
+        @click="handleTagSelect(index)"
+      >
+        <!-- 标签路径 -->
+        <div class="tag-path">
+          <span>{{ tag.path }}</span>
+          <i v-if="tag.selected" class="el-icon-check selected-icon"></i>
+        </div>
+        
+        <!-- 推荐依据 -->
+        <div class="recommend-basis">
+          <div class="basis-label">推荐依据:</div>
+          <div class="basis-content">{{ tag.basis }}</div>
+        </div>
+        
+        <!-- 不准确反馈 -->
+        <div class="feedback">
+          <div class="feedback-label">不准确反馈:</div>
+          <el-input
+            v-model="tag.feedback"
+            type="textarea"
+            placeholder="请输入"
+            :rows="2"
+            class="feedback-input"
+          ></el-input>
+        </div>
+      </div>
+    </div>
+    
+    <!-- 操作按钮 -->
+    <div class="dialog-footer">
+      <el-button @click="handleCancel">取消</el-button>
+      <el-button type="primary" @click="handleConfirmTagging" :disabled="!hasSelectedTag">确认打标</el-button>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'IntelligentTagging',
+  props: {
+    visible: {
+      type: Boolean,
+      default: false
+    },
+    isEditMode: {
+      type: Boolean,
+      default: false
+    },
+    editData: {
+      type: Object,
+      default: () => ({})
+    }
+  },
+  data() {
+    return {
+      // 标签推荐结果
+      tagRecommendations: [
+        {
+          path: '海洋产业 / 海洋渔业 / 海洋捕捞 / 远洋捕捞',
+          basis: '文本中明确提到"主要从事远洋捕捞业务"、"拥有5艘远洋捕捞船"、"购买新的远洋捕捞设备"等关键信息,直接指向"远洋捕捞"标签。企业名称"舟山远洋渔业有限公司"也包含"远洋渔业"关键词,进一步支持此标签。',
+          feedback: '',
+          selected: true
+        },
+        {
+          path: '海洋经济 / 海洋产业 / 海洋船舶工业 / 海洋船舶制造',
+          basis: '文本中明确提到"主要从事远洋捕捞业务"、"拥有5艘远洋捕捞船"、"购买新的远洋捕捞设备"等关键信息,直接指向"远洋捕捞"标签。企业名称"舟山远洋渔业有限公司"也包含"远洋渔业"关键词,进一步支持此标签。',
+          feedback: '',
+          selected: false
+        },
+        {
+          path: '海洋经济 / 海洋产业 / 海洋船舶工业 / 海洋船舶制造',
+          basis: '文本中明确提到"主要从事远洋捕捞业务"、"拥有5艘远洋捕捞船"、"购买新的远洋捕捞设备"等关键信息,直接指向"远洋捕捞"标签。企业名称"舟山远洋渔业有限公司"也包含"远洋渔业"关键词,进一步支持此标签。',
+          feedback: '',
+          selected: false
+        }
+      ]
+    }
+  },
+  computed: {
+    // 检查是否有选中的标签
+    hasSelectedTag() {
+      return this.tagRecommendations.some(tag => tag.selected);
+    }
+  },
+  methods: {
+    // 关闭窗口
+    handleClose() {
+      this.$emit('close');
+    },
+    
+    // 取消
+    handleCancel() {
+      this.$emit('close');
+    },
+    
+    // 确认打标
+    handleConfirmTagging() {
+      if (!this.hasSelectedTag) {
+        this.$message.warning('请至少选择一个标签');
+        return;
+      }
+      
+      // 获取选中的标签
+      const selectedTags = this.tagRecommendations.filter(tag => tag.selected);
+      console.log('确认打标:', selectedTags);
+      
+      // 这里可以添加打标逻辑
+      this.$message.success('打标成功');
+      this.$emit('close');
+    },
+    
+    // 选择标签
+    handleTagSelect(index) {
+      this.tagRecommendations[index].selected = !this.tagRecommendations[index].selected;
+    }
+  }
+}
+</script>
+
+<style scoped>
+.intelligent-tagging {
+  padding: 20px;
+  max-height: 80vh;
+  overflow-y: auto;
+}
+
+.header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 20px;
+}
+
+.title {
+  font-size: 18px;
+  font-weight: 500;
+  color: #303133;
+  margin: 0;
+}
+
+.close-btn {
+  cursor: pointer;
+  font-size: 16px;
+  color: #909399;
+}
+
+.close-btn:hover {
+  color: #606266;
+}
+
+.system-tip {
+  display: flex;
+  align-items: flex-start;
+  padding: 12px 16px;
+  background-color: #ECF5FF;
+  border-radius: 4px;
+  margin-bottom: 24px;
+  border-left: 4px solid #409EFF;
+}
+
+.system-tip i {
+  color: #409EFF;
+  margin-right: 12px;
+  margin-top: 2px;
+  font-size: 16px;
+}
+
+.system-tip span {
+  flex: 1;
+  font-size: 14px;
+  color: #606266;
+  line-height: 1.5;
+}
+
+.tag-list {
+  margin-bottom: 30px;
+}
+
+.tag-item {
+  border: 1px solid #E4E7ED;
+  border-radius: 4px;
+  padding: 16px;
+  margin-bottom: 16px;
+  cursor: pointer;
+  transition: all 0.3s ease;
+}
+
+.tag-item:hover {
+  border-color: #C0C4CC;
+  box-shadow: 0 2px 4px rgba(0,0,0,0.05);
+}
+
+.tag-item.selected {
+  border-color: #67C23A;
+  background-color: #F0F9EB;
+}
+
+.tag-path {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 16px;
+  font-size: 14px;
+  font-weight: 500;
+  color: #303133;
+}
+
+.selected-icon {
+  color: #67C23A;
+  font-size: 16px;
+}
+
+.recommend-basis {
+  margin-bottom: 16px;
+}
+
+.basis-label {
+  font-size: 13px;
+  color: #909399;
+  margin-bottom: 8px;
+}
+
+.basis-content {
+  font-size: 13px;
+  color: #606266;
+  line-height: 1.5;
+  background-color: #F5F7FA;
+  padding: 10px;
+  border-radius: 4px;
+}
+
+.feedback {
+  margin-top: 12px;
+}
+
+.feedback-label {
+  font-size: 13px;
+  color: #909399;
+  margin-bottom: 8px;
+}
+
+.feedback-input {
+  width: 100%;
+}
+
+.dialog-footer {
+  display: flex;
+  justify-content: flex-end;
+  gap: 12px;
+  margin-top: 24px;
+  padding-top: 20px;
+  border-top: 1px solid #EBEEF5;
+}
+</style>

+ 359 - 0
web/src/views/content/aiTagging/taggingDetail/index.vue

@@ -0,0 +1,359 @@
+<template>
+  <div class="tagging-detail-container">
+    <!-- 顶部导航栏 -->
+    <!-- <div class="nav-bar">
+      <el-button type="primary" @click="handleBack">返回</el-button>
+      <h1>智能打标详情</h1>
+    </div> -->
+
+    <!-- 业务基本信息 -->
+    <div class="section">
+      <h2 class="section-title">业务基本信息</h2>
+      <div class="info-grid">
+        <div class="info-item">
+          <span class="label">贷款申请编号:</span>
+          <span class="value">{{ businessInfo.loanApplyNo }}</span>
+        </div>
+        <div class="info-item">
+          <span class="label">合同编号:</span>
+          <span class="value">{{ businessInfo.contractNo }}</span>
+        </div>
+        <div class="info-item">
+          <span class="label">投向:</span>
+          <span class="value">{{ businessInfo.investmentDirection }}</span>
+        </div>
+        <div class="info-item">
+          <span class="label">调查报告:</span>
+          <a href="#" class="value file-link">{{ businessInfo.reportName }}</a>
+        </div>
+        <div class="info-item full-width">
+          <span class="label">贷款用途:</span>
+          <span class="value">{{ businessInfo.loanPurpose }}</span>
+        </div>
+      </div>
+    </div>
+
+    <!-- 智能打标结果 -->
+    <div class="section">
+      <div class="section-header">
+        <h2 class="section-title">智能打标结果</h2>
+        <div class="tagging-time">打标时间:{{ taggingInfo.taggingTime }}</div>
+      </div>
+      
+      <!-- 打标结果列表 -->
+      <div class="tagging-results">
+        <div v-for="(result, index) in taggingInfo.results" :key="index" class="tagging-item">
+          <div class="tagging-header">
+            <div class="tag-path">{{ result.tagPath }}</div>
+            <div class="tag-meta">
+              <span class="labeler">标注人员:{{ result.labeler }}</span>
+              <span class="tag-time">标注时间:{{ result.tagTime }}</span>
+              <el-tag :type="result.isCorrect ? 'success' : 'danger'" size="small">
+                {{ result.isCorrect ? '正确' : '不准确' }}
+              </el-tag>
+            </div>
+          </div>
+          
+          <div class="tagging-details">
+            <div class="detail-item">
+              <span class="detail-label">打标手段:</span>
+              <input type="text" class="detail-input" :value="result.tagMethod" readonly>
+            </div>
+            <div class="detail-item">
+              <span class="detail-label">智能体:</span>
+              <input type="text" class="detail-input" :value="result.agent" readonly>
+            </div>
+            <div class="detail-item">
+              <span class="detail-label">打标依据:</span>
+              <textarea class="detail-textarea" :value="result.tagBasis" readonly></textarea>
+            </div>
+            <div class="detail-item">
+              <span class="detail-label">标签验证结果:</span>
+              <textarea class="detail-textarea" :value="result.validationResult" readonly></textarea>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'TaggingDetail',
+  data() {
+    return {
+      businessInfo: {
+        loanApplyNo: '',
+        contractNo: '',
+        investmentDirection: '',
+        reportName: '',
+        loanPurpose: ''
+      },
+      taggingInfo: {
+        taggingTime: '',
+        results: []
+      }
+    }
+  },
+  created() {
+    // 从路由参数中获取贷款申请编号
+    const loanApplyNo = this.$route.query.loanApplyNo
+    if (loanApplyNo) {
+      this.loadDetailData(loanApplyNo)
+    }
+  },
+  methods: {
+    // 加载详情数据
+    loadDetailData(loanApplyNo) {
+      // 模拟数据,实际项目中应该调用后端接口
+      this.businessInfo = {
+        loanApplyNo: 'AP20240302001',
+        contractNo: 'CT20250203002',
+        investmentDirection: 'A041 水产养殖',
+        reportName: 'XX渔业有限公司调查报告.pdf',
+        loanPurpose: '用于购买远洋捕捞设备及船舶升级改造,提升捕捞能力和作业安全系数。项目预计增加捕捞量30%,年新增产值约1200万元。'
+      }
+      
+      this.taggingInfo = {
+        taggingTime: '2026-02-06 17:00:30',
+        results: [
+          {
+            tagPath: '海洋经济 / 海洋产业 / 海洋渔业 / 海洋捕捞 / 远洋捕捞',
+            labeler: '王武',
+            tagTime: '2026-02-07 15:30:43',
+            isCorrect: true,
+            tagMethod: '',
+            agent: '',
+            tagBasis: '文本中明确提到"主要从事远洋捕捞业务"、"拥有5艘远洋捕捞船"、"购买新的远洋捕捞设备"等关键信息,直接指向"远洋捕捞"标签。企业名称"舟山远洋渔业有限公司"也包含"远洋渔业"关键词,进一步支持此标签。',
+            validationResult: '打标正确'
+          },
+          {
+            tagPath: '海洋经济 / 海洋产业 / 海洋船舶工业 / 海洋船舶制造',
+            labeler: '王武',
+            tagTime: '2026-02-07 15:31:12',
+            isCorrect: false,
+            tagMethod: '',
+            agent: '',
+            tagBasis: '文本中明确提到"主要从事远洋捕捞业务"、"拥有5艘远洋捕捞船"、"购买新的远洋捕捞设备"等关键信息,直接指向"远洋捕捞"标签。企业名称"舟山远洋渔业有限公司"也包含"远洋渔业"关键词,进一步支持此标签。',
+            validationResult: '文本中"远洋捕捞船""远洋捕捞设备"等关键词,描述的是企业的生产工具,而非其生产制造的产品,因此不应归类为"海洋船舶制造"。'
+          }
+        ]
+      }
+    },
+    // 返回上一页
+    handleBack() {
+      this.$router.back()
+    }
+  }
+}
+</script>
+
+<style scoped>
+.tagging-detail-container {
+  padding: 0;
+  background-color: transparent;
+  margin: 0 auto;
+}
+
+/* 顶部导航栏 */
+.nav-bar {
+  display: flex;
+  align-items: center;
+  margin-bottom: 30px;
+  padding-bottom: 20px;
+  border-bottom: 1px solid #f0f0f0;
+}
+
+.nav-bar h1 {
+  margin: 0 0 0 20px;
+  font-size: 24px;
+  color: #303133;
+}
+
+/* 通用部分样式 */
+.section {
+  margin-bottom: 15px;
+  padding: 20px;
+  background-color: #fff;
+  border-radius: 4px;
+  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+}
+.section::last-child {
+  margin-bottom: 0;
+}
+
+.section-title {
+  font-size: 18px;
+  font-weight: bold;
+  margin: 0 0 20px 0;
+  padding-bottom: 10px;
+  border-bottom: 2px solid #409EFF;
+  color: #303133;
+  width: fit-content;
+}
+
+.section-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.section-header .tagging-time {
+  font-size: 14px;
+  color: #606266;
+}
+
+/* 信息网格 */
+.info-grid {
+  display: grid;
+  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
+  gap: 16px;
+}
+
+.info-item {
+  display: flex;
+  align-items: flex-start;
+}
+
+.info-item.full-width {
+  grid-column: 1 / -1;
+}
+
+.label {
+  font-weight: bold;
+  margin-right: 8px;
+  min-width: 100px;
+  color: #606266;
+}
+
+.value {
+  color: #303133;
+  flex: 1;
+}
+
+.file-link {
+  color: #409EFF;
+  text-decoration: none;
+}
+
+.file-link:hover {
+  text-decoration: underline;
+}
+
+/* 打标结果 */
+.tagging-results {
+  display: flex;
+  flex-direction: column;
+  gap: 20px;
+}
+
+.tagging-item {
+  padding: 20px;
+  border: 1px solid #f0f0f0;
+  border-radius: 4px;
+  background-color: #f9f9f9;
+}
+
+.tagging-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 16px;
+  padding-bottom: 12px;
+  border-bottom: 1px solid #e4e7ed;
+}
+
+.tag-path {
+  font-weight: bold;
+  color: #303133;
+  flex: 1;
+}
+
+.tag-meta {
+  display: flex;
+  align-items: center;
+  gap: 16px;
+  font-size: 14px;
+  color: #606266;
+}
+
+/* 打标详情 */
+.tagging-details {
+  display: flex;
+  flex-direction: column;
+  gap: 16px;
+}
+
+.detail-item {
+  display: flex;
+  align-items: flex-start;
+}
+
+.detail-label {
+  font-weight: bold;
+  margin-right: 16px;
+  min-width: 100px;
+  color: #606266;
+  flex-shrink: 0;
+}
+
+.detail-input {
+  flex: 1;
+  padding: 8px;
+  border: 1px solid #dcdfe6;
+  border-radius: 4px;
+  background-color: #fff;
+}
+
+.detail-textarea {
+  flex: 1;
+  padding: 8px;
+  border: 1px solid #dcdfe6;
+  border-radius: 4px;
+  background-color: #fff;
+  min-height: 100px;
+  resize: vertical;
+}
+
+/* 响应式设计 */
+@media (max-width: 768px) {
+  .tagging-detail-container {
+    padding: 10px;
+  }
+
+  .nav-bar {
+    flex-direction: column;
+    align-items: flex-start;
+    gap: 10px;
+  }
+
+  .nav-bar h1 {
+    margin: 0;
+  }
+
+  .info-grid {
+    grid-template-columns: 1fr;
+  }
+
+  .tagging-header {
+    flex-direction: column;
+    align-items: flex-start;
+    gap: 10px;
+  }
+
+  .tag-meta {
+    flex-wrap: wrap;
+    gap: 8px;
+  }
+
+  .detail-item {
+    flex-direction: column;
+    gap: 8px;
+  }
+
+  .detail-label {
+    min-width: auto;
+  }
+}
+</style>

+ 225 - 0
web/src/views/content/aiTagging/taggingLogs/components/LogDetailDrawer.vue

@@ -0,0 +1,225 @@
+<template>
+  <el-drawer
+    title="日志详情"
+    :visible.sync="visible"
+    direction="rtl"
+    size="50%"
+    :close-on-click-modal="false"
+    @close="handleClose"
+  >
+    <div class="log-detail-container">
+      <!-- 基本信息 -->
+      <div class="detail-section">
+        <h3 class="section-title">基本信息</h3>
+        <div class="info-grid">
+          <div class="info-item">
+            <span class="label">调用时间:</span>
+            <span class="value">{{ logDetail.callTime }}</span>
+          </div>
+          <div class="info-item">
+            <span class="label">响应时间:</span>
+            <span class="value">{{ logDetail.responseTime }}</span>
+          </div>
+          <div class="info-item">
+            <span class="label">请求ID:</span>
+            <span class="value">{{ logDetail.requestId }}</span>
+          </div>
+          <div class="info-item">
+            <span class="label">接口名称:</span>
+            <span class="value">{{ logDetail.apiName }}</span>
+          </div>
+          <div class="info-item">
+            <span class="label">状态结果:</span>
+            <el-tag :type="getStatusType(logDetail.status)">{{ logDetail.status }}</el-tag>
+          </div>
+          <div class="info-item">
+            <span class="label">调用IP:</span>
+            <span class="value">{{ logDetail.clientIp }}</span>
+          </div>
+        </div>
+      </div>
+
+      <!-- 请求信息 -->
+      <div class="detail-section">
+        <h3 class="section-title">请求信息</h3>
+        <div class="info-item">
+          <span class="label">请求方法:</span>
+          <span class="value">{{ logDetail.requestMethod }} {{ logDetail.requestUrl }}</span>
+        </div>
+        <div class="info-item">
+          <span class="label">请求头:</span>
+          <pre class="code-block">{{ formatJson(logDetail.requestHeaders) }}</pre>
+        </div>
+        <div class="info-item">
+          <span class="label">请求体:</span>
+          <pre class="code-block">{{ formatJson(logDetail.requestBody) }}</pre>
+        </div>
+      </div>
+
+      <!-- 响应信息 -->
+      <div class="detail-section">
+        <h3 class="section-title">响应信息</h3>
+        <div class="info-item">
+          <span class="label">响应状态:</span>
+          <span class="value">{{ logDetail.responseStatus }}</span>
+        </div>
+        <div class="info-item">
+          <span class="label">响应头:</span>
+          <pre class="code-block">{{ formatJson(logDetail.responseHeaders) }}</pre>
+        </div>
+        <div class="info-item">
+          <span class="label">响应体:</span>
+          <pre class="code-block">{{ formatJson(logDetail.responseBody) }}</pre>
+        </div>
+      </div>
+
+      <!-- 底部操作 -->
+      <div class="detail-footer">
+        <el-button type="primary" @click="handleExport">导出</el-button>
+      </div>
+    </div>
+  </el-drawer>
+</template>
+
+<script>
+export default {
+  name: 'LogDetailDrawer',
+  props: {
+    visible: {
+      type: Boolean,
+      default: false
+    },
+    logDetail: {
+      type: Object,
+      default: () => ({})
+    }
+  },
+  methods: {
+    // 处理关闭
+    handleClose() {
+      this.$emit('update:visible', false)
+    },
+    
+    // 处理导出
+    handleExport() {
+      console.log('导出日志详情:', this.logDetail.requestId)
+      this.$message.success('导出成功')
+    },
+    
+    // 根据状态获取标签类型
+    getStatusType(status) {
+      switch (status) {
+        case '成功':
+          return 'success'
+        case '失败':
+          return 'danger'
+        case '响应中':
+          return 'warning'
+        default:
+          return ''
+      }
+    },
+    
+    // 格式化JSON
+    formatJson(json) {
+      if (!json) return ''
+      try {
+        return JSON.stringify(json, null, 2)
+      } catch (error) {
+        return json
+      }
+    }
+  }
+}
+</script>
+
+<style scoped>
+.log-detail-container {
+  padding: 20px;
+  max-height: calc(100vh - 120px);
+  overflow-y: auto;
+}
+
+.detail-section {
+  margin-bottom: 30px;
+  padding-bottom: 20px;
+  border-bottom: 1px solid #f0f0f0;
+}
+
+.detail-section:last-child {
+  border-bottom: none;
+}
+
+.section-title {
+  font-size: 16px;
+  font-weight: bold;
+  margin: 0 0 16px 0;
+  color: #303133;
+}
+
+.info-grid {
+  display: grid;
+  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
+  gap: 16px;
+}
+
+.info-item {
+  display: flex;
+  flex-direction: row;
+  align-items: flex-start;
+  margin-bottom: 16px;
+}
+
+.label {
+  font-weight: bold;
+  color: #606266;
+  min-width: 60px;
+  flex-shrink: 0;
+  margin-right: 12px;
+}
+
+.value {
+  color: #303133;
+  word-break: break-all;
+  flex: 1;
+  min-width: 200px;
+}
+
+.code-block {
+  background-color: #f5f7fa;
+  border: 1px solid #e4e7ed;
+  border-radius: 4px;
+  padding: 12px;
+  font-family: 'Courier New', Courier, monospace;
+  font-size: 14px;
+  line-height: 1.5;
+  overflow-x: auto;
+  white-space: pre-wrap;
+  margin: 0;
+  flex: 1;
+  min-width: 200px;
+}
+
+.detail-footer {
+  display: flex;
+  justify-content: flex-end;
+  margin-top: 40px;
+  padding-top: 20px;
+  border-top: 1px solid #f0f0f0;
+}
+
+/* 响应式设计 */
+@media (max-width: 768px) {
+  .log-detail-container {
+    padding: 10px;
+  }
+
+  .info-grid {
+    grid-template-columns: 1fr;
+  }
+
+  .code-block {
+    font-size: 12px;
+  }
+}
+</style>

+ 258 - 307
web/src/views/content/aiTagging/taggingLogs/index.vue

@@ -1,10 +1,42 @@
 <template>
-  <div class="tag-system-container">
+  <div class="tagging-logs-container">
     <!-- 顶部搜索栏 -->
     <div class="search-bar">
       <el-form :inline="true" :model="searchForm" class="search-form">
-        <el-form-item label="标签体系名称:">
-          <el-input v-model="searchForm.name" placeholder="请输入" style="width: 300px;"></el-input>
+        <el-form-item label="请求ID:">
+          <el-input v-model="searchForm.requestId" placeholder="请输入" style="width: 200px;"></el-input>
+        </el-form-item>
+        <el-form-item label="贷款申请编号:">
+          <el-input v-model="searchForm.loanApplyNo" placeholder="请输入" style="width: 200px;"></el-input>
+        </el-form-item>
+        <el-form-item label="合同编号:">
+          <el-input v-model="searchForm.contractNo" placeholder="请输入" style="width: 200px;"></el-input>
+        </el-form-item>
+        <el-form-item label="调用时间:">
+          <el-date-picker
+            v-model="searchForm.callTime"
+            type="daterange"
+            range-separator="至"
+            start-placeholder="开始日期"
+            end-placeholder="结束日期"
+            style="width: 240px;"
+          ></el-date-picker>
+        </el-form-item>
+        <el-form-item label="接口:">
+          <el-select v-model="searchForm.apiType" placeholder="全部" style="width: 150px;">
+            <el-option label="全部" value=""></el-option>
+            <el-option label="getCustomerTags" value="getCustomerTags"></el-option>
+            <el-option label="queryCustomerTags" value="queryCustomerTags"></el-option>
+            <el-option label="feedbackTagsResult" value="feedbackTagsResult"></el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="状态:">
+          <el-select v-model="searchForm.status" placeholder="全部" style="width: 150px;">
+            <el-option label="全部" value=""></el-option>
+            <el-option label="成功" value="success"></el-option>
+            <el-option label="失败" value="failed"></el-option>
+            <el-option label="响应中" value="pending"></el-option>
+          </el-select>
         </el-form-item>
         <el-form-item>
           <el-button type="primary" @click="handleSearch">查询</el-button>
@@ -12,212 +44,254 @@
         <el-form-item>
           <el-button @click="handleReset">重置</el-button>
         </el-form-item>
+        <el-form-item>
+          <el-button @click="handleRefresh">刷新</el-button>
+        </el-form-item>
       </el-form>
     </div>
 
-    <!-- 标签体系卡片网格 -->
-    <div class="tag-system-grid">
-      <!-- 新建标签体系卡片 -->
-      <div class="tag-system-card create-card" @click="handleCreateTagSystem">
-        <div class="create-icon">
-          <i class="el-icon-plus"></i>
-        </div>
-        <div class="create-title">新建标签体系</div>
-        <div class="create-desc">创建新的标签分类体系,用于业务的标签管理</div>
+    <!-- 表格和分页容器 -->
+    <div class="table-and-pagination-container">
+      <!-- 数据表格 -->
+      <div class="table-container">
+        <el-table :data="logs" style="width: 100%">
+          <el-table-column prop="requestId" label="请求ID" min-width="180"></el-table-column>
+          <el-table-column prop="loanApplyNo" label="贷款申请编号" min-width="150"></el-table-column>
+          <el-table-column prop="contractNo" label="合同编号" min-width="150"></el-table-column>
+          <el-table-column prop="apiName" label="接口" min-width="150"></el-table-column>
+          <el-table-column prop="callTime" label="调用时间" min-width="180"></el-table-column>
+          <el-table-column prop="status" label="状态" min-width="100">
+            <template slot-scope="scope">
+              <el-tag :type="getStatusType(scope.row.status)">{{ scope.row.status }}</el-tag>
+            </template>
+          </el-table-column>
+          <el-table-column prop="action" label="操作" min-width="100">
+            <template slot-scope="scope">
+              <el-button type="text" @click="handleViewDetail(scope.row)">查看详情</el-button>
+            </template>
+          </el-table-column>
+        </el-table>
       </div>
 
-      <!-- 标签体系卡片 -->
-      <div v-for="system in tagSystems" :key="system.id" class="tag-system-card">
-        <div class="card-header">
-          <div class="system-name">{{ system.name }}</div>
-          <div class="card-actions">
-            <el-button type="text" icon="el-icon-edit" @click.stop="handleEditTagSystem(system)"></el-button>
-            <el-dropdown trigger="click" @command="(command) => handleDropdownCommand(command, system)">
-              <el-button type="text" icon="el-icon-more"></el-button>
-              <el-dropdown-menu slot="dropdown">
-                <el-dropdown-item v-if="system.status === 'enabled'" command="disable">停用</el-dropdown-item>
-                <el-dropdown-item v-else command="enable">启用</el-dropdown-item>
-                <el-dropdown-item command="delete" divided>删除</el-dropdown-item>
-              </el-dropdown-menu>
-            </el-dropdown>
-          </div>
-        </div>
-        <div class="system-status">
-          <el-tag :type="system.status === 'enabled' ? 'success' : 'info'">
-            {{ system.status === 'enabled' ? '已启用' : '未启用' }}
-          </el-tag>
-        </div>
-        <div class="system-desc">{{ system.description }}</div>
-        <div class="system-meta">
-          <span class="tag-count">标签数量:{{ system.tagCount }}</span>
-          <span class="create-date">{{ system.createDate }}</span>
-        </div>
-        <div class="card-footer">
-          <el-button type="text" @click.stop="handleViewTags(system)">
-            <i class="el-icon-menu"></i> 查看标签列表
-          </el-button>
-        </div>
+      <!-- 分页控件 -->
+      <div class="pagination-container">
+        <el-pagination
+          :current-page="currentPage"
+          :page-size="pageSize"
+          :page-sizes="[10, 20, 50]"
+          layout="total, sizes, prev, pager, next, jumper"
+          :total="totalCount"
+          @size-change="handleSizeChange"
+          @current-change="handleCurrentChange"
+        ></el-pagination>
       </div>
     </div>
 
-    <!-- 分页控件 -->
-    <div class="pagination-container">
-      <div class="total-count">共 {{ totalCount }} 条数据</div>
-      <el-pagination
-        :current-page="currentPage"
-        :page-size="pageSize"
-        :page-sizes="[10, 20, 50]"
-        layout="prev, pager, next"
-        :total="totalCount"
-        @size-change="handleSizeChange"
-        @current-change="handleCurrentChange"
-      ></el-pagination>
-    </div>
+    <!-- 日志详情抽屉 -->
+    <LogDetailDrawer
+      :visible="drawerVisible"
+      :log-detail="currentLogDetail"
+      @update:visible="drawerVisible = $event"
+    />
   </div>
 </template>
 
 <script>
+import LogDetailDrawer from './components/LogDetailDrawer.vue'
+
 export default {
-  name: 'TagSystemManagement',
+  name: 'TaggingLogs',
+  components: {
+    LogDetailDrawer
+  },
   data() {
     return {
       // 搜索表单
       searchForm: {
-        name: ''
+        requestId: '',
+        loanApplyNo: '',
+        contractNo: '',
+        callTime: '',
+        apiType: '',
+        status: ''
       },
       
-      // 标签体系列表
-      tagSystems: [
+      // 日志列表
+      logs: [
+        {
+          requestId: 'API-20260203-87654',
+          loanApplyNo: 'DKSQ20260203001',
+          contractNo: 'CUST20260203001',
+          apiName: 'getCustomerTags',
+          callTime: '2023-01-01 11:11:11',
+          status: '成功'
+        },
+        {
+          requestId: 'API-20260203-87653',
+          loanApplyNo: 'DKSQ20260203001',
+          contractNo: 'CUST20260203001',
+          apiName: 'queryCustomerTags',
+          callTime: '2023-01-01 11:11:11',
+          status: '成功'
+        },
         {
-          id: 1,
-          name: '海洋经济',
-          status: 'enabled',
-          description: '涵盖海洋渔业、海洋装备、海洋旅游等海洋经济相关产业的标签分类体系',
-          tagCount: 53,
-          createDate: '2026-02-01'
+          requestId: 'API-20260203-87652',
+          loanApplyNo: 'DKSQ20260203001',
+          contractNo: 'CUST20260203001',
+          apiName: 'feedbackTagsResult',
+          callTime: '2023-01-01 11:11:11',
+          status: '失败'
         },
         {
-          id: 2,
-          name: '绿色金融',
-          status: 'disabled',
-          description: '包含绿色能源、节能环保、清洁生产等绿色产业相关的标签分类体系',
-          tagCount: 53,
-          createDate: '2026-02-01'
+          requestId: 'API-20260203-87651',
+          loanApplyNo: 'DKSQ20260203001',
+          contractNo: 'CUST20260203001',
+          apiName: 'getCustomerTags',
+          callTime: '2023-01-01 11:11:11',
+          status: '响应中'
         },
         {
-          id: 3,
-          name: '养老产业',
-          status: 'enabled',
-          description: '涵盖养老服务、健康管理、老年用品等养老产业相关的标签分类体系',
-          tagCount: 53,
-          createDate: '2026-02-01'
+          requestId: 'API-20260203-87650',
+          loanApplyNo: 'DKSQ20260203001',
+          contractNo: 'CUST20260203001',
+          apiName: 'getCustomerTags',
+          callTime: '2023-01-01 11:11:11',
+          status: '成功'
         },
         {
-          id: 4,
-          name: '科技创新',
-          status: 'enabled',
-          description: '包含人工智能、新一代信息技术、生物医药等科技创新领域的标签分类体系',
-          tagCount: 53,
-          createDate: '2026-02-01'
+          requestId: 'API-20260203-87649',
+          loanApplyNo: 'DKSQ20260203001',
+          contractNo: 'CUST20260203001',
+          apiName: 'getCustomerTags',
+          callTime: '2023-01-01 11:11:11',
+          status: '成功'
         },
         {
-          id: 5,
-          name: '乡村振兴',
-          status: 'enabled',
-          description: '暂无描述',
-          tagCount: 53,
-          createDate: '2026-02-01'
+          requestId: 'API-20260203-87648',
+          loanApplyNo: 'DKSQ20260203001',
+          contractNo: 'CUST20260203001',
+          apiName: 'getCustomerTags',
+          callTime: '2023-01-01 11:11:11',
+          status: '成功'
+        },
+        {
+          requestId: 'API-20260203-87647',
+          loanApplyNo: 'DKSQ20260203001',
+          contractNo: 'CUST20260203001',
+          apiName: 'getCustomerTags',
+          callTime: '2023-01-01 11:11:11',
+          status: '成功'
+        },
+        {
+          requestId: 'API-20260203-87646',
+          loanApplyNo: 'DKSQ20260203001',
+          contractNo: 'CUST20260203001',
+          apiName: 'getCustomerTags',
+          callTime: '2023-01-01 11:11:11',
+          status: '成功'
+        },
+        {
+          requestId: 'API-20260203-87645',
+          loanApplyNo: 'DKSQ20260203001',
+          contractNo: 'CUST20260203001',
+          apiName: 'getCustomerTags',
+          callTime: '2023-01-01 11:11:11',
+          status: '成功'
         }
       ],
       
       // 分页数据
-      totalCount: 15,
+      totalCount: 120,
       currentPage: 1,
-      pageSize: 10
+      pageSize: 10,
+      
+      // 抽屉相关
+      drawerVisible: false,
+      currentLogDetail: {}
     }
   },
   methods: {
-    // 搜索标签体系
+    // 根据状态获取标签类型
+    getStatusType(status) {
+      switch (status) {
+        case '成功':
+          return 'success'
+        case '失败':
+          return 'danger'
+        case '响应中':
+          return 'warning'
+        default:
+          return ''
+      }
+    },
+    
+    // 搜索日志
     handleSearch() {
-      console.log('搜索标签体系:', this.searchForm.name)
+      console.log('搜索日志:', this.searchForm)
       // 这里可以调用后端接口进行搜索
       this.$message.success('搜索成功')
     },
 
     // 重置搜索
     handleReset() {
-      this.searchForm.name = ''
+      this.searchForm = {
+        requestId: '',
+        loanApplyNo: '',
+        contractNo: '',
+        callTime: '',
+        apiType: '',
+        status: ''
+      }
       console.log('重置搜索')
     },
 
-    // 创建标签体系
-    handleCreateTagSystem() {
-      console.log('创建标签体系')
-      this.$message.success('打开创建标签体系对话框')
-      // 这里可以打开创建标签体系的对话框
-    },
-
-    // 编辑标签体系
-    handleEditTagSystem(system) {
-      console.log('编辑标签体系:', system.name)
-      // 使用Vue Router跳转到编辑页面,并携带参数
-      this.$router.push({
-        path: '/home/tag-system-edit',
-        query: { id: system.id }
-      })
+    // 刷新日志
+    handleRefresh() {
+      console.log('刷新日志')
+      this.$message.success('刷新成功')
+      // 这里可以重新加载数据
     },
 
-    // 下拉菜单命令处理
-    handleDropdownCommand(command, system) {
-      switch (command) {
-        case 'enable':
-          this.handleEnableTagSystem(system)
-          break
-        case 'disable':
-          this.handleDisableTagSystem(system)
-          break
-        case 'delete':
-          this.handleDeleteTagSystem(system)
-          break
-        default:
-          break
+    // 查看详情
+    handleViewDetail(row) {
+      console.log('查看详情:', row)
+      // 模拟加载日志详情数据
+      this.currentLogDetail = {
+        callTime: '2026-02-03 15:30:45',
+        responseTime: '124ms',
+        requestId: row.requestId,
+        apiName: row.apiName,
+        status: row.status,
+        clientIp: '192.168.1.45',
+        requestMethod: 'POST',
+        requestUrl: '/api/user/login',
+        requestHeaders: {
+          'Content-Type': 'application/json',
+          'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
+        },
+        requestBody: {
+          username: 'testuser',
+          password: '********'
+        },
+        responseStatus: 'HTTP 200',
+        responseHeaders: {
+          'Content-Type': 'application/json',
+          'X-Request-Id': row.requestId
+        },
+        responseBody: {
+          code: 0,
+          message: '登录成功',
+          data: {
+            token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...',
+            userInfo: {
+              id: '1001',
+              username: 'testuser',
+              role: 'user'
+            }
+          }
+        }
       }
-    },
-
-    // 启用标签体系
-    handleEnableTagSystem(system) {
-      console.log('启用标签体系:', system.name)
-      system.status = 'enabled'
-      this.$message.success(`启用标签体系: ${system.name}`)
-    },
-
-    // 停用标签体系
-    handleDisableTagSystem(system) {
-      console.log('停用标签体系:', system.name)
-      system.status = 'disabled'
-      this.$message.success(`停用标签体系: ${system.name}`)
-    },
-
-    // 删除标签体系
-    handleDeleteTagSystem(system) {
-      this.$confirm(`确定要删除标签体系「${system.name}」吗?`, '警告', {
-        confirmButtonText: '确定',
-        cancelButtonText: '取消',
-        type: 'warning'
-      }).then(() => {
-        console.log('删除标签体系:', system.name)
-        // 这里可以调用后端接口删除标签体系
-        this.$message.success(`删除标签体系: ${system.name}`)
-      }).catch(() => {
-        console.log('取消删除标签体系:', system.name)
-      })
-    },
-
-    // 查看标签列表
-    handleViewTags(system) {
-      console.log('查看标签列表:', system.name)
-      this.$message.success(`查看标签列表: ${system.name}`)
-      // 这里可以跳转到标签列表页面
+      this.drawerVisible = true
     },
 
     // 分页大小变化
@@ -238,9 +312,9 @@ export default {
 </script>
 
 <style scoped>
-.tag-system-container {
-  padding: 20px;
-  background-color: #f0f2f5;
+.tagging-logs-container {
+  padding: 0;
+  background-color: transparent;
   min-height: 100vh;
 }
 
@@ -255,175 +329,52 @@ export default {
 
 .search-form {
   display: flex;
+  flex-wrap: wrap;
   align-items: center;
+  gap: 16px;
 }
 
-/* 标签体系卡片网格 */
-.tag-system-grid {
-  display: grid;
-  grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));
-  gap: 20px;
-  margin-bottom: 30px;
-}
-
-/* 标签体系卡片 */
-.tag-system-card {
+/* 表格和分页容器 */
+.table-and-pagination-container {
   background-color: #fff;
   border-radius: 8px;
-  padding: 20px;
   box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
-  transition: all 0.3s ease;
-  cursor: pointer;
-}
-
-.tag-system-card:hover {
-  transform: translateY(-4px);
-  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
-}
-
-/* 创建标签体系卡片 */
-.create-card {
-  display: flex;
-  flex-direction: column;
-  align-items: center;
-  justify-content: center;
-  min-height: 200px;
-  border: 2px dashed #e8e8e8;
-  background-color: #fafafa;
-}
-
-.create-card:hover {
-  border-color: #1890ff;
-  background-color: #f0f9ff;
-}
-
-.create-icon {
-  width: 60px;
-  height: 60px;
-  border-radius: 50%;
-  background-color: #e6f7ff;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  margin-bottom: 16px;
-}
-
-.create-icon i {
-  font-size: 24px;
-  color: #1890ff;
-}
-
-.create-title {
-  font-size: 16px;
-  font-weight: 500;
-  color: #303133;
-  margin-bottom: 8px;
-}
-
-.create-desc {
-  font-size: 14px;
-  color: #909399;
-  text-align: center;
-  line-height: 1.4;
-}
-
-/* 卡片头部 */
-.card-header {
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-  margin-bottom: 12px;
-}
-
-.system-name {
-  font-size: 16px;
-  font-weight: 500;
-  color: #303133;
-}
-
-.card-actions {
-  display: flex;
-  align-items: center;
-  gap: 8px;
-}
-
-/* 卡片内容 */
-.system-status {
-  margin-bottom: 12px;
-}
-
-.system-desc {
-  font-size: 14px;
-  color: #606266;
-  line-height: 1.4;
-  margin-bottom: 16px;
-  min-height: 40px;
-}
-
-.system-meta {
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-  font-size: 12px;
-  color: #909399;
-  margin-bottom: 16px;
-}
-
-.tag-count {
-  display: flex;
-  align-items: center;
-  gap: 4px;
-}
-
-.create-date {
-  display: flex;
-  align-items: center;
-  gap: 4px;
+  margin-bottom: 20px;
+  overflow: hidden;
 }
 
-/* 卡片底部 */
-.card-footer {
-  border-top: 1px solid #f0f0f0;
-  padding-top: 16px;
+/* 表格容器 */
+.table-container {
+  padding: 20px 20px 10px;
 }
 
 /* 分页控件 */
 .pagination-container {
   display: flex;
-  justify-content: space-between;
+  justify-content: flex-end;
   align-items: center;
-  background-color: #fff;
-  padding: 20px;
-  border-radius: 8px;
-  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
-}
-
-.total-count {
-  font-size: 14px;
-  color: #606266;
+  padding: 0 20px 20px;
+  /* border-top: 1px solid #f0f0f0; */
 }
 
 /* 响应式设计 */
 @media (max-width: 1200px) {
-  .tag-system-grid {
-    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
+  .search-form {
+    flex-direction: column;
+    align-items: flex-start;
+    gap: 12px;
   }
 }
 
 @media (max-width: 768px) {
-  .tag-system-container {
+  .tagging-logs-container {
     padding: 10px;
   }
 
-  .tag-system-grid {
-    grid-template-columns: 1fr;
-    gap: 16px;
-  }
-
-  .search-form {
-    flex-direction: column;
-    align-items: flex-start;
-    gap: 12px;
+  .search-bar,
+  .table-container,
+  .pagination-container {
+    padding: 10px;
   }
 
   .pagination-container {

+ 199 - 0
web/src/views/content/aiTagging/taggingResults/components/Detail.vue

@@ -0,0 +1,199 @@
+<template>
+  <div class="detail-container">
+    <!-- 搜索栏 -->
+    <div class="detail-search-bar">
+      <el-form :inline="true" :model="detailSearchForm" class="detail-search-form">
+        <el-form-item label="贷款申请编号:">
+          <el-input v-model="detailSearchForm.loanApplyNo" placeholder="请输入" style="width: 200px;"></el-input>
+        </el-form-item>
+        <el-form-item label="合同编号:">
+          <el-input v-model="detailSearchForm.contractNo" placeholder="请输入" style="width: 200px;"></el-input>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="handleDetailSearch">查询</el-button>
+        </el-form-item>
+        <el-form-item>
+          <el-button @click="handleDetailReset">重置</el-button>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="success" icon="el-icon-download" @click="handleExport">导出数据</el-button>
+        </el-form-item>
+      </el-form>
+    </div>
+
+    <!-- 数据表格 -->
+    <div class="table-container">
+      <el-table :data="detailData" style="width: 100%">
+        <el-table-column prop="loanApplyNo" label="贷款申请编号" width="180"></el-table-column>
+        <el-table-column prop="contractNo" label="合同编号" width="180"></el-table-column>
+        <el-table-column prop="taggingTime" label="打标时间" width="180"></el-table-column>
+        <el-table-column prop="tags" label="智能标签">
+          <template slot-scope="scope">
+            <el-tag v-for="(tag, index) in scope.row.tags" :key="index" size="small" class="tag-item">{{ tag }}</el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column prop="operator" label="标注人员" width="120"></el-table-column>
+        <el-table-column prop="action" label="操作" width="100">
+          <template slot-scope="scope">
+            <el-button type="text" @click="handleViewDetail(scope.row)">查看详情</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+    </div>
+
+    <!-- 分页控件 -->
+    <div class="pagination-container">
+      <el-pagination
+        :current-page="currentDetailPage"
+        :page-size="detailPageSize"
+        :page-sizes="[10, 20, 50]"
+        layout="total, sizes, prev, pager, next, jumper"
+        :total="totalDetailCount"
+        @size-change="handleDetailSizeChange"
+        @current-change="handleDetailCurrentChange"
+      ></el-pagination>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'Detail',
+  props: {
+    detailData: {
+      type: Array,
+      default: () => []
+    },
+    totalDetailCount: {
+      type: Number,
+      default: 0
+    },
+    currentDetailPage: {
+      type: Number,
+      default: 1
+    },
+    detailPageSize: {
+      type: Number,
+      default: 10
+    }
+  },
+  data() {
+    return {
+      // 明细搜索表单
+      detailSearchForm: {
+        loanApplyNo: '',
+        contractNo: ''
+      }
+    }
+  },
+  methods: {
+    // 明细搜索
+    handleDetailSearch() {
+      console.log('明细搜索:', this.detailSearchForm)
+      // 这里可以调用后端接口进行搜索
+      this.$emit('detail-search', this.detailSearchForm)
+      this.$message.success('搜索成功')
+    },
+
+    // 重置明细搜索
+    handleDetailReset() {
+      this.detailSearchForm.loanApplyNo = ''
+      this.detailSearchForm.contractNo = ''
+      console.log('重置明细搜索')
+      this.$emit('detail-reset')
+    },
+
+    // 查看详情
+    handleViewDetail(row) {
+      // console.log('查看详情:', row)
+      // this.$emit('view-detail', row)
+      // 跳转到详情页面
+      this.$router.push({
+        path: '/taggingDetail',
+        query: { loanApplyNo: row.loanApplyNo }
+      })
+    },
+
+    // 导出数据
+    handleExport() {
+      console.log('导出数据')
+      this.$emit('export-data')
+      this.$message.success('导出成功')
+      // 这里可以调用后端接口导出数据
+    },
+
+    // 明细分页大小变化
+    handleDetailSizeChange(size) {
+      console.log('每页条数:', size)
+      this.$emit('size-change', size)
+    },
+
+    // 明细当前页码变化
+    handleDetailCurrentChange(current) {
+      console.log('当前页码:', current)
+      this.$emit('current-change', current)
+    }
+  }
+}
+</script>
+
+<style scoped>
+.detail-container {
+  width: 100%;
+}
+
+/* 明细搜索栏 */
+.detail-search-bar {
+  padding: 20px;
+  border-bottom: 1px solid #f0f0f0;
+}
+
+.detail-search-form {
+  display: flex;
+  align-items: center;
+  gap: 16px;
+}
+
+/* 表格容器 */
+.table-container {
+  padding: 20px;
+}
+
+/* 标签样式 */
+.tag-item {
+  margin-right: 8px;
+  margin-bottom: 8px;
+}
+
+/* 分页控件 */
+.pagination-container {
+  display: flex;
+  justify-content: flex-end;
+  align-items: center;
+  padding:0 20px 20px;
+}
+
+.total-count {
+  font-size: 14px;
+  color: #606266;
+}
+
+/* 响应式设计 */
+@media (max-width: 768px) {
+  .detail-search-form {
+    flex-direction: column;
+    align-items: flex-start;
+    gap: 12px;
+  }
+
+  .pagination-container {
+    flex-direction: column;
+    align-items: flex-start;
+    gap: 16px;
+  }
+
+  .el-pagination {
+    align-self: flex-end;
+  }
+}
+</style>

+ 364 - 0
web/src/views/content/aiTagging/taggingResults/components/Overview.vue

@@ -0,0 +1,364 @@
+<template>
+  <div class="overview-container">
+    <!-- 统计指标 -->
+    <div class="stats-container">
+      <div class="stat-item">
+        <div class="stat-value">1,356</div>
+        <div class="stat-label">总打标数</div>
+        <div class="stat-icon blue"><i class="el-icon-data-analysis"></i></div>
+      </div>
+      <div class="stat-item">
+        <div class="stat-value">1,124</div>
+        <div class="stat-label">准确标签数</div>
+        <div class="stat-rate">准确率: 87.4%</div>
+        <div class="stat-icon green"><i class="el-icon-check"></i></div>
+      </div>
+      <div class="stat-item">
+        <div class="stat-value">202</div>
+        <div class="stat-label">人工调整数</div>
+        <div class="stat-rate">调整率: 13.6%</div>
+        <div class="stat-icon yellow"><i class="el-icon-s-operation"></i></div>
+      </div>
+      <div class="stat-item">
+        <div class="stat-value">1,356</div>
+        <div class="stat-label">平均处理时长</div>
+        <div class="stat-icon purple"><i class="el-icon-time"></i></div>
+      </div>
+    </div>
+
+    <!-- 图表区域 -->
+    <div class="charts-container">
+      <!-- 打标趋势图表 -->
+      <div class="chart-item">
+        <div class="chart-header">
+          <h3>打标趋势</h3>
+          <div class="chart-period">
+            <el-radio-group v-model="trendPeriod" size="small">
+              <el-radio-button label="day">日</el-radio-button>
+              <el-radio-button label="week">周</el-radio-button>
+              <el-radio-button label="month">月</el-radio-button>
+            </el-radio-group>
+          </div>
+        </div>
+        <div ref="trendChart" class="chart-content"></div>
+      </div>
+
+      <!-- 标签分布统计图表 -->
+      <div class="chart-item">
+        <div class="chart-header">
+          <h3>标签分布统计</h3>
+          <div class="chart-sort">
+            <el-select v-model="tagSort" placeholder="数量降序" size="small" style="width: 120px;">
+              <el-option label="数量降序" value="desc"></el-option>
+              <el-option label="数量升序" value="asc"></el-option>
+            </el-select>
+          </div>
+        </div>
+        <div ref="distributionChart" class="chart-content"></div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+// 使用全局echarts变量(通过CDN引入)
+const echarts = window.echarts
+
+export default {
+  name: 'Overview',
+  props: {
+    trendPeriod: {
+      type: String,
+      default: 'month'
+    },
+    tagSort: {
+      type: String,
+      default: 'desc'
+    }
+  },
+  data() {
+    return {
+      // 图表实例
+      trendChart: null,
+      distributionChart: null
+    }
+  },
+  mounted() {
+    // 使用nextTick确保DOM元素已渲染完成
+    this.$nextTick(() => {
+      this.initCharts()
+    })
+  },
+  methods: {
+    // 初始化图表
+    initCharts() {
+      // 检查echarts是否正确加载
+      if (!echarts || typeof echarts.init !== 'function') {
+        console.error('ECharts is not loaded correctly');
+        return;
+      }
+
+      // 模拟数据
+      const trendData = [
+        { month: '1月', value: 60 },
+        { month: '2月', value: 80 },
+        { month: '3月', value: 110 },
+        { month: '4月', value: 65 },
+        { month: '5月', value: 90 },
+        { month: '6月', value: 130 },
+        { month: '7月', value: 110 },
+        { month: '8月', value: 140 },
+        { month: '9月', value: 160 }
+      ]
+      
+      const distributionData = [
+        { name: '远洋捕捞', value: 150 },
+        { name: '船舶制造', value: 130 },
+        { name: '海水养殖', value: 100 },
+        { name: '海洋运输', value: 70 },
+        { name: '海洋旅游', value: 50 },
+        { name: '生物医药', value: 40 }
+      ]
+
+      // 初始化打标趋势图表
+      this.initTrendChart(trendData)
+      // 初始化标签分布图表
+      this.initDistributionChart(distributionData)
+    },
+
+    // 初始化打标趋势图表
+    initTrendChart(data) {
+      if (!this.$refs.trendChart) {
+        console.error('trendChart DOM element not found');
+        return;
+      }
+      
+      try {
+        this.trendChart = echarts.init(this.$refs.trendChart)
+        
+        const option = {
+          tooltip: {
+            trigger: 'axis'
+          },
+          grid: {
+            left: '3%',
+            right: '4%',
+            bottom: '3%',
+            containLabel: true
+          },
+          xAxis: {
+            type: 'category',
+            boundaryGap: false,
+            data: data.map(item => item.month)
+          },
+          yAxis: {
+            type: 'value'
+          },
+          series: [
+            {
+              name: '智能打标数',
+              type: 'line',
+              data: data.map(item => item.value),
+              lineStyle: {
+                color: '#1890ff'
+              },
+              itemStyle: {
+                color: '#1890ff'
+              }
+            }
+          ]
+        }
+        
+        this.trendChart.setOption(option)
+      } catch (error) {
+        console.error('Error initializing trend chart:', error);
+      }
+    },
+
+    // 初始化标签分布图表
+    initDistributionChart(data) {
+      if (!this.$refs.distributionChart) {
+        console.error('distributionChart DOM element not found');
+        return;
+      }
+      
+      try {
+        this.distributionChart = echarts.init(this.$refs.distributionChart)
+        
+        const option = {
+          tooltip: {
+            trigger: 'axis',
+            axisPointer: {
+              type: 'shadow'
+            }
+          },
+          grid: {
+            left: '3%',
+            right: '4%',
+            bottom: '3%',
+            containLabel: true
+          },
+          xAxis: {
+            type: 'category',
+            data: data.map(item => item.name),
+            axisLabel: {
+              rotate: 45
+            }
+          },
+          yAxis: {
+            type: 'value'
+          },
+          series: [
+            {
+              name: '标签数量',
+              type: 'bar',
+              data: data.map(item => item.value),
+              itemStyle: {
+                color: function(params) {
+                  const colors = ['#1890ff', '#36cfc9', '#52c41a', '#faad14', '#722ed1', '#eb2f96']
+                  return colors[params.dataIndex % colors.length]
+                }
+              }
+            }
+          ]
+        }
+        
+        this.distributionChart.setOption(option)
+      } catch (error) {
+        console.error('Error initializing distribution chart:', error);
+      }
+    }
+  }
+}
+</script>
+
+<style scoped>
+.overview-container {
+  width: 100%;
+}
+
+/* 统计指标容器 */
+.stats-container {
+  display: grid;
+  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
+  gap: 20px;
+  padding: 20px;
+  margin-bottom: 20px;
+}
+
+/* 统计指标项 */
+.stat-item {
+  position: relative;
+  background-color: #f9f9f9;
+  border-radius: 8px;
+  padding: 20px;
+  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.05);
+}
+
+.stat-value {
+  font-size: 28px;
+  font-weight: bold;
+  color: #303133;
+  margin-bottom: 8px;
+}
+
+.stat-label {
+  font-size: 14px;
+  color: #606266;
+  margin-bottom: 4px;
+}
+
+.stat-rate {
+  font-size: 12px;
+  color: #909399;
+}
+
+/* 统计图标 */
+.stat-icon {
+  position: absolute;
+  top: 20px;
+  right: 20px;
+  width: 40px;
+  height: 40px;
+  border-radius: 50%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  font-size: 20px;
+}
+
+.stat-icon.blue {
+  background-color: #e6f7ff;
+  color: #1890ff;
+}
+
+.stat-icon.green {
+  background-color: #f6ffed;
+  color: #52c41a;
+}
+
+.stat-icon.yellow {
+  background-color: #fffbe6;
+  color: #faad14;
+}
+
+.stat-icon.purple {
+  background-color: #f9f0ff;
+  color: #722ed1;
+}
+
+/* 图表容器 */
+.charts-container {
+  display: grid;
+  grid-template-columns: repeat(auto-fit, minmax(450px, 1fr));
+  gap: 20px;
+  padding: 0 20px 20px;
+}
+
+/* 图表项 */
+.chart-item {
+  background-color: #f9f9f9;
+  border-radius: 8px;
+  padding: 20px;
+  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.05);
+}
+
+/* 图表头部 */
+.chart-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 20px;
+}
+
+.chart-header h3 {
+  font-size: 16px;
+  font-weight: 500;
+  color: #303133;
+  margin: 0;
+}
+
+/* 图表内容 */
+.chart-content {
+  width: 100%;
+  height: 300px;
+}
+
+/* 响应式设计 */
+@media (max-width: 1200px) {
+  .charts-container {
+    grid-template-columns: 1fr;
+  }
+}
+
+@media (max-width: 768px) {
+  .stats-container {
+    grid-template-columns: 1fr;
+    gap: 16px;
+  }
+
+  .chart-content {
+    height: 250px;
+  }
+}
+</style>

+ 206 - 330
web/src/views/content/aiTagging/taggingResults/index.vue

@@ -1,10 +1,27 @@
 <template>
-  <div class="tag-system-container">
+  <div class="tagging-results-container">
     <!-- 顶部搜索栏 -->
     <div class="search-bar">
       <el-form :inline="true" :model="searchForm" class="search-form">
-        <el-form-item label="标签体系名称:">
-          <el-input v-model="searchForm.name" placeholder="请输入" style="width: 300px;"></el-input>
+        <el-form-item label="打标时间:">
+          <el-date-picker
+            v-model="searchForm.dateRange"
+            type="daterange"
+            range-separator="~"
+            start-placeholder="开始日期"
+            end-placeholder="结束日期"
+            style="width: 300px;"
+          ></el-date-picker>
+        </el-form-item>
+        <el-form-item label="标签体系:">
+          <el-select v-model="searchForm.tagSystem" placeholder="全部" style="width: 200px;">
+            <el-option label="全部" value=""></el-option>
+            <el-option label="海洋经济" value="ocean"></el-option>
+            <el-option label="绿色金融" value="green"></el-option>
+            <el-option label="养老产业" value="elderly"></el-option>
+            <el-option label="科技创新" value="tech"></el-option>
+            <el-option label="乡村振兴" value="rural"></el-option>
+          </el-select>
         </el-form-item>
         <el-form-item>
           <el-button type="primary" @click="handleSearch">查询</el-button>
@@ -15,222 +32,238 @@
       </el-form>
     </div>
 
-    <!-- 标签体系卡片网格 -->
-    <div class="tag-system-grid">
-      <!-- 新建标签体系卡片 -->
-      <div class="tag-system-card create-card" @click="handleCreateTagSystem">
-        <div class="create-icon">
-          <i class="el-icon-plus"></i>
-        </div>
-        <div class="create-title">新建标签体系</div>
-        <div class="create-desc">创建新的标签分类体系,用于业务的标签管理</div>
-      </div>
-
-      <!-- 标签体系卡片 -->
-      <div v-for="system in tagSystems" :key="system.id" class="tag-system-card">
-        <div class="card-header">
-          <div class="system-name">{{ system.name }}</div>
-          <div class="card-actions">
-            <el-button type="text" icon="el-icon-edit" @click.stop="handleEditTagSystem(system)"></el-button>
-            <el-dropdown trigger="click" @command="(command) => handleDropdownCommand(command, system)">
-              <el-button type="text" icon="el-icon-more"></el-button>
-              <el-dropdown-menu slot="dropdown">
-                <el-dropdown-item v-if="system.status === 'enabled'" command="disable">停用</el-dropdown-item>
-                <el-dropdown-item v-else command="enable">启用</el-dropdown-item>
-                <el-dropdown-item command="delete" divided>删除</el-dropdown-item>
-              </el-dropdown-menu>
-            </el-dropdown>
-          </div>
-        </div>
-        <div class="system-status">
-          <el-tag :type="system.status === 'enabled' ? 'success' : 'info'">
-            {{ system.status === 'enabled' ? '已启用' : '未启用' }}
-          </el-tag>
-        </div>
-        <div class="system-desc">{{ system.description }}</div>
-        <div class="system-meta">
-          <span class="tag-count">标签数量:{{ system.tagCount }}</span>
-          <span class="create-date">{{ system.createDate }}</span>
-        </div>
-        <div class="card-footer">
-          <el-button type="text" @click.stop="handleViewTags(system)">
-            <i class="el-icon-menu"></i> 查看标签列表
-          </el-button>
-        </div>
-      </div>
-    </div>
-
-    <!-- 分页控件 -->
-    <div class="pagination-container">
-      <div class="total-count">共 {{ totalCount }} 条数据</div>
-      <el-pagination
-        :current-page="currentPage"
-        :page-size="pageSize"
-        :page-sizes="[10, 20, 50]"
-        layout="prev, pager, next"
-        :total="totalCount"
-        @size-change="handleSizeChange"
-        @current-change="handleCurrentChange"
-      ></el-pagination>
-    </div>
+    <!-- 标签页 -->
+    <el-tabs v-model="activeTab" class="result-tabs">
+      <!-- 数据概览标签页 -->
+      <el-tab-pane label="数据概览" name="overview">
+        <Overview 
+          :trend-period="trendPeriod"
+          :tag-sort="tagSort"
+        />
+      </el-tab-pane>
+
+      <!-- 打标明细标签页 -->
+      <el-tab-pane label="打标明细" name="detail">
+        <Detail 
+          :detail-data="detailData"
+          :total-detail-count="totalDetailCount"
+          :current-detail-page="currentDetailPage"
+          :detail-page-size="detailPageSize"
+          @detail-search="handleDetailSearch"
+          @detail-reset="handleDetailReset"
+          @view-detail="handleViewDetail"
+          @export-data="handleExport"
+          @size-change="handleDetailSizeChange"
+          @current-change="handleDetailCurrentChange"
+        />
+      </el-tab-pane>
+    </el-tabs>
   </div>
 </template>
 
 <script>
+import Overview from './components/Overview.vue'
+import Detail from './components/Detail.vue'
+
 export default {
-  name: 'TagSystemManagement',
+  name: 'TaggingResults',
+  components: {
+    Overview,
+    Detail
+  },
   data() {
     return {
+      // 激活的标签页
+      activeTab: 'overview',
+      
       // 搜索表单
       searchForm: {
-        name: ''
+        dateRange: [],
+        tagSystem: ''
+      },
+      
+      // 打标趋势周期
+      trendPeriod: 'month',
+      
+      // 标签排序方式
+      tagSort: 'desc',
+      
+      // 明细搜索表单
+      detailSearchForm: {
+        loanApplyNo: '',
+        contractNo: ''
       },
       
-      // 标签体系列表
-      tagSystems: [
+      // 明细数据
+      detailData: [
+        {
+          loanApplyNo: 'AP20240302001',
+          contractNo: '',
+          taggingTime: '2023-10-28 14:23:12',
+          tags: ['标签A', '标签B', '标签C'],
+          operator: '智能打标平台'
+        },
+        {
+          loanApplyNo: 'AP20240302002',
+          contractNo: 'CT20250203002',
+          taggingTime: '2023-10-27 14:23:12',
+          tags: ['标签B'],
+          operator: '王武'
+        },
+        {
+          loanApplyNo: 'AP20240302003',
+          contractNo: 'CT20250203003',
+          taggingTime: '2023-10-26 14:23:12',
+          tags: ['标签C'],
+          operator: '王武'
+        },
+        {
+          loanApplyNo: 'AP20240302003',
+          contractNo: 'CT20250203001',
+          taggingTime: '2023-10-26 14:23:12',
+          tags: ['标签E', '标签F', '标签G'],
+          operator: '智能打标平台'
+        },
         {
-          id: 1,
-          name: '海洋经济',
-          status: 'enabled',
-          description: '涵盖海洋渔业、海洋装备、海洋旅游等海洋经济相关产业的标签分类体系',
-          tagCount: 53,
-          createDate: '2026-02-01'
+          loanApplyNo: 'AP20240302001',
+          contractNo: 'CT20250203002',
+          taggingTime: '2023-10-26 14:23:12',
+          tags: ['标签B'],
+          operator: '王武'
         },
         {
-          id: 2,
-          name: '绿色金融',
-          status: 'disabled',
-          description: '包含绿色能源、节能环保、清洁生产等绿色产业相关的标签分类体系',
-          tagCount: 53,
-          createDate: '2026-02-01'
+          loanApplyNo: 'AP20240302002',
+          contractNo: 'CT20250203003',
+          taggingTime: '2023-10-26 14:23:12',
+          tags: ['标签C'],
+          operator: '王武'
         },
         {
-          id: 3,
-          name: '养老产业',
-          status: 'enabled',
-          description: '涵盖养老服务、健康管理、老年用品等养老产业相关的标签分类体系',
-          tagCount: 53,
-          createDate: '2026-02-01'
+          loanApplyNo: 'AP20240302003',
+          contractNo: 'CT20250203001',
+          taggingTime: '2023-10-26 14:23:12',
+          tags: ['标签A'],
+          operator: '王武'
         },
         {
-          id: 4,
-          name: '科技创新',
-          status: 'enabled',
-          description: '包含人工智能、新一代信息技术、生物医药等科技创新领域的标签分类体系',
-          tagCount: 53,
-          createDate: '2026-02-01'
+          loanApplyNo: 'AP20240302003',
+          contractNo: 'CT20250203002',
+          taggingTime: '2023-10-26 14:23:12',
+          tags: ['标签B'],
+          operator: '王武'
         },
         {
-          id: 5,
-          name: '乡村振兴',
-          status: 'enabled',
-          description: '暂无描述',
-          tagCount: 53,
-          createDate: '2026-02-01'
+          loanApplyNo: 'AP20240302003',
+          contractNo: 'CT20250203003',
+          taggingTime: '2023-10-26 14:23:12',
+          tags: ['标签C'],
+          operator: '王武'
+        },
+        {
+          loanApplyNo: 'AP20240302003',
+          contractNo: 'CT20250203001',
+          taggingTime: '2023-10-26 14:23:12',
+          tags: ['标签C'],
+          operator: '王武'
         }
       ],
       
       // 分页数据
-      totalCount: 15,
-      currentPage: 1,
-      pageSize: 10
+      totalDetailCount: 120,
+      currentDetailPage: 1,
+      detailPageSize: 10,
+      
+      // 图表实例
+      trendChart: null,
+      distributionChart: null
     }
   },
+  mounted() {
+    // 初始化图表
+    this.initCharts()
+  },
   methods: {
-    // 搜索标签体系
+    // 搜索
     handleSearch() {
-      console.log('搜索标签体系:', this.searchForm.name)
+      console.log('搜索:', this.searchForm)
       // 这里可以调用后端接口进行搜索
       this.$message.success('搜索成功')
     },
 
     // 重置搜索
     handleReset() {
-      this.searchForm.name = ''
+      this.searchForm.dateRange = []
+      this.searchForm.tagSystem = ''
       console.log('重置搜索')
     },
 
-    // 创建标签体系
-    handleCreateTagSystem() {
-      console.log('创建标签体系')
-      this.$message.success('打开创建标签体系对话框')
-      // 这里可以打开创建标签体系的对话框
-    },
-
-    // 编辑标签体系
-    handleEditTagSystem(system) {
-      console.log('编辑标签体系:', system.name)
-      // 使用Vue Router跳转到编辑页面,并携带参数
-      this.$router.push({
-        path: '/home/tag-system-edit',
-        query: { id: system.id }
-      })
-    },
-
-    // 下拉菜单命令处理
-    handleDropdownCommand(command, system) {
-      switch (command) {
-        case 'enable':
-          this.handleEnableTagSystem(system)
-          break
-        case 'disable':
-          this.handleDisableTagSystem(system)
-          break
-        case 'delete':
-          this.handleDeleteTagSystem(system)
-          break
-        default:
-          break
-      }
+    // 初始化图表
+    initCharts() {
+      // 模拟数据
+      const trendData = [
+        { month: '1月', value: 60 },
+        { month: '2月', value: 80 },
+        { month: '3月', value: 110 },
+        { month: '4月', value: 65 },
+        { month: '5月', value: 90 },
+        { month: '6月', value: 130 },
+        { month: '7月', value: 110 },
+        { month: '8月', value: 140 },
+        { month: '9月', value: 160 }
+      ]
+      
+      const distributionData = [
+        { name: '远洋捕捞', value: 150 },
+        { name: '船舶制造', value: 130 },
+        { name: '海水养殖', value: 100 },
+        { name: '海洋运输', value: 70 },
+        { name: '海洋旅游', value: 50 },
+        { name: '生物医药', value: 40 }
+      ]
+      
+      // 这里可以使用G2Plot或其他图表库初始化图表
+      console.log('初始化图表', trendData, distributionData)
     },
 
-    // 启用标签体系
-    handleEnableTagSystem(system) {
-      console.log('启用标签体系:', system.name)
-      system.status = 'enabled'
-      this.$message.success(`启用标签体系: ${system.name}`)
+    // 明细搜索
+    handleDetailSearch() {
+      console.log('明细搜索:', this.detailSearchForm)
+      // 这里可以调用后端接口进行搜索
+      this.$message.success('搜索成功')
     },
 
-    // 停用标签体系
-    handleDisableTagSystem(system) {
-      console.log('停用标签体系:', system.name)
-      system.status = 'disabled'
-      this.$message.success(`停用标签体系: ${system.name}`)
+    // 重置明细搜索
+    handleDetailReset() {
+      this.detailSearchForm.loanApplyNo = ''
+      this.detailSearchForm.contractNo = ''
+      console.log('重置明细搜索')
     },
 
-    // 删除标签体系
-    handleDeleteTagSystem(system) {
-      this.$confirm(`确定要删除标签体系「${system.name}」吗?`, '警告', {
-        confirmButtonText: '确定',
-        cancelButtonText: '取消',
-        type: 'warning'
-      }).then(() => {
-        console.log('删除标签体系:', system.name)
-        // 这里可以调用后端接口删除标签体系
-        this.$message.success(`删除标签体系: ${system.name}`)
-      }).catch(() => {
-        console.log('取消删除标签体系:', system.name)
-      })
+    // 查看详情
+    handleViewDetail(row) {
+      // console.log('查看详情:', row)
+      // this.$message.success('查看详情')
+      // 这里可以打开详情对话框
     },
 
-    // 查看标签列表
-    handleViewTags(system) {
-      console.log('查看标签列表:', system.name)
-      this.$message.success(`查看标签列表: ${system.name}`)
-      // 这里可以跳转到标签列表页面
+    // 导出数据
+    handleExport() {
+      console.log('导出数据')
+      this.$message.success('导出成功')
+      // 这里可以调用后端接口导出数据
     },
 
-    // 分页大小变化
-    handleSizeChange(size) {
+    // 明细分页大小变化
+    handleDetailSizeChange(size) {
       console.log('每页条数:', size)
-      this.pageSize = size
+      this.detailPageSize = size
       // 这里可以重新加载数据
     },
 
-    // 当前页码变化
-    handleCurrentChange(current) {
+    // 明细当前页码变化
+    handleDetailCurrentChange(current) {
       console.log('当前页码:', current)
-      this.currentPage = current
+      this.currentDetailPage = current
       // 这里可以重新加载数据
     }
   }
@@ -238,7 +271,7 @@ export default {
 </script>
 
 <style scoped>
-.tag-system-container {
+.tagging-results-container {
   padding: 20px;
   background-color: #f0f2f5;
   min-height: 100vh;
@@ -256,184 +289,27 @@ export default {
 .search-form {
   display: flex;
   align-items: center;
+  gap: 16px;
 }
 
-/* 标签体系卡片网格 */
-.tag-system-grid {
-  display: grid;
-  grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));
-  gap: 20px;
-  margin-bottom: 30px;
-}
-
-/* 标签体系卡片 */
-.tag-system-card {
-  background-color: #fff;
-  border-radius: 8px;
-  padding: 20px;
-  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
-  transition: all 0.3s ease;
-  cursor: pointer;
-}
-
-.tag-system-card:hover {
-  transform: translateY(-4px);
-  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
-}
-
-/* 创建标签体系卡片 */
-.create-card {
-  display: flex;
-  flex-direction: column;
-  align-items: center;
-  justify-content: center;
-  min-height: 200px;
-  border: 2px dashed #e8e8e8;
-  background-color: #fafafa;
-}
-
-.create-card:hover {
-  border-color: #1890ff;
-  background-color: #f0f9ff;
-}
-
-.create-icon {
-  width: 60px;
-  height: 60px;
-  border-radius: 50%;
-  background-color: #e6f7ff;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  margin-bottom: 16px;
-}
-
-.create-icon i {
-  font-size: 24px;
-  color: #1890ff;
-}
-
-.create-title {
-  font-size: 16px;
-  font-weight: 500;
-  color: #303133;
-  margin-bottom: 8px;
-}
-
-.create-desc {
-  font-size: 14px;
-  color: #909399;
-  text-align: center;
-  line-height: 1.4;
-}
-
-/* 卡片头部 */
-.card-header {
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-  margin-bottom: 12px;
-}
-
-.system-name {
-  font-size: 16px;
-  font-weight: 500;
-  color: #303133;
-}
-
-.card-actions {
-  display: flex;
-  align-items: center;
-  gap: 8px;
-}
-
-/* 卡片内容 */
-.system-status {
-  margin-bottom: 12px;
-}
-
-.system-desc {
-  font-size: 14px;
-  color: #606266;
-  line-height: 1.4;
-  margin-bottom: 16px;
-  min-height: 40px;
-}
-
-.system-meta {
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-  font-size: 12px;
-  color: #909399;
-  margin-bottom: 16px;
-}
-
-.tag-count {
-  display: flex;
-  align-items: center;
-  gap: 4px;
-}
-
-.create-date {
-  display: flex;
-  align-items: center;
-  gap: 4px;
-}
-
-/* 卡片底部 */
-.card-footer {
-  border-top: 1px solid #f0f0f0;
-  padding-top: 16px;
-}
-
-/* 分页控件 */
-.pagination-container {
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
+/* 标签页样式 */
+.result-tabs {
   background-color: #fff;
-  padding: 20px;
   border-radius: 8px;
   box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
-}
-
-.total-count {
-  font-size: 14px;
-  color: #606266;
+  overflow: hidden;
 }
 
 /* 响应式设计 */
-@media (max-width: 1200px) {
-  .tag-system-grid {
-    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
-  }
-}
-
 @media (max-width: 768px) {
-  .tag-system-container {
+  .tagging-results-container {
     padding: 10px;
   }
 
-  .tag-system-grid {
-    grid-template-columns: 1fr;
-    gap: 16px;
-  }
-
   .search-form {
     flex-direction: column;
     align-items: flex-start;
     gap: 12px;
   }
-
-  .pagination-container {
-    flex-direction: column;
-    align-items: flex-start;
-    gap: 16px;
-  }
-
-  .el-pagination {
-    align-self: flex-end;
-  }
 }
 </style>

+ 5 - 197
web/src/views/content/aiTagging/taggingSystemManage/TagSystemEdit.vue

@@ -26,7 +26,6 @@
           <div class="tag-tree-section">
             <TagConfig 
               :tag-system="currentSystem"
-              :tag-tree-data="tagTreeData"
               :tree-props="treeProps"
               @node-click="handleNodeClick"
               @dropdown-command="handleDropdownCommand"
@@ -78,112 +77,6 @@ export default {
       // 搜索关键词
       searchKeyword: '',
       
-      // 标签树数据
-      tagTreeData: [
-        {
-          id: 1,
-          label: '海洋经济',
-          children: [
-            {
-              id: 2,
-              label: '海洋产业(A)',
-              children: [
-                {
-                  id: 3,
-                  label: '海洋渔业(A1)',
-                  children: [
-                    {
-                      id: 4,
-                      label: '海洋捕捞(A11)',
-                      children: [
-                        {
-                          id: 5,
-                          label: '远洋捕捞(A111)',
-                        },
-                        {
-                          id: 6,
-                          label: '近海捕捞(A112)',
-                        }
-                      ]
-                    },
-                    {
-                      id: 7,
-                      label: '海水养殖(A12)',
-                    }
-                  ]
-                },
-                {
-                  id: 8,
-                  label: '海洋盐业(A2)',
-                }
-              ]
-            },
-            {
-              id: 9,
-              label: '海洋科研教育(B)',
-            },
-            {
-              id: 10,
-              label: '海洋公共管理服务(C)',
-              children: [
-                {
-                  id: 11,
-                  label: '海洋管理(C18)',
-                },
-                {
-                  id: 12,
-                  label: '海洋社会团体基金会与国际组织(C19)',
-                },
-                {
-                  id: 13,
-                  label: '海洋技术服务(C20)',
-                },
-                {
-                  id: 14,
-                  label: '海洋信息服务(C21)',
-                },
-                {
-                  id: 15,
-                  label: '海洋生态环境保护修复(C22)',
-                },
-                {
-                  id: 16,
-                  label: '海洋地质勘查(C23)',
-                  children: [
-                    {
-                      id: 17,
-                      label: '海洋矿产地质勘查(C231)',
-                      children: [
-                        {
-                          id: 18,
-                          label: '海洋能源矿产地质勘查(C2311)',
-                        },
-                        {
-                          id: 19,
-                          label: '海洋固体矿产地质勘查(C2312)',
-                        },
-                        {
-                          id: 20,
-                          label: '其他海洋矿产地质勘查(C2319)',
-                        }
-                      ]
-                    }
-                  ]
-                }
-              ]
-            },
-            {
-              id: 21,
-              label: '海洋上游相关产业(D)',
-            },
-            {
-              id: 22,
-              label: '海洋下游相关产业(E)',
-            }
-          ]
-        }
-      ],
-      
       // 树节点配置
       treeProps: {
         children: 'children',
@@ -298,8 +191,8 @@ export default {
 
 <style scoped>
 .edit-page {
-  padding: 20px;
-  background-color: #f0f2f5;
+  padding: 0;
+  background-color: transparent;
   min-height: 100vh;
 }
 
@@ -370,68 +263,6 @@ export default {
   /* margin-top: 20px; */
 }
 
-.tag-tree-header {
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-  margin-bottom: 16px;
-  padding-bottom: 12px;
-  border-bottom: 1px solid #e8e8e8;
-}
-
-.tree-header-left {
-  display: flex;
-  align-items: center;
-  gap: 16px;
-}
-
-.tree-header-left h3 {
-  font-size: 16px;
-  font-weight: 600;
-  color: #303133;
-  margin: 0;
-}
-
-.tree-header-actions {
-  display: flex;
-  gap: 8px;
-}
-
-.tree-header-search {
-  display: flex;
-  align-items: center;
-}
-
-.tag-content {
-  display: flex;
-  gap: 20px;
-  min-height: 600px;
-}
-
-.tag-actions {
-  flex: 1;
-  background-color: #fafafa;
-  border-radius: 8px;
-  padding: 20px;
-  overflow-y: auto;
-}
-
-.empty-data {
-  text-align: center;
-  padding: 60px 20px;
-}
-
-.empty-data img {
-  width: 200px;
-  height: 200px;
-  margin-bottom: 16px;
-}
-
-.empty-data p {
-  font-size: 16px;
-  color: #909399;
-}
-
 .tag-test-section {
   text-align: center;
   color: #909399;
@@ -439,23 +270,14 @@ export default {
 
 /* 确保TagTree组件的宽度 */
 :deep(.tag-tree) {
-  flex: 0 0 350px;
+  flex: 1;
+  min-width: 200px;
+  max-width: 500px;
   max-height: 600px;
   overflow-y: auto;
 }
 
 /* 响应式设计 */
-@media (max-width: 1200px) {
-  .tag-content {
-    flex-direction: column;
-  }
-  
-  .tag-tree {
-    flex: none;
-    max-height: 300px;
-  }
-}
-
 @media (max-width: 768px) {
   .edit-header {
     flex-direction: column;
@@ -465,19 +287,5 @@ export default {
   .header-right {
     align-self: flex-start;
   }
-  
-  .edit-toolbar {
-    flex-direction: column;
-    align-items: flex-start;
-    gap: 16px;
-  }
-  
-  .toolbar-right {
-    align-self: stretch;
-  }
-  
-  .toolbar-right .el-input {
-    width: 100%;
-  }
 }
 </style>

+ 38 - 57
web/src/views/content/aiTagging/taggingSystemManage/components/TagConfig.vue

@@ -3,16 +3,13 @@
     <!-- 标签树和操作区 -->
     <div class="tag-content">
       <!-- 标签树 -->
-      <TagTree 
-        :tree-data="tagTreeData" 
-        :tree-props="treeProps"
-        @node-click="handleNodeClick"
-        @dropdown-command="handleDropdownCommand"
-        @add-node="handleAddNode"
-        @import-nodes="handleImport"
-        @refresh-nodes="handleRefresh"
-        @search="handleSearch"
-      />
+      <div class="tag-tree-container">
+        <TagTree 
+          :tree-props="treeProps"
+          @node-click="handleNodeClick"
+          @dropdown-command="handleDropdownCommand"
+        />
+      </div>
 
       <!-- 右侧操作区 -->
       <div class="tag-actions">
@@ -25,7 +22,7 @@
           @cancel="handleCancelEdit"
         />
         <div v-else class="empty-data">
-          <img src="https://trae-api-cn.mchost.guru/api/ide/v1/text_to_image?prompt=empty%20state%2C%20box%20with%20confetti%2C%20no%20data%20illustration%2C%20simple%20style&image_size=square" alt="暂无数据">
+          <!-- <img src="https://trae-api-cn.mchost.guru/api/ide/v1/text_to_image?prompt=empty%20state%2C%20box%20with%20confetti%2C%20no%20data%20illustration%2C%20simple%20style&image_size=square" alt="暂无数据"> -->
           <p>请选择一个标签节点查看详情</p>
         </div>
       </div>
@@ -48,10 +45,6 @@ export default {
       type: Object,
       default: () => ({})
     },
-    tagTreeData: {
-      type: Array,
-      default: () => ([])
-    },
     treeProps: {
       type: Object,
       default: () => ({
@@ -74,8 +67,6 @@ export default {
       this.selectedNode = this.enrichNodeData(data, node);
       // 退出编辑模式
       this.isEditMode = false;
-      // 触发父组件事件
-      this.$emit('node-click', data, node);
     },
 
     // 丰富节点数据,添加标签详情信息
@@ -92,14 +83,37 @@ export default {
       return {
         ...data,
         path: path.join(' / '),
+        version: '1.0',
         revisionTime: '2026-02-05 12:00:00',
         revisionUser: '张三',
         description: data.description || '包含海洋行政管理、涉海行业管理、海洋开发区管理和海洋社会保障服务等活动',
         regex: data.regex || '(abc)|(adc)|(adc)|(adc)|(adc)|(adc)|(adc)|(adc)|(adc)|(adc)|(adc)|(adc)|(adc)',
         hintWords: data.hintWords || '',
-        name: path.join(' / '),
+        name: data.label || path.join(' / '),
         scope: '文本内容涉及海洋行政管理、涉海行业管理、海洋开发区管理、海洋社会保障服务等相关活动时,标注上述标签。',
-        rules: '逐句分析文本,判断是否包含标签适用范围内的核心行为与管理场景;只要文本涵盖海洋行政管理、涉海行业监管、海洋园区/开发区运营管理、海洋领域社会保障服务任一内容,即匹配标签;严格按照给定格式输出标签,不得修改、拆分、合并标签文字,无匹配内容输出「无匹配标签」。'
+        rules: '逐句分析文本,判断是否包含标签适用范围内的核心行为与管理场景;只要文本涵盖海洋行政管理、涉海行业监管、海洋园区/开发区运营管理、海洋领域社会保障服务任一内容,即匹配标签;严格按照给定格式输出标签,不得修改、拆分、合并标签文字,无匹配内容输出「无匹配标签」。',
+        revisions: [
+          {
+            version: '1.0',
+            revisionTime: '2026-02-05 12:00:00',
+            revisionUser: '张三',
+            description: '包含海洋行政管理、涉海行业管理、海洋开发区管理和海洋社会保障服务等活动',
+            regex: '(abc)|(adc)|(adc)|(adc)|(adc)|(adc)|(adc)|(adc)|(adc)|(adc)|(adc)|(adc)|(adc)',
+            name: data.label || path.join(' / '),
+            scope: '文本内容涉及海洋行政管理、涉海行业管理、海洋开发区管理、海洋社会保障服务等相关活动时,标注上述标签。',
+            rules: '逐句分析文本,判断是否包含标签适用范围内的核心行为与管理场景;只要文本涵盖海洋行政管理、涉海行业监管、海洋园区/开发区运营管理、海洋领域社会保障服务任一内容,即匹配标签;严格按照给定格式输出标签,不得修改、拆分、合并标签文字,无匹配内容输出「无匹配标签」。'
+          },
+          {
+            version: '0.9',
+            revisionTime: '2026-02-01 10:30:00',
+            revisionUser: '李四',
+            description: '包含海洋行政管理、涉海行业管理和海洋开发区管理等活动',
+            regex: '(abc)|(adc)|(adc)|(adc)|(adc)',
+            name: data.label || path.join(' / '),
+            scope: '文本内容涉及海洋行政管理、涉海行业管理、海洋开发区管理等相关活动时,标注上述标签。',
+            rules: '逐句分析文本,判断是否包含标签适用范围内的核心行为与管理场景;只要文本涵盖海洋行政管理、涉海行业监管、海洋园区/开发区运营管理任一内容,即匹配标签;严格按照给定格式输出标签,不得修改、拆分、合并标签文字,无匹配内容输出「无匹配标签」。'
+          }
+        ]
       };
     },
 
@@ -113,7 +127,6 @@ export default {
       switch(command) {
         case 'add':
           console.log('新增子节点到:', data.label);
-          // 这里可以添加新增节点的逻辑
           break;
         case 'edit':
           console.log('编辑节点:', data.label);
@@ -122,18 +135,13 @@ export default {
           break;
         case 'delete':
           console.log('删除节点:', data.label);
-          // 这里可以添加删除节点的逻辑
           break;
       }
-      
-      // 触发父组件事件
-      this.$emit('dropdown-command', command, data, node);
     },
 
     // 编辑标签
     handleEditTag() {
       this.isEditMode = true;
-      this.$emit('edit-tag');
     },
 
     // 保存标签
@@ -145,38 +153,11 @@ export default {
       this.isEditMode = false;
       // 更新选中节点的数据
       this.selectedNode = { ...this.selectedNode, ...formData };
-      // 触发父组件事件
-      this.$emit('save-tag', formData);
     },
 
     // 取消编辑
     handleCancelEdit() {
       this.isEditMode = false;
-      this.$emit('cancel-edit');
-    },
-
-    // 添加节点
-    handleAddNode() {
-      console.log('添加节点');
-      this.$emit('add-node');
-    },
-
-    // 导入
-    handleImport() {
-      console.log('导入节点');
-      this.$emit('import-nodes');
-    },
-
-    // 刷新
-    handleRefresh() {
-      console.log('刷新节点');
-      this.$emit('refresh-nodes');
-    },
-
-    // 搜索
-    handleSearch() {
-      console.log('搜索:', this.searchKeyword);
-      this.$emit('search', this.searchKeyword);
     }
   }
 }
@@ -199,7 +180,6 @@ export default {
   flex: 1;
   background-color: #fafafa;
   border-radius: 8px;
-  padding: 20px;
   overflow-y: auto;
 }
 
@@ -219,9 +199,9 @@ export default {
   color: #909399;
 }
 
-/* 确保TagTree组件的宽度 */
-:deep(.tag-tree) {
-  flex: 0 0 350px;
+/* 标签树容器 */
+.tag-tree-container {
+  flex: 0 0 220px;
   max-height: 600px;
   overflow-y: auto;
 }
@@ -232,9 +212,10 @@ export default {
     flex-direction: column;
   }
   
-  .tag-tree {
+  .tag-tree-container {
     flex: none;
     max-height: 300px;
+    width: 100%;
   }
 }
 

+ 19 - 158
web/src/views/content/aiTagging/taggingSystemManage/components/TagDetail.vue

@@ -1,52 +1,8 @@
 <template>
   <div class="tag-detail">
-    <!-- 标签路径 -->
-    <div class="tag-path">
-      {{ tagData.path || '无路径信息' }}
-    </div>
-    
-    <!-- 修订信息 -->
-    <div class="revision-info">
-      修订时间: {{ tagData.revisionTime || '未知' }} | 修订人: {{ tagData.revisionUser || '未知' }}
-    </div>
-    
     <!-- 详情展示模式 -->
-    <div v-if="!isEditMode" class="detail-view">
-      <!-- 标签描述 -->
-      <div class="detail-section">
-        <h4 class="section-title">标签描述</h4>
-        <p class="section-content">{{ tagData.description || '无描述信息' }}</p>
-      </div>
-      
-      <!-- 标签正则表达式 -->
-      <div class="detail-section">
-        <h4 class="section-title">标签正则表达式</h4>
-        <p class="section-content code">{{ tagData.regex || '无正则表达式' }}</p>
-      </div>
-      
-      <!-- 标签提示词 -->
-      <div class="detail-section">
-        <h4 class="section-title">标签提示词</h4>
-        <p class="section-content">{{ tagData.hintWords || '无提示词' }}</p>
-      </div>
-      
-      <!-- 标签名称 -->
-      <div class="detail-section">
-        <h4 class="section-title">标签名称</h4>
-        <p class="section-content">{{ tagData.name || '无名称' }}</p>
-      </div>
-      
-      <!-- 标签适用范围 -->
-      <div class="detail-section">
-        <h4 class="section-title">标签适用范围</h4>
-        <p class="section-content">{{ tagData.scope || '无适用范围' }}</p>
-      </div>
-      
-      <!-- 标注规则 -->
-      <div class="detail-section">
-        <h4 class="section-title">标注规则</h4>
-        <p class="section-content">{{ tagData.rules || '无标注规则' }}</p>
-      </div>
+    <div v-if="!isEditMode">
+      <TagDetailView :tag-data="tagData" />
       
       <!-- 编辑按钮 -->
       <div class="action-buttons">
@@ -56,62 +12,25 @@
     
     <!-- 编辑模式 -->
     <div v-else class="edit-view">
-      <!-- 标签描述 -->
-      <div class="edit-section">
-        <h4 class="section-title">标签描述</h4>
-        <el-input
-          type="textarea"
-          v-model="editForm.description"
-          placeholder="请输入标签描述"
-          :rows="3"
-        ></el-input>
-        <p class="section-hint">请简要描述标签的概念、内涵和适用范围,用于辅助智能标注体对标签含义的准确理解</p>
-      </div>
-      
-      <!-- 标签正则表达式 -->
-      <div class="edit-section">
-        <h4 class="section-title">标签正则表达式</h4>
-        <div class="regex-input-container">
-          <el-input
-            v-model="editForm.regex"
-            placeholder="请输入"
-          ></el-input>
-          <div class="regex-tools">
-            <el-button type="text" size="mini" title="括号">(</el-button>
-            <el-button type="text" size="mini" title="括号">)</el-button>
-            <el-button type="text" size="mini" title="竖线">|</el-button>
-            <el-button type="text" size="mini" title="脱字符">^</el-button>
-            <el-button type="text" size="mini" title="美元符">$</el-button>
-            <el-button type="text" size="mini" title="星号">*</el-button>
-          </div>
-        </div>
-        <p class="section-hint">优先根据正则表达式进行标注</p>
-      </div>
-      
-      <!-- 标签提示词 -->
-      <div class="edit-section">
-        <h4 class="section-title">标签提示词</h4>
-        <el-input
-          type="textarea"
-          v-model="editForm.hintWords"
-          placeholder="请输入"
-          :rows="3"
-        ></el-input>
-        <p class="section-hint">正则匹配失败时,智能体将依据提示词理解标签含义,完成智能打标。提示词需清晰描述标签的概念、内涵和适用场景,以确保打标标准准确性。</p>
-      </div>
-      
-      <!-- 操作按钮 -->
-      <div class="action-buttons edit-actions">
-        <el-button @click="handleCancel">取消</el-button>
-        <el-button type="primary" @click="handleSave">保存</el-button>
-      </div>
+      <TagDetailEdit
+        :form-data="editForm"
+        @save="handleSave"
+        @cancel="handleCancel"
+      />
     </div>
   </div>
 </template>
 
 <script>
+import TagDetailEdit from './TagDetailEdit.vue';
+import TagDetailView from './TagDetailView.vue';
+
 export default {
   name: 'TagDetail',
+  components: {
+    TagDetailEdit,
+    TagDetailView
+  },
   props: {
     tagData: {
       type: Object,
@@ -125,6 +44,7 @@ export default {
   data() {
     return {
       editForm: {
+        name: '',
         description: '',
         regex: '',
         hintWords: ''
@@ -148,6 +68,7 @@ export default {
   methods: {
     updateEditForm(data) {
       this.editForm = {
+        name: data.name || '',
         description: data.description || '',
         regex: data.regex || '',
         hintWords: data.hintWords || ''
@@ -198,38 +119,8 @@ export default {
   gap: 20px;
 }
 
-.detail-section,
-.edit-section {
-  display: flex;
-  flex-direction: column;
-  gap: 8px;
-}
-
-.section-title {
-  font-size: 14px;
-  font-weight: 500;
-  color: #303133;
-  margin: 0;
-  padding-left: 8px;
-  border-left: 3px solid #409eff;
-}
-
-.section-content {
-  font-size: 14px;
-  color: #606266;
-  line-height: 1.5;
-  margin: 0;
-}
-
-.section-content.code {
-  font-family: monospace;
-  background-color: #f5f7fa;
-  padding: 8px;
-  border-radius: 4px;
-}
-
 .action-buttons {
-  margin-top: auto;
+  margin-top: 20px;
   display: flex;
   justify-content: flex-end;
   gap: 10px;
@@ -237,39 +128,9 @@ export default {
   border-top: 1px solid #e8e8e8;
 }
 
-.edit-actions {
-  margin-top: 20px;
-}
-
-.regex-input-container {
+.edit-view {
   display: flex;
   flex-direction: column;
-  gap: 8px;
-}
-
-.regex-tools {
-  display: flex;
-  gap: 8px;
-}
-
-.section-hint {
-  font-size: 12px;
-  color: #909399;
-  margin: 0;
-  margin-top: 4px;
-  padding: 4px 0;
-}
-
-.el-input {
-  width: 100%;
-}
-
-.el-input__inner {
-  font-size: 14px;
-}
-
-.el-textarea__inner {
-  font-size: 14px;
-  line-height: 1.5;
+  gap: 20px;
 }
 </style>

+ 279 - 0
web/src/views/content/aiTagging/taggingSystemManage/components/TagDetailEdit.vue

@@ -0,0 +1,279 @@
+<template>
+  <div class="tag-edit">
+    <!-- 标签名称 -->
+    <div class="edit-section">
+      <h4 class="section-title">标签名称<span class="required">*</span></h4>
+      <el-input
+        v-model="editForm.name"
+        placeholder="请输入"
+      ></el-input>
+    </div>
+    
+    <!-- 上级标签 (仅新增时显示) -->
+    <div v-if="isAddMode" class="edit-section">
+      <h4 class="section-title">上级标签<span class="required">*</span></h4>
+      <div class="tree-select-container">
+        <TreeSelect
+          v-model="editForm.parent"
+          :data="parentOptions"
+          :tree-props="treeProps"
+          placeholder="请选择"
+        ></TreeSelect>
+      </div>
+    </div>
+    
+    <!-- 标签描述 -->
+    <div class="edit-section">
+      <h4 class="section-title">标签描述<span class="required">*</span></h4>
+      <el-input
+        type="textarea"
+        v-model="editForm.description"
+        placeholder="请输入标签描述"
+        :rows="3"
+      ></el-input>
+      <p class="section-hint">请简要描述标签的概念、内涵和适用范围,用于辅助智能标注体对标签含义的准确理解</p>
+    </div>
+    
+    <!-- 标签正则表达式 -->
+    <div class="edit-section">
+      <h4 class="section-title">标签正则表达式<span class="required">*</span></h4>
+      <div class="regex-input-container">
+        <el-input
+          v-model="editForm.regex"
+          placeholder="请输入"
+        ></el-input>
+        <div class="regex-tools">
+          <el-button 
+            size="mini" 
+            title="括号" 
+            @click="insertRegexChar('(')"
+            class="regex-tool-btn"
+          >(</el-button>
+          <el-button 
+            size="mini" 
+            title="括号" 
+            @click="insertRegexChar(')')"
+            class="regex-tool-btn"
+          >)</el-button>
+          <el-button 
+            size="mini" 
+            title="竖线" 
+            @click="insertRegexChar('|')"
+            class="regex-tool-btn"
+          >|</el-button>
+          <el-button 
+            size="mini" 
+            title="脱字符" 
+            @click="insertRegexChar('^')"
+            class="regex-tool-btn"
+          >^</el-button>
+          <el-button 
+            size="mini" 
+            title="美元符" 
+            @click="insertRegexChar('$')"
+            class="regex-tool-btn"
+          >$</el-button>
+          <el-button 
+            size="mini" 
+            title="星号" 
+            @click="insertRegexChar('*')"
+            class="regex-tool-btn"
+          >*</el-button>
+        </div>
+      </div>
+      <p class="section-hint">优先根据正则表达式进行标注</p>
+    </div>
+    
+    <!-- 标签提示词 -->
+    <div class="edit-section">
+      <h4 class="section-title">标签提示词<span class="required">*</span></h4>
+      <el-input
+        type="textarea"
+        v-model="editForm.hintWords"
+        placeholder="请输入"
+        :rows="3"
+      ></el-input>
+      <p class="section-hint">正则匹配失败时,智能体将依据提示词理解标签含义,完成智能打标。提示词需清晰描述标签的概念、内涵和适用场景,以确保打标标准准确性。</p>
+    </div>
+    
+    <!-- 操作按钮 -->
+    <div class="action-buttons edit-actions">
+      <el-button @click="handleCancel">取消</el-button>
+      <el-button type="primary" @click="handleSave">保存</el-button>
+    </div>
+  </div>
+</template>
+
+<script>
+import TreeSelect from './TreeSelect.vue';
+
+export default {
+  name: 'TagDetailEdit',
+  components: {
+    TreeSelect
+  },
+  props: {
+    formData: {
+      type: Object,
+      default: () => ({
+        name: '',
+        parent: '',
+        description: '',
+        regex: '',
+        hintWords: ''
+      })
+    },
+    isAddMode: {
+      type: Boolean,
+      default: false
+    },
+    parentOptions: {
+      type: Array,
+      default: () => []
+    },
+    treeProps: {
+      type: Object,
+      default: () => ({
+        children: 'children',
+        label: 'label'
+      })
+    }
+  },
+  data() {
+    return {
+      editForm: {
+        name: '',
+        parent: '',
+        description: '',
+        regex: '',
+        hintWords: ''
+      }
+    }
+  },
+  watch: {
+    formData: {
+      handler(newData) {
+        this.updateEditForm(newData)
+      },
+      deep: true,
+      immediate: true
+    }
+  },
+  methods: {
+    updateEditForm(data) {
+      this.editForm = {
+        name: data.name || '',
+        parent: data.parent || '',
+        description: data.description || '',
+        regex: data.regex || '',
+        hintWords: data.hintWords || ''
+      }
+    },
+    insertRegexChar(char) {
+      this.editForm.regex += char;
+    },
+    handleSave() {
+      this.$emit('save', this.editForm)
+    },
+    handleCancel() {
+      this.$emit('cancel')
+      this.updateEditForm(this.formData)
+    }
+  }
+}
+</script>
+
+<style scoped>
+.tag-edit {
+  display: flex;
+  flex-direction: column;
+  gap: 20px;
+}
+
+.edit-section {
+  display: flex;
+  flex-direction: column;
+  gap: 8px;
+}
+
+.section-title {
+  font-size: 14px;
+  font-weight: 500;
+  color: #303133;
+  margin: 0;
+  padding-left: 8px;
+  border-left: 3px solid #409eff;
+}
+
+.required {
+  color: #f56c6c;
+  margin-left: 4px;
+}
+
+.action-buttons {
+  margin-top: auto;
+  display: flex;
+  justify-content: flex-end;
+  gap: 10px;
+  padding-top: 20px;
+  border-top: 1px solid #e8e8e8;
+}
+
+.edit-actions {
+  margin-top: 20px;
+}
+
+.regex-input-container {
+  display: flex;
+  flex-direction: column;
+  gap: 8px;
+}
+
+.regex-tools {
+  display: flex;
+  gap: 0;
+  align-items: center;
+}
+
+/* 使用::v-deep确保样式应用到Element UI按钮 */
+.regex-tools ::v-deep .regex-tool-btn {
+  width: 28px;
+  height: 28px;
+  min-width: 28px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  font-size: 14px;
+  border-radius: 4px;
+  transition: all 0.3s ease;
+  background-color: #ecf5ff;
+  color: #409eff;
+  border: 1px solid transparent;
+}
+
+.regex-tools ::v-deep .regex-tool-btn:hover {
+  background-color: #3a8ee6;
+  color: #fff;
+}
+
+.section-hint {
+  font-size: 12px;
+  color: #909399;
+  margin: 0;
+  margin-top: 4px;
+  padding: 4px 0;
+}
+
+.el-input {
+  width: 100%;
+}
+
+.el-input__inner {
+  font-size: 14px;
+}
+
+.el-textarea__inner {
+  font-size: 14px;
+  line-height: 1.5;
+}
+</style>

+ 282 - 0
web/src/views/content/aiTagging/taggingSystemManage/components/TagDetailView.vue

@@ -0,0 +1,282 @@
+<template>
+  <div class="detail-view">
+    <!-- 标签路径 -->
+    <div class="tag-path">
+      {{ tagData.path || '无路径信息' }}
+    </div>
+    
+    <!-- 版本信息 -->
+    <div class="version-info">
+      版本{{ tagData.version || '1.0' }}. 修订时间: {{ tagData.revisionTime || '未知' }} 修订人: {{ tagData.revisionUser || '未知' }}
+    </div>
+    
+    <!-- 标签描述 -->
+    <div class="detail-section">
+      <h4 class="section-title">标签描述*</h4>
+      <p class="section-content">{{ tagData.description || '无描述信息' }}</p>
+    </div>
+    
+    <!-- 标签正则表达式 -->
+    <div class="detail-section">
+      <h4 class="section-title">标签正则表达式*</h4>
+      <p class="section-content code">{{ tagData.regex || '无正则表达式' }}</p>
+    </div>
+    
+    <!-- 标签提示词 -->
+    <div class="detail-section">
+      <h4 class="section-title">标签提示词*</h4>
+      <p class="section-content">
+        <span class="info-label">标签名称:</span>{{ tagData.name || '无名称' }}<br>
+        <span class="info-label">标签适用范围:</span>{{ tagData.scope || '无适用范围' }}<br>
+        <span class="info-label">标注规则:</span>{{ tagData.rules || '无标注规则' }}
+      </p>
+    </div>
+    
+    <!-- 修订记录 -->
+    <div class="detail-section">
+      <h4 class="section-title">修订记录</h4>
+      <div class="revision-list">
+        <div 
+          v-for="(revision, index) in tagData.revisions || []" 
+          :key="index" 
+          class="revision-item"
+        >
+          <div class="revision-info">
+            版本{{ revision.version }}. 修订时间: {{ revision.revisionTime }} 修订人: {{ revision.revisionUser }}
+          </div>
+          <el-button 
+            type="text" 
+            @click="showVersionDetail(revision)"
+            class="view-button"
+            icon="el-icon-view"
+          ></el-button>
+        </div>
+        <div v-if="!tagData.revisions || tagData.revisions.length === 0" class="no-revisions">
+          无修订记录
+        </div>
+      </div>
+    </div>
+    
+    <!-- 版本详情弹框 -->
+    <el-dialog
+      title="版本详情"
+      :visible.sync="dialogVisible"
+      width="600px"
+    >
+      <div class="version-detail">
+        <div class="detail-header">
+          {{ selectedVersion.name || '无名称' }}
+        </div>
+        <div class="detail-meta">
+          版本{{ selectedVersion.version }}. 修订时间: {{ selectedVersion.revisionTime }} 修订人: {{ selectedVersion.revisionUser }}
+        </div>
+        
+        <div class="detail-content">
+          <!-- 标签描述 -->
+          <div class="detail-item">
+            <h5 class="item-title">标签描述*</h5>
+            <p class="item-content">{{ selectedVersion.description || '无描述信息' }}</p>
+          </div>
+          
+          <!-- 标签正则表达式 -->
+          <div class="detail-item">
+            <h5 class="item-title">标签正则表达式*</h5>
+            <p class="item-content code">{{ selectedVersion.regex || '无正则表达式' }}</p>
+          </div>
+          
+          <!-- 标签提示词 -->
+          <div class="detail-item">
+            <h5 class="item-title">标签提示词*</h5>
+            <p class="item-content">
+              <span class="info-label">标签名称:</span>{{ selectedVersion.name || '无名称' }}<br>
+              <span class="info-label">标签适用范围:</span>{{ selectedVersion.scope || '无适用范围' }}<br>
+              <span class="info-label">标注规则:</span>{{ selectedVersion.rules || '无标注规则' }}
+            </p>
+          </div>
+        </div>
+      </div>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="dialogVisible = false">版本回溯</el-button>
+      </span>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'TagDetailView',
+  props: {
+    tagData: {
+      type: Object,
+      default: () => ({})
+    }
+  },
+  data() {
+    return {
+      dialogVisible: false,
+      selectedVersion: {}
+    }
+  },
+  methods: {
+    showVersionDetail(revision) {
+      this.selectedVersion = revision;
+      this.dialogVisible = true;
+    }
+  }
+}
+</script>
+
+<style scoped>
+.detail-view {
+  display: flex;
+  flex-direction: column;
+  gap: 20px;
+}
+
+/* 标签路径 */
+.tag-path {
+  font-size: 16px;
+  font-weight: 500;
+  color: #303133;
+  margin-bottom: 10px;
+}
+
+/* 版本信息 */
+.version-info {
+  font-size: 14px;
+  color: #909399;
+  margin-bottom: 15px;
+}
+
+.detail-section {
+  display: flex;
+  flex-direction: column;
+  gap: 8px;
+}
+
+.section-title {
+  font-size: 14px;
+  font-weight: 500;
+  color: #303133;
+  margin: 0;
+  padding-left: 8px;
+  border-left: 3px solid #409eff;
+}
+
+.section-content {
+  font-size: 14px;
+  color: #606266;
+  line-height: 1.5;
+  margin: 0;
+}
+
+.section-content.code {
+  font-family: monospace;
+  background-color: #f5f7fa;
+  padding: 8px;
+  border-radius: 4px;
+  word-break: break-all;
+}
+
+/* 信息标签 */
+.info-label {
+  font-weight: 500;
+  color: #303133;
+}
+
+/* 修订记录 */
+.revision-list {
+  border: 1px solid #e8e8e8;
+  border-radius: 4px;
+  overflow: hidden;
+}
+
+.revision-item {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 12px 16px;
+  border-bottom: 1px solid #e8e8e8;
+}
+
+.revision-item:last-child {
+  border-bottom: none;
+}
+
+.revision-info {
+  font-size: 14px;
+  color: #606266;
+}
+
+.view-button {
+  padding: 0;
+  margin-left: 10px;
+}
+
+.no-revisions {
+  padding: 20px;
+  text-align: center;
+  color: #909399;
+  font-size: 14px;
+}
+
+/* 版本详情弹框 */
+.version-detail {
+  display: flex;
+  flex-direction: column;
+  gap: 16px;
+}
+
+.detail-header {
+  font-size: 16px;
+  font-weight: 500;
+  color: #303133;
+}
+
+.detail-meta {
+  font-size: 14px;
+  color: #909399;
+  padding-bottom: 10px;
+  border-bottom: 1px solid #e8e8e8;
+}
+
+.detail-content {
+  display: flex;
+  flex-direction: column;
+  gap: 16px;
+}
+
+.detail-item {
+  display: flex;
+  flex-direction: column;
+  gap: 8px;
+}
+
+.item-title {
+  font-size: 14px;
+  font-weight: 500;
+  color: #303133;
+  margin: 0;
+  padding-left: 8px;
+  border-left: 3px solid #409eff;
+}
+
+.item-content {
+  font-size: 14px;
+  color: #606266;
+  line-height: 1.5;
+  margin: 0;
+}
+
+.item-content.code {
+  font-family: monospace;
+  background-color: #f5f7fa;
+  padding: 8px;
+  border-radius: 4px;
+  word-break: break-all;
+}
+
+.dialog-footer {
+  text-align: right;
+}
+</style>

+ 392 - 76
web/src/views/content/aiTagging/taggingSystemManage/components/TagTree.vue

@@ -1,20 +1,10 @@
 <template>
   <div class="tag-tree">
-    <!-- 标签树顶部操作区 -->
-    <div class="tree-top-actions">
-      <!-- 操作按钮 -->
-      <div class="tree-header-actions">
-        <el-button type="text" icon="el-icon-plus" @click="handleAddNode"></el-button>
-        <el-button type="text" icon="el-icon-upload2" @click="handleImport"></el-button>
-        <el-button type="text" icon="el-icon-refresh" @click="handleRefresh"></el-button>
-      </div>
-      
-      <!-- 搜索框 -->
-      <div class="tree-header-search">
-        <el-input v-model="searchKeyword" placeholder="请输入" style="width: 100%;">
-          <el-button slot="append" icon="el-icon-search" @click="handleSearch"></el-button>
-        </el-input>
-      </div>
+    <!-- 搜索框 -->
+    <div class="tree-header-search">
+      <el-input v-model="searchKeyword" placeholder="请输入关键字" style="width: 100%;">
+        <el-button slot="append" icon="el-icon-search" @click="handleSearch"></el-button>
+      </el-input>
     </div>
     
     <!-- 标签树 -->
@@ -23,38 +13,37 @@
       :props="treeProps"
       node-key="id"
       default-expand-all
+      :render-content="renderContent"
       @node-click="handleNodeClick"
+    ></el-tree>
+    
+    <!-- 新增标签弹框 -->
+    <el-dialog
+      title="新增标签"
+      :visible.sync="addDialogVisible"
+      width="600px"
     >
-      <span class="custom-tree-node" slot-scope="{ node, data }">
-        <span class="node-label">{{ node.label }}</span>
-        <el-dropdown 
-          v-if="node.level > 1" 
-          trigger="click" 
-          @command="(command) => handleDropdownCommand(command, data, node)"
-          style="margin-left: 8px;"
-        >
-          <span class="el-dropdown-link">
-            <el-button type="text" size="mini" icon="el-icon-more"></el-button>
-          </span>
-          <el-dropdown-menu slot="dropdown">
-            <el-dropdown-item command="add">新增</el-dropdown-item>
-            <el-dropdown-item command="edit">编辑</el-dropdown-item>
-            <el-dropdown-item command="delete" divided>删除</el-dropdown-item>
-          </el-dropdown-menu>
-        </el-dropdown>
-      </span>
-    </el-tree>
+      <TagDetailEdit
+        :form-data="addForm"
+        :is-add-mode="true"
+        :parent-options="tagTreeData"
+        :tree-props="treeProps"
+        @save="handleAddSave"
+        @cancel="handleAddCancel"
+      />
+    </el-dialog>
   </div>
 </template>
 
 <script>
+import TagDetailEdit from './TagDetailEdit.vue';
+
 export default {
   name: 'TagTree',
+  components: {
+    TagDetailEdit
+  },
   props: {
-    treeData: {
-      type: Array,
-      default: () => []
-    },
     treeProps: {
       type: Object,
       default: () => ({
@@ -65,14 +54,127 @@ export default {
   },
   data() {
     return {
-      searchKeyword: ''
+      searchKeyword: '',
+      addDialogVisible: false,
+      addForm: {
+        name: '',
+        parent: '',
+        description: '',
+        regex: '',
+        hintWords: ''
+      },
+      // 标签树模拟数据
+      tagTreeData: [
+        {
+          id: 1,
+          label: '海洋经济',
+          children: [
+            {
+              id: 2,
+              label: '海洋产业(A)',
+              children: [
+                {
+                  id: 3,
+                  label: '海洋渔业(A1)',
+                  children: [
+                    {
+                      id: 4,
+                      label: '海洋捕捞(A11)',
+                      children: [
+                        {
+                          id: 5,
+                          label: '远洋捕捞(A111)',
+                        },
+                        {
+                          id: 6,
+                          label: '近海捕捞(A112)',
+                        }
+                      ]
+                    },
+                    {
+                      id: 7,
+                      label: '海水养殖(A12)',
+                    }
+                  ]
+                },
+                {
+                  id: 8,
+                  label: '海洋盐业(A2)',
+                }
+              ]
+            },
+            {
+              id: 9,
+              label: '海洋科研教育(B)',
+            },
+            {
+              id: 10,
+              label: '海洋公共管理服务(C)',
+              children: [
+                {
+                  id: 11,
+                  label: '海洋管理(C18)',
+                },
+                {
+                  id: 12,
+                  label: '海洋社会团体基金会与国际组织(C19)',
+                },
+                {
+                  id: 13,
+                  label: '海洋技术服务(C20)',
+                },
+                {
+                  id: 14,
+                  label: '海洋信息服务(C21)',
+                },
+                {
+                  id: 15,
+                  label: '海洋生态环境保护修复(C22)',
+                },
+                {
+                  id: 16,
+                  label: '海洋地质勘查(C23)',
+                  children: [
+                    {
+                      id: 17,
+                      label: '海洋矿产地质勘查(C231)',
+                      children: [
+                        {
+                          id: 18,
+                          label: '海洋能源矿产地质勘查(C2311)',
+                        },
+                        {
+                          id: 19,
+                          label: '海洋固体矿产地质勘查(C2312)',
+                        },
+                        {
+                          id: 20,
+                          label: '其他海洋矿产地质勘查(C2319)',
+                        }
+                      ]
+                    }
+                  ]
+                }
+              ]
+            },
+            {
+              id: 21,
+              label: '海洋上游相关产业(D)',
+            },
+            {
+              id: 22,
+              label: '海洋下游相关产业(E)',
+            }
+          ]
+        }
+      ]
     }
   },
   computed: {
     // 过滤后的树数据
     filteredTreeData() {
       if (!this.searchKeyword) {
-        return this.treeData;
+        return this.tagTreeData;
       }
       
       const keyword = this.searchKeyword.toLowerCase();
@@ -94,36 +196,219 @@ export default {
         });
       };
       
-      return filterTree(JSON.parse(JSON.stringify(this.treeData)));
+      return filterTree(JSON.parse(JSON.stringify(this.tagTreeData)));
     }
   },
   methods: {
+    // 渲染树节点内容
+    renderContent(h, { node, data, store }) {
+      return h('span', { class: 'custom-tree-node' }, [
+        h('span', {
+          class: 'node-label',
+          attrs: { title: node.label }
+        }, node.label),
+        h('span', {
+          class: 'node-dropdown'
+        }, [
+          h('el-dropdown', {
+            props: { trigger: 'click' },
+            on: {
+              command: (command) => this.handleDropdownCommand(command, data, node)
+            }
+          }, [
+            h('span', { class: 'el-dropdown-link vertical-dots' }, [
+              '⋮'
+            ]),
+            h('el-dropdown-menu', {
+              slot: 'dropdown'
+            }, [
+              h('el-dropdown-item', {
+                props: { command: 'add' }
+              }, '新增'),
+              h('el-dropdown-item', {
+                props: { command: 'delete' }
+              }, '删除')
+            ])
+          ])
+        ])
+      ]);
+    },
+
     handleNodeClick(data, node) {
+      console.log('点击节点:', data.label);
+      // 触发节点点击事件,传递给父组件
       this.$emit('node-click', data, node);
     },
 
     handleDropdownCommand(command, data, node) {
+      console.log('执行命令:', command, '目标节点:', data.label);
+      // 触发下拉菜单命令事件,传递给父组件
       this.$emit('dropdown-command', command, data, node);
+      
+      switch(command) {
+        case 'add':
+          this.handleAddNode(data, node);
+          break;
+        case 'up':
+          this.handleMoveUp(data, node);
+          break;
+        case 'down':
+          this.handleMoveDown(data, node);
+          break;
+        case 'delete':
+          this.handleDeleteNode(data, node);
+          break;
+      }
     },
 
     // 添加节点
-    handleAddNode() {
-      this.$emit('add-node');
+    handleAddNode(parentData, parentNode) {
+      console.log('新增节点到:', parentData ? parentData.label : '根节点');
+      
+      // 重置新增表单
+      this.addForm = {
+        name: '',
+        parent: parentData || '',
+        description: '',
+        regex: '',
+        hintWords: ''
+      };
+      
+      // 打开新增标签弹框
+      this.addDialogVisible = true;
+    },
+    
+    // 处理新增标签保存
+    handleAddSave(formData) {
+      console.log('保存新增标签:', formData);
+      
+      // 生成新节点ID
+      const newId = Math.max(...this.getAllNodeIds(this.tagTreeData)) + 1;
+      
+      // 创建新节点
+      const newNode = {
+        id: newId,
+        label: formData.name,
+        children: []
+      };
+      
+      // 获取父节点ID(兼容对象和数字两种情况)
+      const parentId = typeof formData.parent === 'object' && formData.parent ? formData.parent.id : formData.parent;
+      
+      // 查找父节点
+      const parentNode = this.findNodeById(this.tagTreeData, parentId);
+      
+      // 添加到父节点或根节点
+      if (parentNode) {
+        if (!parentNode.children) {
+          parentNode.children = [];
+        }
+        parentNode.children.push(newNode);
+      } else {
+        this.tagTreeData.push(newNode);
+      }
+      
+      // 关闭弹框
+      this.addDialogVisible = false;
+      
+      // 提示保存成功
+      this.$message.success('标签新增成功');
+    },
+    
+    // 处理新增标签取消
+    handleAddCancel() {
+      console.log('取消新增标签');
+      // 关闭弹框
+      this.addDialogVisible = false;
+    },
+    
+    // 根据ID查找节点
+    findNodeById(tree, id) {
+      for (const node of tree) {
+        if (node.id === id) {
+          return node;
+        }
+        if (node.children && node.children.length > 0) {
+          const found = this.findNodeById(node.children, id);
+          if (found) {
+            return found;
+          }
+        }
+      }
+      return null;
     },
 
-    // 导入节点
-    handleImport() {
-      this.$emit('import-nodes');
+    // 获取所有节点ID
+    getAllNodeIds(tree, ids = []) {
+      for (const node of tree) {
+        ids.push(node.id);
+        if (node.children && node.children.length > 0) {
+          this.getAllNodeIds(node.children, ids);
+        }
+      }
+      return ids;
     },
 
-    // 刷新节点
-    handleRefresh() {
-      this.$emit('refresh-nodes');
+    // 上移节点
+    handleMoveUp(data, node) {
+      console.log('上移节点:', data.label);
+      
+      // 找到父节点
+      const parent = node.parent;
+      if (!parent || parent.level === 0) return;
+      
+      // 找到当前节点在父节点children中的索引
+      const siblings = parent.data.children || [];
+      const index = siblings.findIndex(item => item.id === data.id);
+      
+      // 如果不是第一个节点,则上移
+      if (index > 0) {
+        // 交换位置
+        [siblings[index], siblings[index - 1]] = [siblings[index - 1], siblings[index]];
+      }
+    },
+
+    // 下移节点
+    handleMoveDown(data, node) {
+      console.log('下移节点:', data.label);
+      
+      // 找到父节点
+      const parent = node.parent;
+      if (!parent || parent.level === 0) return;
+      
+      // 找到当前节点在父节点children中的索引
+      const siblings = parent.data.children || [];
+      const index = siblings.findIndex(item => item.id === data.id);
+      
+      // 如果不是最后一个节点,则下移
+      if (index < siblings.length - 1) {
+        // 交换位置
+        [siblings[index], siblings[index + 1]] = [siblings[index + 1], siblings[index]];
+      }
+    },
+
+    // 删除节点
+    handleDeleteNode(data, node) {
+      console.log('删除节点:', data.label);
+      
+      // 找到父节点
+      const parent = node.parent;
+      if (!parent) return;
+      
+      // 找到当前节点在父节点children中的索引
+      const siblings = parent.data.children || [];
+      const index = siblings.findIndex(item => item.id === data.id);
+      
+      // 删除节点
+      if (index > -1) {
+        siblings.splice(index, 1);
+      }
     },
 
     // 搜索
     handleSearch() {
-      this.$emit('search', this.searchKeyword);
+      console.log('搜索:', this.searchKeyword);
+      // 搜索功能已经通过computed属性实现
     }
   }
 }
@@ -131,51 +416,82 @@ export default {
 
 <style scoped>
 .tag-tree {
-  background-color: #fafafa;
-  border-radius: 8px;
-  padding: 16px;
+  background-color: #ffffff;
   max-height: 600px;
   overflow-y: auto;
-}
-
-/* 顶部操作区 */
-.tree-top-actions {
-  display: flex;
-  flex-direction: column;
-  gap: 12px;
-  margin-bottom: 16px;
-  padding-bottom: 12px;
-  border-bottom: 1px solid #e8e8e8;
-}
-
-/* 操作按钮 */
-.tree-header-actions {
-  display: flex;
-  justify-content: flex-end;
-  gap: 8px;
+  box-sizing: border-box;
 }
 
 /* 搜索框 */
 .tree-header-search {
-  display: flex;
-  align-items: center;
+  margin-bottom: 12px;
   width: 100%;
 }
 
 .tag-tree .el-tree {
   background-color: transparent;
+  border: none;
 }
 
-.custom-tree-node {
+.tag-tree ::v-deep .custom-tree-node {
   flex: 1;
   display: flex;
   align-items: center;
   justify-content: space-between;
   font-size: 14px;
-  padding-right: 8px;
+  min-width: 0;
+  padding: 4px 0;
 }
 
-.node-label {
+.tag-tree ::v-deep .node-label {
   flex: 1;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  margin-right: 8px;
+  max-width: calc(100% - 20px);
+}
+
+/* 使用::v-deep()确保样式能够正确应用 */
+.tag-tree ::v-deep .node-dropdown {
+  opacity: 0;
+  transition: opacity 0.3s;
+}
+
+.tag-tree ::v-deep .custom-tree-node:hover .node-dropdown {
+  opacity: 1;
+}
+
+.tag-tree ::v-deep .el-dropdown-link {
+  cursor: pointer;
+  color: #909399;
+  font-size: 12px;
+  margin-left: 8px;
+}
+
+.tag-tree ::v-deep .el-dropdown-link.vertical-dots {
+  font-size: 16px;
+  line-height: 1;
+  margin-left: 3px;
+  margin-right: 3px;
+}
+
+.tag-tree ::v-deep .el-dropdown-link:hover {
+  color: #409eff;
+}
+
+/* 确保下拉菜单显示 */
+.tag-tree ::v-deep .el-dropdown {
+  position: relative;
+  z-index: 1000;
+}
+
+/* 树节点样式 */
+.tag-tree .el-tree-node.is-current > .el-tree-node__content {
+  background-color: #ecf5ff;
+}
+
+.tag-tree .el-tree-node__content {
+  padding-right: 8px;
 }
-</style>
+</style>

+ 183 - 0
web/src/views/content/aiTagging/taggingSystemManage/components/TreeSelect.vue

@@ -0,0 +1,183 @@
+<template>
+  <div class="tree-select">
+    <el-input
+      v-model="displayText"
+      :placeholder="placeholder"
+      @click.native="handleInputClick"
+      @input="handleInput"
+    >
+      <i
+        v-if="selectedNode"
+        slot="suffix"
+        class="el-input__icon el-icon-circle-close"
+        @click.stop="handleClear"
+      ></i>
+      <i
+        v-else
+        slot="suffix"
+        class="el-input__icon"
+        :class="showTree ? 'el-icon-arrow-up' : 'el-icon-arrow-down'"
+      ></i>
+    </el-input>
+    
+    <div v-if="showTree" class="tree-dropdown">
+      <el-tree
+        :data="filteredData"
+        :props="treeProps"
+        node-key="id"
+        default-expand-all
+        :highlight-current="true"
+        @node-click="handleNodeClick"
+      ></el-tree>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'TreeSelect',
+  props: {
+    value: {
+      type: [String, Number, Object],
+      default: ''
+    },
+    data: {
+      type: Array,
+      default: () => []
+    },
+    treeProps: {
+      type: Object,
+      default: () => ({
+        children: 'children',
+        label: 'label'
+      })
+    },
+    placeholder: {
+      type: String,
+      default: '请选择'
+    }
+  },
+  data() {
+    return {
+      showTree: false,
+      selectedNode: null,
+      inputText: ''
+    }
+  },
+  computed: {
+    displayText() {
+      return this.inputText || (this.selectedNode ? this.selectedNode[this.treeProps.label] : '');
+    },
+    filteredData() {
+      if (!this.inputText) {
+        return this.data;
+      }
+      
+      const keyword = this.inputText.toLowerCase();
+      
+      const filterTree = (tree) => {
+        return tree.filter(node => {
+          const matches = node[this.treeProps.label].toLowerCase().includes(keyword);
+          
+          if (node.children && node.children.length > 0) {
+            node.children = filterTree(node.children);
+            return matches || node.children.length > 0;
+          }
+          
+          return matches;
+        });
+      };
+      
+      return filterTree(JSON.parse(JSON.stringify(this.data)));
+    }
+  },
+  watch: {
+    value: {
+      handler(newVal) {
+        if (newVal) {
+          const nodeId = typeof newVal === 'object' ? newVal.id : newVal;
+          this.selectedNode = this.findNodeById(this.data, nodeId);
+        } else {
+          this.selectedNode = null;
+        }
+      },
+      immediate: true
+    }
+  },
+  methods: {
+    handleInput(value) {
+      this.inputText = value;
+      if (!this.showTree) {
+        this.showTree = true;
+      }
+    },
+    handleInputClick() {
+      console.log('点击输入框,当前showTree:', this.showTree);
+      this.showTree = !this.showTree;
+      console.log('点击后showTree:', this.showTree);
+    },
+    handleNodeClick(data, node) {
+      console.log('点击节点:', data.label);
+      this.selectedNode = data;
+      this.inputText = '';
+      this.showTree = false;
+      this.$emit('input', data);
+      this.$emit('change', data);
+    },
+    handleClear() {
+      console.log('清空选择');
+      this.selectedNode = null;
+      this.inputText = '';
+      this.$emit('input', '');
+      this.$emit('change', '');
+    },
+    findNodeById(tree, id) {
+      for (const node of tree) {
+        if (node.id === id) {
+          return node;
+        }
+        if (node.children && node.children.length > 0) {
+          const found = this.findNodeById(node.children, id);
+          if (found) {
+            return found;
+          }
+        }
+      }
+      return null;
+    }
+  }
+}
+</script>
+
+<style scoped>
+.tree-select {
+  position: relative;
+}
+
+.tree-dropdown {
+  position: absolute;
+  top: 100%;
+  left: 0;
+  right: 0;
+  margin-top: 8px;
+  background-color: #fff;
+  border: 1px solid #e4e7ed;
+  border-radius: 4px;
+  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+  max-height: 300px;
+  overflow-y: auto;
+  z-index: 1000;
+}
+
+.tree-dropdown ::v-deep .el-tree {
+  background-color: transparent;
+}
+
+.tree-dropdown ::v-deep .el-tree-node__content {
+  padding-right: 8px;
+}
+
+.tree-dropdown ::v-deep .el-tree-node.is-current > .el-tree-node__content {
+  background-color: #ecf5ff;
+}
+</style>

+ 2 - 2
web/src/views/content/aiTagging/taggingSystemManage/index.vue

@@ -321,8 +321,8 @@ export default {
 
 <style scoped>
 .tag-system-container {
-  padding: 20px;
-  background-color: #f0f2f5;
+  padding: 0;
+  background-color: transparent;
   min-height: 100vh;
 }