فهرست منبع

update:模型列表

Yan 4 سال پیش
والد
کامیت
c7df262f93
8فایلهای تغییر یافته به همراه575 افزوده شده و 247 حذف شده
  1. 144 144
      src/api/config.js
  2. 1 1
      src/api/model.js
  3. 7 2
      src/components/Sidebar.vue
  4. 10 2
      src/router/index.js
  5. 8 6
      src/views/ConfigList.vue
  6. 221 78
      src/views/ModelList.vue
  7. 163 0
      src/views/Upload.vue
  8. 21 14
      src/views/file/FileDetail.vue

+ 144 - 144
src/api/config.js

@@ -31,146 +31,146 @@ export const getAllConfig = payload => {
   const {uid} = payload;
   console.log("payload",payload);
   console.log("uid",uid);
-  // return axios.get(`${CONFIG_MODULE}/get/all?userId=${uid}`).then(res => {
-  //
-  //   return res.data;
-  // });
-  return Promise.resolve({
-    "timestamp": 1649419361037,
-    "status": 200,
-    "data": [
-      {
-        "fileId": "1",
-        "fileName": "event_data",
-        "configId": "1",
-        "modelTypeId": "2",
-        "modelTypeName": "决策树",
-        "confName": "config1",
-        "featureList": [
-          {
-            "id": 105,
-            "fileInfoId": 1,
-            "fieldName": "road",
-            "aliasName": "",
-            "fieldDes": "",
-            "nullsRatio": 0.0,
-            "conOrDis": 0,
-            "fieldType": "string",
-            "valueInfo": "[\"R\",\"L\"]"
-          },
-          {
-            "id": 106,
-            "fileInfoId": 1,
-            "fieldName": "lane",
-            "aliasName": "",
-            "fieldDes": "",
-            "nullsRatio": 0.0,
-            "conOrDis": 0,
-            "fieldType": "string",
-            "valueInfo": "[\"r\",\"m\",\"l\"]"
-          },
-          {
-            "id": 107,
-            "fileInfoId": 1,
-            "fieldName": "vehicle_class",
-            "aliasName": "",
-            "fieldDes": "",
-            "nullsRatio": 0.0,
-            "conOrDis": 0,
-            "fieldType": "string",
-            "valueInfo": "[\"car\",\"truck\",\"bus\"]"
-          },
-          {
-            "id": 110,
-            "fileInfoId": 1,
-            "fieldName": "duration",
-            "aliasName": "",
-            "fieldDes": "",
-            "nullsRatio": 0.0,
-            "conOrDis": 0,
-            "fieldType": "string",
-            "valueInfo": "[\"48,60\",\"24,36\",\"36,48\",\"12,24\",\"0,12\"]"
-          },
-          {
-            "id": 109,
-            "fileInfoId": 1,
-            "fieldName": "event_type",
-            "aliasName": "",
-            "fieldDes": "",
-            "nullsRatio": 0.0,
-            "conOrDis": 0,
-            "fieldType": "string",
-            "valueInfo": "[\"cruise\",\"overdrive\"]"
-          }
-        ]
-      },
-      {
-        "fileId": "1",
-        "fileName": "event_data",
-        "configId": "3",
-        "modelTypeId": "9",
-        "modelTypeName": "K-均值",
-        "confName": "Kmeans-Test",
-        "featureList": [
-          {
-            "id": 105,
-            "fileInfoId": 1,
-            "fieldName": "road",
-            "aliasName": "",
-            "fieldDes": "",
-            "nullsRatio": 0.0,
-            "conOrDis": 0,
-            "fieldType": "string",
-            "valueInfo": "[\"R\",\"L\"]"
-          },
-          {
-            "id": 106,
-            "fileInfoId": 1,
-            "fieldName": "lane",
-            "aliasName": "",
-            "fieldDes": "",
-            "nullsRatio": 0.0,
-            "conOrDis": 0,
-            "fieldType": "string",
-            "valueInfo": "[\"r\",\"m\",\"l\"]"
-          },
-          {
-            "id": 107,
-            "fileInfoId": 1,
-            "fieldName": "vehicle_class",
-            "aliasName": "",
-            "fieldDes": "",
-            "nullsRatio": 0.0,
-            "conOrDis": 0,
-            "fieldType": "string",
-            "valueInfo": "[\"car\",\"truck\",\"bus\"]"
-          },
-          {
-            "id": 110,
-            "fileInfoId": 1,
-            "fieldName": "duration",
-            "aliasName": "",
-            "fieldDes": "",
-            "nullsRatio": 0.0,
-            "conOrDis": 0,
-            "fieldType": "string",
-            "valueInfo": "[\"48,60\",\"24,36\",\"36,48\",\"12,24\",\"0,12\"]"
-          },
-          {
-            "id": 109,
-            "fileInfoId": 1,
-            "fieldName": "event_type",
-            "aliasName": "",
-            "fieldDes": "",
-            "nullsRatio": 0.0,
-            "conOrDis": 0,
-            "fieldType": "string",
-            "valueInfo": "[\"cruise\",\"overdrive\"]"
-          }
-        ]
-      }
-    ]
-  })
+  return axios.get(`${CONFIG_MODULE}/get/all?userId=${uid}`).then(res => {
+
+    return res.data;
+  });
+  // return Promise.resolve({
+  //   "timestamp": 1649419361037,
+  //   "status": 200,
+  //   "data": [
+  //     {
+  //       "fileId": "1",
+  //       "fileName": "event_data",
+  //       "configId": "1",
+  //       "modelTypeId": "2",
+  //       "modelTypeName": "决策树",
+  //       "confName": "config1",
+  //       "featureList": [
+  //         {
+  //           "id": 105,
+  //           "fileInfoId": 1,
+  //           "fieldName": "road",
+  //           "aliasName": "",
+  //           "fieldDes": "",
+  //           "nullsRatio": 0.0,
+  //           "conOrDis": 0,
+  //           "fieldType": "string",
+  //           "valueInfo": "[\"R\",\"L\"]"
+  //         },
+  //         {
+  //           "id": 106,
+  //           "fileInfoId": 1,
+  //           "fieldName": "lane",
+  //           "aliasName": "",
+  //           "fieldDes": "",
+  //           "nullsRatio": 0.0,
+  //           "conOrDis": 0,
+  //           "fieldType": "string",
+  //           "valueInfo": "[\"r\",\"m\",\"l\"]"
+  //         },
+  //         {
+  //           "id": 107,
+  //           "fileInfoId": 1,
+  //           "fieldName": "vehicle_class",
+  //           "aliasName": "",
+  //           "fieldDes": "",
+  //           "nullsRatio": 0.0,
+  //           "conOrDis": 0,
+  //           "fieldType": "string",
+  //           "valueInfo": "[\"car\",\"truck\",\"bus\"]"
+  //         },
+  //         {
+  //           "id": 110,
+  //           "fileInfoId": 1,
+  //           "fieldName": "duration",
+  //           "aliasName": "",
+  //           "fieldDes": "",
+  //           "nullsRatio": 0.0,
+  //           "conOrDis": 0,
+  //           "fieldType": "string",
+  //           "valueInfo": "[\"48,60\",\"24,36\",\"36,48\",\"12,24\",\"0,12\"]"
+  //         },
+  //         {
+  //           "id": 109,
+  //           "fileInfoId": 1,
+  //           "fieldName": "event_type",
+  //           "aliasName": "",
+  //           "fieldDes": "",
+  //           "nullsRatio": 0.0,
+  //           "conOrDis": 0,
+  //           "fieldType": "string",
+  //           "valueInfo": "[\"cruise\",\"overdrive\"]"
+  //         }
+  //       ]
+  //     },
+  //     {
+  //       "fileId": "1",
+  //       "fileName": "event_data",
+  //       "configId": "3",
+  //       "modelTypeId": "9",
+  //       "modelTypeName": "K-均值",
+  //       "confName": "Kmeans-Test",
+  //       "featureList": [
+  //         {
+  //           "id": 105,
+  //           "fileInfoId": 1,
+  //           "fieldName": "road",
+  //           "aliasName": "",
+  //           "fieldDes": "",
+  //           "nullsRatio": 0.0,
+  //           "conOrDis": 0,
+  //           "fieldType": "string",
+  //           "valueInfo": "[\"R\",\"L\"]"
+  //         },
+  //         {
+  //           "id": 106,
+  //           "fileInfoId": 1,
+  //           "fieldName": "lane",
+  //           "aliasName": "",
+  //           "fieldDes": "",
+  //           "nullsRatio": 0.0,
+  //           "conOrDis": 0,
+  //           "fieldType": "string",
+  //           "valueInfo": "[\"r\",\"m\",\"l\"]"
+  //         },
+  //         {
+  //           "id": 107,
+  //           "fileInfoId": 1,
+  //           "fieldName": "vehicle_class",
+  //           "aliasName": "",
+  //           "fieldDes": "",
+  //           "nullsRatio": 0.0,
+  //           "conOrDis": 0,
+  //           "fieldType": "string",
+  //           "valueInfo": "[\"car\",\"truck\",\"bus\"]"
+  //         },
+  //         {
+  //           "id": 110,
+  //           "fileInfoId": 1,
+  //           "fieldName": "duration",
+  //           "aliasName": "",
+  //           "fieldDes": "",
+  //           "nullsRatio": 0.0,
+  //           "conOrDis": 0,
+  //           "fieldType": "string",
+  //           "valueInfo": "[\"48,60\",\"24,36\",\"36,48\",\"12,24\",\"0,12\"]"
+  //         },
+  //         {
+  //           "id": 109,
+  //           "fileInfoId": 1,
+  //           "fieldName": "event_type",
+  //           "aliasName": "",
+  //           "fieldDes": "",
+  //           "nullsRatio": 0.0,
+  //           "conOrDis": 0,
+  //           "fieldType": "string",
+  //           "valueInfo": "[\"cruise\",\"overdrive\"]"
+  //         }
+  //       ]
+  //     }
+  //   ]
+  // })
 }
 
 //   console.log("uid",uid);
@@ -369,10 +369,10 @@ export const changeConfig = payload => {
  * @param {*} payload
  * @returns
  */
-export const deleteModelByModelId = payload => {
-  console.log("deletepara",payload);
-  const { configId } = payload;
-  return axios.get(`${CONFIG_MODULE}/delete/${configId}`).then(res => {
+export const deleteModelByModelId = configId => {
+  //console.log("deletepara",payload);
+  //const { configId } = payload;
+  return axios.get(`${CONFIG_MODULE}/delete?configId=${configId}`).then(res => {
 
     return res.data;
   });

+ 1 - 1
src/api/model.js

@@ -49,7 +49,7 @@ export const deleteModel=async modelId=>{
      */
     export const getAllModel = async userId => {
         const res = await axios.get(`${MODEL_MODULE}/get/all`, {params: {userId: userId}})
-        return res//response
+        return res.data//response
     }
     /**
      * 获取深度学习模型 GET /model/get/all/dl

+ 7 - 2
src/components/Sidebar.vue

@@ -64,9 +64,14 @@ export default {
               title: "模型配置",
           },
           {
-            icon: "el-icon-lx-redpacket_fill",
+            icon: "el-icon-coin",
             index: "/modelList",
-            title:"深度学习",
+            title:"机器学习模型",
+          },
+          {
+            icon: "el-icon-coin",
+            index: "/dlModelList",
+            title:"深度学习模型",
           },
           {
             icon: "el-icon-pie-chart",

+ 10 - 2
src/router/index.js

@@ -24,9 +24,17 @@ const routes = [
                 path: "/modelList",
                 name: "modelList",
                 meta: {
-                    title: '模型列表'
+                    title: '机器学习模型'
                 },
-                component: () => import ( /* webpackChunkName: "dashboard" */ "../views/modelList.vue")
+                component: () => import ( /* webpackChunkName: "dashboard" */ "../views/ModelList.vue")
+            },
+            {
+                path: "/dlModelList",
+                name: "dlModelList",
+                meta: {
+                    title: '深度学习模型'
+                },
+                component: () => import ( /* webpackChunkName: "dashboard" */ "../views/DLModelList.vue")
             },
             {
                 path: "/fileDetail",

+ 8 - 6
src/views/ConfigList.vue

@@ -69,7 +69,7 @@
                     <template #default="scope">
 
                       <router-link :to="{path:'/ConfigDetail',query:{configId:scope.row.configId}}">
-                        <el-button type="text" icon="el-icon-edit" >查看详情
+                        <el-button type="text" icon="el-icon-view" >查看详情
                         </el-button>
                       </router-link>
                         <el-button type="text" icon="el-icon-delete" class="red"
@@ -214,12 +214,14 @@ export default {
                     // ElMessage.success("删除成功");
                     // tableData.value.splice(index, 1);
                   console.log("删除");
-                  let idx=tableData._rawValue[index].id;
+                  let idx=tableData.value[index].configId;
                   console.log(idx);
-                  deleteModelByModelId({
-                    configId:idx
-                  }).then(res=>{
-                    console.log("deleteres",res);
+                  deleteModelByModelId(idx
+                  ).then(res=>{
+                    //console.log("deleteres",res);
+                    if(res.status===200){
+                      location.reload();
+                    }
                   });
 
                 })

+ 221 - 78
src/views/ModelList.vue

@@ -2,107 +2,250 @@
   <div class="">
     <div class="crumbs">
       <el-breadcrumb separator="/">
-        <el-breadcrumb-item><i class="el-icon-lx-file"></i> 我的模型</el-breadcrumb-item>
+        <el-breadcrumb-item>
+          <i class="el-icon-lx-cascades"></i> 我的模型
+        </el-breadcrumb-item>
       </el-breadcrumb>
     </div>
+
     <div class="container">
-      <el-tabs v-model="message">
-        <el-tab-pane :label="`我的模型列表`" name="first">
-          <el-table :data="state.unread" :show-header="false" style="width: 100%">
-            <el-table-column>
-              <template #default="scope">
-                <span class="message-title">{{scope.row.title}}</span>
-              </template>
-            </el-table-column>
-            <el-table-column prop="date" width="180"></el-table-column>
-            <el-table-column width="120">
-              <template #default="scope">
-                <!----------------------------todo------------------------------->
-                <!----------------------------获取文件详细信息、跳转到响应页面;删除文件------------------------------->
-                <router-link to="/dashboard">
-                <el-button size="small" @click="handleRead(scope.$index)">获取详情</el-button>
-
-                </router-link>
-                <el-button size="small" @click="handleRead(scope.$index)">删除</el-button>
-              </template>
-            </el-table-column>
-          </el-table>
-        </el-tab-pane>
-      </el-tabs>
-<!--          <div class="handle-row">-->
-<!--            <el-button type="primary">全部标为已读</el-button>-->
-<!--          </div>-->
-
-<!--            <button class="el-button el-button&#45;&#45;primary" type="button" data-v-4eda24fc="">&lt;!&ndash;v-if&ndash;&gt;<i class="el-icon-upload"></i><span>上传</span></button>-->
-
-<!--            <router-link to="/config">-->
-<!--&lt;!&ndash;            <button class="el-button el-button&#45;&#45;primary" type="button" data-v-4eda24fc="">&lt;!&ndash;v-if&ndash;&gt;<i class="el-icon-s-home"></i><span>添加模型</span></button>&ndash;&gt;-->
-<!--              <el-button type="primary" size="large">配置模型</el-button>-->
-<!--            </router-link>-->
+      <div class="handle-box">
+        <el-select v-model="query.file" placeholder="模型类别" class="handle-select mr10">
+          <el-option key="0" label="所有" value="0"></el-option>
+          <el-option key="1" label="逻辑回归" value="1"></el-option>
+          <el-option key="2" label="决策树" value="2"></el-option>
+          <el-option key="3" label="随机森林" value="3"></el-option>
+          <el-option key="4" label="梯度提升决策树" value="4"></el-option>
+          <el-option key="5" label="多层感知器分类器" value="5"></el-option>
+          <el-option key="6" label="朴素贝叶斯" value="6"></el-option>
+          <el-option key="7" label="随机森林回归" value="7"></el-option>
+          <el-option key="8" label="K-均值" value="8"></el-option>
+        </el-select>
+        <el-input v-model="query.name" placeholder="模型名" class="handle-input mr10"></el-input>
+        <el-button type="primary" icon="el-icon-search" @click="handleSearch">搜索</el-button>
+      </div>
+      <el-table
+          :data="tableData" border class="table" ref="multipleTable"
+          header-cell-class-name="table-header"
+          @selection-change="handleSelectionChange"
+          @row-dblclick="getConfigDetail"
+      >
+        <el-table-column prop="modelName" label="模型名"></el-table-column>
+        <el-table-column prop="configName" label="配置名"></el-table-column>
+        <el-table-column label="模型类别">
+          <template #default="scope">{{ scope.row.modelTypeName }}</template>
+        </el-table-column>
+        <el-table-column prop="arguments" label="参数值">
+          <template #default="scope">
+            <div v-for="(item,index) in scope.row.arguments" :key="index">{{item}}</div>
+          </template>
+        </el-table-column>
+        <el-table-column prop="trainedStatus" label="训练状态"></el-table-column>
+        <el-table-column label="操作" width="180" align="center">
+          <template #default="scope">
 
+            <router-link :to="{path:'/ModelDetail',query:{modelId:scope.row.modelId}}">
+              <el-button type="text" icon="el-icon-view" >查看详情
+              </el-button>
+            </router-link>
+            <el-button type="text" icon="el-icon-delete" class="red"
+                       @click="handleDelete(scope.$index, scope.row)">删除</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      <div class="pagination">
+        <el-pagination background layout="total, prev, pager, next" :current-page="query.pageIndex"
+                       :page-size="query.pageSize" :total="pageTotal" @current-change="handlePageChange"></el-pagination>
+      </div>
     </div>
   </div>
 </template>
 
 <script>
 import { ref, reactive } from "vue";
+import { ElMessage, ElMessageBox } from "element-plus";
+import {getAllModel} from "../api/model";
+
 export default {
-  name: "tabs",
+  name: "model",
   setup() {
-    const message = ref("first");
-    const state = reactive({
-      unread: [
-        {
-          date: "2018-04-19 20:00:00",
-          title: "文件1",
-        },
-        {
-          date: "2018-04-19 21:00:00",
-          title: "文件2",
-        },
-      ],
-      read: [
-        {
-          date: "2018-04-19 20:00:00",
-          title: "【系统通知】该系统将于今晚凌晨2点到5点进行升级维护",
-        },
-      ],
-      recycle: [
-        {
-          date: "2018-04-19 20:00:00",
-          title: "【系统通知】该系统将于今晚凌晨2点到5点进行升级维护",
-        },
-      ],
+    const featureSty = reactive({
+
+      resource: "小天才",
+
+    });
+    const modelSty = reactive({
+
+      resource: "小天才",
+
+    });
+    const query = reactive({
+      file: "",
+      name: "",
+      pageIndex: 1,
+      pageSize: 10,
     });
 
-    const handleRead = (index) => {
-      const item = state.unread.splice(index, 1);
-      console.log(item);
-      state.read = item.concat(state.read);
+    const typeList=["所有","分类","聚类","回归","自动分类器"];
+    const featureList=["所有","手动选择","自动选择"];
+    const multipleSelection =ref([]);
+
+    // const tableData = ref([]);
+    const tableData = ref();
+
+    const pageTotal = ref(0);
+    // 获取表格数据
+
+    const getpage=()=> {
+      // console.log("getpage");
+      const uid=1;
+      getAllModel(
+        uid
+      ).then(res => {
+        console.log("res",res);
+        tableData.value = res.data;
+        pageTotal.value=tableData.value.length
+        for(let i=0;i<tableData.value.length;i++) {
+          const reg=new RegExp("\"","g");
+          tableData.value[i].arguments = ((JSON.stringify(tableData.value[i].arguments))+"")
+              .replace(reg,"")
+              .replace("{","")
+              .replace("}","")
+              .split(",");
+          if(tableData.value[i].trainedStatus===1){
+            tableData.value[i].trainedStatus="已训练";
+          }else{
+            tableData.value[i].trainedStatus="未训练";
+          }
+        }
+      })
+    };
+    getpage();
+    // 查询操作
+    const handleSearch = () => {
+      query.pageIndex = 1;
+      getData();
+    };
+    // 分页导航
+    const handlePageChange = (val) => {
+      query.pageIndex = val;
+      getData();
+    };
+
+    // 删除操作(单个)
+    const handleDelete = (index) => {
+      // 二次确认删除
+      ElMessageBox.confirm("确定要删除吗?", "提示", {
+        type: "warning",
+      })
+          .then(() => {
+            // ElMessage.success("删除成功");
+            // tableData.value.splice(index, 1);
+            console.log("删除");
+            let idx=tableData.value[index].id;
+            console.log(idx);
+
+          })
+          .catch(() => {});
+    };
+
+    //TODO
+    const handleSelectionChange = (val) => {
+      multipleSelection.value = val
     };
-    const handleDel = (index) => {
-      const item = state.read.splice(index, 1);
-      state.recycle = item.concat(state.recycle);
+
+    //TODO 批量删除
+    const handleBatchDelete =()=>{
+      // 二次确认
+      if(multipleSelection.value.length<=0){
+        ElMessageBox.alert("请先勾选要删除的模型", '提示', {
+          confirmButtonText: '好的'
+        })
+      }
+      else{
+        ElMessageBox.confirm("确定要删除这些模型吗?", "提示", {
+          type: "warning",
+        })
+            .then(() => {
+              let idList=[];
+              for(let i=0;i<multipleSelection.value.length;i++){
+                let id=multipleSelection.value[i]['id'];
+                idList.push(id);
+              }
+              idList.sort();
+              console.log(idList);
+              for (let i = idList[idList.length-1]; i >=0 ; i--) {
+                tableData.value.splice(i,1);
+              }
+              ElMessage.success("删除成功");
+            })
+            .catch(() => {});
+      }
     };
-    const handleRestore = (index) => {
-      const item = state.recycle.splice(index, 1);
-      state.read = item.concat(state.read);
+
+    const editVisible = ref(false);
+    let form = reactive({
+      name: "",
+      file: "",
+      // classification:"",
+      // feature:"",
+    });
+    let idx = -1;
+    const handleEdit = (index, row) => {
+      idx = index;
+      Object.keys(form).forEach((item) => {
+        form[item] = row[item];
+      });
+      editVisible.value = true;
     };
 
     return {
-      message,
-      state,
-      handleRead,
-      handleDel,
-      handleRestore,
+      query,
+      tableData,
+      pageTotal,
+      editVisible,
+      form,
+      handleSearch,
+      handlePageChange,
+      handleDelete,
+      handleSelectionChange,
+      handleBatchDelete,
+      handleEdit,
+      featureSty,
+      modelSty,
+      getpage,
     };
   },
 };
 </script>
 
-<style>
-.message-title {
-  cursor: pointer;
+<style scoped>
+.handle-box {
+  margin-bottom: 20px;
 }
-</style>
 
+.handle-select {
+  width: 120px;
+}
+
+.handle-input {
+  width: 300px;
+  display: inline-block;
+}
+.table {
+  width: 100%;
+  font-size: 14px;
+}
+.red {
+  color: #ff0000;
+}
+.mr10 {
+  margin-right: 10px;
+}
+.table-td-thumb {
+  display: block;
+  margin: auto;
+  width: 40px;
+  height: 40px;
+}
+</style>

+ 163 - 0
src/views/Upload.vue

@@ -0,0 +1,163 @@
+<template>
+    <div>
+        <div class="crumbs">
+            <el-breadcrumb separator="/">
+                <el-breadcrumb-item>
+                    <i class="el-icon-lx-calendar"></i> 表单
+                </el-breadcrumb-item>
+                <el-breadcrumb-item>图片上传</el-breadcrumb-item>
+            </el-breadcrumb>
+        </div>
+        <div class="container">
+            <div class="content-title">支持拖拽</div>
+            <!--<div class="plugins-tips">
+                Element UI自带上传组件。
+                访问地址:
+                <a href="http://element.eleme.io/#/zh-CN/component/upload" target="_blank">Element UI Upload</a>
+            </div>-->
+            <el-upload class="upload-demo" drag action=""
+                       accept=".jpg,.png,.csv"
+                       :limit="10"
+                       :on-exceed="handleExceed"
+                       :on-remove="handleRemove"
+                       :before-remove="beforeRemove"
+                       :auto-upload="false" multiple>
+                <i class="el-icon-upload"></i>
+                <div class="el-upload__text">
+                    将文件拖到此处,或
+                    <em>点击上传</em>
+                </div>
+                <template #tip>
+                    <div class="el-upload__tip">请上传jpg/png图像文件或csv结构化文件,且不超过 500kb,一次最多上传10个文件</div>
+                </template>
+            </el-upload>
+            <!--<div class="content-title">支持裁剪</div>
+            <div class="plugins-tips">
+                vue-cropperjs:一个封装了 cropperjs 的 Vue 组件。
+                访问地址:
+                <a href="https://github.com/Agontuk/vue-cropperjs" target="_blank">vue-cropperjs</a>
+            </div>-->
+        </div>
+    </div>
+</template>
+
+<script>
+import { ref } from "vue";
+import VueCropper from "vue-cropperjs";
+import "cropperjs/dist/cropper.css";
+import defaultSrc from "../assets/img/img.jpg";
+import { ElMessage, ElMessageBox } from "element-plus"
+
+export default {
+    name: "upload",
+    components: {
+        VueCropper,
+    },
+    setup() {
+        const imgSrc = ref("");
+        const cropImg = ref(defaultSrc);
+        const dialogVisible = ref(false);
+        const cropper = ref(null);
+
+        const setImage = (e) => {
+            const file = e.target.files[0];
+            if (!file.type.includes("image/")) {
+                return;
+            }
+            const reader = new FileReader();
+            reader.onload = (event) => {
+                dialogVisible.value = true;
+                imgSrc.value = event.target.result;
+                cropper.value && cropper.value.replace(event.target.result);
+            };
+            reader.readAsDataURL(file);
+        };
+        const cropImage = () => {
+            cropImg.value = cropper.value.getCroppedCanvas().toDataURL();
+        };
+        const cancelCrop = () => {
+            dialogVisible.value = false;
+            cropImg.value = defaultSrc;
+        };
+
+        //todo:
+        const handleExceed=(files,fileList)=>{
+            console.log("handleExceed")
+            console.log(files)
+            console.log(fileList)
+            ElMessage.warning(
+              `一次最多上传10个文件, 你一次上传了${files.length}个文件`
+          )
+        }
+        const handleRemove=(file,fileList)=>{
+          console.log("handleRemove")
+          console.log(file)
+          console.log(fileList)
+        }
+      const beforeRemove = (file, filelist) => {
+        return ElMessageBox.confirm(
+            `取消上传${file.name} ?`
+        ).then(
+            () => true,
+            () => false
+        )
+      }
+        return {
+            cropper,
+            imgSrc,
+            cropImg,
+            dialogVisible,
+            setImage,
+            cropImage,
+            cancelCrop,
+            handleExceed,
+            handleRemove,
+            beforeRemove
+        };
+    },
+};
+</script>
+
+<style scoped>
+.content-title {
+    font-weight: 400;
+    line-height: 50px;
+    margin: 10px 0;
+    font-size: 22px;
+    color: #1f2f3d;
+}
+
+.pre-img {
+    width: 100px;
+    height: 100px;
+    background: #f8f8f8;
+    border: 1px solid #eee;
+    border-radius: 5px;
+}
+.crop-demo {
+    display: flex;
+    align-items: flex-end;
+}
+.crop-demo-btn {
+    position: relative;
+    width: 100px;
+    height: 40px;
+    line-height: 40px;
+    padding: 0 20px;
+    margin-left: 30px;
+    background-color: #409eff;
+    color: #fff;
+    font-size: 14px;
+    border-radius: 4px;
+    box-sizing: border-box;
+}
+.crop-input {
+    position: absolute;
+    width: 100px;
+    height: 40px;
+    left: 0;
+    top: 0;
+    opacity: 0;
+    cursor: pointer;
+}
+</style>

+ 21 - 14
src/views/file/FileDetail.vue

@@ -110,7 +110,7 @@
       </template>
     </el-dialog>
 
-    <el-dialog title="新建配置" v-model="configCreate" width="30%">
+    <el-dialog title="新建配置" v-model="configCreate" width="50%">
       <el-form label-width="120px">
         <el-form-item label="配置名" required>
           <el-input v-model="form.name"></el-input>
@@ -129,6 +129,10 @@
           </el-select>
         </el-form-item>
         <el-form-item label="已选择字段" required>
+          <el-alert type="info" description="您下列选择的最后一个字段为分类模型的目标字段"
+                    show-icon style="height: 40px;"></el-alert>
+          <el-alert type="info" description="k-means模型没有目标字段"
+                    show-icon style="height: 40px;"></el-alert>
           <el-table :data="selectData" border class="table"  header-cell-class-name="table-header" >
             <el-table-column label="字段名">
               <template #default="scope"><span>{{ scope.row.fieldName }}</span></template>
@@ -155,6 +159,7 @@ import {getFileDetail,analysisFile} from "../../api/file";
 import {useRoute}from "vue-router";
 import {useRouter}from "vue-router";
 import { toRaw } from '@vue/reactivity'
+import {addConfig} from "../../api/config";
 
 export default {
   name: "config",
@@ -329,21 +334,23 @@ export default {
       const fieldTable = ref(null)
       //console.log(fieldTable)
       console.log(selectData.value)
-       onMounted(() => {
-        console.log(fieldTable.value.selection)
-      })
-
       configCreate.value = true;
     };
-
-    const saveConfig = () => {
-      configCreate.value = false;
-      ElMessage.success(`已成功生成配置`);
-      //todo: 调用Config相关接口
-
-
-
-    };
+    const saveConfig=()=>{
+      const route=useRoute()
+      const payload={fileInfoId:selectData.value[0].fileInfoId,userId:1, modelTypeId:form.type, confName:form.name , fieldIds:[]}
+      for(let i=0;i<selectData.value.length;i++){
+        payload.fieldIds.push(selectData.value[i].id);
+      }
+      addConfig(payload).then(res=>{
+        if(res.status===200) {
+          ElMessage.success(`已成功生成配置`);
+          configCreate.value = false;
+        }
+        else ElMessage.error(`生成配置失败`);
+      })
+      console.log(payload)
+    }
     const handleSelectChange=val=>{
       selectData.value=val;
     };