Kaynağa Gözat

修改登录页及首页

yangg 8 ay önce
ebeveyn
işleme
6c9e2a5b44

Dosya farkı çok büyük olduğundan ihmal edildi
+ 0 - 0
dist/index.html


Dosya farkı çok büyük olduğundan ihmal edildi
+ 0 - 0
dist/static/css/app.7fd9d64f.css


Dosya farkı çok büyük olduğundan ihmal edildi
+ 0 - 0
dist/static/css/chunk-043b1151.79985b25.css


Dosya farkı çok büyük olduğundan ihmal edildi
+ 0 - 0
dist/static/css/chunk-712c0160.1d59ca2f.css


Dosya farkı çok büyük olduğundan ihmal edildi
+ 0 - 0
dist/static/js/app.41f79839.js


Dosya farkı çok büyük olduğundan ihmal edildi
+ 0 - 0
dist/static/js/chunk-043b1151.c47e440f.js


Dosya farkı çok büyük olduğundan ihmal edildi
+ 0 - 0
dist/static/js/chunk-3718fade.cfced357.js


Dosya farkı çok büyük olduğundan ihmal edildi
+ 0 - 0
dist/static/js/chunk-712c0160.de531471.js


+ 32 - 0
src/api/knowledge.js

@@ -608,4 +608,36 @@ export function doc_status(data) {
     method: 'get',
     data
   })
+}
+
+/* 新建项目内容  */
+
+export function create_items(data) {
+  return request({
+    timeout:100000,
+    url: 'project-input/create-items',
+    method: 'post',
+    data
+  })
+}
+
+/* 删除项目  project-input/delete-items */
+
+export function delete_items(data) {
+  return request({
+    timeout:100000,
+    url: 'project-input/delete-items',
+    method: 'post',
+    data
+  })
+}
+/* 更新项目 project-input/update-items */
+
+export function update_items(data) {
+  return request({
+    timeout:100000,
+    url: 'project-input/update-items',
+    method: 'post',
+    data
+  })
 }

+ 1 - 1
src/components/chartIcon/index.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="chat-icon" @click="toggleChat">
     <i class="el-icon-chat-dot-round animate-pulse"></i>
-    <div v-if="$store.state.app.showChat" class="chat-window" :style="chatWindowStyle" ref="chatWindow" @click.stop>
+    <div v-show="$store.state.app.showChat" class="chat-window" :style="chatWindowStyle" ref="chatWindow" @click.stop>
       <div class="chat-header">
         <div class="resize-handle" @mousedown="startResize">
           <i class="el-icon-d-caret"></i>

+ 3 - 1
src/store/index.js

@@ -1,6 +1,7 @@
 import Vue from 'vue'
 import Vuex from 'vuex'
 import getters from './getters'
+import project from './modules/project'
 
 Vue.use(Vuex)
 // https://webpack.js.org/guides/dependency-management/#requirecontext
@@ -16,7 +17,8 @@ const modules = modulesFiles.keys().reduce((modules, modulePath) => {
 
 const store = new Vuex.Store({
   modules,
-  getters
+  getters,
+  project
 })
 
 export default store

+ 26 - 0
src/store/modules/project.js

@@ -0,0 +1,26 @@
+const state = {
+    currentProjectId: null,
+    currentProjectName: ''
+  }
+  
+  const mutations = {
+    SET_CURRENT_PROJECT: (state, { id, name }) => {
+      state.currentProjectId = id
+      state.currentProjectName = name
+    }
+  }
+  
+  const actions = {
+    setCurrentProject({ commit }, project) {
+      commit('SET_CURRENT_PROJECT', project)
+      // 保存到 localStorage,以便刷新后保持状态
+      localStorage.setItem('currentProject', JSON.stringify(project))
+    }
+  }
+  
+  export default {
+    namespaced: true,
+    state,
+    mutations,
+    actions
+  }

+ 102 - 33
src/views/dashboard/admin/chart.vue

@@ -362,7 +362,7 @@
                           <div class="card">
                             <div class="card-body">
                               <span>文件未解析数量</span>
-                              <h3>{{ docList.run_0}}</h3>
+                              <h3>{{ docList.run_0 }}</h3>
                               <div
                                 ref="real1Chart"
                                 style="height: 20px; width: 100%"
@@ -431,13 +431,13 @@ import * as am4charts from "@amcharts/amcharts4/charts";
 import am4themes_animated from "@amcharts/amcharts4/themes/animated";
 import BootstrapWrapper from "@/components/BootstrapWrapper/index.vue";
 import { searchlistDoc, searchList } from "@/api/document";
-import {pageTemplate } from "@/api/template";
+import { pageTemplate } from "@/api/template";
 import {
   listBuckets,
   structure_count,
   GET_Rbq,
   gpu_info,
-  doc_status
+  doc_status,
 } from "@/api/knowledge";
 export default {
   name: "WidgetChart",
@@ -458,7 +458,9 @@ export default {
       docTotal: 0,
       temTotal: 0,
       pageTotal: 0,
-      docList:{}
+      docList: {},
+      chartUpdateInterval: null, // 添加新的数据属性用于存储定时器
+      isPageVisible: !document.hidden, // 添加新的数据属性
     };
   },
   watch: {
@@ -469,9 +471,26 @@ export default {
         this.handleRouteChange();
       },
     },
+    // 监听页面可见性
+    isPageVisible: {
+      immediate: true,
+      handler(newValue) {
+        console.log(newValue);
+        if (newValue) {
+          // 页面变为可见时
+          console.log("Page became visible");
+           this.initSiteVisitorChart();
+        } else {
+          // 页面变为不可见时
+          console.log("Page became hidden");
+          this.cleanupCharts();
+        }
+      },
+    },
   },
 
   mounted() {
+    document.addEventListener("visibilitychange", this.handleVisibilityChange);
     // 使用动画主题
     am4core.useTheme(am4themes_animated);
     this.init();
@@ -485,16 +504,40 @@ export default {
     this.initDeviceChart(); // 添加这行
   },
 
+  // 修改生命周期钩子
+  activated() {
+    console.log(1123);
+    // 当组件被激活时重新初始化图表
+    this.initSiteVisitorChart();
+  },
+
+  deactivated() {
+    // 当组件被停用时清理资源
+    this.cleanupCharts();
+  },
+
   beforeDestroy() {
-    // 销毁所有图表实例
+    // 组件销毁前清理所有资源
+    this.cleanupCharts();
+    this.closeWebSocket();
+
+    // 清理其他图表实例
     Object.values(this.charts).forEach((chart) => {
       if (chart) {
-        chart.dispose();
+        if (typeof chart.dispose === "function") {
+          chart.dispose();
+        } else if (typeof chart === "number") {
+          clearInterval(chart);
+        }
       }
     });
   },
 
   methods: {
+    // 处理页面可见性变化
+    handleVisibilityChange() {
+      this.isPageVisible = !document.hidden;
+    },
     closeWebSocket() {
       if (this.ws) {
         this.ws.close();
@@ -565,12 +608,13 @@ export default {
       chart.logo.disabled = true;
       chart.innerRadius = am4core.percent(82);
 
-      // 主轴配置
+      // 修改主轴配置
       const axis = chart.xAxes.push(new am4charts.ValueAxis());
       axis.min = 0;
       axis.max = 100;
       axis.strictMinMax = true;
-      axis.renderer.radius = am4core.percent(80);
+      // 设置固定的半径
+      axis.renderer.radius = 80; // 使用固定像素值而不是百分比
       axis.renderer.inside = true;
       axis.renderer.line.strokeOpacity = 0;
       axis.renderer.ticks.template.strokeOpacity = 1;
@@ -579,11 +623,13 @@ export default {
       axis.renderer.labels.template.radius = 40;
       axis.renderer.labels.template.adapter.add("text", () => "");
 
-      // 第二轴配置
+      // 修改第二轴配置
       const axis2 = chart.xAxes.push(new am4charts.ValueAxis());
       axis2.min = 0;
       axis2.max = 100;
-      axis2.renderer.innerRadius = 75;
+      // 设置固定的内半径
+      axis2.renderer.innerRadius = 65; // 使用固定像素值
+      axis2.renderer.radius = 80; // 设置固定的外半径
 
       axis2.strictMinMax = true;
       axis2.renderer.labels.template.disabled = true;
@@ -637,6 +683,8 @@ export default {
         range1.value = ev.target.value;
         axis2.invalidate();
       });
+      // 设置图表容器的固定大小
+      //chart.width = 160; // 设置固定宽度
 
       // 定时更新数据
       const interval = setInterval(() => {
@@ -784,6 +832,10 @@ export default {
     },
     // 修改initSiteVisitorChart方法
     initSiteVisitorChart() {
+      // 如果已存在图表实例,先销毁它
+      if (this.charts.siteVisitorChart) {
+        this.charts.siteVisitorChart.dispose();
+      }
       const chart = am4core.create(
         this.$refs.siteVisitorChart,
         am4charts.XYChart
@@ -900,32 +952,50 @@ export default {
       // 存储图表实例
       this.charts.siteVisitorChart = chart;
 
-      // 启动数据更新
+      /*  // 启动数据更新
       setTimeout(() => {
         this.startVisitorDataInterval(cpuSeries, gpuSeries);
-      }, 100);
+      }, 100); */
+      // 修改数据更新逻辑
+      this.startVisitorDataInterval(cpuSeries, gpuSeries);
     },
 
-    startVisitorDataInterval(series) {
-      let visits = 10;
-      const interval = setInterval(() => {
-        visits =
-          visits +
-          Math.round((Math.random() < 0.5 ? 1 : -1) * Math.random() * 5);
-        const lastDataItem = series.dataItems.getIndex(
-          series.dataItems.length - 1
-        );
-        series.chart.addData(
-          {
-            date: new Date(lastDataItem.dateX.getTime() + 1000),
-            cpuValue: this.cpuValue || 0, //value: Math.abs(visits),
-            gpuValue: this.GpuValue || 0,
-          },
-          1
+    // 修改 startVisitorDataInterval 方法
+    startVisitorDataInterval(cpuSeries, gpuSeries) {
+      // 清除已存在的定时器
+      if (this.chartUpdateInterval) {
+        clearInterval(this.chartUpdateInterval);
+      }
+
+      this.chartUpdateInterval = setInterval(() => {
+        const lastDataItem = cpuSeries.dataItems.getIndex(
+          cpuSeries.dataItems.length - 1
         );
+        if (lastDataItem && lastDataItem.dateX) {
+          cpuSeries.chart.addData(
+            {
+              date: new Date(lastDataItem.dateX.getTime() + 1000),
+              cpuValue: this.cpuValue || 0,
+              gpuValue: this.GpuValue || 0,
+            },
+            1
+          );
+        }
       }, 1000);
+    },
+    // 添加清理方法
+    cleanupCharts() {
+      // 清除定时器
+      if (this.chartUpdateInterval) {
+        clearInterval(this.chartUpdateInterval);
+        this.chartUpdateInterval = null;
+      }
 
-      this.charts.siteVisitorInterval = interval;
+      // 清除图表实例
+      if (this.charts.siteVisitorChart) {
+        this.charts.siteVisitorChart.dispose();
+        this.charts.siteVisitorChart = null;
+      }
     },
 
     handleVisitorChartVisibility() {
@@ -1107,11 +1177,10 @@ export default {
         this.pageTotal = res.data.dataList.length;
       });
       /* 获取文件解析数量 */
-      doc_status().then(res=>{
-        
-        this.docList=res.data.data.run_stats
+      doc_status().then((res) => {
+        this.docList = res.data.data.run_stats;
         console.log(this.docList.run_3);
-      })
+      });
     },
 
     /* 选择知识库 */

+ 97 - 68
src/views/login/index.vue

@@ -114,7 +114,11 @@
                 autocomplete="on"
               />
               <span class="show-pwd">
-                <el-button type="primary" :disabled="isDisabled" @click="getCode">
+                <el-button
+                  type="primary"
+                  :disabled="isDisabled"
+                  @click="getCode"
+                >
                   {{ buttonText }}
                 </el-button>
               </span>
@@ -463,112 +467,129 @@ export default {
       canvas.width = window.innerWidth;
       canvas.height = window.innerHeight;
 
-      let area = Math.sqrt(canvas.width * canvas.height);
-      let radiusLength = (canvas.width * canvas.height) / 8000;
-
-      let particlesArray;
-
       let mouse = {
         x: null,
         y: null,
-        radius: radiusLength,
+        radius: 150, // 可以调整鼠标影响范围
       };
 
-      window.addEventListener("mousemove", function (event) {
+      canvas.addEventListener("mousemove", function (event) {
         mouse.x = event.x;
         mouse.y = event.y;
       });
 
-      window.addEventListener("mouseout", function (event) {
+      canvas.addEventListener("mouseout", function () {
         mouse.x = undefined;
         mouse.y = undefined;
       });
 
-      window.addEventListener("resize", function (event) {
-        canvas.width = innerWidth;
-        canvas.height = innerHeight;
-        radiusLength = (canvas.width * canvas.height) / 9000;
-        createParticles();
-      });
-
       class Particle {
-        constructor(x, y, velX, velY, size, color) {
-          this.x = x;
-          this.y = y;
-          this.velX = velX;
-          this.velY = velY;
-          this.size = size;
-          this.color = color;
+        constructor() {
+          this.x = Math.random() * canvas.width;
+          this.y = Math.random() * canvas.height;
+          this.size = Math.random() * 3 + 1;
+          this.baseX = this.x;
+          this.baseY = this.y;
+          this.density = Math.random() * 30 + 1;
+          // 增加速度范围到 -2 到 2
+          this.speedX = (Math.random() - 0.5) * 3.5; // 从2改为4
+          this.speedY = (Math.random() - 0.5) * 3.5; // 从2改为4
+          // 添加额外的动画参数
+          this.angle = Math.random() * 360;
+          this.angleSpeed = (Math.random() - 0.5) * 2; // 旋转速度
+          this.oscillationRadius = Math.random() * 5; // 振荡幅度
         }
 
         draw() {
           ctx.beginPath();
-          ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2, false);
+          ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
           ctx.fillStyle = "#ffffff";
           ctx.fill();
         }
 
         update() {
-          if (this.x > canvas.width || this.x < 0) {
-            this.velX = -this.velX;
+          // 优化计算,减少三角函数计算频率
+          if (this.angle > 360) this.angle -= 360;
+          const angleRad = (this.angle * Math.PI) / 180;
+          const oscillation = Math.sin(angleRad) * this.oscillationRadius * 0.1;
+
+          this.baseX += this.speedX + oscillation;
+          this.baseY += this.speedY + oscillation;
+
+          // 边界检查 - 添加随机性
+          if (this.baseX > canvas.width || this.baseX < 0) {
+            this.speedX *= -1;
+            //this.speedX += (Math.random() - 0.5) * 0.5; // 添加随机速度变化
           }
-          if (this.y > canvas.height || this.y < 0) {
-            this.velY = -this.velY;
+          if (this.baseY > canvas.height || this.baseY < 0) {
+            this.speedY *= -1;
+            // this.speedY += (Math.random() - 0.5) * 0.5; // 添加随机速度变化
           }
 
+          // 限制最大速度
+          const maxSpeed = 5;
+          this.speedX = Math.max(Math.min(this.speedX, maxSpeed), -maxSpeed);
+          this.speedY = Math.max(Math.min(this.speedY, maxSpeed), -maxSpeed);
+
+          // 鼠标交互
           let dx = mouse.x - this.x;
           let dy = mouse.y - this.y;
-          let dist = Math.sqrt(dx * dx + dy * dy);
-          if (dist < mouse.radius + this.size) {
-            const buffer = this.size * 10;
-            if (mouse.x < this.x && this.x < canvas.width - buffer) {
-              this.x += 10;
-            }
-            if (mouse.x > this.x && this.x > buffer) {
-              this.x -= 10;
-            }
-            if (mouse.y < this.y && this.y < canvas.height - buffer) {
-              this.y += 10;
+          let distance = Math.sqrt(dx * dx + dy * dy);
+          let forceDirectionX = dx / distance;
+          let forceDirectionY = dy / distance;
+          let maxDistance = mouse.radius;
+          let force = (maxDistance - distance) / maxDistance;
+          let directionX = forceDirectionX * force * this.density;
+          let directionY = forceDirectionY * force * this.density;
+
+          if (distance < mouse.radius && mouse.x != undefined) {
+            // 增加鼠标排斥力
+            this.x -= directionX * 2; // 增加排斥力度
+            this.y -= directionY * 2;
+          } else {
+            // 更快地回到基准位置
+            if (this.x !== this.baseX) {
+              let dx = this.x - this.baseX;
+              this.x -= dx / 5; // 从10改为5,使回归更快
             }
-            if (mouse.y > this.y && this.y > buffer) {
-              this.y -= 10;
+            if (this.y !== this.baseY) {
+              let dy = this.y - this.baseY;
+              this.y -= dy / 5;
             }
           }
-
-          this.x += this.velX;
-          this.y += this.velY;
-          this.draw();
         }
       }
 
-      function createParticles() {
+      let particlesArray = [];
+
+      function init() {
         particlesArray = [];
-        let noOfParticles = (canvas.width * canvas.height) / 10000;
-        for (let i = 0; i < noOfParticles; i++) {
-          let size = Math.random() * 5 + 1;
-          let x = Math.random() * (innerWidth - 2 * size) + 2 * size;
-          let y = Math.random() * (innerHeight - 2 * size) + 2 * size;
-          let velX = Math.random() * 2;
-          let velY = Math.random() * 2;
-          let color = "#ffffff";
-          particlesArray.push(new Particle(x, y, velX, velY, size, color));
+        // 增加粒子数量
+        const numberOfParticles = (canvas.width * canvas.height) / 7000; // 从9000改为7000
+        for (let i = 0; i < numberOfParticles; i++) {
+          particlesArray.push(new Particle());
         }
       }
 
       function connect() {
-        let vicinityDist = (canvas.width * canvas.height) / 81;
-        for (let i = 0; i < particlesArray.length; i++) {
-          for (let j = i; j < particlesArray.length; j++) {
+        let opacityValue = 1;
+        for (let a = 0; a < particlesArray.length; a++) {
+          for (let b = a; b < particlesArray.length; b++) {
             let distance =
-              Math.pow(particlesArray[i].x - particlesArray[j].x, 2) +
-              Math.pow(particlesArray[i].y - particlesArray[j].y, 2);
-            let opacity = 1 - distance / 25000;
-            if (distance < vicinityDist) {
-              ctx.strokeStyle = "rgba(255,255,255," + opacity + ")";
+              (particlesArray[a].x - particlesArray[b].x) *
+                (particlesArray[a].x - particlesArray[b].x) +
+              (particlesArray[a].y - particlesArray[b].y) *
+                (particlesArray[a].y - particlesArray[b].y);
+
+            // 增加连线距离和可见度
+            if (distance < (canvas.width / 6) * (canvas.height / 6)) {
+              // 从7改为6
+              opacityValue = 1 - distance / 15000; // 从20000改为15000,使线条更明显
+              ctx.strokeStyle = `rgba(255,255,255,${opacityValue})`;
               ctx.lineWidth = 1;
               ctx.beginPath();
-              ctx.moveTo(particlesArray[i].x, particlesArray[i].y);
-              ctx.lineTo(particlesArray[j].x, particlesArray[j].y);
+              ctx.moveTo(particlesArray[a].x, particlesArray[a].y);
+              ctx.lineTo(particlesArray[b].x, particlesArray[b].y);
               ctx.stroke();
             }
           }
@@ -576,15 +597,23 @@ export default {
       }
 
       function animate() {
-        requestAnimationFrame(animate);
-        ctx.clearRect(0, 0, innerWidth, innerHeight);
+        ctx.clearRect(0, 0, canvas.width, canvas.height);
+
         for (let i = 0; i < particlesArray.length; i++) {
           particlesArray[i].update();
+          particlesArray[i].draw();
         }
         connect();
+        requestAnimationFrame(animate);
       }
 
-      createParticles();
+      window.addEventListener("resize", function () {
+        canvas.width = window.innerWidth;
+        canvas.height = window.innerHeight;
+        init();
+      });
+
+      init();
       animate();
     },
   },

+ 191 - 184
src/views/project/components/dataInfo.vue

@@ -2,20 +2,19 @@
   <div class="data-info">
     <el-card>
       <el-form :model="dataForm" label-width="120px">
-
         <el-form-item label="项目名称:">
           <el-input v-model="dataForm.name"></el-input>
         </el-form-item>
 
         <el-form-item label="项目介绍:">
           <el-input
-          rows="10"
-          type="textarea"
-          v-model="dataForm.intro"></el-input>
-
+            rows="10"
+            type="textarea"
+            v-model="dataForm.intro"
+          ></el-input>
         </el-form-item>
 
-        <el-form-item label="所属客户:">
+        <!--<el-form-item label="所属客户:">
           <el-select v-model="dataForm.customer_id"  placeholder="请选择客户" size="large"   style="width:100%;">
               <el-option
                 v-for="item in customerList"
@@ -34,208 +33,216 @@
               :value="item.id"
             />
           </el-select>
-      </el-form-item>
+      </el-form-item>-->
         <el-form-item label="所属分类:">
-          <el-select v-model="dataForm.category_id"  placeholder="请选择所属分类" size="large"   style="width:100%;">
-              <el-option
-                v-for="item in allCategories"
-                :key="item.id"
-                :label="item.name"
-                :value="item.id"
-              />
-            </el-select>
+          <el-select
+            v-model="dataForm.category_id"
+            placeholder="请选择所属分类"
+            size="large"
+            style="width: 100%"
+          >
+            <el-option
+              v-for="item in allCategories"
+              :key="item.id"
+              :label="item.name"
+              :value="item.id"
+            />
+          </el-select>
         </el-form-item>
 
         <el-form-item label="项目状态:">
-          <el-select v-model="dataForm.status"  placeholder="请选择状态" size="large"   style="width:100%;">
-              <el-option
-                v-for="item in statusOptions"
-                :key="item.status"
-                :label="item.name"
-                :value="item.status"
-              />
-            </el-select>
+          <el-select
+            v-model="dataForm.status"
+            placeholder="请选择状态"
+            size="large"
+            style="width: 100%"
+          >
+            <el-option
+              v-for="item in statusOptions"
+              :key="item.status"
+              :label="item.name"
+              :value="item.status"
+            />
+          </el-select>
         </el-form-item>
-
-
       </el-form>
-
     </el-card>
 
-
-      <div style="text-align:right; margin-top:20px;">
-          <el-button type="warning" @click="btnSave">确认保存</el-button>
-      </div>
+    <div style="text-align: right; margin-top: 20px">
+      <el-button type="warning" @click="btnSave">确认保存</el-button>
+    </div>
   </div>
 </template>
 
 <script>
-  import Tinymce from "@/components/Tinymce";
-  import {searchCategory,createProject,updateProject,getProjectInfo} from'@/api/project'
-  import {searchCustomer} from"@/api/customer"
-  import {searchDocument} from "@/api/document"
-  export default{
-    components:{
-      Tinymce
+import Tinymce from "@/components/Tinymce";
+import {
+  searchCategory,
+  createProject,
+  updateProject,
+  getProjectInfo,
+} from "@/api/project";
+import { searchCustomer } from "@/api/customer";
+import { searchDocument } from "@/api/document";
+export default {
+  components: {
+    Tinymce,
+  },
+  emits: ["onClose"],
+  props: {
+    id: {
+      type: Number,
+      default: 0,
     },
-    emits:['onClose'],
-    props:{
-      id:{
-        type:Number,
-        default:0
+  },
+  watch: {
+    id: {
+      handler(v) {
+        let _this = this;
+        if (v == null) return;
+        if (v == 0) {
+          this.dataForm = {
+            id: 0,
+            name: "",
+            intro: "",
+            customer_id: "",
+            category_id: "",
+            status: 5,
+            /*  linkDoc:[], */
+          };
+          return;
+        }
+        _this.getInfo(v);
       },
+      immediate: true,
+      deep: true,
     },
-    watch:{
-      id:{
-        handler(v){
-            let _this=this;
-            if(v==null )return;
-            if(v==0){
-
-              this.dataForm={
-                id:0,
-                name:'',
-                intro:'',
-                customer_id:'',
-                category_id:'',
-                status:5,
-                linkDoc:[],
-              }
-              return;
-            }
-            _this.getInfo(v);
+  },
+  data() {
+    return {
+      activeName: "base",
+      currentCategory: [],
+      allCategories: [],
+      imageUrl: "",
+      customerList: [],
+      articleList: [],
+      dataForm: {
+        id: 0,
+        name: "",
+        intro: "",
+        customer_id: "",
+        category_id: "",
+        status: 5,
+        /*  linkDoc:[], */
+      },
+      statusOptions: [
+        {
+          status: 5,
+          name: "启用",
         },
-        immediate: true,
-        deep: true
-      }
-    },
-    data(){
-      return{
-        activeName:'base',
-        currentCategory:[],
-        allCategories:[],
-        imageUrl:"",
-        customerList:[],
-        articleList:[],
-        dataForm:{
-          id:0,
-          name:'',
-          intro:'',
-          customer_id:'',
-          category_id:'',
-          status:5,
-          linkDoc:[],
+        {
+          status: 6,
+          name: "停用",
         },
-        statusOptions:[
-          {
-            status:5,
-            name:'启用'
-          },
-          {
-            status:6,
-            name:'停用'
-          }
+      ],
+    };
+  },
+
+  mounted() {
+    let _this = this;
+    _this.uploadUrl = process.env.VUE_APP_BASE_API + "/upload";
+    _this.initAllCategory();
+    this.initCustomer();
+    this.initDocList();
+  },
+  methods: {
+    initDocList() {
+      let _this = this;
+      searchDocument({
+        page: 1,
+        pageSize: 10,
+      }).then((res) => {
+        if (res.status != 200) return;
+        _this.articleList = res.data.dataList;
+      });
+    },
+    //图片上传成功
+    onUploadSuccess(e) {
+      console.log("onUploadSuccess", e);
+    },
+    //保存更新
+    btnSave(e) {
+      let _this = this;
 
-        ],
+      if (_this.dataForm.title == "") {
+        _this.$alert("产品标题不能为空");
+        return;
+      }
+      /* _this.dataForm.links=JSON.stringify(_this.dataForm.linkDoc); */
+      if (_this.dataForm.id > 0) {
+        updateProject(_this.dataForm).then((res) => {
+          if (res.status !== 200) return;
+          _this.$alert("项目信息更新成功");
+          _this.$emit("onClose");
+        });
+      } else {
+        createProject(_this.dataForm).then((res) => {
+          if (res.status !== 200) return;
+          _this.$alert("项目信息创建成功");
+          _this.$emit("onClose");
+        });
       }
     },
 
-    mounted() {
-      let _this=this;
-      _this.uploadUrl=process.env.VUE_APP_BASE_API+"/upload"
-      _this.initAllCategory();
-      this.initCustomer();
-      this.initDocList();
+    //产品详情
+    getInfo(id) {
+      let _this = this;
+      let par = {
+        id: id,
+      };
+      getProjectInfo(par).then((res) => {
+        if (!res) return;
+        if (res.status != 200) return;
+        _this.dataForm = res.data;
+        _this.dataForm.category_id = res.data.categoryId;
+        _this.dataForm.customer_id = res.data.customerId;
+      });
     },
-    methods:{
-      initDocList(){
-        let _this = this;
-        searchDocument({
-          page: 1,
-          pageSize: 10
-        }).then(res => {
-          if (res.status != 200) return;
-          _this.articleList = res.data.dataList;
-        })
-      },
-      //图片上传成功
-      onUploadSuccess(e){
-        console.log("onUploadSuccess",e);
-      },
-      //保存更新
-      btnSave(e){
-          let _this=this;
-
-          if(_this.dataForm.title==''){
-            _this.$alert("产品标题不能为空");
-              return;
-          }
-          _this.dataForm.links=JSON.stringify(_this.dataForm.linkDoc);
-          if(_this.dataForm.id>0){
-            updateProject(_this.dataForm).then(res=>{
-              _this.$alert("项目信息更新成功");
-              _this.$emit("onClose")
-            })
-          }else{
-            createProject(_this.dataForm).then(res=>{
-              _this.$alert("项目信息创建成功");
-              _this.$emit("onClose");
-            })
-          }
-
-      },
-
-      //产品详情
-      getInfo(id){
-          let _this=this;
-          let par={
-            id:id,
-          };
-          getProjectInfo(par).then(res=>{
-              if(!res)return;
-              if(res.status!=200)return;
-              _this.dataForm=res.data;
-              _this.dataForm.category_id=res.data.categoryId;
-              _this.dataForm.customer_id=res.data.customerId;
 
-          })
-      },
-
-      onChangeStatus(e){
-          this.dataForm.status=e;
-      },
-      //修改分类信息
-      onChangeCategory(e){
-         let _this=this;
-         _this.dataForm.categoryId=e;
-      },
-      //初始化所有分类
-      initAllCategory(){
-          let _this=this;
-          let par={
-            page:1,
-            pageSize:9999,
-            status:5
-          };
-          searchCategory(par).then(res=>{
-            _this.allCategories=res.data.dataList;
-          })
-      },
-      initCustomer(){
-        let _this=this;
-        let par={
-          page:1,
-          pageSize:99,
-        }
-        searchCustomer(par).then(res=>{
-          _this.customerList=res.data.dataList;
-        })
-      }
-
-    }
-  }
+    onChangeStatus(e) {
+      this.dataForm.status = e;
+    },
+    //修改分类信息
+    onChangeCategory(e) {
+      let _this = this;
+      _this.dataForm.categoryId = e;
+    },
+    //初始化所有分类
+    initAllCategory() {
+      let _this = this;
+      let par = {
+        page: 1,
+        pageSize: 9999,
+        status: 5,
+      };
+      searchCategory(par).then((res) => {
+        _this.allCategories = res.data.dataList;
+      });
+    },
+    initCustomer() {
+      let _this = this;
+      let par = {
+        page: 1,
+        pageSize: 99,
+      };
+      searchCustomer(par).then((res) => {
+        _this.customerList = res.data.dataList;
+      });
+    },
+  },
+};
 </script>
 
 <style lang="scss">
- @import './dataInfo.scss'
+@import "./dataInfo.scss";
 </style>

+ 4 - 4
src/views/project/components/dataList.vue

@@ -4,8 +4,8 @@
 
       <el-table :data="dataList" style="width: 100%" header-row-class-name="headerBg" empty-text="没有项目信息">
         <el-table-column prop="id" label="ID" align="center" width="80"/>
-        <el-table-column prop="category.name" label="所属分类" align="left" min-width="180"/>
-        <el-table-column prop="customer.name" label="所属客户" align="left" min-width="180"/>
+       <el-table-column prop="categoryId" label="所属分类" align="left" min-width="180"/>
+         <!-- <el-table-column prop="customer.name" label="所属客户" align="left" min-width="180"/> -->
         <el-table-column prop="name" label="项目名称" align="left" min-width="180"/>
         <el-table-column prop="createTime" label="创建时间" align="center" width="180"/>
         <el-table-column prop="statusName" label="项目状态" align="center" width="180">
@@ -14,7 +14,7 @@
               <div v-if="scope.row.status==6">停用</div>
           </template>
         </el-table-column>
-        <el-table-column label="操作" align="center"  fixed="right" width="150">
+        <el-table-column label="操作" align="center"  fixed="right" width="200">
           <template #default="scope">
             <div class="btns">
               <el-button type="primary" size="small" @click="btnEdit(scope.row)"><svg-icon icon-class="edit"/>编辑</el-button>
@@ -28,7 +28,7 @@
 
       <div class="page-info">
       	<el-pagination
-      	v-model:currentPage="queryForm.page"
+      	:currentPage="queryForm.page"
       	:page-size="queryForm.pageSize"
       	:total="recordCount"
       	:page-count="pageTotal"

+ 523 - 134
src/views/templateLoca/index.vue

@@ -3,151 +3,204 @@
     <el-tabs v-model="activeTab" @tab-click="handleTabClick"
       ><!-- 新增的第二个标签页 -->
       <el-tab-pane label="文献项目输入表" name="first">
-        <div class="operation-bar">
-          <el-form :inline="true" :model="gsprSearchForm" class="search-form">
-            <el-form-item label="内容">
-              <el-input
-                v-model="gsprSearchForm.keyword"
-                placeholder="请输入项目名称/技术报告位置"
-                style="width: 300px"
-                clearable
-              />
-            </el-form-item>
-            <el-form-item label="部门">
+        <!-- 项目选择器始终显示 -->
+        <div class="project-selector">
+          <el-form :inline="true">
+            <el-form-item label="当前项目">
               <el-select
-                v-model="gsprSearchForm.department"
-                placeholder="请选择部门"
-                clearable
+                v-model="selectedProjectId"
+                placeholder="请选择项目"
+                style="width: 300px"
+                @change="handleProjectConfirm"
               >
                 <el-option
-                  v-for="(item, index) in departList"
-                  :key="index"
-                  :label="item.label"
-                  :value="item.label"
+                  v-for="project in projectOptions"
+                  :key="project.id"
+                  :label="project.name"
+                  :value="project.id"
                 />
               </el-select>
             </el-form-item>
             <el-form-item>
-              <el-button type="primary" @click="handleGsprSearch"
-                >搜索</el-button
+              <!--  <el-button type="primary" @click="handleProjectConfirm"
+                >确认选择</el-button
+              > -->
+              <el-button
+                type="primary"
+                @click="handleAddGspr"
+                v-if="!hasExistingData"
+                >创建输入项目</el-button
               >
-              <el-button @click="handleGsprReset">重置</el-button>
-            </el-form-item>
-          </el-form>
-          <el-button type="primary" @click="handleAddGspr">新增</el-button>
-        </div>
-
-        <el-table
-          :data="gsprTableData"
-          style="width: 100%"
-          :default-sort="{ prop: sort_field, order: sort_order }"
-          @sort-change="handleSortChange"
-        >
-          <el-table-column prop="name" label="项目名称" sortable="custom" />
-          <el-table-column prop="tech_report_location" label="技术报告位置" />
-          <el-table-column prop="department" label="部门" sortable="custom" />
-          <el-table-column prop="content" label="内容">
-            <template slot-scope="scope">
-              <div style="display: flex; align-items: center">
-                <span style="margin-right: 10px">{{ scope.row.content }}</span>
-                <i
-                  class="el-icon-edit"
-                  @click="handleEditContent(scope.row)"
-                  style="cursor: pointer; margin-left: 5px"
-                ></i>
-              </div>
-            </template>
-          </el-table-column>
-          <el-table-column label="操作" width="200">
-            <template slot-scope="scope">
-              <el-button type="primary" @click="handleEditGspr(scope.row)"
-                >编辑</el-button
+              <el-button type="primary" @click="handleUpdateGspr" v-else
+                >更新输入项目</el-button
               >
-              <el-button type="danger" @click="handleDeleteGspr(scope.row)"
+              <el-button type="danger" @click="handleDeleteItems"
                 >删除</el-button
               >
-            </template>
-          </el-table-column>
-        </el-table>
-
-        <div class="pagination-container">
-          <el-pagination
-            @size-change="handleGsprSizeChange"
-            @current-change="handleGsprCurrentChange"
-            :current-page="gsprPageForm.page"
-            :page-sizes="[10, 20, 30, 50]"
-            :page-size="gsprPageForm.page_size"
-            layout="total, sizes, prev, pager, next, jumper"
-            :total="gsprTotal"
-          />
+            </el-form-item>
+          </el-form>
         </div>
+        <!-- 使用 v-if 控制其余内容的显示 -->
+        <template v-if="currentProjectId">
+          <div class="operation-bar">
+            <el-form :inline="true" :model="gsprSearchForm" class="search-form">
+              <el-form-item label="内容">
+                <el-input
+                  v-model="gsprSearchForm.keyword"
+                  placeholder="请输入项目名称/技术报告位置"
+                  style="width: 300px"
+                  clearable
+                />
+              </el-form-item>
+              <el-form-item label="部门">
+                <el-select
+                  v-model="gsprSearchForm.department"
+                  placeholder="请选择部门"
+                  clearable
+                >
+                  <el-option
+                    v-for="(item, index) in departList"
+                    :key="index"
+                    :label="item.label"
+                    :value="item.label"
+                  />
+                </el-select>
+              </el-form-item>
+              <el-form-item>
+                <el-button type="primary" @click="handleGsprSearch"
+                  >搜索</el-button
+                >
+                <el-button @click="handleGsprReset">重置</el-button>
+              </el-form-item>
+            </el-form>
+          </div>
 
-        <!-- GSPR表单弹窗 -->
-        <el-dialog
-          :title="gsprDialogTitle"
-          :visible.sync="gsprDialogVisible"
-          width="700px"
-        >
-          <el-form
-            :model="gsprForm"
-            ref="gsprForm"
-            :rules="gsprRules"
-            label-width="120px"
+          <el-table
+            :data="gsprTableData"
+            style="width: 100%"
+            :default-sort="{ prop: sort_field, order: sort_order }"
+            @sort-change="handleSortChange"
           >
-            <el-form-item label="名称" prop="name">
-              <el-input v-model="gsprForm.name" />
-            </el-form-item>
-            <el-form-item label="技术报告位置" prop="tech_report_location">
-              <el-input v-model="gsprForm.tech_report_location" />
-            </el-form-item>
+            <el-table-column prop="name" label="项目名称" sortable="custom" />
+            <el-table-column prop="tech_report_location" label="技术报告位置" />
+            <el-table-column prop="department" label="部门" sortable="custom" />
+            <el-table-column prop="content" label="内容">
+              <template slot-scope="scope">
+                <div style="display: flex; align-items: center">
+                  <span style="margin-right: 10px">{{
+                    scope.row.content
+                  }}</span>
+                  <i
+                    class="el-icon-edit"
+                    @click="handleEditContent(scope.row)"
+                    style="cursor: pointer; margin-left: 5px"
+                  ></i>
+                </div>
+              </template>
+            </el-table-column>
+            <el-table-column label="操作" width="200">
+              <template slot-scope="scope">
+                <el-button type="primary" @click="handleEditGspr(scope.row)"
+                  >编辑</el-button
+                >
+                <el-button type="danger" @click="handleDeleteGspr(scope.row)"
+                  >删除</el-button
+                >
+              </template>
+            </el-table-column>
+          </el-table>
 
-            <el-form-item label="部门" prop="department">
-              <el-select v-model="gsprForm.department" placeholder="请选择状态">
-                <el-option
-                  v-for="(item, index) in departList"
-                  :key="index"
-                  :label="item.label"
-                  :value="item.label"
-                />
-              </el-select>
-            </el-form-item>
-            <el-form-item label="内容" prop="content">
-              <el-input
-                type="textarea"
-                v-model="gsprForm.content"
-                :rows="4"
-                placeholder="请输入内容"
-              />
-            </el-form-item>
-          </el-form>
-          <div slot="footer">
-            <el-button @click="gsprDialogVisible = false">取消</el-button>
-            <el-button type="primary" @click="handleGsprSubmit">确定</el-button>
+          <div class="pagination-container">
+            <el-pagination
+              @size-change="handleGsprSizeChange"
+              @current-change="handleGsprCurrentChange"
+              :current-page="gsprPageForm.page"
+              :page-sizes="[10, 20, 30, 50]"
+              :page-size="gsprPageForm.page_size"
+              layout="total, sizes, prev, pager, next, jumper"
+              :total="gsprTotal"
+            />
           </div>
-        </el-dialog>
-        <!-- 添加内容编辑弹窗 -->
-        <el-dialog
-          title="编辑内容"
-          :visible.sync="contentDialogVisible"
-          width="600px"
-        >
-          <el-form :model="contentForm" ref="contentForm">
-            <el-form-item label="内容" prop="content">
-              <el-input
-                type="textarea"
-                v-model="contentForm.content"
-                :rows="4"
-                placeholder="请输入内容"
-              />
-            </el-form-item>
-          </el-form>
-          <div slot="footer">
-            <el-button @click="contentDialogVisible = false">取消</el-button>
-            <el-button type="primary" @click="handleContentSubmit"
-              >确定</el-button
+
+          <!-- GSPR表单弹窗 -->
+          <el-dialog
+            :title="gsprDialogTitle"
+            :visible.sync="gsprDialogVisible"
+            width="700px"
+          >
+            <el-form
+              :model="gsprForm"
+              ref="gsprForm"
+              :rules="gsprRules"
+              label-width="120px"
             >
-          </div>
-        </el-dialog>
+              <el-form-item label="名称" prop="name">
+                <el-input v-model="gsprForm.name" />
+              </el-form-item>
+              <el-form-item label="技术报告位置" prop="tech_report_location">
+                <el-input v-model="gsprForm.tech_report_location" />
+              </el-form-item>
+
+              <el-form-item label="部门" prop="department">
+                <el-select
+                  v-model="gsprForm.department"
+                  placeholder="请选择状态"
+                >
+                  <el-option
+                    v-for="(item, index) in departList"
+                    :key="index"
+                    :label="item.label"
+                    :value="item.label"
+                  />
+                </el-select>
+              </el-form-item>
+              <el-form-item label="内容" prop="content">
+                <el-input
+                  type="textarea"
+                  v-model="gsprForm.content"
+                  :rows="4"
+                  placeholder="请输入内容"
+                />
+              </el-form-item>
+            </el-form>
+            <div slot="footer">
+              <el-button @click="gsprDialogVisible = false">取消</el-button>
+              <el-button type="primary" @click="handleGsprSubmit"
+                >确定</el-button
+              >
+            </div>
+          </el-dialog>
+          <!-- 添加内容编辑弹窗 -->
+          <el-dialog
+            title="编辑内容"
+            :visible.sync="contentDialogVisible"
+            width="600px"
+          >
+            <el-form :model="contentForm" ref="contentForm">
+              <el-form-item label="内容" prop="content">
+                <el-input
+                  type="textarea"
+                  v-model="contentForm.content"
+                  :rows="4"
+                  placeholder="请输入内容"
+                />
+              </el-form-item>
+            </el-form>
+            <div slot="footer">
+              <el-button @click="contentDialogVisible = false">取消</el-button>
+              <el-button type="primary" @click="handleContentSubmit"
+                >确定</el-button
+              >
+            </div>
+          </el-dialog>
+        </template>
+
+        <!-- 未选择项目时显示提示 -->
+        <el-empty
+          v-else
+          description="请先选择一个项目"
+          :image-size="200"
+        ></el-empty>
       </el-tab-pane>
       <!-- 第一个标签页 - 原有的模板位置表 -->
       <el-tab-pane label="模板位置表" name="second">
@@ -173,7 +226,7 @@
                 <el-option
                   v-for="(item, index) in typeList"
                   :key="index"
-                  :label="item.label"
+                  :label="item.value"
                   :value="item.value"
                 />
                 <!-- <el-option label="WE" value="WE" /> -->
@@ -236,6 +289,41 @@
         </div>
       </el-tab-pane>
     </el-tabs>
+    <!-- 添加删除确认对话框 -->
+    <el-dialog
+      title="删除确认"
+      :visible.sync="deleteDialogVisible"
+      width="400px"
+    >
+      <!-- 添加提示信息区域 -->
+      <div class="delete-warning" style="margin-bottom: 20px">
+        <i
+          class="el-icon-warning"
+          style="color: #e6a23c; margin-right: 8px"
+        ></i>
+        <span
+          >此操作将永久删除该项目下的所有输入项目,请输入'DELETE'确认删除</span
+        >
+      </div>
+
+      <el-form
+        :model="deleteForm"
+        :rules="deleteRules"
+        ref="deleteForm"
+        label-width="100px"
+      >
+        <el-form-item label="确认文本" prop="confirmText">
+          <el-input
+            v-model="deleteForm.confirmText"
+            placeholder="请输入'DELETE'"
+          ></el-input>
+        </el-form-item>
+      </el-form>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="deleteDialogVisible = false">取消</el-button>
+        <el-button type="danger" @click="confirmDelete">确认删除</el-button>
+      </span>
+    </el-dialog>
   </div>
 </template>
   
@@ -251,11 +339,24 @@ import {
   projectUpdate,
   projectDelete,
   get_action_types,
+  create_items,
+  delete_items,
+  update_items,
 } from "@/api/knowledge";
+import { searchProject } from "@/api/project";
 import axios from "axios";
+import { mapState } from "vuex";
 export default {
   name: "TemplateLocation",
   data() {
+    // 自定义验证规则
+    const validateDeleteConfirm = (rule, value, callback) => {
+      if (value !== "DELETE") {
+        callback(new Error("请输入正确的确认文本"));
+      } else {
+        callback();
+      }
+    };
     return {
       tableData: [],
       dialogVisible: false,
@@ -338,17 +439,279 @@ export default {
       /* 排序 */
       sort_field: "name", // 默认排序字段
       sort_order: "desc", // 默认排序方向
+      /* 新增项目 */
+      selectedProjectId: null, // 新增本地属性来存储选中的项目ID
+      projectOptions: [], // 项目选项列表
+      gsprSearchForm: {
+        keyword: "",
+        department: "",
+        project_id: null, // 添加项目ID字段
+      },
+      /* 删除逻辑 */
+      deleteDialogVisible: false,
+      deleteForm: {
+        confirmText: "",
+      },
+      deleteRules: {
+        confirmText: [
+          { required: true, message: "请输入确认文本", trigger: "blur" },
+          { validator: validateDeleteConfirm, trigger: "blur" },
+        ],
+      },
+      hasExistingData: false, // 添加标记是否有现有数据的属性
     };
   },
+  computed: {
+    ...mapState("project", ["currentProjectId"]),
+  },
+  // created 钩子中的修改
+  created() {
+    // 从 localStorage 恢复项目状态
+    const savedProject = localStorage.getItem("currentProject");
+    if (savedProject) {
+      const { id, name } = JSON.parse(savedProject);
+      this.$store.dispatch("project/setCurrentProject", { id, name });
+      this.selectedProjectId = id; // 同步设置本地选中状态
+    }
+  },
+
+  // 添加 watch 来监听 Vuex 中的 currentProjectId 变化
+  watch: {
+    currentProjectId: {
+      immediate: true, // 添加 immediate: true 确保组件创建时就执行
+      handler(newVal) {
+        if (newVal) {
+          this.selectedProjectId = newVal;
+          this.gsprSearchForm.project_id = newVal;
+          this.fetchGsprData(); // 自动加载数据
+        }
+      },
+    },
+  },
   mounted() {
-    this.fetchGsprData();
+    this.fetchProjects();
+    /*  this.fetchGsprData(); */
     this.init();
   },
   methods: {
+    // 处理删除按钮点击
+    handleDeleteItems() {
+      if (!this.currentProjectId) {
+        this.$message.warning("请先选择一个项目");
+        return;
+      }
+
+      const selectedProject = this.projectOptions.find(
+        (p) => p.id === this.currentProjectId
+      );
+
+      this.$confirm(
+        `您确定要删除项目 "${selectedProject.name}" 的所有输入项目吗?此操作不可恢复。`,
+        "警告",
+        {
+          confirmButtonText: "继续删除",
+          cancelButtonText: "取消",
+          type: "warning",
+        }
+      )
+        .then(() => {
+          this.deleteForm.confirmText = "";
+          this.deleteDialogVisible = true;
+        })
+        .catch(() => {
+          this.$message({
+            type: "info",
+            message: "已取消删除",
+          });
+        });
+    },
+
+    // 确认删除
+    confirmDelete() {
+      this.$refs.deleteForm.validate(async (valid) => {
+        if (!valid) {
+          return false;
+        }
+
+        try {
+          const loading = this.$loading({
+            lock: true,
+            text: "正在删除...",
+            spinner: "el-icon-loading",
+            background: "rgba(0, 0, 0, 0.7)",
+          });
+
+          const response = await delete_items({
+            project_id: this.currentProjectId,
+          });
+
+          loading.close();
+
+          if (response.status === 200) {
+            this.$message.success("删除成功");
+            this.deleteDialogVisible = false;
+            // 重新加载数据
+            this.fetchGsprData();
+          } else {
+            this.$message.error(response.message || "删除失败");
+          }
+        } catch (error) {
+          this.$message.error("删除失败:" + (error.message || "未知错误"));
+        }
+      });
+    },
+    /* 初始化请求项目列表接口 */
+    async fetchProjects() {
+      try {
+        const response = await searchProject({ page: 1, pageSize: 999 });
+        if (response.status === 200) {
+          this.projectOptions = response.data.dataList;
+
+          // 如果有当前项目ID但没有选中项目,自动选中
+          if (this.currentProjectId && !this.selectedProjectId) {
+            this.selectedProjectId = this.currentProjectId;
+            this.handleProjectConfirm();
+          }
+        }
+      } catch (error) {
+        this.$message.error("获取项目列表失败");
+      }
+    },
+
+    // 修改 handleProjectConfirm 方法
+    handleProjectConfirm() {
+      if (!this.selectedProjectId) {
+        this.$message.warning("请先选择一个项目");
+        return;
+      }
+
+      const selectedProject = this.projectOptions.find(
+        (p) => p.id === this.selectedProjectId
+      );
+
+      if (!selectedProject) {
+        this.$message.error("未找到选中的项目");
+        return;
+      }
+
+      this.$store.dispatch("project/setCurrentProject", {
+        id: selectedProject.id,
+        name: selectedProject.name,
+      });
+
+      // 保存到 localStorage
+      localStorage.setItem(
+        "currentProject",
+        JSON.stringify({
+          id: selectedProject.id,
+          name: selectedProject.name,
+        })
+      );
+
+      this.gsprSearchForm.project_id = this.selectedProjectId;
+      this.fetchGsprData();
+    },
+
+    // 创建项目的方法
+    async handleAddGspr() {
+      if (!this.currentProjectId) {
+        this.$message.warning("请先选择一个项目");
+        return;
+      }
+      const selectedProject = this.projectOptions.find(
+        (p) => p.id === this.currentProjectId
+      );
+
+      const loading = this.$loading({
+        lock: true,
+        text: "正在创建项目...",
+        spinner: "el-icon-loading",
+        background: "rgba(0, 0, 0, 0.7)",
+      });
+
+      try {
+        const res = await create_items({
+          project_id: selectedProject.id,
+          project_name: selectedProject.name,
+        });
+
+        if (res.status !== 200) {
+          throw new Error("创建失败");
+        }
+
+        this.$message.success(
+          `成功创建 ${res.data.data.created_count} 个输入项目!`
+        );
+        await this.fetchGsprData();
+      } catch (error) {
+        this.$message.error("创建失败: " + (error.message || "未知错误"));
+      } finally {
+        loading.close();
+      }
+    },
+
+    // 新增更新项目的方法
+    async handleUpdateGspr() {
+      if (!this.currentProjectId) {
+        this.$message.warning("请先选择一个项目");
+        return;
+      }
+      const selectedProject = this.projectOptions.find(
+        (p) => p.id === this.currentProjectId
+      );
+
+      try {
+        await this.$confirm(
+          "此操作将更新当前项目的所有输入项目,是否继续?",
+          "提示",
+          {
+            confirmButtonText: "确定",
+            cancelButtonText: "取消",
+            type: "warning",
+          }
+        );
+
+        const loading = this.$loading({
+          lock: true,
+          text: "正在更新项目...",
+          spinner: "el-icon-loading",
+          background: "rgba(0, 0, 0, 0.7)",
+        });
+
+        try {
+          const res = await update_items({
+            // 假设有一个update_items的API
+            project_id: selectedProject.id,
+            project_name: selectedProject.name,
+          });
+
+          if (res.status !== 200) {
+            throw new Error("更新失败");
+          }
+
+          this.$message.success(
+            `成功更新 ${res.data.data.updated_count} 个输入项目!`
+          );
+          await this.fetchGsprData();
+        } finally {
+          loading.close();
+        }
+      } catch (error) {
+        if (error !== "cancel") {
+          this.$message.error("更新失败: " + (error.message || "未知错误"));
+        }
+      }
+    },
     /* 编辑内容 */
     handleEditContent(row) {
+      const selectedProject = this.projectOptions.find(
+        (p) => p.id === this.currentProjectId
+      );
       this.contentForm = {
+        project: selectedProject.id,
+        project_name: selectedProject.name,
         id: row.id,
+        tech_report_location: row.tech_report_location,
         content: row.content,
         name: row.name,
         department: row.department,
@@ -528,10 +891,10 @@ export default {
     // 新增:处理标签页切换
     handleTabClick(tab) {
       if (tab.name === "second" && !this.isSecondTabLoaded) {
-         this.fetchData();
+        this.fetchData();
         this.isSecondTabLoaded = false;
       } else {
-       this.fetchGsprData();
+        this.fetchGsprData();
         this.isSecondTabLoaded = true;
       }
     },
@@ -563,6 +926,10 @@ export default {
     },
     // 修改 fetchGsprData 方法,添加搜索参数
     async fetchGsprData() {
+      if (!this.currentProjectId) {
+        return; // 如果没有选择项目,直接返回
+      }
+
       const loading = this.$loading({
         lock: true,
         text: "加载中...",
@@ -574,6 +941,7 @@ export default {
         const params = {
           sort_field: this.sort_field,
           sort_order: this.sort_order,
+          project_id: this.currentProjectId,
           ...this.gsprPageForm,
           ...this.gsprSearchForm,
         };
@@ -581,6 +949,7 @@ export default {
         if (response.status === 200) {
           this.gsprTableData = response.data.list;
           this.gsprTotal = response.data.total;
+          this.hasExistingData = this.gsprTotal > 0;
         }
       } catch (error) {
         console.error("获取数据失败:", error);
@@ -602,7 +971,7 @@ export default {
     },
 
     // GSPR表单操作
-    handleAddGspr() {
+    /* handleAddGspr() {
       this.gsprDialogTitle = "新增文献项目";
       this.gsprForm = {
         name: "",
@@ -611,11 +980,12 @@ export default {
         status: 5,
       };
       this.gsprDialogVisible = true;
-    },
+    }, */
 
     handleEditGspr(row) {
       this.gsprDialogTitle = "编辑文献项目";
       this.gsprForm = { ...row };
+      console.log(this.gsprForm);
       this.gsprDialogVisible = true;
     },
 
@@ -669,6 +1039,12 @@ export default {
 </script>
   
   <style scoped>
+.project-selector {
+  margin-bottom: 20px;
+}
+/* .el-form-item {
+  margin-bottom: 0;
+} */
 .template-location-container {
   padding: 20px;
 }
@@ -679,4 +1055,17 @@ export default {
   display: flex;
   justify-content: end;
 }
+.delete-warning {
+  padding: 12px 16px;
+  background-color: #fdf6ec;
+  border-radius: 4px;
+  color: #e6a23c;
+  line-height: 1.4;
+  font-size: 14px;
+  display: flex;
+  align-items: center;
+}
+::v-deep .el-tabs__nav-wrap::after {
+  width: 13%;
+}
 </style>

Bu fark içinde çok fazla dosya değişikliği olduğu için bazı dosyalar gösterilmiyor