Pārlūkot izejas kodu

修改项目项并打包

yangg 7 mēneši atpakaļ
vecāks
revīzija
429720d8db

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 0 - 0
dist/index.html


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 0 - 0
dist/static/css/app.4bfea3f5.css


+ 1 - 0
dist/static/css/chunk-21c68cbd.857f893e.css

@@ -0,0 +1 @@
+.data-search{padding:20px 10px 0 10px}.data-list .btns{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.data-list .w_input{width:60%}.data-list .page-info{margin-top:10px}.data-list .page-info,.data-list .page-info .opt{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.data-list .page-info .opt{width:50%;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.data-list .page-info .opt .pick{width:100px}.data-list .page-info .opt .section{margin-left:10px}.data-list .page-info .page-data{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;-webkit-box-align:center;-ms-flex-align:center;align-items:center;width:100%}.data-list .page-info .page-data .page-item{width:100%}.data-list .page-info .page-data .page-opt{width:100%;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end}.sub-imgs{padding:0;margin:0}.sub-imgs li{float:left;margin-right:10px;width:100px;height:100px;list-style:none}.project-search{padding:30px;font-size:12px}

+ 0 - 1
dist/static/css/chunk-d4c547ca.e30e9787.css

@@ -1 +0,0 @@
-.data-search{padding:20px 10px 0 10px}.sub-imgs{padding:0;margin:0}.sub-imgs li{float:left;margin-right:10px;width:100px;height:100px;list-style:none}.data-list .btns,.data-list .page-info{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.data-list .page-info{margin-top:10px}.data-list .page-info .opt{width:50%;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.data-list .page-info .opt .pick{width:100px}.data-list .page-info .opt .section{margin-left:10px}.data-list .page-info .page-data{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;-webkit-box-align:center;-ms-flex-align:center;align-items:center;width:100%}.data-list .page-info .page-data .page-item{width:100%}.data-list .page-info .page-data .page-opt{width:100%;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end}.project-search{padding:30px;font-size:12px}

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 0 - 0
dist/static/js/app.6b75fdae.js


+ 0 - 0
dist/static/js/chunk-10b289e2.d06e3c4c.js → dist/static/js/chunk-10b289e2.35f756ba.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 0 - 0
dist/static/js/chunk-21c68cbd.6abdfa45.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 0 - 0
dist/static/js/chunk-d4c547ca.bfb382e5.js


+ 30 - 0
src/api/customer.js

@@ -15,3 +15,33 @@ export function syncCustomer() {
     method: 'post'
   })
 }
+
+/* 新增客户  */
+
+export function createCustomer(data) {
+  return request({
+    url: '/customer/create',
+    method: 'post',
+    data
+  })
+}
+
+/* 更新客户 customer/update */
+
+export function updateCustomer(data) {
+  return request({
+    url: '/customer/update',
+    method: 'post',
+    data
+  })
+}
+
+/* customer/delete */
+
+export function deleteCustomer(data) {
+  return request({
+    url: '/customer/delete',
+    method: 'post',
+    data
+  })
+}

+ 19 - 0
src/api/knowledge.js

@@ -664,4 +664,23 @@ export function vague_search(data) {
     method: 'post',
     data
   })
+}
+
+/* 修改序号  */
+
+export function sequence(data) {
+  return request({
+    url: 'project-input/sequence',
+    method: 'post',
+    data
+  })
+}
+
+/* 输入项目打分 */
+export function rateScope(data) {
+  return request({
+    url: 'project-input/score',
+    method: 'post',
+    data
+  })
 }

+ 38 - 0
src/api/project.js

@@ -118,5 +118,43 @@ export function searchTemplateList(data) {
   })
 }
 
+/* 阶段 project/getphases */
 
+export function getphases(data) {
+  return request({
+    url: '/project/getphases',
+    method: 'post',
+    data
+  })
+}
+
+/* 目前状态  */
+
+export function getstatus(data) {
+  return request({
+    url: '/project/getstatus',
+    method: 'post',
+    data
+  })
+}
 
+/* 完成度 */
+
+export function calculate(data) {
+  return request({
+    url: '/project/calculate',
+    method: 'post',
+    data
+  })
+}
+
+/* 导出文献列表 */
+
+export function exportItems(data) {
+  return request({
+    url: '/project-input/export',
+    method: 'post',
+    data,
+    responseType: 'blob'  // 重要:需要设置responseType为blob以接收文件流
+  })
+}

+ 6 - 1
src/styles/sidebar.scss

@@ -125,6 +125,9 @@
 
       .el-tooltip {
         padding: 0 !important;
+        display: flex !important;
+        justify-content: center;
+        align-items: center;
 
         .svg-icon {
           margin-left: 20px;
@@ -142,7 +145,9 @@
       &>.el-submenu__title {
         background-color: $subMenuBg !important;
         padding: 0 !important;
-
+        display: flex !important;
+        justify-content: center;
+        align-items: center;
         .svg-icon {
           margin-left: 20px;
         }

+ 192 - 0
src/views/Information/index.vue

@@ -0,0 +1,192 @@
+<template>
+    <div class="information-container">
+      <!-- 添加搜索栏 -->
+      <div class="search-container">
+        <el-form :inline="true" :model="queryParams" class="demo-form-inline">
+          <el-form-item label="项目名称">
+            <el-input
+              v-model="queryParams.project_name"
+              placeholder="请输入项目名称"
+              clearable
+              @keyup.enter="handleQuery"
+            />
+          </el-form-item>
+          <el-form-item label="部门">
+            <el-input
+              v-model="queryParams.department"
+              placeholder="请输入部门"
+              clearable
+              @keyup.enter="handleQuery"
+            />
+          </el-form-item>
+          <el-form-item>
+            <el-button type="primary" @click="handleQuery">搜索</el-button>
+            <el-button @click="resetQuery">重置</el-button>
+          </el-form-item>
+        </el-form>
+      </div>
+      <el-table :data="projectList" stripe>
+        <el-table-column prop="sequence" label="序号" width="80" />
+        <el-table-column prop="project_name" label="项目名称" />
+        <el-table-column prop="name" label="文件名称" />
+        <el-table-column prop="tech_report_location" label="技术文档位置" />
+        <el-table-column prop="department" label="部门" />
+        <el-table-column prop="create_time" label="创建时间" />
+        <el-table-column prop="status" label="状态">
+          <template #default="scope">
+            <el-tag :type="getStatusType(scope.row.status)">
+              {{ getStatusText(scope.row.status) }}
+            </el-tag>
+          </template>
+        </el-table-column>
+        <!-- 添加操作列 -->
+        <el-table-column label="操作" width="150">
+          <template #default="scope">
+            <el-button type="primary" size="small" @click="handleEdit(scope.row)"
+              >编辑</el-button
+            >
+          </template>
+        </el-table-column>
+      </el-table>
+      <!-- 添加分页组件 -->
+      <div class="pagination-container">
+        <el-pagination
+          :current-page="queryParams.page"
+          :page-size="queryParams.page_size"
+          :page-sizes="[10, 20, 50, 100]"
+          :total="total"
+          layout="total, sizes, prev, pager, next, jumper"
+          @size-change="handleSizeChange"
+          @current-change="handleCurrentChange"
+        />
+      </div>
+      <el-dialog
+        :visible.sync="dialogVisible"
+        title="修改序号"
+        width="30%"
+        append-to-body
+        v-el-drag-dialog
+      >
+        <el-form :model="sequenceForm" label-width="80px">
+          <el-form-item label="序号">
+            <el-input-number
+              v-model="sequenceForm.sequence"
+              :min="0"
+              controls-position="right"
+            />
+          </el-form-item>
+        </el-form>
+        <template #footer>
+          <span class="dialog-footer">
+            <el-button @click="dialogVisible = false">取消</el-button>
+            <el-button type="primary" @click="submitSequence">确定</el-button>
+          </span>
+        </template>
+      </el-dialog>
+    </div>
+  </template>
+    
+    <script>
+  import { projectList, sequence } from "@/api/knowledge";
+  import elDragDialog from "@/directive/el-drag-dialog";
+  export default {
+    directives: { elDragDialog },
+    name: "Information",
+    data() {
+      return {
+        projectList: [],
+        total: 0,
+        queryParams: {
+          sort_field:'sequence',
+          sort_order:"asc",
+          page: 1,
+          page_size: 10,
+          project_name: "", // 添加搜索参数
+          department: "", // 添加搜索参数
+        },
+        dialogVisible: false,
+        sequenceForm: {
+          sequence: 1,
+          id: null,
+        },
+      };
+    },
+    methods: {
+      async getProjectList() {
+        try {
+          // 修改请求,添加分页参数
+          const response = await projectList(this.queryParams);
+          this.projectList = response.data.list;
+          this.total = response.data.total; // 假设后端返回总数
+        } catch (error) {
+          console.error("获取项目列表失败:", error);
+        }
+      },
+      // 添加分页处理方法
+      handleSizeChange(val) {
+        this.queryParams.page_size = val;
+        this.getProjectList();
+      },
+      handleCurrentChange(val) {
+        this.queryParams.page = val;
+        this.getProjectList();
+      },
+      // 获取状态标签类型
+      getStatusType(status) {
+        const statusMap = {
+          5: "success",
+          // 可以根据实际状态码添加更多映射
+        };
+        return statusMap[status] || "info";
+      },
+      // 获取状态文本
+      getStatusText(status) {
+        const statusMap = {
+          5: "正常",
+          // 可以根据实际状态码添加更多映射
+        };
+        return statusMap[status] || "未知状态";
+      },
+      // 添加搜索相关方法
+      handleQuery() {
+        this.queryParams.page = 1;
+        this.getProjectList();
+      },
+      resetQuery() {
+        this.queryParams.project_name = "";
+        this.queryParams.department = "";
+        this.handleQuery();
+      },
+      // 打开编辑序号对话框
+      handleEdit(row) {
+        this.sequenceForm.sequence = row.sequence;
+        this.sequenceForm.id = row.id;
+        this.dialogVisible = true;
+      },
+  
+      // 提交序号修改
+      async submitSequence() {
+        try {
+          await sequence({
+            id: this.sequenceForm.id,
+            new_sequence: this.sequenceForm.sequence,
+          });
+          this.$message.success("修改序号成功");
+          this.dialogVisible = false;
+          this.getProjectList(); // 刷新列表
+        } catch (error) {
+          this.$message.error("修改序号失败:" + error.message);
+        }
+      },
+    },
+    created() {
+      this.getProjectList();
+    },
+  };
+  </script>
+    
+    <style lang="scss" scoped>
+  .information-container {
+    padding: 20px;
+  }
+  </style>

+ 3 - 1
src/views/customer/components/dataList.scss

@@ -7,7 +7,9 @@
     flex-direction: row;
   }
 
-
+.w_input{
+  width: 60%;
+}
 
 
   .page-info{

+ 347 - 126
src/views/customer/components/dataList.vue

@@ -1,153 +1,374 @@
 <template>
   <div class="data-list">
+    <div class="data-search">
+      <el-form :inline="true" :model="queryForm" class="demo-form-inline">
+        <el-form-item label="客户名称:">
+          <el-input
+            v-model="queryForm.name"
+            placeholder="请选择客户名称"
+          ></el-input>
+        </el-form-item>
 
+        <el-form-item label="状态:">
+          <el-select
+            v-model="queryForm.status"
+            class="m-2"
+            placeholder="请选择状态"
+            size="large"
+          >
+            <el-option
+              v-for="item in statusOptions"
+              :key="item.value"
+              :label="item.label"
+              :value="item.value"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="onSubmit">
+            <svg-icon icon-class="search" /> 搜索</el-button
+          >
+          <el-button type="danger" @click="resetQuery">
+            <!-- <svg-icon icon-class="reset" />  -->重置</el-button
+          >
+          <el-button type="primary" @click="onAdd">
+            <!-- <svg-icon icon-class="add" /> -->新增客户</el-button
+          >
+        </el-form-item>
+      </el-form>
+    </div>
+    <el-table :data="dataList" style="width: 100%; margin-top: 20px">
+      <el-table-column prop="code" label="客户编码" />
+      <el-table-column prop="name" label="客户名称" />
+      <el-table-column prop="enName" label="英文名称" />
+      <el-table-column prop="mobile" label="手机号码" />
+      <el-table-column prop="contact" label="联系人" />
+      <el-table-column prop="address" label="地址" />
+      <el-table-column prop="other" label="其他信息" />
+      <el-table-column prop="createTime" label="创建时间" />
+      <el-table-column prop="status" label="状态">
+        <template #default="scope">
+          {{ scope.row.status === 5 ? "启用" : "停用" }}
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" width="150">
+        <template #default="scope">
+          <el-button size="small" @click="handleEdit(scope.row)"
+            >编辑</el-button
+          >
+          <el-button size="small" type="danger" @click="handleDelete(scope.row)"
+            >删除</el-button
+          >
+        </template>
+      </el-table-column>
+    </el-table>
 
-      <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="code" label="客户代码" align="left" min-width="180"/> -->
-        <el-table-column prop="name" label="客户名称" align="left" min-width="180"/>
-        <el-table-column prop="enName" label="英文名称" align="left" min-width="180"/>
-<!--
-        <el-table-column prop="mobile" label="手机号码" align="center" width="180"/>
-        <el-table-column prop="contact" label="联系人" align="center" width="180"/>
-        <el-table-column prop="address" label="联系地址" align="left" min-width="180"/>
--->
-        <el-table-column prop="createTime" label="创建时间" align="center" width="180"/>
-        <el-table-column prop="status" label="客户状态" align="center" width="180">
-           <template #default="scope">
-              <div v-if="scope.row.status==5">启用</div>
-              <div v-if="scope.row.status==6">停用</div>
-          </template>
-        </el-table-column>
-      </el-table>
-
-
-      <div class="page-info">
-      	<el-pagination
-      	v-model:currentPage="queryForm.page"
-      	:page-size="queryForm.pageSize"
-      	:total="recordCount"
-      	:page-count="pageTotal"
-      	 background
-      	 layout="prev, pager, next"
-      	 @current-change="ChangePage"
-      	 >
-      	 </el-pagination>
-      </div>
-
-     <el-dialog  :visible.sync="dialogVisible" append-to-body v-el-drag-dialog  width="80%" custom-class="prod-verify" title="创建项目信息">
-
-          <dataInfo ></dataInfo>
-      </el-dialog>
+    <div class="page-info">
+      <el-pagination
+        :currentPage="queryForm.page"
+        :page-size="queryForm.pageSize"
+        :total="recordCount"
+        :page-count="pageTotal"
+        background
+        layout="prev, pager, next"
+        @current-change="ChangePage"
+      >
+      </el-pagination>
+    </div>
 
+    <el-dialog title="新增客户" :visible.sync="dialogVisible" width="50%">
+      <el-form :model="customerForm" label-width="120px">
+        <el-form-item label="客户编码" required>
+          <el-input
+            v-model="customerForm.code"
+            placeholder="请输入客户编码"
+            class="w_input"
+          />
+        </el-form-item>
+        <el-form-item label="客户名称" required>
+          <el-input
+            v-model="customerForm.name"
+            placeholder="请输入客户名称"
+            class="w_input"
+          />
+        </el-form-item>
+        <el-form-item label="英文名称" required>
+          <el-input
+            v-model="customerForm.en_name"
+            placeholder="请输入英文名称"
+            class="w_input"
+          />
+        </el-form-item>
+        <el-form-item label="手机号码" required>
+          <el-input
+            v-model="customerForm.mobile"
+            placeholder="请输入手机号码"
+            class="w_input"
+          />
+        </el-form-item>
+        <el-form-item label="联系人" required>
+          <el-input
+            v-model="customerForm.contact"
+            placeholder="请输入联系人"
+            class="w_input"
+          />
+        </el-form-item>
+        <el-form-item label="地址" required>
+          <el-input
+            v-model="customerForm.address"
+            placeholder="请输入地址"
+            class="w_input"
+          />
+        </el-form-item>
+        <el-form-item label="其他信息">
+          <el-input
+            v-model="customerForm.other"
+            placeholder="请输入其他信息"
+            class="w_input"
+          />
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <span class="dialog-footer">
+          <el-button @click="dialogVisible = false">取消</el-button>
+          <el-button type="primary" @click="handleCreate">确定</el-button>
+        </span>
+      </template>
+    </el-dialog>
   </div>
-
-
 </template>
 
 <script>
-  import{searchCustomer} from'@/api/customer';
-  import dataInfo from './dataInfo.vue';
-  import elDragDialog from '@/directive/el-drag-dialog'
-  export default{
-    components:{
-      dataInfo,
-    },
-    directives: { elDragDialog },
-    props:{
-      queryForm:{
-        type:Object,
-        default:()=>{
-          return {
-            page:1,
-            pageSize:10,
-            name:'',
-            status:'',
-          }
-        }
-      }
+import { searchCustomer, syncCustomer, createCustomer, updateCustomer,deleteCustomer } from "@/api/customer";
+/* import dataInfo from "./dataInfo.vue"; */
+import elDragDialog from "@/directive/el-drag-dialog";
+export default {
+  /* components: {
+    dataInfo,
+  }, */
+  directives: { elDragDialog },
+  props: {
+    queryForm: {
+      type: Object,
+      default: () => {
+        return {
+          page: 1,
+          pageSize: 10,
+          name: "",
+          status: "",
+        };
+      },
+    },
+  },
+  watch: {
+    queryForm: {
+      handler: function (val) {
+        this.search();
+      },
+      // immediate: true,//立即执行
+      deep: true,
+    },
+  },
+  data() {
+    return {
+      currentDataId: 0,
+      recordCount: 0,
+      pageTotal: 1,
+      dataList: [],
+      currentData: {},
+      statusOptions: [
+        {
+          value: "",
+          label: "请选择状态",
+        },
+        {
+          value: 5,
+          label: "启用",
+        },
+        {
+          value: 6,
+          label: "停用",
+        },
+      ],
+      dialogVisible: false,
+      customerForm: {
+        code: "",
+        name: "",
+        en_name: "",
+        mobile: "",
+        contact: "",
+        address: "",
+        other: "",
+      },
+      tableData: [], // Add tableData
+      isEdit: false, // Add flag for edit mode
+    };
+  },
+  mounted() {
+    this.search();
+  },
+  methods: {
+    // 处理创建/更新客户
+    handleEdit(row) {
+      this.isEdit = true;
+      this.customerForm = { ...row,en_name:row.enName };
+      this.dialogVisible = true;
     },
-    watch:{
 
-        'queryForm': {
-          handler: function(val) {
+    handleDelete(row) {
+      this.$confirm("确认删除该客户?", "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning",
+      }).then(() => {
+        deleteCustomer({id:row.id})
+          .then(() => {
+            this.$message.success("删除成功");
+            this.search()
+          })
+          .catch(() => {
+            this.$message.error("删除失败");
+          });
+      });
+    },
 
-            this.search();
-          },
-          // immediate: true,//立即执行
-          deep: true
+    handleCreate() {
+      const request = this.isEdit
+        ? updateCustomer(this.customerForm)
+        : createCustomer(this.customerForm);
+      request
+        .then(() => {
+          this.$message.success(this.isEdit ? "更新成功" : "创建成功");
+          this.dialogVisible = false;
+          this.resetForm();
+          this.search();
+        })
+        .catch(() => {
+          this.$message.error(this.isEdit ? "更新失败" : "创建失败");
+        });
+    },
 
-        },
+    onAdd() {
+      this.isEdit = false;
+      this.customerForm = {
+        code: "",
+        name: "",
+        en_name: "",
+        mobile: "",
+        contact: "",
+        address: "",
+        other: "",
+      };
+      this.dialogVisible = true;
     },
-    data(){
-      return{
-        dialogVisible:false,//控制产品审核
-        currentDataId:0,
-        recordCount:0,
-        pageTotal:1,
-        dataList:[],
-        currentData:{},
-      }
-    },
-    mounted() {
-      this.search();
+
+    // 重置表单
+    resetForm() {
+      this.customerForm = {
+        code: "",
+        name: "",
+        en_name: "",
+        mobile: "",
+        contact: "",
+        address: "",
+        other: "",
+      };
     },
-    methods:{
+    // 搜索提交
+    onSubmit() {
+      // 重置页码
+      this.queryForm.page = 1;
 
-      onFocusVal(e){
-        let _this=this;
-        _this.currentDataId=e.target.dataset.id;
-      },
+      // 构建搜索参数
+      const searchParams = {
+        ...this.queryForm,
+        name: this.queryForm.name.trim(),
+        status: this.queryForm.status,
+      };
 
-      onChangeVal(e){
-        let _this=this;
-        let par={
-          id:_this.currentDataId,
-          val:e,
-        };
+      // 移除空值参数
+      Object.keys(searchParams).forEach((key) => {
+        if (
+          searchParams[key] === "" ||
+          searchParams[key] === null ||
+          searchParams[key] === undefined
+        ) {
+          delete searchParams[key];
+        }
+      });
 
-      },
+      this.search();
+    },
 
-      searchData(){
-        let _this=this;
-        _this.dialogVisible=false;
-        _this.search();
-      },
+    // 重置搜索条件
+    resetQuery() {
+      this.queryForm = {
+        page: 1,
+        pageSize: 10,
+        name: "",
+        status: "",
+      };
+      this.onSubmit();
+    },
+    /* 搜索 */
+    onSync(e) {
+      let _this = this;
+      syncCustomer().then((res) => {
+        console.log("res", res);
+      });
+    },
+    onFocusVal(e) {
+      let _this = this;
+      _this.currentDataId = e.target.dataset.id;
+    },
 
+    onChangeVal(e) {
+      let _this = this;
+      let par = {
+        id: _this.currentDataId,
+        val: e,
+      };
+    },
 
-      //编辑
-      btnEdit(e){
-        let _this=this;
-        _this.currentDataId=e.id
-        _this.dialogVisible=true;
-      },
+    searchData() {
+      let _this = this;
+      _this.dialogVisible = false;
+      _this.search();
+    },
 
-      onClose(){
-        let _this=this;
-        _this.currentDataId=0;
-        _this.dialogVisible=false;
-      },
+    //编辑
+    btnEdit(e) {
+      let _this = this;
+      _this.currentDataId = e.id;
+      _this.dialogVisible = true;
+    },
 
-      //搜索
-      search(){
-        let _this=this;
-        searchCustomer(_this.queryForm).then(res=>{
-          // if(!res)return;
-          _this.dataList=res.data.dataList;
-          _this.recordCount=res.data.totalRecord;
-          _this.pageTotal=res.data.totalPage;
-        })
-      },
-      //修改分页
-      ChangePage(e){
-      	let _this=this;
-      	_this.queryForm.page=e;
-      	_this.search();
-      },
-    }
-  }
+    onClose() {
+      let _this = this;
+      _this.currentDataId = 0;
+      _this.dialogVisible = false;
+    },
+
+    //搜索
+    search() {
+      let _this = this;
+      searchCustomer(_this.queryForm).then((res) => {
+        // if(!res)return;
+        _this.dataList = res.data.dataList;
+        _this.recordCount = res.data.totalRecord;
+        _this.pageTotal = res.data.totalPage;
+      });
+    },
+    //修改分页
+    ChangePage(e) {
+      let _this = this;
+      _this.queryForm.page = e;
+      _this.search();
+    },
+  },
+};
 </script>
 
 <style lang="scss">
-@import './dataList.scss';
+@import "./dataList.scss";
 </style>

+ 131 - 67
src/views/customer/components/dataSearch.vue

@@ -1,89 +1,153 @@
 <template>
   <div class="data-search">
     <el-form :inline="true" :model="queryForm" class="demo-form-inline">
-        <el-form-item label="客户名称:">
-          <el-input v-model="queryForm.name" placeholder="请选择客户名称"></el-input>
-        </el-form-item>
+      <el-form-item label="客户名称:">
+        <el-input
+          v-model="queryForm.name"
+          placeholder="请选择客户名称"
+        ></el-input>
+      </el-form-item>
 
-        <el-form-item label="状态:">
-          <el-select v-model="queryForm.status" class="m-2" placeholder="请选择状态" size="large">
-              <el-option
-                v-for="item in statusOptions"
-                :key="item.value"
-                :label="item.label"
-                :value="item.value"
-              />
-            </el-select>
+      <el-form-item label="状态:">
+        <el-select
+          v-model="queryForm.status"
+          class="m-2"
+          placeholder="请选择状态"
+          size="large"
+        >
+          <el-option
+            v-for="item in statusOptions"
+            :key="item.value"
+            :label="item.label"
+            :value="item.value"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" @click="onSubmit">
+          <svg-icon icon-class="search" /> 搜索</el-button
+        >
+        <el-button type="primary" @click="onAdd">
+          <svg-icon icon-class="add" />新增客户</el-button
+        >
+      </el-form-item>
+    </el-form>
+    <el-dialog title="新增客户" v-model="dialogVisible" width="50%">
+      <el-form :model="customerForm" label-width="120px">
+        <el-form-item label="客户编码" required>
+          <el-input v-model="customerForm.code" placeholder="请输入客户编码" />
+        </el-form-item>
+        <el-form-item label="客户名称" required>
+          <el-input v-model="customerForm.name" placeholder="请输入客户名称" />
+        </el-form-item>
+        <el-form-item label="英文名称" required>
+          <el-input
+            v-model="customerForm.en_name"
+            placeholder="请输入英文名称"
+          />
+        </el-form-item>
+        <el-form-item label="手机号码" required>
+          <el-input
+            v-model="customerForm.mobile"
+            placeholder="请输入手机号码"
+          />
         </el-form-item>
-        <el-form-item>
-          <el-button type="primary" @click="onSubmit">  <svg-icon icon-class="search"/> 搜索</el-button>
-          <el-button type="primary" @click="onSync">  <svg-icon icon-class="search"/> 同步客户数据</el-button>
+        <el-form-item label="联系人" required>
+          <el-input v-model="customerForm.contact" placeholder="请输入联系人" />
+        </el-form-item>
+        <el-form-item label="地址" required>
+          <el-input v-model="customerForm.address" placeholder="请输入地址" />
+        </el-form-item>
+        <el-form-item label="其他信息">
+          <el-input v-model="customerForm.other" placeholder="请输入其他信息" />
         </el-form-item>
       </el-form>
-
-
+      <template #footer>
+        <span class="dialog-footer">
+          <el-button @click="dialogVisible = false">取消</el-button>
+          <el-button type="primary" @click="handleCreate">确定</el-button>
+        </span>
+      </template>
+    </el-dialog>
   </div>
 </template>
 
 <script>
-import {syncCustomer} from "@/api/customer"
-export default{
-  props:{
-    queryForm:{
-        type:Object,
-        default:()=>{
-          return {
-             page:1,
-             pageSize:10,
-             name:'',
-             status:'',
-          }
-        }
+import { syncCustomer, create,update } from "@/api/customer";
+export default {
+  props: {
+    queryForm: {
+      type: Object,
+      default: () => {
+        return {
+          page: 1,
+          pageSize: 10,
+          name: "",
+          status: "",
+        };
+      },
     },
   },
-  data(){
-    return{
-        statusOptions:[
-          {
-            value:'',
-            label:"请选择状态"
-          },
-          {
-            value:5,
-            label:'启用'
-          },
-          {
-            value:6,
-            label:"停用"
-          },
-
-        ],
-        dialogVisible:false,
-    }
-  },
-  created() {
-
+  data() {
+    return {
+      statusOptions: [
+        {
+          value: "",
+          label: "请选择状态",
+        },
+        {
+          value: 5,
+          label: "启用",
+        },
+        {
+          value: 6,
+          label: "停用",
+        },
+      ],
+      dialogVisible: false,
+      customerForm: {
+        code: "",
+        name: "",
+        en_name: "",
+        mobile: "",
+        contact: "",
+        address: "",
+        other: "",
+      },
+    };
   },
-  methods:{
-
-    onSync(e){
-      let _this=this;
-      syncCustomer().then(res=>{
-        console.log('res',res);
-      })
+  created() {},
+  methods: {
+    handleCreate() {
+      createCustomer(this.customerForm)
+        .then((res) => {
+          this.$message.success("创建成功");
+          this.dialogVisible = false;
+          this.$emit("bindSetQuery", this.$props.queryForm); // 刷新列表
+        })
+        .catch((err) => {
+          this.$message.error("创建失败");
+        });
+    },
+    onAdd() {},
+    onSync(e) {
+      let _this = this;
+      syncCustomer().then((res) => {
+        console.log("res", res);
+      });
     },
 
-    onCreate(e){
-      this.dialogVisible=true;
+    onCreate(e) {
+      this.dialogVisible = true;
     },
     //搜索
-    onSubmit(){
-      this.$emit("bindSetQuery",this.$props.queryForm);
-    }
-  }
-}
+    onSubmit() {
+      this.$emit("bindSetQuery", this.$props.queryForm);
+    },
+  },
+};
 </script>
 
 <style lang="scss">
-@import "./dataSearch.scss"
+@import "./dataSearch.scss";
 </style>

+ 1 - 1
src/views/customer/search.vue

@@ -1,6 +1,6 @@
 <template>
   <div class="project-search">
-    <dataSearch @bindSetQuery="setQuery"></dataSearch>
+   <!--  <dataSearch @bindSetQuery="setQuery"></dataSearch> -->
     <dataList :queryForm="queryForm"></dataList>
   </div>
 

+ 15 - 11
src/views/product/components/dataInfo.scss

@@ -1,11 +1,15 @@
- .sub-imgs{
-    padding:0px;
-    margin:0px;
-      li{
-        float:left;
-        margin-right:10px;
-        width:100px;
-        height:100px;
-        list-style: none;
-      }
-  }
+.sub-imgs{
+  padding:0px;
+  margin:0px;
+    li{
+      float:left;
+      margin-right:10px;
+      width:100px;
+      height:100px;
+      list-style: none;
+    }
+}
+
+.w_input{
+  width: 60%;
+}

+ 305 - 279
src/views/product/components/dataInfo.vue

@@ -1,60 +1,78 @@
 <template>
   <div class="data-info">
-
-
-    <el-tabs v-model="activeName" class="demo-tabs">
-      <el-tab-pane label="基本信息" name="base">
-        <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-cascader v-model="category" style="width:100%;" @change="onChangeCategory" :options="allCategories" :show-all-levels="false" />
-          </el-form-item>
-          <el-form-item label="所属品牌:">
-            <el-select v-model="dataForm.brand_id"  placeholder="请选择品牌" size="large" style="width:100%;">
-                <el-option
-                  v-for="item in brandList"
-                  :key="item.id"
-                  :label="item.name"
-                  :value="item.id"
-                />
-              </el-select>
-          </el-form-item>
-          <el-form-item label="所属供应商:">
-            <el-select v-model="dataForm.supplier_id"  placeholder="请选择供应商" size="large"  style="width:100%;">
-                <el-option
-                  v-for="item in supplierList"
-                  :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" @change="onChangeStatus" style="width:100%;">
-                <el-option
-                  v-for="item in statusOptions"
-                  :key="item.value"
-                  :label="item.label"
-                  :value="item.value"
-                />
-              </el-select>
-          </el-form-item>
-          <el-form-item label="市场价格:">
-            <el-input v-model="dataForm.price"></el-input>
-          </el-form-item>
-          <el-form-item label="产地:">
-            <el-input v-model="dataForm.product_area"></el-input>
-          </el-form-item>
-        </el-form>
-
-
-
-      </el-tab-pane>
-      <el-tab-pane label="产品属性" name="attrs">
+    <!-- <el-tabs v-model="activeName" class="demo-tabs">
+      <el-tab-pane label="基本信息" name="base"> -->
+    <el-form :model="dataForm" label-width="120px">
+      <el-form-item label="产品名称:">
+        <el-input v-model="dataForm.name" class="w_input"></el-input>
+      </el-form-item>
+      <el-form-item label="所属分类:">
+        <el-cascader
+          v-model="category"
+          class="w_input"
+          @change="onChangeCategory"
+          :options="allCategories"
+          :props="props"
+          :show-all-levels="false"
+        />
+      </el-form-item>
+      <el-form-item label="所属品牌:">
+        <el-select
+          v-model="dataForm.brand_id"
+          placeholder="请选择品牌"
+          size="large"
+          class="w_input"
+        >
+          <el-option
+            v-for="item in brandList"
+            :key="item.id"
+            :label="item.name"
+            :value="item.id"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="所属供应商:">
+        <el-select
+          v-model="dataForm.supplier_id"
+          placeholder="请选择供应商"
+          size="large"
+          class="w_input"
+        >
+          <el-option
+            v-for="item in supplierList"
+            :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"
+          @change="onChangeStatus"
+          class="w_input"
+        >
+          <el-option
+            v-for="item in statusOptions"
+            :key="item.value"
+            :label="item.label"
+            :value="item.value"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="市场价格:">
+        <el-input v-model="dataForm.price" class="w_input"></el-input>
+      </el-form-item>
+      <el-form-item label="产地:">
+        <el-input v-model="dataForm.product_area" class="w_input"></el-input>
+      </el-form-item>
+    </el-form>
+
+    <!--  </el-tab-pane> -->
+    <!-- <el-tab-pane label="产品属性" name="attrs">
          <el-form :model="dataForm" label-width="120px">
             <el-form-item label="产品属性:">
                 <ProductAttrItem   :items="extAttrs"  @onSetAttr="onSetAttr"/>
@@ -143,10 +161,10 @@
 
         </el-form>
 
-      </el-tab-pane>
-    </el-tabs>
+      </el-tab-pane> -->
+    <!--  </el-tabs> -->
 
-  <!--
+    <!--
     <el-card>
       <el-form :model="dataForm" label-width="120px">
 
@@ -255,245 +273,253 @@
       </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 {searchAllCategories,createProduct,updateProduct,getProductInfo} from '@/api/product'
-  import {searchBrand} from '@/api/brand'
-  import {searchSupplier} from '@/api/supplier'
-  import {searchDocument} from '@/api/document'
-  import ProductAttrItem from "@/components/ProductAttrItem"
-
-  export default{
-    components:{
-      Tinymce,
-      ProductAttrItem
+import Tinymce from "@/components/Tinymce";
+import {
+  searchAllCategories,
+  createProduct,
+  updateProduct,
+  getProductInfo,
+} from "@/api/product";
+import { searchBrand } from "@/api/brand";
+import { searchSupplier } from "@/api/supplier";
+import { searchDocument } from "@/api/document";
+import ProductAttrItem from "@/components/ProductAttrItem";
+
+export default {
+  components: {
+    Tinymce,
+    ProductAttrItem,
+  },
+  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 || v <= 0) return;
+        _this.getInfo(v);
       },
+      immediate: true,
+      deep: true,
     },
-    watch:{
-      id:{
-        handler(v){
-            let _this=this;
-            if(v==null || v<=0)return;
-            _this.getInfo(v);
+  },
+  data() {
+    return {
+      activeName: "base",
+      currentCategory: [],
+      allCategories: [],
+      brandList: [],
+      supplierList: [],
+      category: [],
+      documentList: [],
+      dataForm: {
+        id: 0,
+        name: "",
+        price: "",
+        product_area: "",
+        category_id: "",
+        brand_id: "",
+        supplier_id: "",
+        is_package: "否",
+        package_intro: "无",
+        is_safe: "否",
+        safe_time: "无",
+        intro: "",
+        qualifications: "",
+        attrs: [],
+      },
+      extAttrs: [
+        {
+          name: "属性1",
+          type: 1,
+          value: "",
+          valueItems: "",
+        },
+      ],
+      packageList: [
+        {
+          value: "",
+          label: "请选择",
+        },
+        {
+          value: "是",
+          label: "是",
+        },
+        {
+          value: "否",
+          label: "否",
+        },
+      ],
+      safeTime: [
+        {
+          value: "",
+          label: "请选择",
+        },
+        {
+          value: "一年",
+          label: "一年",
         },
-        immediate: true,
-        deep: true
+        {
+          value: "两年",
+          label: "两年",
+        },
+      ],
+
+      statusOptions: [
+        {
+          value: "",
+          label: "请选择状态",
+        },
+        {
+          value: 5,
+          label: "使用中",
+        },
+        {
+          value: 6,
+          label: "已停用",
+        },
+      ],
+      cateAttr: [],
+      props: {
+        value: "id",
+        label: "label",
+        children: "children",
+        checkStrictly: true,
+      },
+    };
+  },
+
+  mounted() {
+    let _this = this;
+    this.initBrand();
+    this.initSupplier();
+    this.initCategories();
+/*     this.initDocumentList(); */
+  },
+  methods: {
+   /*  initDocumentList() {
+      let _this = this;
+      searchDocument({ page: 1, pageSize: 999, status: 5 }).then((res) => {
+        if (res.status != 200) return;
+        _this.documentList = res.data.dataList;
+      });
+    }, */
+
+    onSetAttr(e) {
+      this.dataForm.attrs = e;
+    },
+    //保存更新
+    btnSave(e) {
+      let _this = this;
+      if (_this.category.length >= 1) {
+        _this.dataForm.category_id = _this.category[0];
+      }
+      _this.dataForm.attrs = JSON.stringify(this.extAttrs);
+      _this.dataForm.links = JSON.stringify(this.dataForm.linkDocument);
+
+      if (_this.dataForm.id > 0) {
+        updateProduct(_this.dataForm).then((res) => {
+          if (res.status != 200) return;
+          _this.$message.success("产品信息更新成功");
+          _this.$emit("onClose", true); // 添加参数表示需要刷新
+        });
+      } else {
+        createProduct(_this.dataForm).then((res) => {
+          if (res.status != 200) return;
+          _this.$message.success("产品信息创建成功");
+          _this.$emit("onClose", true); // 添加参数表示需要刷新
+        });
       }
     },
-    data(){
-      return{
-        activeName:'base',
-        currentCategory:[],
-        allCategories:[],
-        brandList:[],
-        supplierList:[],
-        category:[],
-        documentList:[],
-        dataForm:{
-          id:0,
-          name:'',
-          price:'',
-          product_area:'',
-          category_id:'',
-          brand_id:'',
-          supplier_id:'',
-          is_package:'否',
-          package_intro:'无',
-          is_safe:'否',
-          safe_time:'无',
-          intro:'',
-          qualifications:'',
-          attrs:[],
-        },
-        extAttrs:[
-          {
-            name:'属性1',
-            type:1,
-            value:"",
-            valueItems:'',
-          }
-        ],
-        packageList:[
-          {
-            value:"",
-            label:"请选择"
-          },
-          {
-            value:"是",
-            label:"是"
-          },
-          {
-            value:"否",
-            label:"否"
-          }
-        ],
-        safeTime:[
-          {
-            value:"",
-            label:"请选择"
-          },
-          {
-            value:"一年",
-            label:"一年"
-          },
-          {
-            value:"两年",
-            label:"两年"
-          }
-        ],
-
-        statusOptions:[
-            {
-              value:'',
-              label:"请选择状态"
-            },
-            {
-              value:5,
-              label:'使用中'
-            },
+
+    //产品详情
+    getInfo(id) {
+      let _this = this;
+      let par = {
+        id: id,
+      };
+      getProductInfo(par).then((res) => {
+        if (!res) return;
+        if (res.status != 200) return;
+        _this.dataForm = res.data;
+        _this.extAttrs = JSON.parse(res.data.attrs);
+        if (_this.extAttrs.length <= 0) {
+          _this.extAttrs = [
             {
-              value:6,
-              label:"已停用"
+              name: "属性1",
+              type: 1,
+              value: "",
+              valueItems: "",
             },
-        ],
-        cateAttr:[]
-      }
+          ];
+        }
+        _this.category = [res.data.category.parent_id, res.data.category.id];
+      });
     },
 
-    mounted() {
-      let _this=this;
-      this.initBrand();
-      this.initSupplier();
-      this.initCategories();
-      this.initDocumentList();
+    onChangeStatus(e) {
+      this.dataForm.status = e;
     },
-    methods:{
-
-
-      initDocumentList(){
-        let _this=this;
-        searchDocument({page:1,pageSize:999,status:5}).then(res=>{
-            if(res.status!=200)return;
-            _this.documentList=res.data.dataList;
-        })
-      },
-
-      onSetAttr(e){
-        this.dataForm.attrs=e;
-      },
-      //保存更新
-      btnSave(e){
-        let _this=this;
-        if(_this.category.length>=1){
-          _this.dataForm.category_id=_this.category[1];
-        }
-        _this.dataForm.attrs=JSON.stringify(this.extAttrs);
-        _this.dataForm.links=JSON.stringify(this.dataForm.linkDocument);
-
-        if(_this.dataForm.id>0){
-          updateProduct(_this.dataForm).then(res=>{
-            if(res.status!=200)return;
-            _this.$alert("产品信息更新成功");
-            _this.$emit("onClose");
-          })
-        }else{
-          createProduct(_this.dataForm).then(res=>{
-            if(res.status!=200)return;
-            _this.$alert("产品信息创建成功");
-            _this.$emit("onClose");
-          })
-        }
-      },
-
-      //产品详情
-      getInfo(id){
-          let _this=this;
-          let par={
-            id:id,
-          };
-          getProductInfo(par).then(res=>{
-              if(!res)return;
-              if(res.status!=200)return;
-              _this.dataForm=res.data;
-              _this.extAttrs=JSON.parse(res.data.attrs);
-              if(_this.extAttrs.length<=0){
-                _this.extAttrs=[{
-                  name:'属性1',
-                  type:1,
-                  value:"",
-                  valueItems:'',
-                }];
-              }
-              _this.category=[res.data.category.parent_id,res.data.category.id]
-          })
-      },
-
-      onChangeStatus(e){
-          this.dataForm.status=e;
-      },
-      //修改分类信息
-      onChangeCategory(e){
-         let _this=this;
-          console.log(e);
-
-         let categories=_this.allCategories.filter(o=>o.id==e[0]);
-        let sub=categories[0].children.filter(o=>o.id==e[1]);
-        if(sub.length>0){
-          _this.cateAttr=JSON.parse(sub[0].attrs);
-          _this.extAttrs=[];
-          for(var i=0;i<_this.cateAttr.length;i++){
-            _this.extAttrs.push({
-              name:_this.cateAttr[i].name,
-              type:1,
-              value:"",
-              valueItems:'',
-            })
-          }
-
-          console.log(_this.extAttrs);
+    //修改分类信息
+    onChangeCategory(e) {
+      let _this = this;
+      console.log(e);
+
+      let categories = _this.allCategories.filter((o) => o.id == e[0]);
+      let sub = categories[0].children.filter((o) => o.id == e[1]);
+      if (sub.length > 0) {
+        _this.cateAttr = JSON.parse(sub[0].attrs);
+        _this.extAttrs = [];
+        for (var i = 0; i < _this.cateAttr.length; i++) {
+          _this.extAttrs.push({
+            name: _this.cateAttr[i].name,
+            type: 1,
+            value: "",
+            valueItems: "",
+          });
         }
-      },
-      //初始化所有分类
-      initCategories(){
-        let _this=this;
-        searchAllCategories().then(res=>{
-          if(res.status!=200)return;
-          _this.allCategories=res.data;
-
-        })
-      },
-      initSupplier(){
-        let _this=this;
-        searchSupplier({page:1,pageSize:999,status:5}).then(res=>{
-          if(res.status!=200)return;
-          _this.supplierList=[{"id":0,"name":"请选择"},...res.data.dataList]
-        })
-      },
-      initBrand(){
-        let _this=this;
-        searchBrand({page:1,pageSize:999,status:5}).then(res=>{
-          if(res.status!=200)return;
-          _this.brandList=[{id:0,name:"请选择"},...res.data.dataList];
-        })
-      },
 
-    }
-  }
+        console.log(_this.extAttrs);
+      }
+    },
+    //初始化所有分类
+    initCategories() {
+      let _this = this;
+      searchAllCategories().then((res) => {
+        if (res.status != 200) return;
+        _this.allCategories = res.data;
+      });
+    },
+    initSupplier() {
+      let _this = this;
+      searchSupplier({ page: 1, pageSize: 999, status: 5 }).then((res) => {
+        if (res.status != 200) return;
+        _this.supplierList = [{ id: 0, name: "请选择" }, ...res.data.dataList];
+      });
+    },
+    initBrand() {
+      let _this = this;
+      searchBrand({ page: 1, pageSize: 999, status: 5 }).then((res) => {
+        if (res.status != 200) return;
+        _this.brandList = [{ id: 0, name: "请选择" }, ...res.data.dataList];
+      });
+    },
+  },
+};
 </script>
 
 <style lang="scss">
- @import './dataInfo.scss'
+@import "./dataInfo.scss";
 </style>

+ 200 - 151
src/views/product/components/dataList.vue

@@ -1,172 +1,221 @@
 <template>
   <div class="data-list">
-
-
-      <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="name" label="产品名称" align="left" min-width="180"/>
-        <el-table-column prop="brand.name" label="品牌" align="center" min-width="180"/>
-        <el-table-column prop="supplier.name" label="供应商" align="center" min-width="180"/>
-        <el-table-column prop="price" label="价格" align="center" min-width="180"/>
-        <el-table-column prop="product_area" label="产地" align="center" min-width="180"/>
-        <el-table-column prop="category.name" label="分类" align="center" min-width="180"/>
-        <el-table-column prop="createTime" label="创建时间" align="center" width="180"/>
-        <el-table-column prop="status" label="分类状态" align="center" width="180">
-          <template #default="scope">
-              <div v-if="scope.row.status==5">已使用</div>
-              <div v-if="scope.row.status==6">已停用</div>
-          </template>
-        </el-table-column>
-        <el-table-column label="操作" fixed="right" align="center" width="150">
-          <template #default="scope">
-            <div class="btns">
-              <el-button type="primary" size="small" @click="btnEdit(scope.row)"><svg-icon icon-class="edit"/>编辑</el-button>
-              <el-button type="danger" size="small" @click="btnDelete(scope.row.id)"><svg-icon icon-class="delete"/>删除</el-button>
-            </div>
-          </template>
-        </el-table-column>
-      </el-table>
-
-
-
-      <div class="page-info">
-      	<el-pagination
-      	v-model:currentPage="queryForm.page"
-      	:page-size="queryForm.pageSize"
-      	:total="recordCount"
-      	:page-count="pageTotal"
-      	 background
-      	 layout="prev, pager, next"
-      	 @current-change="ChangePage"
-      	 >
-      	 </el-pagination>
-      </div>
-
-     <el-dialog  :visible.sync="dialogVisible" append-to-body v-el-drag-dialog  width="80%" custom-class="prod-verify" title="创建产品信息">
-
-          <dataInfo :id="currentDataId" @onClose="onClose"></dataInfo>
-      </el-dialog>
-
+    <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="name"
+        label="产品名称"
+        align="left"
+        min-width="180"
+      />
+      <el-table-column
+        prop="brand.name"
+        label="品牌"
+        align="center"
+        min-width="180"
+      />
+      <el-table-column
+        prop="supplier.name"
+        label="供应商"
+        align="center"
+        min-width="180"
+      />
+      <el-table-column
+        prop="price"
+        label="价格"
+        align="center"
+        min-width="180"
+      />
+      <el-table-column
+        prop="product_area"
+        label="产地"
+        align="center"
+        min-width="180"
+      />
+      <el-table-column
+        prop="category.name"
+        label="分类"
+        align="center"
+        min-width="180"
+      />
+      <el-table-column
+        prop="createTime"
+        label="创建时间"
+        align="center"
+        width="180"
+      />
+      <el-table-column
+        prop="status"
+        label="分类状态"
+        align="center"
+        width="180"
+      >
+        <template #default="scope">
+          <div v-if="scope.row.status == 5">已使用</div>
+          <div v-if="scope.row.status == 6">已停用</div>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" fixed="right" align="center" width="150">
+        <template #default="scope">
+          <div class="btns">
+            <el-button type="primary" size="small" @click="btnEdit(scope.row)"
+              ><svg-icon icon-class="edit" />编辑</el-button
+            >
+            <el-button
+              type="danger"
+              size="small"
+              @click="btnDelete(scope.row.id)"
+              ><svg-icon icon-class="delete" />删除</el-button
+            >
+          </div>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <div class="page-info">
+      <el-pagination
+        :currentPage="queryForm.page"
+        :page-size="queryForm.pageSize"
+        :total="recordCount"
+        :page-count="pageTotal"
+        background
+        layout="prev, pager, next"
+        @current-change="ChangePage"
+      >
+      </el-pagination>
+    </div>
+
+    <el-dialog
+      :visible.sync="dialogVisible"
+      append-to-body
+      v-el-drag-dialog
+      width="50%"
+      custom-class="prod-verify"
+      title="创建产品信息"
+    >
+      <dataInfo :id="currentDataId" @onClose="onClose"></dataInfo>
+    </el-dialog>
   </div>
-
-
 </template>
 
 <script>
-  import{searchProduct,deleteProduct} from'@/api/product';
-  import dataInfo from './dataInfo.vue';
-  import elDragDialog from '@/directive/el-drag-dialog'
-  export default{
-    components:{
-      dataInfo,
-    },
-    directives: { elDragDialog },
-    props:{
-      queryForm:{
-        type:Object,
-        default:()=>{
-          return {
-            page:1,
-            pageSize:10,
-            name:'',
-            category_id:'',
-            brand_id:'',
-            supplier_id:'',
-            is_package:'',
-            status:''
-          }
-        }
-      }
-    },
-    watch:{
-
-        'queryForm': {
-          handler: function(val) {
-
-            this.search();
-          },
-          immediate: true,//立即执行
-          deep: true
-
-        },
+import { searchProduct, deleteProduct } from "@/api/product";
+import dataInfo from "./dataInfo.vue";
+import elDragDialog from "@/directive/el-drag-dialog";
+export default {
+  components: {
+    dataInfo,
+  },
+  directives: { elDragDialog },
+  props: {
+    queryForm: {
+      type: Object,
+      default: () => {
+        return {
+          page: 1,
+          pageSize: 10,
+          name: "",
+          category_id: "",
+          brand_id: "",
+          supplier_id: "",
+          is_package: "",
+          status: "",
+        };
+      },
     },
-    data(){
-      return{
-        dialogVisible:false,//控制产品审核
-        currentDataId:0,
-        recordCount:0,
-        pageTotal:1,
-        dataList:[],
-        currentData:{},
-      }
+  },
+  watch: {
+    queryForm: {
+      handler: function (val) {
+        this.search();
+      },
+      immediate: true, //立即执行
+      deep: true,
     },
-    mounted() {
-      this.search();
+  },
+  data() {
+    return {
+      dialogVisible: false, //控制产品审核
+      currentDataId: 0,
+      recordCount: 0,
+      pageTotal: 1,
+      dataList: [],
+      currentData: {},
+    };
+  },
+  mounted() {
+    this.search();
+  },
+  methods: {
+    searchData() {
+      let _this = this;
+      _this.dialogVisible = false;
+      _this.search();
     },
-    methods:{
 
-
-      searchData(){
-        let _this=this;
-        _this.dialogVisible=false;
-        _this.search();
-      },
-
-
-      btnDelete(e){
-        let _this=this;
-        let par={
-          id:e,
-        }
-        _this.$confirm("您是否确认删除该记录?","提示",{
-          confirmButtonText: '确认',
-          cancelButtonText: '取消',
-          type: 'warning',
-        }).then((res)=>{
+    btnDelete(e) {
+      let _this = this;
+      let par = {
+        id: e,
+      };
+      _this
+        .$confirm("您是否确认删除该记录?", "提示", {
+          confirmButtonText: "确认",
+          cancelButtonText: "取消",
+          type: "warning",
+        })
+        .then((res) => {
           // console.log("AAA")
-             deleteProduct(par).then(res=>{
-               _this.search();
-             })
-        }).catch(()=>{
+          deleteProduct(par).then((res) => {
+            _this.search();
+          });
         })
-      },
-
+        .catch(() => {});
+    },
 
-      //编辑
-      btnEdit(e){
-        let _this=this;
-        _this.currentDataId=e.id;
-        _this.dialogVisible=true;
-      },
+    //编辑
+    btnEdit(e) {
+      let _this = this;
+      _this.currentDataId = e.id;
+      _this.dialogVisible = true;
+    },
 
-      onClose(){
-        let _this=this;
-        _this.currentDataId=0;
-        _this.dialogVisible=false;
+    onClose(needRefresh) {
+      let _this = this;
+      _this.currentDataId = 0;
+      _this.dialogVisible = false;
+      if (needRefresh) {
+        // 根据参数决定是否刷新
         _this.search();
-      },
+      }
+    },
 
-      //搜索
-      search(){
-        let _this=this;
+    //搜索
+    search() {
+      let _this = this;
 
-        searchProduct(_this.queryForm).then(res=>{
-          if(!res)return;
-          _this.dataList=res.data.dataList;
-          _this.recordCount=res.data.totalRecord;
-          _this.pageTotal=res.data.totalPage;
-        })
-      },
-      //修改分页
-      ChangePage(e){
-      	let _this=this;
-      	_this.queryForm.page=e;
-      	_this.search();
-      },
-    }
-  }
+      searchProduct(_this.queryForm).then((res) => {
+        if (!res) return;
+        _this.dataList = res.data.dataList;
+        _this.recordCount = res.data.totalRecord;
+        _this.pageTotal = res.data.totalPage;
+      });
+    },
+    //修改分页
+    ChangePage(e) {
+      let _this = this;
+      _this.queryForm.page = e;
+      _this.search();
+    },
+  },
+};
 </script>
 
 <style lang="scss">
-@import './dataList.scss';
+@import "./dataList.scss";
 </style>

+ 180 - 144
src/views/product/components/dataSearch.vue

@@ -1,175 +1,211 @@
 <template>
   <div class="data-search">
     <el-form :inline="true" :model="queryForm" class="demo-form-inline">
-        <el-form-item label="产品名称:">
-          <el-input v-model="queryForm.name" placeholder="请选择产品名称"></el-input>
-        </el-form-item>
-        <el-form-item label="产品分类:">
-          <el-cascader v-model="queryForm.category_id" :options="allCategories" :show-all-levels="false" />
-
-        </el-form-item>
-        <el-form-item label="品牌:">
-          <el-select v-model="queryForm.brand_id" class="m-2" placeholder="请选择" size="large">
-              <el-option
-                v-for="item in brandList"
-                :key="item.id"
-                :label="item.name"
-                :value="item.id"
-              />
-            </el-select>
-        </el-form-item>
-        <el-form-item label="供应商:">
-          <el-select v-model="queryForm.supplier_id" class="m-2" placeholder="请选择" size="large">
-              <el-option
-                v-for="item in supplierList"
-                :key="item.id"
-                :label="item.name"
-                :value="item.id"
-              />
-            </el-select>
-        </el-form-item>
-        <el-form-item label="套餐商品:">
-          <el-select v-model="queryForm.is_package" class="m-2" placeholder="请选择" size="large">
-              <el-option
-                v-for="item in packageList"
-                :key="item.value"
-                :label="item.label"
-                :value="item.value"
-              />
-            </el-select>
-        </el-form-item>
-        <el-form-item label="状态:">
-          <el-select v-model="queryForm.status" class="m-2" placeholder="请选择状态" size="large">
-              <el-option
-                v-for="item in statusOptions"
-                :key="item.value"
-                :label="item.label"
-                :value="item.value"
-              />
-            </el-select>
-        </el-form-item>
-        <el-form-item>
-          <el-button type="primary" @click="onSubmit">  <svg-icon icon-class="search"/> 搜索</el-button>
-          <el-button type="success" @click="onCreate" >  <svg-icon icon-class="edit"/> 创建产品</el-button>
-        </el-form-item>
-      </el-form>
-
-    <el-dialog  :visible.sync="dialogVisible" append-to-body v-el-drag-dialog  width="80%" custom-class="prod-verify" title="创建产品">
-         <dataInfo @onClose='onClose'></dataInfo>
-     </el-dialog>
+      <el-form-item label="产品名称:">
+        <el-input
+          v-model="queryForm.name"
+          placeholder="请选择产品名称"
+        ></el-input>
+      </el-form-item>
+      <el-form-item label="产品分类:">
+        <el-cascader
+          v-model="queryForm.category_id"
+          :options="allCategories"
+          :show-all-levels="false"
+        />
+      </el-form-item>
+      <el-form-item label="品牌:">
+        <el-select
+          v-model="queryForm.brand_id"
+          class="m-2"
+          placeholder="请选择"
+          size="large"
+        >
+          <el-option
+            v-for="item in brandList"
+            :key="item.id"
+            :label="item.name"
+            :value="item.id"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="供应商:">
+        <el-select
+          v-model="queryForm.supplier_id"
+          class="m-2"
+          placeholder="请选择"
+          size="large"
+        >
+          <el-option
+            v-for="item in supplierList"
+            :key="item.id"
+            :label="item.name"
+            :value="item.id"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="套餐商品:">
+        <el-select
+          v-model="queryForm.is_package"
+          class="m-2"
+          placeholder="请选择"
+          size="large"
+        >
+          <el-option
+            v-for="item in packageList"
+            :key="item.value"
+            :label="item.label"
+            :value="item.value"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="状态:">
+        <el-select
+          v-model="queryForm.status"
+          class="m-2"
+          placeholder="请选择状态"
+          size="large"
+        >
+          <el-option
+            v-for="item in statusOptions"
+            :key="item.value"
+            :label="item.label"
+            :value="item.value"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" @click="onSubmit">
+          <svg-icon icon-class="search" /> 搜索</el-button
+        >
+        <el-button type="success" @click="onCreate">
+          <svg-icon icon-class="edit" /> 创建产品</el-button
+        >
+      </el-form-item>
+    </el-form>
 
+    <el-dialog
+      :visible.sync="dialogVisible"
+      append-to-body
+      v-el-drag-dialog
+      width="60%"
+      custom-class="prod-verify"
+      title="创建产品"
+    >
+      <dataInfo @onClose="onClose"></dataInfo>
+    </el-dialog>
   </div>
 </template>
 
 <script>
-import dataInfo from './dataInfo.vue';
-import {searchAllCategories} from '@/api/product'
-import {searchBrand} from '@/api/brand'
-import {searchSupplier} from '@/api/supplier'
+import dataInfo from "./dataInfo.vue";
+import { searchAllCategories } from "@/api/product";
+import { searchBrand } from "@/api/brand";
+import { searchSupplier } from "@/api/supplier";
 
-import elDragDialog from '@/directive/el-drag-dialog'
-export default{
-  components:{
+import elDragDialog from "@/directive/el-drag-dialog";
+export default {
+  components: {
     dataInfo,
   },
   directives: { elDragDialog },
-  props:{
-    queryForm:{
-        type:Object,
-        default:()=>{
-          return {
-             page:1,
-             pageSize:10,
-             name:'',
-             category_id:'',
-             brand_id:'',
-             supplier_id:'',
-             is_package:'',
-             status:''
-          }
-        }
+  props: {
+    queryForm: {
+      type: Object,
+      default: () => {
+        return {
+          page: 1,
+          pageSize: 10,
+          name: "",
+          category_id: "",
+          brand_id: "",
+          supplier_id: "",
+          is_package: "",
+          status: "",
+        };
+      },
     },
   },
-  data(){
-    return{
-        statusOptions:[
-          {
-            value:'',
-            label:"请选择状态"
-          },
-          {
-            value:5,
-            label:'使用中'
-          },
-          {
-            value:6,
-            label:"已停用"
-          },
-        ],
-        packageList:[
-          {
-            value:"",
-            label:"请选择"
-          },
-          {
-            value:"是",
-            label:"是"
-          },
-          {
-            value:"否",
-            label:"否"
-          }
-        ],
-        supplierList:[],
-        brandList:[],
-        allCategories:[],
-        dialogVisible:false,
-    }
+  data() {
+    return {
+      statusOptions: [
+        {
+          value: "",
+          label: "请选择状态",
+        },
+        {
+          value: 5,
+          label: "使用中",
+        },
+        {
+          value: 6,
+          label: "已停用",
+        },
+      ],
+      packageList: [
+        {
+          value: "",
+          label: "请选择",
+        },
+        {
+          value: "是",
+          label: "是",
+        },
+        {
+          value: "否",
+          label: "否",
+        },
+      ],
+      supplierList: [],
+      brandList: [],
+      allCategories: [],
+      dialogVisible: false,
+    };
   },
   created() {
     this.initBrand();
     this.initSupplier();
     this.initCategories();
   },
-  methods:{
-
-    onCreate(e){
-      this.dialogVisible=true;
+  methods: {
+    onCreate(e) {
+      this.dialogVisible = true;
     },
-    onClose(e){
-      this.dialogVisible=false;
+    onClose(e) {
+      this.dialogVisible = false;
+      this.$emit("bindSetQuery", this.$props.queryForm);
     },
 
-    initCategories(){
-      let _this=this;
-      searchAllCategories().then(res=>{
-        if(res.status!=200)return;
-        console.log("searchAllCategories",res);
-        _this.allCategories=res.data;
-      })
+    initCategories() {
+      let _this = this;
+      searchAllCategories().then((res) => {
+        if (res.status != 200) return;
+        console.log("searchAllCategories", res);
+        _this.allCategories = res.data;
+      });
     },
-    initSupplier(){
-      let _this=this;
-      searchSupplier({page:1,pageSize:999,status:5}).then(res=>{
-        if(res.status!=200)return;
-        _this.supplierList=[{"id":0,"name":"请选择"},...res.data.dataList]
-      })
+    initSupplier() {
+      let _this = this;
+      searchSupplier({ page: 1, pageSize: 999, status: 5 }).then((res) => {
+        if (res.status != 200) return;
+        _this.supplierList = [{ id: 0, name: "请选择" }, ...res.data.dataList];
+      });
     },
-    initBrand(){
-      let _this=this;
-      searchBrand({page:1,pageSize:999,status:5}).then(res=>{
-        if(res.status!=200)return;
-        _this.brandList=[{id:0,name:"请选择"},...res.data.dataList];
-      })
+    initBrand() {
+      let _this = this;
+      searchBrand({ page: 1, pageSize: 999, status: 5 }).then((res) => {
+        if (res.status != 200) return;
+        _this.brandList = [{ id: 0, name: "请选择" }, ...res.data.dataList];
+      });
     },
     //搜索
-    onSubmit(){
-      this.$emit("bindSetQuery",this.$props.queryForm);
-    }
-  }
-}
+    onSubmit() {
+      this.$emit("bindSetQuery", this.$props.queryForm);
+    },
+  },
+};
 </script>
 
 <style lang="scss">
-@import "./dataSearch.scss"
+@import "./dataSearch.scss";
 </style>

+ 104 - 8
src/views/project/ProjectInput.vue

@@ -90,10 +90,7 @@
         </el-form>
       </div>
       <div>
-        <el-button
-            type="primary"
-            >导出输入项目</el-button
-          >
+        <el-button type="primary" @click="handleExport">导出输入项目</el-button>
       </div>
       <el-table
         :data="gsprTableData"
@@ -101,7 +98,12 @@
         :default-sort="{ prop: sort_field, order: sort_order }"
         @sort-change="handleSortChange"
       >
-        <el-table-column prop="sort" label="排序" sortable="custom" width="80" />
+        <el-table-column
+          prop="sequence"
+          label="排序"
+          sortable="custom"
+          width="80"
+        />
         <el-table-column prop="name" label="项目名称" sortable="custom" />
         <el-table-column prop="tech_report_location" label="技术报告位置" />
         <el-table-column prop="department" label="部门" sortable="custom" />
@@ -117,7 +119,17 @@
             </div>
           </template>
         </el-table-column>
-        <el-table-column prop="" label="难度" sortable="custom" />
+        <el-table-column prop="" label="难度" sortable="custom">
+          <template slot-scope="scope">
+            <el-rate
+              v-model="scope.row.score"
+              show-score
+              text-color="#ff9900"
+              score-template="{value}"
+              @change="(value) => rateScope(value, scope.row)"
+            />
+          </template>
+        </el-table-column>
         <el-table-column label="操作" width="200">
           <template slot-scope="scope">
             <el-button type="primary" @click="handleEditGspr(scope.row)"
@@ -274,10 +286,12 @@ import {
   create_items,
   delete_items,
   update_items,
+  rateScope,
 } from "@/api/knowledge";
-import { searchProject } from "@/api/project";
+import { searchProject, exportItems } from "@/api/project";
 import { mapState } from "vuex";
 import CKEditor from "ckeditor4-vue";
+import axios from "axios";
 export default {
   compnents: {
     ckeditor: CKEditor.component,
@@ -396,6 +410,85 @@ export default {
   },
 
   methods: {
+    /* 项目导出 */
+    async handleExport() {
+      const loading = this.$loading({
+        lock: true,
+        text: "导出中...",
+      });
+
+      try {
+        const response = await axios({
+          url: `${process.env.VUE_APP_BASE_API}/project-input/export`,
+          method: "post",
+          data: {project_id: this.selectedProjectId},
+          headers: {
+            "Content-Type": "application/json",
+            Authorization: "Bearer " + localStorage.getItem("token"), // 根据实际token获取方式调整
+          },
+        });
+        console.log(response);
+        // 检查响应数据
+        if (
+          !response.data ||
+          !response.data.data ||
+          !response.data.data.data.file_content
+        ) {
+          throw new Error("导出失败:返回数据格式错误");
+        }
+
+        // 获取文件内容和文件名
+        const { file_content, file_name } = response.data.data.data;
+
+        // 将base64转换为blob
+        const byteCharacters = atob(file_content);
+        const byteNumbers = new Array(byteCharacters.length);
+        for (let i = 0; i < byteCharacters.length; i++) {
+          byteNumbers[i] = byteCharacters.charCodeAt(i);
+        }
+        const byteArray = new Uint8Array(byteNumbers);
+        const blob = new Blob([byteArray], {
+          type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
+        });
+
+        // 下载文件
+        const link = document.createElement("a");
+        link.href = window.URL.createObjectURL(blob);
+        link.download = file_name;
+        document.body.appendChild(link);
+        link.click();
+        document.body.removeChild(link);
+        window.URL.revokeObjectURL(link.href);
+
+        this.$message.success(response.data.message || "导出成功");
+      } catch (error) {
+        console.error("导出错误:", error);
+        let errorMessage = "导出失败,请稍后重试";
+
+        if (error.response) {
+          switch (error.response.status) {
+            case 401:
+              errorMessage = "导出失败:未授权,请重新登录";
+              break;
+            case 403:
+              errorMessage = "导出失败:没有导出权限";
+              break;
+            case 404:
+              errorMessage = "导出失败:导出接口不存在";
+              break;
+            case 500:
+              errorMessage = "导出失败:服务器内部错误";
+              break;
+            default:
+              errorMessage = `导出失败:${error.response.status}`;
+          }
+        }
+
+        this.$message.error(errorMessage);
+      } finally {
+        loading.close();
+      }
+    },
     /* 删除 */
     async handleDeleteGspr(row) {
       try {
@@ -900,7 +993,10 @@ export default {
         delete params.dateRange;
         const response = await projectList(params);
         if (response.status === 200) {
-          this.gsprTableData = response.data.list;
+          this.gsprTableData = response.data.list.map((item) => ({
+            ...item,
+            score: item.score || 0,
+          }));
           this.gsprTotal = response.data.total;
           this.hasExistingData = this.gsprTotal > 0;
         }

+ 174 - 45
src/views/project/components/dataInfo.vue

@@ -7,18 +7,53 @@
         ref="dataFormRef"
         label-width="120px"
       >
+        <el-form-item
+          label="客户名称:"
+          prop="customerId"
+          class="form-item-half"
+        >
+          <el-select
+            v-model="dataForm.customerId"
+            placeholder="请选择客户"
+            size="large"
+          >
+            <el-option
+              v-for="item in customerList"
+              :key="item.id"
+              :label="item.name"
+              :value="item.id"
+            />
+          </el-select>
+        </el-form-item>
         <el-form-item label="项目名称:" prop="name" class="form-item-half">
-          <el-input v-model="dataForm.name" placeholder="请输入项目名称"></el-input>
+          <el-input
+            v-model="dataForm.name"
+            placeholder="请输入项目名称"
+          ></el-input>
         </el-form-item>
 
+        <el-form-item label="产品:" prop="product" class="form-item-half">
+          <el-select
+            v-model="dataForm.product"
+            placeholder="请选择产品"
+            size="large"
+          >
+            <el-option
+              v-for="item in productList"
+              :key="item.id"
+              :label="item.name"
+              :value="item.id"
+            />
+          </el-select>
+        </el-form-item>
         <el-form-item
-          label="所属分类:"
-          prop="category_id"
+          label="项目分类:"
+          prop="ProjectCategory"
           class="form-item-half"
         >
           <el-select
-            v-model="dataForm.category_id"
-            placeholder="请选择所属分类"
+            v-model="dataForm.ProjectCategory"
+            placeholder="请选择项目分类"
             size="large"
           >
             <el-option
@@ -29,30 +64,76 @@
             />
           </el-select>
         </el-form-item>
+        <!-- <el-form-item
+          label="产品名称:"
+          prop="productName"
+          class="form-item-half"
+        >
+          <el-input
+            v-model="dataForm.productName"
+            placeholder="请输入产品名称"
+          ></el-input>
+        </el-form-item> -->
+        <el-form-item
+          label="服务内容:"
+          prop="service_content"
+          class="form-item-half"
+        >
+          <el-input
+            v-model="dataForm.service_content"
+            placeholder="请输入服务内容"
+          ></el-input>
+        </el-form-item>
 
-        <el-form-item label="项目状态:" prop="status" class="form-item-half">
+        <el-form-item
+          label="当前阶段:"
+          prop="current_phase"
+          class="form-item-half"
+        >
           <el-select
-            v-model="dataForm.status"
-            placeholder="请选择状态"
+            v-model="dataForm.current_phase"
+            placeholder="请选择当前阶段"
             size="large"
           >
             <el-option
-              v-for="item in statusOptions"
-              :key="item.status"
-              :label="item.name"
-              :value="item.status"
+              v-for="item in currentPhaseList"
+              :key="item.key"
+              :label="item.label"
+              :value="item.value"
             />
           </el-select>
         </el-form-item>
 
-        <!-- 项目介绍保持全宽 -->
-        <el-form-item label="项目介绍:" prop="intro" class="form-item-half">
-          <el-input
-            rows="3"
-            placeholder="请输入项目介绍"
-            type="textarea"
-            v-model="dataForm.intro"
-          ></el-input>
+        <el-form-item
+          label="目前状态:"
+          prop="project_status"
+          class="form-item-half"
+        >
+          <el-select
+            v-model="dataForm.project_status"
+            placeholder="请选择目前状态"
+            size="large"
+          >
+            <el-option
+              v-for="item in getstatusList"
+              :key="item.key"
+              :label="item.label"
+              :value="item.value"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item
+          label="项目日期:"
+          prop="start_date"
+          class="form-item-half"
+        >
+          <el-date-picker
+            v-model="dataForm.start_date"
+            type="date"
+            placeholder="请选择日期"
+            format="yyyy-MM-dd"
+            value-format="yyyy-MM-dd"
+          />
         </el-form-item>
       </el-form>
     </el-card>
@@ -70,7 +151,10 @@ import {
   createProject,
   updateProject,
   getProjectInfo,
+  getphases,
+  getstatus,
 } from "@/api/project";
+import { searchProduct } from "@/api/product";
 import { searchCustomer } from "@/api/customer";
 import { searchDocument } from "@/api/document";
 export default {
@@ -94,10 +178,14 @@ export default {
             id: 0,
             name: "",
             intro: "",
-            customer_id: "",
-            category_id: "",
+            customerId: "",
+            ProjectCategory: "",
             status: 5,
-            /*  linkDoc:[], */
+            product: "",
+            service_content: "",
+            current_phase: "P1", // 设置当前阶段默认值为 P1
+            project_status: 1, // 设置目前状态默认值为 1
+            start_date: new Date().toISOString().slice(0, 10), // 设置默认日期为今天
           };
           return;
         }
@@ -115,14 +203,22 @@ export default {
       imageUrl: "",
       customerList: [],
       articleList: [],
+      currentPhaseList: [], //阶段表
+      getstatusList: [], //状态表
+      productList: [], //产品列表
       dataForm: {
         id: 0,
         name: "",
         intro: "",
-        customer_id: "",
-        category_id: "",
+        customerId: "",
+        ProjectCategory: "", //测试
         status: 5,
-        /*  linkDoc:[], */
+        product: "", // 新增产品类别
+        //productName: "", // 新增产品名称
+        service_content: "", // 新增服务内容
+        current_phase: "P1", // 设置当前阶段默认值为 P1
+        project_status: "1", // 设置目前状态默认值为 1
+        start_date: new Date().toISOString().slice(0, 10), // 新增项目日期
       },
       statusOptions: [
         {
@@ -134,7 +230,7 @@ export default {
           name: "停用",
         },
       ],
-      // 添加校验规则
+      // 更新校验规则
       rules: {
         name: [
           { required: true, message: "请输入项目名称", trigger: "blur" },
@@ -145,21 +241,37 @@ export default {
             trigger: "blur",
           },
         ],
-        /* intro: [
-          { required: true, message: "请输入项目介绍", trigger: "blur" },
+        customerId: [
+          { required: true, message: "请选择客户", trigger: "change" },
+        ],
+        product: [{ required: true, message: "请选择产品", trigger: "change" }],
+        /*  productName: [
+          { required: true, message: "请输入产品名称", trigger: "blur" },
           {
             min: 1,
-            max: 500,
-            message: "长度在 1 到 500 个字符之间",
+            max: 50,
+            message: "长度在 1 到 50 个字符之间",
             trigger: "blur",
           },
         ], */
-        category_id: [
-          { required: true, message: "请选择所属分类", trigger: "change" },
+        service_content: [
+          { required: true, message: "请输入服务内容", trigger: "blur" },
+          {
+            min: 1,
+            max: 200,
+            message: "长度在 1 到 200 个字符之间",
+            trigger: "blur",
+          },
         ],
-        status: [
+        current_phase: [
+          { required: true, message: "请选择当前阶段", trigger: "change" },
+        ],
+        project_status: [
           { required: true, message: "请选择项目状态", trigger: "change" },
         ],
+        start_date: [
+          { required: true, message: "请选择项目日期", trigger: "change" },
+        ],
       },
     };
   },
@@ -218,17 +330,23 @@ export default {
 
     //产品详情
     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;
-      });
+      const par = { id };
+      getProjectInfo(par)
+        .then((res) => {
+          if (!res || res.status !== 200) return;
+
+          const { data } = res;
+          this.dataForm = {
+            ...data,
+            ProjectCategory: data?.ProjectCategory?.id ?? "",
+            customerId: data?.customerId ?? "",
+            product: data?.productId ?? "",
+          };
+        })
+        .catch((error) => {
+          console.error("获取项目信息失败:", error);
+          this.$message.error("获取项目信息失败");
+        });
     },
 
     onChangeStatus(e) {
@@ -260,6 +378,17 @@ export default {
       searchCustomer(par).then((res) => {
         _this.customerList = res.data.dataList;
       });
+      getphases().then((res) => {
+        _this.currentPhaseList = res.data.options;
+      });
+      getstatus().then((res) => {
+        _this.getstatusList = res.data.options;
+      });
+      /* 获取产品列表 */
+      searchProduct({ page: 1, pageSize: 999 }).then((res) => {
+        _this.productList = res.data.dataList;
+        console.log(res.data.dataList);
+      });
     },
   },
 };

+ 182 - 17
src/views/project/components/dataList.vue

@@ -6,17 +6,52 @@
       header-row-class-name="headerBg"
       empty-text="没有项目信息"
     >
-      <el-table-column prop="id" label="ID" align="center" width="80" />
-      <el-table-column prop="categoryId" label="所属分类" align="left">
+      <el-table-column prop="id" label="项目编号" align="center" width="80" />
+      <el-table-column prop="customer_id" label="客户名称" align="left" >
         <template #default="scope">
-          <span>{{ getCategoryName(scope.row.categoryId) }}</span>
+          <span>{{ getCusomName(scope.row.customer_id) }}</span>
         </template>
       </el-table-column>
-      <!--  -->
       <el-table-column prop="name" label="项目名称" align="left" />
-      <el-table-column prop="createTime" label="创建时间" align="center" />
-      <el-table-column prop="updateTime" label="更新时间" align="center" />
-      <el-table-column prop="" label="完成度" align="center" />
+
+      <el-table-column prop="categoryId" label="产品类别" align="left">
+        <template #default="scope">
+          <span>{{ getCategoryTypeName(scope.row.product_id) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column prop="productName" label="产品名称" align="left">
+        <template #default="scope">
+          <span>{{ getCategoryName(scope.row.product_id) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column prop="service_content" label="服务内容" align="left" />
+      <el-table-column prop="current_phase" label="当前阶段" align="left">
+        <template #default="scope">
+          <el-tag :type="getPhaseType(scope.row.current_phase)" effect="plain">
+            {{ getPhaseName(scope.row.current_phase) }}
+          </el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column prop="project_status" label="目前状态" align="center">
+        <template #default="scope">
+          <el-tag
+            :type="getStatusType(scope.row.project_status)"
+            effect="plain"
+          >
+            {{ getStatusName(scope.row.project_status) }}
+          </el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column prop="start_date" label="项目开始日期" align="center" />
+      <el-table-column prop="updateTime" label="最后更新日期" align="center" />
+      <el-table-column prop="calculate" label="完成度" align="center">
+        <template #default="scope">
+          <span :class="getCompletionClass(scope.row.calculate)">
+            {{ formatCompletion(scope.row.calculate) }}
+          </span>
+        </template>
+      </el-table-column>
+      <!-- <el-table-column prop="" label="完成度" align="center" />
       <el-table-column
         prop="statusName"
         label="项目状态"
@@ -31,7 +66,7 @@
             {{ scope.row.status === 5 ? "启用" : "停用" }}
           </el-tag>
         </template>
-      </el-table-column>
+      </el-table-column> -->
       <el-table-column label="操作" align="center" fixed="right">
         <template #default="scope">
           <el-dropdown @command="handleCommand" :data="scope.row">
@@ -223,8 +258,13 @@ import {
   searchCategory,
   relate,
   searchTemplateList,
+  getstatus,
+  calculate,
+  getphases,
 } from "@/api/project";
 import { searchList, updateDocument } from "@/api/document";
+import { searchCustomer } from "@/api/customer";
+import { searchProduct } from "@/api/product";
 /* import {searchTemplate} from "@/api/template" */
 import dataInfo from "./dataInfo.vue";
 import elDragDialog from "@/directive/el-drag-dialog";
@@ -289,6 +329,10 @@ export default {
       boundTemplateLoading: false, // 添加已绑定模版加载状态
       selectedBoundTemplates: [], // 新增:已选择的绑定模版
       batchReplaceLoading: false, // 新增:批量替换loading状态
+      getstatusList: [], //状态列表
+      customList: [], //客户列表
+      productList: [], //产品列表
+      currentPhaseList: [], //阶段表
     };
   },
   mounted() {
@@ -296,6 +340,73 @@ export default {
     this.init();
   },
   methods: {
+    /* 客户名称 */
+    getCusomName(phaseId){
+      const product = this.customList.find((item) => item.id === phaseId);
+      return product ? product.name : "未知客户";
+    },
+    /* 当前阶段 */
+    getPhaseName(phaseId) {
+      const product = this.currentPhaseList.find((item) => item.value === phaseId);
+      return product ? product.label : "未知阶段";
+    },
+
+    getPhaseType(phaseId) {
+      const product = this.currentPhaseList.find((item) => item.value === phaseId);
+      if (!product) return "info";
+
+      // 根据不同阶段返回不同的类型
+      // 这里的判断逻辑需要根据实际的产品阶段来调整
+      switch (product.status) {
+        case 1:
+          return "success"; // 已完成
+        case 2:
+          return "warning"; // 进行中
+        case 3:
+          return "danger"; // 待处理
+        default:
+          return "info"; // 其他状态
+      }
+    },
+    /*目前状态  */
+    getStatusName(statusId) {
+      const status = this.getstatusList.find((item) => item.value === statusId);
+      return status ? status.label : "未知状态";
+    },
+
+    getStatusType(statusId) {
+      // 这里可以根据不同状态返回不同的类型
+      // 可用的类型有:success/warning/danger/info
+      const status = this.getstatusList.find((item) => item.value === statusId);
+      if (!status) return "info";
+
+      // 根据状态值返回对应的类型
+      switch (status.value) {
+        case 5:
+          return "success";
+        case 4:
+          return "warning";
+        case 3:
+          return "danger";
+        default:
+          return "info";
+      }
+    },
+    // 格式化完成度显示
+    formatCompletion(rate) {
+      if (rate === undefined || rate === null) {
+        return "0%";
+      }
+      return `${rate}%`;
+    },
+
+    // 根据完成度返回对应的CSS类名
+    getCompletionClass(rate) {
+      if (!rate) return "completion-low";
+      if (rate >= 100) return "completion-high";
+      if (rate >= 50) return "completion-medium";
+      return "completion-low";
+    },
     handleCommand(command) {
       switch (command.type) {
         case "template":
@@ -1176,8 +1287,13 @@ export default {
         query: { id: row.id },
       });
     },
+    /* 产品分类名称 */
+    getCategoryTypeName(categoryId){
+      const category = this.productList.find((item) => item.id === categoryId);
+      return category ? category.category.name : categoryId;
+    },
     getCategoryName(categoryId) {
-      const category = this.categoryList.find((item) => item.id === categoryId);
+      const category = this.productList.find((item) => item.id === categoryId);
       return category ? category.name : categoryId;
     },
     searchData() {
@@ -1227,15 +1343,33 @@ export default {
     },
 
     //搜索
-    search() {
-      console.log("search triggered"); // 添加调试日志
-      let _this = this;
-      searchProject(_this.queryForm).then((res) => {
+    async search() {
+      try {
+        const res = await searchProject(this.queryForm);
         if (!res) return;
-        _this.dataList = res.data.dataList;
-        _this.recordCount = res.data.totalRecord;
-        _this.pageTotal = res.data.totalPage;
-      });
+
+        // 获取所有项目的完成度
+        const calculatePromises = res.data.dataList.map(async (item) => {
+          try {
+            const calcRes = await calculate({ id: item.id });
+            if (calcRes.status === 200) {
+              item.calculate = calcRes.data.completionRate;
+            }
+          } catch (err) {
+            console.error(`获取项目${item.id}完成度失败:`, err);
+            item.calculate = 0;
+          }
+        });
+
+        await Promise.all(calculatePromises);
+
+        this.dataList = res.data.dataList;
+        this.recordCount = res.data.totalRecord;
+        this.pageTotal = res.data.totalPage;
+      } catch (err) {
+        console.error("搜索失败:", err);
+        this.$message.error("获取项目列表失败");
+      }
     },
     //修改分页
     ChangePage(e) {
@@ -1248,6 +1382,22 @@ export default {
         if (res.status !== 200) return;
         this.categoryList = res.data.dataList;
       });
+      /* 获取阶段 */
+      getphases().then((res) => {
+        this.currentPhaseList = res.data.options;
+      });
+      /* 获取目前状态 */
+      getstatus().then((res) => {
+        this.getstatusList = res.data.options;
+      });
+      /* 获取客户列表 */
+      searchCustomer({ page: 1, pageSize: 999 }).then((res) => {
+        this.customList = res.data.dataList;
+      });
+      /* 获取产品列表 */
+      searchProduct({ page: 1, pageSize: 999 }).then((res) => {
+        this.productList = res.data.dataList;
+      });
     },
   },
 };
@@ -1276,4 +1426,19 @@ export default {
     }
   }
 }
+// 完成度文字样式
+.completion-high {
+  color: #67c23a;
+  font-weight: bold;
+}
+
+.completion-medium {
+  color: #e6a23c;
+  font-weight: bold;
+}
+
+.completion-low {
+  color: #f56c6c;
+  font-weight: bold;
+}
 </style>

+ 1 - 0
src/views/project/components/dataSearch.vue

@@ -98,6 +98,7 @@ export default{
     onClose(e){
       this.dialogVisible=false;
       this.queryForm.isUpdate=!this.queryForm.isUpdate
+      this.$emit("bindSetQuery",this.$props.queryForm);
     },
     //搜索
     onSubmit(){

Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels