191250061 hace 4 años
padre
commit
98f2c7d73d
Se han modificado 5 ficheros con 746 adiciones y 28 borrados
  1. 88 3
      src/api/config.js
  2. 8 0
      src/router/index.js
  3. 3 25
      src/views/Config.vue
  4. 333 0
      src/views/ConfigDetail.vue
  5. 314 0
      src/views/save.vue

+ 88 - 3
src/api/config.js

@@ -253,10 +253,95 @@ export const getAllNew = payload => {
  */
 export const getOneConfig = payload => {
   const { configId } = payload;
-  return axios.get(`${CONFIG_MODULE}/get/one/config/${configId}?`).then(res => {
+  // return axios.get(`${CONFIG_MODULE}/get/one/config/${configId}?`).then(res => {
+
+    // return res.data;
+    return Promise.resolve({
+      "timestamp": 1649473724362,
+      "status": 200,
+      "data": {
+        "configId": "1",
+        "modelTypeId": "6",
+        "modelTypeName": "多层感知器分类器",
+        "modelDes": "",
+        "modelDetileDes": "",
+        "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\"]"
+          }
+        ],
+        "modelInfos": [
+          {
+            "modelName": "event_data",
+            "modelDetailName": "DecisionTree",
+            "trainedStatus": 1
+          },
+          {
+            "modelName": "event_data2",
+            "modelDetailName": "DecisionTree",
+            "trainedStatus": -1
+          },
+          {
+            "modelName": "event_data3",
+            "modelDetailName": "MultilayerPerceptronClassifier",
+            "trainedStatus": -1
+          }
+        ]
+      }
+    });
 
-    return res.data;
-  });
 }
 
 /**

+ 8 - 0
src/router/index.js

@@ -155,6 +155,14 @@ const routes = [
                     title:'更改配置'
                 },
                 component:()=>import(/*webpackChunkName:"configform" */ '../views/changeConfig.vue')
+            },
+            {
+                path:'/ConfigDetail',
+                name:'configdetail',
+                meta:{
+                    title:'配置详情'
+                },
+                component:()=>import(/*webpackChunkName:"configform" */ '../views/ConfigDetail.vue')
             }
 
         ]

+ 3 - 25
src/views/Config.vue

@@ -72,10 +72,10 @@
 <!--                      <router-link :to="`/configformpf/${scope.$index}`">-->
 <!--                      <router-link :to="`/configformp/${scope.row.configId}`">-->
 <!--                      :to="{path:'/news/detail',query:{id:1}}"-->
-<!--                      <router-link :to="{path:'/configform',query:{id:scope.row.id}}">-->
+                      <router-link :to="{path:'/ConfigDetail',query:{configId:scope.row.configId}}">
                         <el-button type="text" icon="el-icon-edit" >查看详情
                         </el-button>
-<!--                      </router-link>-->
+                      </router-link>
                         <el-button type="text" icon="el-icon-delete" class="red"
                             @click="handleDelete(scope.$index, scope.row)">删除</el-button>
                     </template>
@@ -178,29 +178,7 @@ export default {
 
         // const tableData = ref([]);
     const tableData = ref([
-      {
-        "id": 1,
-        "name": "name1",
-        "type": "类型一",
-        "feature": "特征一",
-        "time": 1}
-
-  ,{
-  "id": 2,
-      "name": "name2",
-      "type": "类型二",
-      "feature": "特征二",
-      "time": 1
-
-},
-{
-  "id": 3,
-    "name": "name3",
-    "type": "类型二",
-    "feature": "特征二",
-    "time": 1
-
-}]);
+      ]);
 
         const pageTotal = ref(0);
         // 获取表格数据

+ 333 - 0
src/views/ConfigDetail.vue

@@ -0,0 +1,333 @@
+<template>
+  <div>
+    <div class="crumbs">
+      <el-breadcrumb separator="/">
+        <el-breadcrumb-item>
+          <i class="el-icon-lx-cascades"></i> 配置详情
+        </el-breadcrumb-item>
+      </el-breadcrumb>
+    </div>
+
+      <div class="handle-box">
+
+
+
+      </div>
+
+<!--  <el-tab-pane :label="featureList"> </el-tab-pane>-->
+      <div class="container">
+        <div class="form-box" >
+          <el-form ref="formRef" label-width="120px">
+            <el-form-item label="模型类型名:" >
+              {{config.modelTypeName}}
+            </el-form-item>
+            <el-form-item label="模型描述:" >
+              {{config.modelDes}}
+            </el-form-item>
+            <el-form-item label="模型详情:" >
+              {{}}
+            </el-form-item>
+            <el-form-item label="特征字段:" >
+              <el-table :data="tableData" border class="table" ref="fieldTable" header-cell-class-name="table-header" @selection-change="handleSelectChange">
+                <el-table-column width="50" type="selection" ></el-table-column>
+                <el-table-column label="字段名">
+                  <template #default="scope"><span>{{ scope.row.fieldName }}</span></template>
+                </el-table-column>
+                <el-table-column label="别名">
+                  <template #default="scope">{{ scope.row.aliasName }}</template>
+                </el-table-column>
+                <el-table-column label="描述">
+                  <template #default="scope">{{ scope.row.fieldDes }}</template>
+                </el-table-column>
+                <el-table-column label="取值类型">
+                  <template #default="scope">{{ scope.row.fieldType }}</template>
+                </el-table-column>
+                <el-table-column label="分布类型">
+                  <template #default="scope">{{ scope.row.conOrDis }}</template>
+                </el-table-column>
+                <el-table-column label="空值率">
+                  <template #default="scope">{{ scope.row.nullsRatio }}</template>
+                </el-table-column>
+
+                <el-table-column label="值域" >
+                  <template #default="scope">{{ scope.row.valueInfo }}</template>
+                </el-table-column>
+              </el-table>
+            </el-form-item>
+
+            <el-form-item label="模型列表:" >
+            <el-table :data="modelData" border class="table" ref="fieldTable" header-cell-class-name="table-header" @selection-change="handleSelectChange">
+              <el-table-column width="50" type="selection" ></el-table-column>
+              <el-table-column label="模型名">
+                <template #default="scope"><span>{{ scope.row.modelName }}</span></template>
+              </el-table-column>
+              <el-table-column label="详情">
+                <template #default="scope">{{ scope.row.modelDetailName }}</template>
+              </el-table-column>
+              <el-table-column label="训练状态">
+                <template #default="scope">{{ scope.row.trainedStatus}}</template>
+              </el-table-column>
+
+            </el-table>
+            </el-form-item>
+          </el-form>
+          </div>
+        </div>
+
+
+<!--      <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>
+
+    <!-- 编辑弹出框 -->
+    <el-dialog title="选择字段" v-model="editVisible" width="30%">
+      <el-form label-width="120px">
+        <el-form-item label="统计分析" required>
+          <el-input v-model="form.name"></el-input>
+        </el-form-item>
+        <el-form-item label="所选方法简介" required>
+          <el-input v-model="form.address"></el-input>
+        </el-form-item>
+        <el-form-item label="可选择字段" required>
+
+        </el-form-item>
+
+      </el-form>
+      <template #footer>
+                <span class="dialog-footer">
+                    <el-button @click="editVisible = false">取 消</el-button>
+                    <el-button type="primary" @click="saveEdit">确 定</el-button>
+                </span>
+      </template>
+    </el-dialog>
+    <el-dialog title="新建配置" v-model="configCreate" width="30%">
+      <el-form label-width="120px">
+        <el-form-item label="配置名" required>
+          <el-input v-model="form.name"></el-input>
+        </el-form-item>
+        <el-form-item label="模型类别" required>
+          <el-select v-model="form.type" 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-form-item>
+        <el-form-item label="已选择字段" required>
+          <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>
+            </el-table-column>
+          </el-table>
+        </el-form-item>
+
+      </el-form>
+      <template #footer>
+                <span class="dialog-footer">
+                    <el-button @click="editVisible = false">取 消</el-button>
+                    <el-button type="primary" @click="saveConfig">确 定</el-button>
+                </span>
+      </template>
+    </el-dialog>
+
+</template>
+
+<script>
+import {ref, reactive, getCurrentInstance, onMounted} from "vue";
+import { ElMessage, ElMessageBox } from "element-plus";
+import { fetchData } from "../api/index";
+import {getFileDetail} from "../api/file";
+import {getOneConfig} from "../api/config";
+import {useRoute}from "vue-router";
+export default {
+  name: "configDetail",
+  //训练特征
+  setup() {
+    const query = reactive({
+      address: "",
+      name: "",
+      pageIndex: 1,
+      pageSize: 10,
+    });
+    const fileId=1;
+    //new TODO
+    //TODO
+    const fieldNameList=[]; //字段名
+    const aliasList=[];   //别名
+    const descList=[];      //描述
+    const aList=[];   //取值类型
+    const bList=[];   //分布类型
+    const cList=[];   //空值率
+    const dList=[];
+
+
+    const tableData = ref([]);
+    const selectData = ref([]);
+    const pageTotal = ref(0);
+
+    const modelData=ref([]);
+    const config=ref([]);
+    // 获取表格数据
+    const getData = () => {
+      const route=useRoute()
+      //todo:调用获取文件具体信息获取字段列表
+      // console.log("queryId",route.query.configId);
+      if(route.query.configId!=null) {
+        getOneConfig(route.query.configId).then(res => {
+          // console.log("configdetail",res);
+          config.value=res.data;
+          console.log("config",config);
+          tableData.value = res.data.featureList;
+          for (var i = 0; i < tableData.value.length; i++) {
+            if (tableData.value[i].conOrDis === 1) {
+              tableData.value[i].conOrDis = "连续值"
+            } else {
+              tableData.value[i].conOrDis = "离散值"
+            }
+          }
+          //console.log(tableData)
+
+          modelData.value=res.data.modelInfos;
+          console.log("tableData",tableData);
+        })
+      }
+
+    };
+    getData();
+
+    // 查询操作
+    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);
+          })
+          .catch(() => {});
+    };
+
+    // 表格编辑时弹窗和保存
+    const editVisible = ref(false);
+    let form = reactive({
+      name: "",
+      type: "",
+      // classification:"",
+      // feature:"",
+    });
+    let idx = -1;
+    const handleEdit = () => {
+      editVisible.value = true;
+    };
+
+    const configCreate = ref(false);
+    const createConfig =() => {
+      const fieldTable = ref(null)
+      //console.log(fieldTable)
+      console.log(selectData.value)
+      onMounted(() => {
+        console.log(fieldTable.value.selection)
+      })
+
+      configCreate.value = true;
+    };
+    const saveEdit = () => {
+      editVisible.value = false;
+      //todo: 数理分析相关
+
+
+      // ElMessage.success(`修改第 ${idx + 1} 行成功`);
+      // Object.keys(form).forEach((item) => {
+      //   tableData.value[idx][item] = form[item];
+      // });
+    };
+    const saveConfig = () => {
+      editVisible.value = false;
+      ElMessage.success(`已成功生成配置`);
+      //todo: 调用Config相关接口
+
+    };
+    const handleSelectChange=val=>{
+      selectData.value=val;
+    }
+
+    return {
+      config,
+      query,
+      tableData,
+      pageTotal,
+      modelData,
+      editVisible,
+      form,
+      configCreate,
+      selectData,
+      handleSelectChange,
+      handleSearch,
+      handlePageChange,
+      handleDelete,
+      handleEdit,
+      saveEdit,
+      createConfig
+    };
+  },
+};
+
+
+</script>
+
+<style scoped>
+.handle-box {
+  margin-bottom: 20px;
+}
+.handle-table{
+  margin-bottem: 40px;
+}
+
+.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>

+ 314 - 0
src/views/save.vue

@@ -0,0 +1,314 @@
+<template>
+  <div>
+    <div class="crumbs">
+      <el-breadcrumb separator="/">
+        <el-breadcrumb-item>
+          <i class="el-icon-lx-cascades"></i> 文件详情
+        </el-breadcrumb-item>
+      </el-breadcrumb>
+    </div>
+    <div class="container">
+      <div class="handle-box">
+        <router-link to="/fileList">
+          <el-button type="primary" plain icon="el-icon-lx-file" >选择文件</el-button>
+        </router-link>
+        <el-button type="primary" icon="el-icon-thumb" @click="handleEdit">数理分析</el-button>
+        <el-button type="primary" icon="el-icon-thumb" @click="createConfig">生成配置文件</el-button>
+
+
+      </div>
+      <div class="handle-box">
+        <!--  <el-tab-pane :label="featureList"> </el-tab-pane>-->
+        <el-form-item label="特征字段" >
+          <el-table :data="tableData" border class="table" ref="fieldTable" header-cell-class-name="table-header" @selection-change="handleSelectChange">
+            <el-table-column width="50" type="selection" ></el-table-column>
+            <el-table-column label="字段名">
+              <template #default="scope"><span>{{ scope.row.fieldName }}</span></template>
+            </el-table-column>
+            <el-table-column label="别名">
+              <template #default="scope">{{ scope.row.aliasName }}</template>
+            </el-table-column>
+            <el-table-column label="描述">
+              <template #default="scope">{{ scope.row.fieldDes }}</template>
+            </el-table-column>
+            <el-table-column label="取值类型">
+              <template #default="scope">{{ scope.row.fieldType }}</template>
+            </el-table-column>
+            <el-table-column label="分布类型">
+              <template #default="scope">{{ scope.row.conOrDis }}</template>
+            </el-table-column>
+            <el-table-column label="空值率">
+              <template #default="scope">{{ scope.row.nullsRatio }}</template>
+            </el-table-column>
+
+            <el-table-column label="值域" >
+              <template #default="scope">{{ scope.row.valueInfo }}</template>
+            </el-table-column>
+          </el-table>
+        </el-form-item>
+      </div>
+      <!--      <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>-->
+
+      <el-table :data="modelData" border class="table" ref="fieldTable" header-cell-class-name="table-header" @selection-change="handleSelectChange">
+        <el-table-column width="50" type="selection" ></el-table-column>
+        <el-table-column label="模型名">
+          <template #default="scope"><span>{{ scope.row.modelName }}</span></template>
+        </el-table-column>
+        <el-table-column label="详情">
+          <template #default="scope">{{ scope.row.modelDetailName }}</template>
+        </el-table-column>
+        <el-table-column label="训练状态">
+          <template #default="scope">{{ scope.row.trainedStatus}}</template>
+        </el-table-column>
+
+      </el-table>
+
+
+    </div>
+
+    <!-- 编辑弹出框 -->
+    <el-dialog title="选择字段" v-model="editVisible" width="30%">
+      <el-form label-width="120px">
+        <el-form-item label="统计分析" required>
+          <el-input v-model="form.name"></el-input>
+        </el-form-item>
+        <el-form-item label="所选方法简介" required>
+          <el-input v-model="form.address"></el-input>
+        </el-form-item>
+        <el-form-item label="可选择字段" required>
+
+        </el-form-item>
+
+      </el-form>
+      <template #footer>
+                <span class="dialog-footer">
+                    <el-button @click="editVisible = false">取 消</el-button>
+                    <el-button type="primary" @click="saveEdit">确 定</el-button>
+                </span>
+      </template>
+    </el-dialog>
+    <el-dialog title="新建配置" v-model="configCreate" width="30%">
+      <el-form label-width="120px">
+        <el-form-item label="配置名" required>
+          <el-input v-model="form.name"></el-input>
+        </el-form-item>
+        <el-form-item label="模型类别" required>
+          <el-select v-model="form.type" 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-form-item>
+        <el-form-item label="已选择字段" required>
+          <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>
+            </el-table-column>
+          </el-table>
+        </el-form-item>
+
+      </el-form>
+      <template #footer>
+                <span class="dialog-footer">
+                    <el-button @click="editVisible = false">取 消</el-button>
+                    <el-button type="primary" @click="saveConfig">确 定</el-button>
+                </span>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import {ref, reactive, getCurrentInstance, onMounted} from "vue";
+import { ElMessage, ElMessageBox } from "element-plus";
+import { fetchData } from "../api/index";
+import {getFileDetail} from "../api/file";
+import {getOneConfig} from "../api/config";
+import {useRoute}from "vue-router";
+export default {
+  name: "configDetail",
+  //训练特征
+  setup() {
+    const query = reactive({
+      address: "",
+      name: "",
+      pageIndex: 1,
+      pageSize: 10,
+    });
+    const fileId=1;
+    //new TODO
+    //TODO
+    const fieldNameList=[]; //字段名
+    const aliasList=[];   //别名
+    const descList=[];      //描述
+    const aList=[];   //取值类型
+    const bList=[];   //分布类型
+    const cList=[];   //空值率
+    const dList=[];
+
+
+    const tableData = ref([]);
+    const selectData = ref([]);
+    const pageTotal = ref(0);
+
+    const modelData=ref([]);
+
+    // 获取表格数据
+    const getData = () => {
+      const route=useRoute()
+      //todo:调用获取文件具体信息获取字段列表
+      // console.log("queryId",route.query.configId);
+      if(route.query.configId!=null) {
+        getOneConfig(route.query.configId).then(res => {
+          // console.log("configdetail",res);
+          tableData.value = res.data.featureList;
+          for (var i = 0; i < tableData.value.length; i++) {
+            if (tableData.value[i].conOrDis === 1) {
+              tableData.value[i].conOrDis = "连续值"
+            } else {
+              tableData.value[i].conOrDis = "离散值"
+            }
+          }
+          //console.log(tableData)
+
+          modelData.value=res.data.modelInfos;
+          console.log("tableData",tableData);
+        })
+      }
+
+    };
+    getData();
+
+    // 查询操作
+    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);
+          })
+          .catch(() => {});
+    };
+
+    // 表格编辑时弹窗和保存
+    const editVisible = ref(false);
+    let form = reactive({
+      name: "",
+      type: "",
+      // classification:"",
+      // feature:"",
+    });
+    let idx = -1;
+    const handleEdit = () => {
+      editVisible.value = true;
+    };
+
+    const configCreate = ref(false);
+    const createConfig =() => {
+      const fieldTable = ref(null)
+      //console.log(fieldTable)
+      console.log(selectData.value)
+      onMounted(() => {
+        console.log(fieldTable.value.selection)
+      })
+
+      configCreate.value = true;
+    };
+    const saveEdit = () => {
+      editVisible.value = false;
+      //todo: 数理分析相关
+
+
+      // ElMessage.success(`修改第 ${idx + 1} 行成功`);
+      // Object.keys(form).forEach((item) => {
+      //   tableData.value[idx][item] = form[item];
+      // });
+    };
+    const saveConfig = () => {
+      editVisible.value = false;
+      ElMessage.success(`已成功生成配置`);
+      //todo: 调用Config相关接口
+
+    };
+    const handleSelectChange=val=>{
+      selectData.value=val;
+    }
+
+    return {
+      query,
+      tableData,
+      pageTotal,
+      modelData,
+      editVisible,
+      form,
+      configCreate,
+      selectData,
+      handleSelectChange,
+      handleSearch,
+      handlePageChange,
+      handleDelete,
+      handleEdit,
+      saveEdit,
+      createConfig
+    };
+  },
+};
+
+
+</script>
+
+<style scoped>
+.handle-box {
+  margin-bottom: 20px;
+}
+.handle-table{
+  margin-bottem: 40px;
+}
+
+.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>