Browse Source

Merge branch 'Dev' into 'Test'

Dev

See merge request crowd-2019/crowd-test-service-front!7
薛晓波 5 years ago
parent
commit
91a76febbc
52 changed files with 9614 additions and 2476 deletions
  1. 3 1
      config/dev.env.js
  2. 3 11
      config/index.js
  3. 3 1
      config/prod.env.js
  4. 9 0
      config/proxyConfig.js
  5. 415 324
      package-lock.json
  6. 5 4
      package.json
  7. 49 5
      src/App.vue
  8. 216 9
      src/components/Home.vue
  9. 20 10
      src/components/InstitutionRank.vue
  10. 306 66
      src/components/Mine.vue
  11. 26 14
      src/components/PersonRank.vue
  12. 85 64
      src/components/Square.vue
  13. 458 0
      src/components/authen/AgencyAuthentication.vue
  14. 429 0
      src/components/authen/AgencyAuthenticationCreate.vue
  15. 0 198
      src/components/authen/Authentication.vue
  16. 77 0
      src/components/authen/AuthenticationIndex.vue
  17. 362 0
      src/components/authen/AuthenticationManage.vue
  18. 360 0
      src/components/authen/EnterpriseAuthentication.vue
  19. 332 0
      src/components/authen/EnterpriseAuthenticationCreate.vue
  20. 349 0
      src/components/authen/IndividualAuthentication.vue
  21. 307 0
      src/components/authen/IndividualAuthenticationCreate.vue
  22. 270 60
      src/components/cheat/AgencyAdd.vue
  23. 343 0
      src/components/cheat/AgencyDetail.vue
  24. 187 72
      src/components/cheat/ProjectAdd.vue
  25. 561 25
      src/components/commons/Header.vue
  26. 82 18
      src/components/commons/ProjectItem.vue
  27. 22 25
      src/components/commons/TaskItem.vue
  28. 532 343
      src/components/project/Project.vue
  29. 242 152
      src/components/project/ProjectCreate.vue
  30. 300 0
      src/components/report/ProjectReport.vue
  31. 281 0
      src/components/report/ProjectReportCreate.vue
  32. 0 297
      src/components/report/Report.vue
  33. 23 15
      src/components/report/ReportList.vue
  34. 300 0
      src/components/report/TaskReport.vue
  35. 96 78
      src/components/report/TaskReportCreate.vue
  36. 499 226
      src/components/task/Task.vue
  37. 164 124
      src/components/task/TaskCreate.vue
  38. 37 9
      src/js/api.js
  39. 44 0
      src/js/fileService.js
  40. 167 0
      src/js/generalService.js
  41. 10 23
      src/js/http.js
  42. 775 112
      src/js/index.js
  43. 65 0
      src/js/projectService.js
  44. 48 0
      src/js/reportService.js
  45. 69 0
      src/js/taskService.js
  46. 0 0
      src/js/test.js
  47. 310 0
      src/js/userService.js
  48. 176 43
      src/main.js
  49. 158 15
      src/router/index.js
  50. 11 0
      tool4deploy/Dockerfile
  51. 28 0
      tool4deploy/conf.d/nginx.conf
  52. 0 132
      tool4deploy/nginx.conf

+ 3 - 1
config/dev.env.js

@@ -3,5 +3,7 @@ const merge = require('webpack-merge')
 const prodEnv = require('./prod.env')
 
 module.exports = merge(prodEnv, {
-  NODE_ENV: '"development"'
+  NODE_ENV: '"development"',
+  API_ROOT: '"//crowd.mooctest.net"',
+  LOGIN_URL: '"http://user.mooctest.net:8081/page/login?redirect=http%3a%2f%2fcrowd.dev.mooctest.net%2f%23%2fmine"'
 })

+ 3 - 11
config/index.js

@@ -3,22 +3,14 @@
 // see http://vuejs-templates.github.io/webpack for documentation.
 
 const path = require('path')
-
+const proxyTable = require('./proxyConfig')
 module.exports = {
   dev: {
 
     // Paths
     assetsSubDirectory: 'static',
     assetsPublicPath: '/',
-    proxyTable: {// config/index.js  文件
-      '/api': {
-        target: 'http://localhost:8080/', // 设置你调用的接口域名和端口号
-        changeOrigin: true,     // 跨域
-        pathRewrite: {
-          '^/api': '/'
-        }
-      },
-    },
+    proxyTable: proxyTable,
 
     // Various Dev Server settings
     host: 'localhost', // can be overwritten by process.env.HOST
@@ -58,7 +50,7 @@ module.exports = {
     // Paths
     assetsRoot: path.resolve(__dirname, '../dist'),
     assetsSubDirectory: 'static',
-    assetsPublicPath: '/',
+    assetsPublicPath: './',
 
     /**
      * Source Maps

+ 3 - 1
config/prod.env.js

@@ -1,4 +1,6 @@
 'use strict'
 module.exports = {
-  NODE_ENV: '"production"'
+  NODE_ENV: '"production"',
+  API_ROOT: '"//crowd.mooctest.net"',
+  LOGIN_URL:'"http://user.mooctest.net:8081/page/login?redirect=http%3a%2f%2fcrowd.mooctest.net%2f%23%2fmine"'
 }

+ 9 - 0
config/proxyConfig.js

@@ -0,0 +1,9 @@
+module.exports = {
+  '/api': {
+    target: 'http://localhost:8080/', // 设置你调用的接口域名和端口号
+    changeOrigin: true,     // 跨域
+    pathRewrite: {
+      '^/api': '/'
+    }
+  },
+}

File diff suppressed because it is too large
+ 415 - 324
package-lock.json


+ 5 - 4
package.json

@@ -12,7 +12,8 @@
   },
   "dependencies": {
     "axios": "latest",
-    "element-ui": "^2.8.2",
+    "echarts": "^4.2.1",
+    "element-ui": "^2.11.0",
     "font-awesome": "^4.7.0",
     "mockjs": "^1.0.1-beta3",
     "vue": "^2.5.2",
@@ -32,7 +33,7 @@
     "babel-preset-stage-2": "^6.22.0",
     "chalk": "^2.0.1",
     "copy-webpack-plugin": "^4.0.1",
-    "css-loader": "^0.28.0",
+    "css-loader": "^3.2.0",
     "eslint": "^4.15.0",
     "eslint-config-standard": "^10.2.1",
     "eslint-friendly-formatter": "^3.0.0",
@@ -61,12 +62,12 @@
     "semver": "^5.3.0",
     "shelljs": "^0.7.6",
     "uglifyjs-webpack-plugin": "^1.1.1",
-    "url-loader": "^0.5.8",
+    "url-loader": "^2.1.0",
     "vue-loader": "^13.3.0",
     "vue-style-loader": "^3.0.1",
     "vue-template-compiler": "^2.5.2",
     "webpack": "^3.6.0",
-    "webpack-bundle-analyzer": "^2.9.0",
+    "webpack-bundle-analyzer": "^3.4.1",
     "webpack-dev-server": "^2.9.1",
     "webpack-merge": "^4.1.0"
   },

+ 49 - 5
src/App.vue

@@ -1,7 +1,9 @@
 <template>
   <div style="height:100%;width:100%;">
     <header-container/>
-    <div class="main-container"><router-view/></div>
+    <div class="main-container">
+      <router-view/>
+    </div>
     <footer-container/>
   </div>
 </template>
@@ -9,18 +11,60 @@
 <script>
 import HeaderContainer from '@/components/commons/Header'
 import FooterContainer from '@/components/commons/Footer'
+import {getCurrentUser, storageGet, storageSave} from '@/js/index'
 
 export default {
   name: 'App',
-  components:{HeaderContainer,FooterContainer},
-  name: 'App'
+  components: {HeaderContainer, FooterContainer},
+  methods: {
+    setUserInfo () {
+      // storageGet('user').then((res)=>{
+      //   if (res == null){
+      //     this.setCurrUserByHttp()
+      //   }else{
+      //     this.fullScreenLoading = false
+      //     this.isLogin = true
+      //   }
+      // }).catch((error)=>{
+      //   this.setCurrUserByHttp()
+      // })
+
+
+      // if (storageGet('user') == null) {
+      //   storageSave('rolesPermissions', {
+      //     'isRegionManager': false,
+      //     'isIndividualUser': false,
+      //     'isEnterpriseUser': false,
+      //     'isAgency': false,
+      //     'isSystemAdministrator': false
+      //   })
+      //   console.log('本地没有用户信息,开始加载用户信息')
+      //   getCurrentUser().then((res) => {
+      //     console.log(res)
+      //     storageSave('user', res)
+      //     storageSave('rolesPermissions', getRolesPermissions(res.roleList))
+      //     console.log('用户信息加载成功')
+      //   }).catch(error => {
+      //     console.log('用户信息加载失败')
+      //     if (error.status == 401) {
+      //       notify('warning', error.data)
+      //     } else {
+      //       notify('error', error.data)
+      //     }
+      //   })
+      // } else {
+      //   this.fullScreenLoading = false
+      //   this.isLogin = true
+      // }
+    },
+  }
 }
 </script>
 
 <style>
-.main-container{
+  .main-container {
     width: 100%;
     min-height: calc(100% - 70px - 64px);
     margin: 0 auto;
-}
+  }
 </style>

+ 216 - 9
src/components/Home.vue

@@ -1,16 +1,148 @@
 <template>
-  <div class="home-container">
+  <div class="home-container" v-loading="loading">
     <div class="home-banner-wrap">
       <el-carousel height="400px" :interval="10000" arrow="always">
         <el-carousel-item v-for="(img,index) in imgList" :key="index">
           <img class="banner_back banner_back_1" v-bind:src="img">
-          <router-link :to="{ name: 'ProjectCreate'}">
-            <div class="btn btn-medium btn-home-apply">申请项目</div>
+          <router-link
+            v-if="user != null && rolesPermissions != null &&( rolesPermissions.isAgency || rolesPermissions.isIndividualUser || rolesPermissions.isSystemAdministrator || rolesPermissions.isEnterpriseUser)"
+            :to="{ name: 'ProjectCreate'}">
+              <el-button class="btn-home-apply" type="primary">创建项目</el-button>
           </router-link>
         </el-carousel-item>
       </el-carousel>
     </div>
     <div class="home-body-wrap">
+      <div class="title h2">系统统计信息</div>
+      <el-row type="flex" align="middle" justify="center" style="font-size: 14px;">
+        <el-col :span="6" type="flex" align="middle" justify="center" >
+          <el-card class="box-card" shadow="hover" style="margin-right: 40px; background-color: #20A0FF;">
+            <div slot="header" class="clearfix">
+              <span style="font-size: 30px;color: white"><i class="el-icon-user"></i></span>
+            </div>
+            <el-row type="flex" align="middle" justify="center" style="font-size: 14px;">
+              <el-col :span="18" type="flex" align="middle" justify="start"><span style="font-size: 50px; color: white;">{{systemStatistics[0].value}}</span>
+              </el-col>
+              <el-col :span="20" type="flex" align="bottom" justify="end"><span> <el-link style="font-size: 16px; color: white;"
+                                                                                          type="success"
+                                                                                          :underline="false">{{systemStatistics[0].name}}</el-link></span>
+              </el-col>
+            </el-row>
+          </el-card>
+        </el-col>
+        <el-col :span="6" type="flex" align="middle" justify="center">
+          <el-card class="box-card" shadow="hover" style="margin-right: 40px;background-color: #13CE66;">
+            <div slot="header" class="clearfix">
+              <span style="font-size: 30px;color: white;"><i class="el-icon-setting"></i></span>
+            </div>
+            <el-row type="flex" align="middle" justify="center" style="font-size: 14px;">
+              <el-col :span="18" type="flex" align="middle" justify="start"><span style="font-size: 50px;color: white;">{{systemStatistics[1].value}}</span>
+              </el-col>
+              <el-col :span="20" type="flex" align="bottom" justify="end"><span> <el-link style="font-size: 16px;color: white;"
+                                                                                          type="success"
+                                                                                          :underline="false">{{systemStatistics[1].name}}</el-link></span>
+              </el-col>
+            </el-row>
+          </el-card>
+        </el-col>
+        <!--<el-col :span="4">{{project.id}}</el-col>-->
+        <el-col :span="6" type="flex" align="middle" justify="center">
+          <el-card class="box-card" shadow="hover" style="margin-right: 40px;background-color: #F7BA2A;">
+            <div slot="header" class="clearfix">
+              <span style="font-size: 30px;color: white;"><i class="el-icon-user-solid"></i></span>
+            </div>
+            <el-row type="flex" align="middle" justify="center" style="font-size: 14px;">
+              <el-col :span="18" type="flex" align="middle" justify="start"><span style="font-size: 50px;color: white;">{{systemStatistics[2].value}}</span>
+              </el-col>
+              <el-col :span="20" type="flex" align="bottom" justify="end"><span> <el-link style="font-size: 16px;color: white;"
+                                                                                          type="success"
+                                                                                          :underline="false">{{systemStatistics[2].name}}</el-link></span>
+              </el-col>
+            </el-row>
+          </el-card>
+        </el-col>
+        <el-col :span="6" type="flex" align="middle" justify="center">
+          <el-card class="box-card" shadow="hover" style="margin-right: 40px;background-color: #FF4949;">
+            <div slot="header" class="clearfix">
+              <span style="font-size: 30px;color: white;"><i class="el-icon-cpu"></i></span>
+            </div>
+            <el-row type="flex" align="middle" justify="center" style="font-size: 14px;">
+              <el-col :span="18" type="flex" align="middle" justify="start"><span style="font-size: 50px;color: white;">{{systemStatistics[3].value}}</span>
+              </el-col>
+              <el-col :span="20" type="flex" align="bottom" justify="end"><span> <el-link style="font-size: 16px;color: white;"
+                                                                                          type="success"
+                                                                                          :underline="false">{{systemStatistics[3].name}}</el-link></span>
+              </el-col>
+            </el-row>
+          </el-card>
+        </el-col>
+      </el-row>
+      <el-row type="flex" align="middle" justify="center" style="font-size: 14px; margin-top: 15px;">
+        <el-col :span="6" type="flex" align="middle" justify="center">
+          <el-card class="box-card" shadow="hover" style="margin-right: 40px;background-color: #20A0FF;">
+            <div slot="header" class="clearfix">
+              <span style="font-size: 30px;color: white;"><i class="el-icon-coin"></i></span>
+            </div>
+            <el-row type="flex" align="middle" justify="center" style="font-size: 14px;">
+              <el-col :span="18" type="flex" align="middle" justify="start"><span style="font-size: 50px;color: white;">{{systemStatistics[4].value}}</span>
+              </el-col>
+              <el-col :span="20" type="flex" align="bottom" justify="end"><span> <el-link style="font-size: 16px;color: white;"
+                                                                                          type="success"
+                                                                                          :underline="false">{{systemStatistics[4].name}}</el-link></span>
+              </el-col>
+            </el-row>
+          </el-card>
+        </el-col>
+        <el-col :span="6" type="flex" align="middle" justify="center">
+          <el-card class="box-card" shadow="hover" style="margin-right: 40px;background-color: #13CE66;color: white;">
+            <div slot="header" class="clearfix">
+              <span style="font-size: 30px;color: white;"><i class="el-icon-bank-card"></i></span>
+            </div>
+            <el-row type="flex" align="middle" justify="center" style="font-size: 14px;">
+              <el-col :span="18" type="flex" align="middle" justify="start"><span style="font-size: 50px;color: white;">{{systemStatistics[5].value}}</span>
+              </el-col>
+              <el-col :span="20" type="flex" align="bottom" justify="end"><span> <el-link style="font-size: 16px;color: white;"
+                                                                                          type="success"
+                                                                                          :underline="false">{{systemStatistics[5].name}}</el-link></span>
+              </el-col>
+            </el-row>
+          </el-card>
+        </el-col>
+        <!--<el-col :span="4">{{project.id}}</el-col>-->
+        <el-col :span="6" type="flex" align="middle" justify="center">
+          <el-card class="box-card" shadow="hover" style="margin-right: 40px;background-color: #F7BA2A;">
+            <div slot="header" class="clearfix">
+              <span style="font-size: 30px;color: white;"><i class="el-icon-notebook-1"></i></span>
+            </div>
+            <el-row type="flex" align="middle" justify="center" style="font-size: 14px;">
+              <el-col :span="18" type="flex" align="middle" justify="start"><span style="font-size: 50px;color: white;">{{systemStatistics[6].value}}</span>
+              </el-col>
+              <el-col :span="20" type="flex" align="bottom" justify="end"><span> <el-link style="font-size: 16px;color: white;"
+                                                                                          type="success"
+                                                                                          :underline="false">{{systemStatistics[6].name}}</el-link></span>
+              </el-col>
+            </el-row>
+          </el-card>
+        </el-col>
+        <el-col :span="6" type="flex" align="middle" justify="center">
+          <el-card class="box-card" shadow="hover" style="margin-right: 40px;background-color: #FF4949;">
+            <div slot="header" class="clearfix">
+              <span style="font-size: 30px;color: white;"><i class="el-icon-notebook-2"></i></span>
+            </div>
+            <el-row type="flex" align="middle" justify="center" style="font-size: 14px;">
+              <el-col :span="18" type="flex" align="middle" justify="start"><span style="font-size: 50px;color: white;">{{systemStatistics[7].value}}</span>
+              </el-col>
+              <el-col :span="20" type="flex" align="bottom" justify="end"><span> <el-link style="font-size: 16px;color: white;"
+                                                                                          type="success"
+                                                                                          :underline="false">{{systemStatistics[7].name}}</el-link></span>
+              </el-col>
+            </el-row>
+          </el-card>
+        </el-col>
+
+      </el-row>
+    </div>
+    <div class="home-body-wrap">
       <div class="home-block">
         <div class="title">
           热门任务
@@ -49,38 +181,112 @@ import PersonRank from '@/components/PersonRank'
 import Http from '@/js/http.js'
 import Apis from '@/js/api.js'
 import {notify} from '@/constants/index'
+import {defaultValue, getIndexStatisticsInfo, getRolesPermissions, storageGet} from '@/js/index'
 
 export default {
   name: 'Home',
   components: {TaskCard, InstitutionRank, PersonRank},
   data () {
     return {
+      user: null,
+      loading: false,
+      defaultValue: defaultValue,
       hotTaskList: [],
       institutionRank: [],
       personRank: [],
       imgList: [],
-
+      rolesPermissions: {},
+      statisticsData: {
+        userNum: 100,
+        agencyNum: 200,
+        deviceNum: 345,
+        projectNum: 23,
+        taskNum: 123
+      },
+        systemStatistics: [{},{},{},{},{},{},{},{}]
     }
   },
+  mounted () {
+    console.log('mine mount')
+    this.$nextTick(() => {
+      this.init()
+    })
+  },
   methods: {
+    init () {
+      // storageGet('user').then((res)=>{
+      //   if (res == null){
+      //     //notify('warning','请登录后访问')
+      //   }else{
+      //     this.user = res
+      //     this.setRolesPermissions()
+      //     this.loadData()
+      //   }
+      // }).catch((error)=>{
+      //   notify('error','用户信息获取失败')
+      // })
+      this.setUserInfo()
+      // if (this.rolesPermissions == null) {
+      //   let NewPage = '_empty' + '?time=' + new Date().getTime() / 500
+      //   this.$router.push(NewPage)
+      //   this.$router.go(-1)
+      // }
+      this.loadData()
+    },
     //加载数据
     loadData: function () {
+      this.showLoading()
       console.log('loadData')
       Http.get(Apis.PAGE.HOME_PAGE).then((res) => {
         console.log(res)
+        this.hideLoading()
         this.hotTaskList = res.hotTaskList
         this.institutionRank = res.agencyRank
         this.personRank = res.userRank
         this.imgList = res.imgList
+        this.systemStatistics = res.systemStatistics
+      }).catch((error) => {
+        this.hideLoading()
+        notify('error', '主页加载失败:' + error.data)
       })
     },
+    setUserInfo () {
+      this.user = storageGet('user')
+      this.rolesPermissions = storageGet('rolesPermissions')
+    },
+    showLoading () {
+      this.loading = true
+    },
+    hideLoading () {
+      this.loading = false
+    },
+    getStatisticsData () {
+      getIndexStatisticsInfo().then((res) => {
+        this.statisticsData = res
+      }).catch((error) => {
+        notify('error', '统计数据加载失败')
+      })
+    },
+    getStatisticsDataSuccess () {
+
+    },
+    getStatisticsDataFail () {
+
+    }
   },
   created: function () {
     //notify('info', 'info')
     //notify('success', 'success')
     //notify('error', 'error')
     //notify('warning', 'warning')
-    this.loadData()
+    //this.loadData()
+  },
+  watch: {
+    rolesPermissions (val) {
+      console.log(this.rolesPermissions)
+      console.log(val)
+      this.rolesPermissions = val
+    }
   }
 }
 </script>
@@ -94,7 +300,8 @@ export default {
       height: 100%;
     }
     .banner_back_1 {
-      float: right;
+      width: 100%;
+      //float: right;
     }
   }
 
@@ -115,7 +322,7 @@ export default {
   }
 
   .home-body-wrap {
-    padding: 40px 80px;
+    padding: 20px 80px;
   }
 
   .more-info {
@@ -126,8 +333,8 @@ export default {
 
   .btn-home-apply {
     position: absolute;
-    bottom: 10%;
-    left: 20%;
+    bottom: 15%;
+    left: 80%;
   }
 
   .home-block {

+ 20 - 10
src/components/InstitutionRank.vue

@@ -1,30 +1,40 @@
 <template>
   <div>
-    <el-table :data="tableData" :showHeader="false" border style="width: 100%">
-      <el-table-column type="index" width="50"></el-table-column>
-      <el-table-column prop="logo" width="120">
-        <template slot-scope="scope">
-          <img class="logo-img" :src="scope.row.logo"/>
+    <el-table :data="tableData" :showHeader="true" border style="width: 100%">
+      <el-table-column type="index" width="50" label="排名"></el-table-column>
+      <el-table-column prop="logo" width="120" label="机构logo">
+        <template slot-scope="scope" >
+          <img class="logo-img" :src="scope.row.logo==null?defaultValue.image:scope.row.logo"/>
         </template>
       </el-table-column>
-      <el-table-column prop="name">
-        <template slot-scope="scope"><span class="institution-name">{{scope.row.name}}</span></template>
+      <el-table-column prop="name" label="机构名称">
+        <template slot-scope="scope"><span class="institution-name" style="font-size: 12px">{{scope.row.name}}</span></template>
+      </el-table-column>
+      <el-table-column prop="name" label="金额">
+        <template slot-scope="scope">
+          <span class="institution-name" style="font-size: 12px">
+            {{scope.row.allTaskPrice}}
+          </span>
+        </template>
       </el-table-column>
     </el-table>
   </div>
 </template>
 
 <script>
+import {defaultValue} from '@/js/index'
+
 export default {
   name: 'InstitutionRank',
   props: {item: {}},
   data () {
     return {
-      tableData: this.item
+      tableData: this.item,
+      defaultValue: defaultValue
     }
   },
-  watch:{
-    item(){
+  watch: {
+    item () {
       this.tableData = this.item
     }
   }

+ 306 - 66
src/components/Mine.vue

@@ -1,70 +1,150 @@
 <template>
   <div class="mine-container">
-    <div class="mine-top-wrapper">
-      <el-row :gutter="0" style="height:100%">
-        <el-col :span="16">
-          <div class="advertise-imgs">
-            <img
-              src="http://sinastorage.com/storage.miaosha.sina.com.cn/products/201903/e496d11b3d74cf660c286fbd5ab8d0bb.png"
-            >
-          </div>
-        </el-col>
-        <el-col :span="8">
-          <div class="user-banner">
-            <p class="head">
-              <a href="javascript:;" class="login-link">
-                <img src="http://www.mooctest.net/assets/img/mooctest.png" class="user-img">
-                <span class="vertify hide"></span>
-              </a>
-            </p>
-            <div class="username_box">
-              <div class="username_icon username_"></div>
-              <span class="username">{{user.name}}</span>
-            </div>
-            <!--<p class="name">-->
-            <!--<a href="javascript:;" class="login-btn btn btn-medium btn-info">登录</a>-->
-            <!--<a-->
-            <!--href="https://login.sina.com.cn/signup/signup?entry=tech"-->
-            <!--class="register-btn btn btn-medium btn-info"-->
-            <!--target="_blank"-->
-            <!--&gt;注册</a>-->
-            <!--</p>-->
-            <p class="scores">
-              <a href="/rule/merit" target="_blank">
-                积分
-                <em class="num1">{{user.score}}</em>
-              </a>
-              <span class="line">|</span>
-              <a href="/rule/merit" target="_blank">
-                威望
-                <em class="num2">{{user.prestige}}</em>
-              </a>
-            </p>
-            <p>
-              <router-link :to="{ name: 'ProjectCreate'}">
-                <div class="btn btn-medium">申请项目</div>
-              </router-link>
-            </p>
-          </div>
-        </el-col>
-      </el-row>
-    </div>
-    <div class="mine-body">
-      <el-tabs tabPosition="top" type="card">
-        <el-tab-pane label="未完成任务">
+    <div id="myChart" style="width: 100%;height: 200px;padding-top: 40px"></div>
+    <!--<div class="mine-top-wrapper">-->
+    <!--<el-row :gutter="0" style="height:100%">-->
+    <!--<el-col :span="16">-->
+    <!--<div class="advertise-imgs">-->
+    <!--<img-->
+    <!--src="http://sinastorage.com/storage.miaosha.sina.com.cn/products/201903/e496d11b3d74cf660c286fbd5ab8d0bb.png"-->
+    <!--&gt;-->
+    <!--</div>-->
+    <!--</el-col>-->
+    <!--<el-col :span="8">-->
+    <!--<div class="user-banner">-->
+    <!--<p class="head">-->
+    <!--<a href="javascript:;" class="login-link">-->
+    <!--<img :src="user == null || user.userVO.photoUrl == null?defaultValue.image:user.userVO.photoUrl"-->
+    <!--class="user-img">-->
+    <!--<span class="vertify hide"></span>-->
+    <!--</a>-->
+    <!--</p>-->
+    <!--<div class="username_box">-->
+    <!--<div class="username_icon username_"></div>-->
+    <!--<span class="username">{{user == null?'...':user.userVO.name}}</span>-->
+    <!--</div>-->
+    <!--&lt;!&ndash;<p class="name">&ndash;&gt;-->
+    <!--&lt;!&ndash;<a href="javascript:;" class="login-btn btn btn-medium btn-info">登录</a>&ndash;&gt;-->
+    <!--&lt;!&ndash;<a&ndash;&gt;-->
+    <!--&lt;!&ndash;href="https://login.sina.com.cn/signup/signup?entry=tech"&ndash;&gt;-->
+    <!--&lt;!&ndash;class="register-btn btn btn-medium btn-info"&ndash;&gt;-->
+    <!--&lt;!&ndash;target="_blank"&ndash;&gt;-->
+    <!--&lt;!&ndash;&gt;注册</a>&ndash;&gt;-->
+    <!--&lt;!&ndash;</p>&ndash;&gt;-->
+    <!--&lt;!&ndash;<p class="scores">&ndash;&gt;-->
+    <!--&lt;!&ndash;<a href="/rule/merit" target="_blank">&ndash;&gt;-->
+    <!--&lt;!&ndash;积分&ndash;&gt;-->
+    <!--&lt;!&ndash;<em class="num1">{{user.score}}</em>&ndash;&gt;-->
+    <!--&lt;!&ndash;</a>&ndash;&gt;-->
+    <!--&lt;!&ndash;<span class="line">|</span>&ndash;&gt;-->
+    <!--&lt;!&ndash;<a href="/rule/merit" target="_blank">&ndash;&gt;-->
+    <!--&lt;!&ndash;威望&ndash;&gt;-->
+    <!--&lt;!&ndash;<em class="num2">{{user.prestige}}</em>&ndash;&gt;-->
+    <!--&lt;!&ndash;</a>&ndash;&gt;-->
+    <!--&lt;!&ndash;</p>&ndash;&gt;-->
+    <!--<p>-->
+    <!--<router-link :to="{ name: 'AuthenticationIndex'}">-->
+    <!--<div class="btn btn-medium">实名认证</div>-->
+    <!--</router-link>-->
+    <!--</p>-->
+    <!--</div>-->
+    <!--</el-col>-->
+    <!--</el-row>-->
+    <!--</div>-->
+    <div class="mine-body" style="text-align: center;">
+      <el-tabs value="myProject" @tab-click="handleTabClick" v-loading="loading" style="width: 90%;margin-left: 5%">
+        <el-tab-pane name="unFinishedTask">
+          <span slot="label">
+            <el-badge class="item" style="margin-top: 10px;margin-bottom: 25px; font-size: 16px;">未完成任务</el-badge>
+          </span>
+          <el-row v-if="unFinishedTaskList != null && unFinishedTaskList.length != 0" type="flex" align="middle"
+                  justify="center" style="font-size: 14px;">
+            <el-col :span="6">任务封面</el-col>
+            <el-col :span="5">任务名称</el-col>
+            <el-col :span="5">任务类型</el-col>
+            <el-col :span="4">任务预算</el-col>
+            <el-col :span="4">操作</el-col>
+          </el-row>
           <span v-if="unFinishedTaskList == null || unFinishedTaskList.length == 0"> 暂无任务 </span>
           <task-item v-if="unFinishedTaskList != null || unFinishedTaskList.length > 0"
-                     v-for="(item,index) in unFinishedTaskList" :key="index" :task="item"/>
+                     v-for="(item,index1) in unFinishedTaskList" :key="index1" :task="item"/>
         </el-tab-pane>
-        <el-tab-pane label="已完成任务">
+        <el-tab-pane name="finishedTask">
+          <span slot="label">
+            <el-badge class="item" style="margin-top: 10px;margin-bottom: 25px; font-size: 16px;">已完成任务</el-badge>
+          </span>
+          <el-row v-if="finishedTaskList != null && finishedTaskList.length != 0" type="flex" align="middle"
+                  justify="center" style="font-size: 14px;">
+
+            <el-col :span="6">任务封面</el-col>
+            <el-col :span="5">任务名称</el-col>
+            <el-col :span="5">任务类型</el-col>
+            <el-col :span="4">任务预算</el-col>
+            <el-col :span="4">操作</el-col>
+          </el-row>
           <span v-if="finishedTaskList == null || finishedTaskList.length == 0"> 暂无任务 </span>
           <task-item v-if="finishedTaskList != null || finishedTaskList.length > 0"
-                     v-for="(item,index) in finishedTaskList" :key="index" :task="item"/>
+                     v-for="(item,index2) in finishedTaskList" :key="index2" :task="item"/>
+        </el-tab-pane>
+
+
+        <el-tab-pane name="myProject">
+
+          <span slot="label">
+            <el-badge v-if="myProjectNoticeCount>0" :value="myProjectNoticeCount" class="item"
+                      style="height:auto;margin-top: 10px;margin-bottom: 25px; font-size: 16px;">我的项目</el-badge>
+            <el-badge v-if="myProjectNoticeCount==null || myProjectNoticeCount == 0" class="item"
+                      style="margin-top: 10px;margin-bottom: 25px; font-size: 16px;">我的项目</el-badge>
+          </span>
+          <span v-if="myProjects == null || myProjects.length == 0"> 暂无项目 </span>
+          <el-row v-if="myProjects != null && myProjects.length != 0" type="flex" align="middle" justify="center"
+                  style="font-size: 14px;">
+            <el-col :span="6" type="flex" align="middle" justify="center">项目图片</el-col>
+            <el-col :span="6" type="flex" align="middle" justify="center">项目名称</el-col>
+            <el-col :span="6" type="flex" align="middle" justify="center">项目平台</el-col>
+            <el-col :span="2" type="flex" align="middle" justify="center">项目预算</el-col>
+            <el-col :span="4" type="flex" align="middle" justify="center">操作</el-col>
+          </el-row>
+          <project-item v-if="myProjects != null || myProjects.length > 0"
+                        v-for="(item,index3) in myProjects" :key="index3" :projectItem="item"/>
+        </el-tab-pane>
+        <el-tab-pane name="handlingProject">
+          <span slot="label">
+            <el-badge v-if="processProjectNoticeCount>0" :value="processProjectNoticeCount" class="item"
+                      style="margin-top: 10px;margin-bottom: 25px; font-size: 16px;">处理中项目</el-badge>
+            <el-badge v-if="processProjectNoticeCount==null || processProjectNoticeCount==0" class="item"
+                      style="margin-top: 10px;margin-bottom: 25px; font-size: 16px;">处理中项目</el-badge>
+          </span>
+          <el-row v-if="handlingProjects != null && handlingProjects.length != 0" type="flex" align="middle"
+                  justify="center" style="font-size: 14px;">
+            <el-col :span="6">项目图片</el-col>
+            <el-col :span="6">项目名称</el-col>
+            <el-col :span="6">项目平台</el-col>
+            <el-col :span="2">项目预算</el-col>
+            <el-col :span="4">操作</el-col>
+          </el-row>
+          <span v-if="handlingProjects == null || handlingProjects.length == 0"> 暂无项目 </span>
+          <project-item v-if="handlingProjects != null || handlingProjects.length > 0"
+                        v-for="(item,index4) in handlingProjects" :key="index4" :projectItem="item"/>
         </el-tab-pane>
-        <el-tab-pane label="已申请项目">
-          <span v-if="appliedProjectList == null || appliedProjectList.length == 0"> 暂无项目 </span>
-          <project-item v-if="appliedProjectList != null || appliedProjectList.length > 0"
-                        v-for="(item,index) in appliedProjectList" :key="index" :projectItem="item"/>
+        <el-tab-pane name="acceptableProject">
+          <span slot="label">
+            <el-badge v-if="acceptableProjectNoticeCount>0" :value="acceptableProjectNoticeCount" class="item"
+                      style="margin-top: 10px;margin-bottom: 25px; font-size: 16px;">可接收项目</el-badge>
+            <el-badge v-if="acceptableProjectNoticeCount==null || acceptableProjectNoticeCount==0" class="item"
+                      style="margin-top: 10px;margin-bottom: 25px; font-size: 16px;">可接收项目</el-badge>
+          </span>
+          <el-row v-if="acceptableProjects != null && acceptableProjects.length != 0" type="flex" align="middle"
+                  justify="center" style="font-size: 14px;">
+            <el-col :span="6">项目图片</el-col>
+            <el-col :span="6">项目名称</el-col>
+            <el-col :span="6">项目平台</el-col>
+            <el-col :span="2">项目预算</el-col>
+            <el-col :span="4">操作</el-col>
+          </el-row>
+          <span v-if="acceptableProjects == null || acceptableProjects.length == 0"> 暂无项目 </span>
+          <project-item v-if="acceptableProjects != null || acceptableProjects.length > 0"
+                        v-for="(item,index) in acceptableProjects" :key="index" :projectItem="item"/>
         </el-tab-pane>
       </el-tabs>
     </div>
@@ -77,37 +157,197 @@ import ProjectItem from '@/components/commons/ProjectItem'
 import Http from '@/js/http.js'
 import Apis from '@/js/api.js'
 import {notify} from '@/constants/index'
+import {defaultValue, getRolesPermissions, storageGet} from '@/js/index'
+import echarts from 'echarts'
+
 export default {
   name: 'Mine',
   components: {TaskItem, ProjectItem},
+  watch: {
+    user (val) {
+      this.user = val
+    },
+    rolesPermissions (val) {
+      this.rolesPermissions = val
+    },
+    deep: true
+  },
   data () {
     return {
+      loading: false,
       unFinishedTaskList: [],
       finishedTaskList: [],
       appliedProjectList: [],
-      user: {}
+      myProjects: [],
+      handlingProjects: [],
+      acceptableProjects: [],
+      defaultValue: defaultValue,
+      myProjectNoticeCount: 0,
+      processProjectNoticeCount: 0,
+      acceptableProjectNoticeCount: 0,
+      rolesPermissions: {
+        isRegionManager: false,
+        isIndividualUser: false,
+        isEnterpriseUser: false,
+        isAgency: false,
+        isSystemAdministrator: false
+      },
+      user: {
+        userVO: {
+          id: '',
+          name: '',
+          photo: '',
+          roleList: []
+        }
+      }
     }
   },
+  mounted () {
+    this.$nextTick(() => {
+      this.init()
+    })
+  },
   methods: {
+    init () {
+      this.setUserInfo()
+      this.setRolesPermissions()
+      this.loadData()
+      this.setEcharts()
+      // storageGet('user').then((res)=>{
+      //   this.user = res;
+      //   this.setRolesPermissions()
+      //   this.loadData()
+      // })
+
+    },
     loadData () {
-      Http.get(Apis.PAGE.MY_CROWD_TEST_PAGE.replace('{userId}', 3), {}).then((res) => {
+      this.showLoading()
+      Http.get(Apis.PAGE.MY_CROWD_TEST_PAGE.replace('{userId}', this.user.userVO.id)).then((res) => {
+        this.hideLoading()
+        this.processProjectNoticeCount = res.processProjectNoticeCount == null ? 0 : res.processProjectNoticeCount
+        this.myProjectNoticeCount = res.myProjectNoticeCount == null ? 0 : res.myProjectNoticeCount
+        this.acceptableProjectNoticeCount = res.acceptableProjectNoticeCount == null ? 0 : res.acceptableProjectNoticeCount
         if (res.unfinishedTasks != null && res.unfinishedTasks.length > 0) {
           this.unFinishedTaskList = res.unfinishedTasks
         }
         if (res.finishedTasks != null && res.finishedTasks.length > 0) {
           this.finishedTaskList = res.finishedTasks
         }
-        if (res.crowdProjectVOList != null && res.crowdProjectVOList.length > 0) {
-          this.appliedProjectList = res.crowdProjectVOList
+        if (res.myProjects != null && res.myProjects.length > 0) {
+          this.myProjects = res.myProjects
+        }
+        if (res.handlingProjects != null && res.handlingProjects.length > 0) {
+          this.handlingProjects = res.handlingProjects
         }
-        if (res.userVO != null && res.userVO.length > 0) {
-          this.user = res.userVO
+        if (res.acceptableProjects != null && res.acceptableProjects.length > 0) {
+          this.acceptableProjects = res.acceptableProjects
         }
+        // if (res.userVO != null && res.userVO.length > 0) {
+        //   this.user = res.userVO
+        // }
+      }).catch((error) => {
+        this.hideLoading()
+        notify('error', '加载失败:' + error.data)
       })
+    },
+    setUserInfo () {
+      this.user = storageGet('user')
+    },
+    setRolesPermissions () {
+      this.rolesPermissions = storageGet('rolesPermissions')
+    },
+    setEcharts () {
+      // 基于准备好的dom,初始化echarts实例
+      let myChart = echarts.init(document.getElementById('myChart'))
+      // 绘制图表
+      var option = {
+        title: {
+          text: ''
+        },
+        tooltip: {
+          //trigger: 'axis'
+        },
+        legend: {
+          data: ['接收项目数量', '完成项目数量', '接收任务数量', '完成任务数量', '发布项目数量']
+        },
+        grid: {
+          left: '5%',
+          right: '8%',
+          bottom: '3%',
+          top: '10%',
+          containLabel: true
+        },
+        toolbox: {
+          feature: {
+            saveAsImage: {
+              title: '保存为图片',
+              name: '我的众测'
+            }
+          },
+          right: '20px'
+        },
+        xAxis: {
+          type: 'category',
+          boundaryGap: false,
+          data: ['2019年5月', '2019年6月', '2019年7月', '2019年8月', '2019年9月', '2019年10月', '2019年11月']
+        },
+        yAxis: {
+          type: 'value'
+        },
+        series: [
+          {
+            name: '接收项目数量',
+            type: 'line',
+            stack: '总量',
+            data: [2, 3, 3, 2, 4, 5, 6]
+          },
+          {
+            name: '完成项目数量',
+            type: 'line',
+            stack: '总量',
+            data: [2, 3, 3, 2, 4, 5, 6]
+          },
+          {
+            name: '接收任务数量',
+            type: 'line',
+            stack: '总量',
+            data: [22, 33, 41, 14, 55, 33, 41]
+          },
+          {
+            name: '完成任务数量',
+            type: 'line',
+            stack: '总量',
+            data: [21, 33, 31, 14, 39, 33, 32]
+          },
+          {
+            name: '发布项目数量',
+            type: 'line',
+            stack: '总量',
+            data: [2, 3, 1, 0, 1, 2, 2]
+          }
+        ]
+      }
+      myChart.setOption(option)
+    },
+    showLoading () {
+      this.loading = true
+    },
+    hideLoading () {
+      this.loading = false
+    },
+    handleTabClick (event) {
+      if (event.name == 'myProject') {
+        //this.myProjectNoticeCount = 0
+      }
+      if (event.name == 'handlingProject') {
+        //this.processProjectNoticeCount = 0
+      }
+      console.log('123')
+      console.log(event)
     }
   },
   created: function () {
-    this.loadData()
+
   }
 }
 </script>

+ 26 - 14
src/components/PersonRank.vue

@@ -1,38 +1,50 @@
 <template>
   <div>
-    <el-table :data="tableData" :showHeader="false" border style="width: 100%">
-      <el-table-column type="index" width="50"></el-table-column>
-      <el-table-column prop="logo" width="70">
+    <el-table :data="tableData" :showHeader="true" border style="width: 100%">
+      <el-table-column type="index" width="50" label="排名"></el-table-column>
+      <el-table-column prop="logo" width="70" label="头像">
         <template slot-scope="scope">
-            <img class="user-img" :src="scope.row.logo"/>
+          <img class="user-img" :src="scope.row.logo==null?defaultValue.image:scope.row.logo"/>
+        </template>
+      </el-table-column>
+      <el-table-column prop="name" label="用户名">
+        <template slot-scope="scope"><span class="institution-style" style="font-size: 12px">{{scope.row.name}}</span>
+        </template>
+      </el-table-column>
+      <el-table-column prop="number" label="金额">
+        <template slot-scope="scope">
+          <span class="institution-style" style="font-size: 12px">
+            {{scope.row.allProjectPrice}}
+          </span>
         </template>
       </el-table-column>
-      <el-table-column prop="name"><template slot-scope="scope"><span class="institution-style">{{scope.row.name}}</span></template></el-table-column>
-      <el-table-column prop="number"><template slot-scope="scope"><span class="institution-style">{{scope.row.number}}</span></template></el-table-column>
     </el-table>
   </div>
 </template>
 
 <script>
+import {defaultValue} from '@/js/index'
+
 export default {
-  name: "PersonRank",
+  name: 'PersonRank',
   props: {item: {}},
-  data() {
+  data () {
     return {
-      tableData: this.item
+      tableData: this.item,
+      defaultValue: defaultValue
     }
   },
-  watch:{
-    item(){
+  watch: {
+    item () {
       this.tableData = this.item
     }
   }
-};
+}
 </script>
 
 <style lang="less" scoped>
-.institution-style{
+  .institution-style {
     font-size: 16px;
     font-weight: 600;
-}
+  }
 </style>

+ 85 - 64
src/components/Square.vue

@@ -2,87 +2,95 @@
   <div class="square-container">
     <div class="title">全部任务</div>
 
-    <div class="square-list-container">
-      <task-item v-for="(item,index) in list" :key="index" :task="item" />
-      <div v-if="loading" class="loading">
-        <span></span>
-        <span></span>
-        <span></span>
-        <span></span>
-        <span></span>
-        <span></span>
-        <span></span>
-      </div>
-      <div v-if="nomore" class="nomore">没有更多</div>
+    <div class="square-list-container" v-loading="loading" type="flex" align="middle">
+      <el-row v-if="list != null && list.length != 0" type="flex" align="middle" justify="center"  style="font-size: 14px;">
+        <el-col :span="6">任务封面</el-col>
+        <el-col :span="5">任务名称</el-col>
+        <el-col :span="5">任务类型</el-col>
+        <el-col :span="4">任务预算</el-col>
+        <el-col :span="4">操作</el-col>
+      </el-row>
+      <task-item v-if="list!=null&&list.length>0" v-for="(item,index) in list" :key="index" :task="item"/>
+      <!--<div v-if="loading" class="loading">-->
+      <!--<span></span>-->
+      <!--<span></span>-->
+      <!--<span></span>-->
+      <!--<span></span>-->
+      <!--<span></span>-->
+      <!--<span></span>-->
+      <!--<span></span>-->
+      <!--</div>-->
+      <div v-if="list==null || list.length === 0" class="nomore">暂无任务</div>
     </div>
   </div>
 </template>
 
 <script>
-import TaskItem from "@/components/commons/TaskItem";
-import Http from '@/js/http.js';
-import Apis from '@/js/api.js';
+import TaskItem from '@/components/commons/TaskItem'
+import Http from '@/js/http.js'
+import Apis from '@/js/api.js'
 import {notify} from '@/constants/index'
+
 export default {
-  name: "Square",
-  components: { TaskItem },
-  data() {
+  name: 'Square',
+  components: {TaskItem},
+  data () {
     return {
       loading: true,
-      nomore:false,
+      nomore: false,
       list: [],
-    };
+    }
   },
-  mounted() {
-    window.addEventListener("scroll", this.throttle(this.setpage, 1000), false);
+  mounted () {
+    window.addEventListener('scroll', this.throttle(this.setpage, 1000), false)
   },
-  created() {
+  created () {
     this.loadData()
   },
   methods: {
-    throttle(func, wait, options) {
-      let context, args, result;
-      let timeout = null;
-      let previous = 0;
-      if (!options) options = {};
-      let later = function() {
-        previous = options.leading === false ? 0 : Number(new Date());
-        timeout = null;
-        result = func.apply(context, args);
-        if (!timeout) context = args = null;
-      };
+    throttle (func, wait, options) {
+      let context, args, result
+      let timeout = null
+      let previous = 0
+      if (!options) options = {}
+      let later = function () {
+        previous = options.leading === false ? 0 : Number(new Date())
+        timeout = null
+        result = func.apply(context, args)
+        if (!timeout) context = args = null
+      }
       return (..._args) => {
-        let now = Number(new Date());
-        if (!previous && options.leading === false) previous = now;
-        let remaining = wait - (now - previous);
-        context = this;
-        args = _args;
+        let now = Number(new Date())
+        if (!previous && options.leading === false) previous = now
+        let remaining = wait - (now - previous)
+        context = this
+        args = _args
         if (remaining <= 0 || remaining > wait) {
-          clearTimeout(timeout);
-          timeout = null;
-          previous = now;
-          result = func.apply(context, args);
-          if (!timeout) context = args = null;
+          clearTimeout(timeout)
+          timeout = null
+          previous = now
+          result = func.apply(context, args)
+          if (!timeout) context = args = null
         } else if (!timeout && options.trailing !== false) {
-          timeout = setTimeout(later, remaining);
+          timeout = setTimeout(later, remaining)
         }
-        return result;
-      };
+        return result
+      }
     },
-    setpage() {
-      if (this.nomore && !this.loading) return; //到达底部不再执行
+    setpage () {
+      if (this.nomore && !this.loading) return //到达底部不再执行
       var scrollTop =
-        document.documentElement.scrollTop || document.body.scrollTop;
+        document.documentElement.scrollTop || document.body.scrollTop
       //变量windowHeight是可视区的高度
       var windowHeight =
-        document.documentElement.clientHeight || document.body.clientHeight;
+        document.documentElement.clientHeight || document.body.clientHeight
       //变量scrollHeight是滚动条的总高度
       var scrollHeight =
-        document.documentElement.scrollHeight || document.body.scrollHeight;
-    //   console.log(scrollTop, windowHeight, scrollHeight);
+        document.documentElement.scrollHeight || document.body.scrollHeight
+      //   console.log(scrollTop, windowHeight, scrollHeight);
       //滚动条到底部的条件
       if (scrollTop + windowHeight + 5 >= scrollHeight) {
-        console.log("加载更多数据");
+        console.log('加载更多数据')
         // this.loading=true;
         //获取数据请求 请求结束后
         //成功设置 this.list =[...this.list,...this.list1];  this.loading=false;
@@ -91,27 +99,40 @@ export default {
         // console.log(this.list);},5000)
 
       }
-      else{this.loading=false;}
-      window.clearTimeout();
+      else {
+        this.loading = false
+      }
+      window.clearTimeout()
     },
-    loadData() {
-      console.log("loadData")
+    loadData () {
+      console.log('loadData')
+      this.showLoading()
       Http.get(Apis.PAGE.SQUARE_PAGE).then((res) => {
         this.list = res.crowdTaskVOList
+        this.hideLoading()
+      }).catch((error) => {
+        notify('error', '任务加载失败' + error.data)
       })
+    },
+    showLoading () {
+      this.loading = true
+    },
+    hideLoading () {
+      this.loading = false
     }
   }
-};
+}
 </script>
 
 <style lang="less" scoped>
-.square-container {
-  padding: 40px 80px;
-}
-.nomore{
+  .square-container {
+    padding: 40px 80px;
+  }
+
+  .nomore {
     text-align: center;
     font-size: 1.4rem;
     color: #8a8a8a;
     padding: 5px;
-}
+  }
 </style>

+ 458 - 0
src/components/authen/AgencyAuthentication.vue

@@ -0,0 +1,458 @@
+<template>
+  <div class="create-container">
+    <div class="create-body" v-loading="loading" style="width: 100%">
+      <div class="title">测评机构认证</div>
+      <el-form :model="authentication" :rules="rules" ref="authentication" label-width="12%" class="demo-report">
+        <el-form-item prop="agencyPhoto" label="机构logo">
+          <el-upload
+            v-if="isModifyMode"
+            class="avatar-uploader"
+            action=""
+            :show-file-list="false"
+            :http-request="uploadFile"
+            :before-upload="beforeFileUpload">
+            <img v-if="authentication.agencyPhoto" :src="authentication.agencyPhoto" class="avatar">
+            <i v-else class="el-icon-plus avatar-uploader-icon"></i>
+          </el-upload>
+          <span v-if="!isModifyMode">
+          <el-image
+            style="width: 100px;"
+            :src="authentication.agencyPhoto"
+            fit="scale-down"></el-image>
+        </span>
+        </el-form-item>
+        <el-form-item label="机构名称" prop="evaluationAgencyName">
+          <el-input v-if="isModifyMode" v-model="authentication.evaluationAgencyName"></el-input>
+          <span v-if="!isModifyMode">{{authentication.evaluationAgencyName}}</span>
+        </el-form-item>
+        <!--<el-form-item label="机构电话" prop="name">-->
+        <!--<el-input v-if="isModifyMode" v-model="authentication.mobile"></el-input>-->
+        <!--&lt;!&ndash;<span v-if="!isModifyMode">{{authentication.name}}</span>&ndash;&gt;-->
+        <!--</el-form-item>-->
+        <el-form-item v-if="!isModifyMode" label="认证状态" prop="name">
+          <el-tag :type="authentication.authStatus.style">{{authentication.authStatus.text}}</el-tag>
+        </el-form-item>
+        <el-form-item v-if="!isModifyMode && authentication.authStatus.text == '认证失败'" label="失败原因" prop="name">
+          <el-link v-if="authentication.explain!=null&&authentication.explain!=''" type="danger" disabled>
+            {{authentication.explain}}
+          </el-link>
+          <el-link v-if="authentication.explain==null || authentication.explain==''" type="danger" disabled>管理员未填写
+          </el-link>
+        </el-form-item>
+        <el-form-item label="对公账户" prop="bankAccount">
+          <el-input v-if="isModifyMode" v-model="authentication.bankAccount"></el-input>
+          <span v-if="!isModifyMode">{{authentication.bankAccount}}</span>
+        </el-form-item>
+        <el-form-item label="地址" prop="address">
+          <el-input v-if="isModifyMode" v-model="authentication.address"></el-input>
+          <span v-if="!isModifyMode">{{authentication.address}}</span>
+        </el-form-item>
+        <el-form-item label="测评机构能力" prop="evaluationAgencyAbilityList">
+          <el-checkbox-group v-if="isModifyMode" v-model="authentication.evaluationAgencyAbilityList">
+            <span v-for="(item,index) in serviceTypes" :key="index">
+              <el-checkbox :label="item" name="type">{{item}}&nbsp;&nbsp;&nbsp;&nbsp;</el-checkbox>
+            </span>
+          </el-checkbox-group>
+          <span v-if="!isModifyMode" v-for="(item,index) in authentication.evaluationAgencyAbilityList"
+                :key="index"><span class="badge">{{item}}</span></span>
+        </el-form-item>
+        <el-form-item label="测评机构资源" prop="evaluationAgencyResourceList">
+          <span v-if="isModifyMode" v-for="item in authentication.evaluationAgencyResourceList" :key="item.id"
+                style="width: 2000px">
+            资源类型:&nbsp;<el-select v-model="item.type" placeholder="请选择" style="width: 15%;margin-bottom: 10px"
+                                  :value="item.type">
+              <el-option
+                v-for="item in resourceTypes"
+                :key="item"
+                :label="item"
+                :value="item">
+              </el-option>
+            </el-select>
+            资源名称:&nbsp;<el-input v-model="item.name" style="width: 15%"></el-input>
+            总量:&nbsp;<el-input-number :min="0" v-model="item.totalNum" style="width: 15%"></el-input-number>
+            可用数量:&nbsp;<el-input-number :min="0" :max="item.totalNum" style="width: 15%"
+                                        v-model="item.availableNum"></el-input-number>
+            <el-button type="danger" icon="el-icon-delete" @click="removeAgencyResource(item.id)"></el-button>
+            <br/>
+          </span>
+          <el-button v-if="isModifyMode" type="primary" icon="el-icon-circle-plus" plain size="small"
+                     @click="addAgencyResource">添加资源
+          </el-button>
+          <span v-if="!isModifyMode" v-for="item in authentication.evaluationAgencyResourceList" :key="item.id">
+            资源类型:{{item.type}};&nbsp;&nbsp;资源名称:{{item.name}};&nbsp;&nbsp;资源总量:{{item.totalNum}};&nbsp;&nbsp;可用资源:{{item.availableNum}}<br/>
+          </span>
+        </el-form-item>
+
+        <el-form-item v-if="!isModifyMode">
+          <div class="btn btn-medium btn-info" @click="modifyInfo()">修改</div>
+        </el-form-item>
+        <el-form-item v-if="isModifyMode">
+          <div class="btn btn-primary btn-info" @click="updateAuthInfo()">提交</div>
+          <div class="btn btn-primary" @click="cancelModify()">取消</div>
+        </el-form-item>
+      </el-form>
+    </div>
+  </div>
+</template>
+
+<script>
+import Http from '@/js/http'
+import Apis from '@/js/api'
+import {notify} from '@/constants/index'
+import {
+  defaultValue,
+  getAllAgencyResourceTypes,
+  getAllServiceTypes,
+  getCurrentAgencyAuthInfo,
+  getCurrentAuthenInfo,
+  getCurrentUser,
+  getRolesPermissions,
+  storageGet,
+  storageSave,
+  updateAgencyAuthInfo
+} from '@/js/index'
+
+export default {
+  name: 'AgencyAuthentication',
+  data () {
+    return {
+      userId: 0,
+      user: {},
+      loading: false,
+      isModifyMode: false,
+      resourceTypes: [],
+      serviceTypes: [],
+      authentication: {
+        mobile: '',
+        evaluationAgencyName: '',
+        bankAccount: '',
+        address: '',
+        evaluationAgencyAbilityList: [],
+        evaluationAgencyResourceList: [],
+        photo: [],
+        authStatus: {},
+        agencyPhoto: defaultValue.image,
+        explain: ''
+      },
+      rules: {
+        // agencyPhoto: [
+        //   {required: true, message: '请输入机构名称', trigger: 'blur'},
+        //   { min: 3, max: 50, message: "机构名称长度在 3 到 50 个字符", trigger: "blur" }
+        // ],
+        evaluationAgencyName: [
+          {required: true, message: '请输入机构名称', trigger: 'blur'},
+          {min: 3, max: 50, message: '机构名称长度在 3 到 50 个字符', trigger: 'blur'}
+        ],
+        bankAccount: [
+          {required: true, message: '请输入银行卡账户', trigger: 'blur'},
+          {
+            validator: (rule, value, callback) => {
+              if (!this.checkNumber(value)) {
+                callback(new Error('银行卡账户输入有误'))
+              } else {
+                callback()
+              }
+            }, trigger: 'blur'
+          },
+        ],
+        address: [
+          {required: true, message: '请输入地址', trigger: 'blur'}
+        ],
+        evaluationAgencyAbilityList: [
+          {
+            type: 'array',
+            required: true,
+            message: '请至少选择一种服务类型',
+            trigger: 'change'
+          }
+        ],
+        evaluationAgencyResourceList: [
+          {
+            validator: (rule, value, callback) => {
+              var isError = false
+              if (value == null || value.length == 0) {
+                callback(new Error('机构资源不可为空'))
+              } else {
+                for (var i = 0; i < value.length; i++) {
+                  if (value[i].name == '') {
+                    isError = true
+                    break
+                  }
+                }
+              }
+              if (isError) {
+                callback(new Error('资源名称不可为空'))
+              } else {
+                callback()
+              }
+            }, trigger: 'blur'
+          },
+        ],
+        agencyPhoto: [
+          {
+            validator: (rule, value, callback) => {
+              if (value == null || value == '') {
+                callback(new Error('机构logo不可为空'))
+              } else {
+                callback()
+              }
+            }, trigger: 'blur'
+          },
+        ]
+      }
+    }
+  },
+  mounted () {
+    this.$nextTick(() => {
+      this.init()
+    })
+  },
+  methods: {
+    //初始化数据
+    init () {
+      this.setServiceTypes()
+      this.setResourceTypes()
+      this.setUserInfo()
+      this.getAuthInfo()
+    },
+    //加载数据
+    getAuthInfo () {
+      this.showLoading()
+      getCurrentAgencyAuthInfo(this.user.userVO.id, this.getAuthInfoSuccess, this.getAuthInfoFail)
+    },
+    getAuthInfoSuccess (res) {
+      this.hideLoading()
+      this.authentication.agencyPhoto = res.agencyPhoto == null ? defaultValue.image : res.agencyPhoto
+      this.authentication.evaluationAgencyName = res.evaluationAgencyName == null ? '暂未填写' : res.evaluationAgencyName
+      this.authentication.evaluationAgencyAbilityList = res.evaluationAgencyAbilityList == null ? [] : res.evaluationAgencyAbilityList
+      this.authentication.evaluationAgencyResourceList = res.evaluationAgencyResourceList == null ? [] : res.evaluationAgencyResourceList
+      this.authentication.bankAccount = res.bankAccount == null ? '暂未填写' : res.bankAccount
+      this.authentication.address = res.address == null ? '暂未填写' : res.address
+      this.authentication.authStatus = res.authStatus
+      this.authentication.explain = res.explain
+      console.log(this.authentication)
+    },
+    getAuthInfoFail (error) {
+      this.hideLoading()
+      notify('error', '加载认证信息失败:' + error.data)
+    },
+    //表单进入可编辑状态,可修改表单,不再使用
+    modifyInfo () {
+      this.isModifyMode = true
+    },
+    //提交认证信息
+    updateAuthInfo () {
+      //this.isModifyMode = false
+      this.$refs['authentication'].validate(valid => {
+        if (valid) {
+          this.showLoading()
+          const newAuthentication = {
+            userId: this.user.userVO.id,
+            evaluationAgencyName: this.authentication.evaluationAgencyName,
+            bankAccount: this.authentication.bankAccount,
+            address: this.authentication.address,
+            evaluationAgencyAbilityList: this.authentication.evaluationAgencyAbilityList,
+            evaluationAgencyResourceList: this.authentication.evaluationAgencyResourceList,
+            agencyPhoto: this.authentication.agencyPhoto,
+          }
+          //console.log(newAuthentication)
+          updateAgencyAuthInfo(this.user.userVO.id, newAuthentication, this.updateAuthInfoSuccess, this.updateAuthInfoFail)
+        } else {
+          notify('error', '表单填写错误!')
+          return false
+        }
+      })
+    },
+    updateAuthInfoSuccess (res) {
+      console.log(res)
+      this.hideLoading()
+      this.cancelModify()
+      notify('success', '认证信息修改成功,正在为您刷新用户信息')
+      getCurrentUser().then(res => {
+        storageSave('user', res)
+        this.user = res
+        this.sendBusMessage()
+        //this.rolesPermissions = getRolesPermissions(res.roleList)
+        storageSave('rolesPermissions', getRolesPermissions(res.roleList))
+        this.hideLoading()
+        notify('success', '用户信息刷新成功')
+      }).catch((error) => {
+        this.hideLoading()
+        notify('error', '重新获取用户信息失败:' + error.data)
+      })
+    },
+    updateAuthInfoFail (error) {
+      this.hideLoading()
+      notify('error', error.data)
+    },
+    //取消修改表单,表单进入不可编辑状态,不再使用
+    cancelModify () {
+      this.isModifyMode = false
+      this.getAuthInfo()
+    },
+    //上传文件时移除文件的响应函数
+    handleRemove (file, fileList) {
+      console.log(file, fileList)
+    },
+    //添加文件时的响应函数
+    handleExceed (files, fileList) {
+      this.$message.warning(
+        `当前限制选择 1 个文件,本次选择了 ${
+          files.length
+          } 个文件,共选择了 ${files.length + fileList.length} 个文件`
+      )
+    },
+    //移除文件前的响应函数
+    beforeRemove (file, fileList) {
+      //return this.$confirm(`确定移除 ${file.name}?`)
+    },
+    //文件上传前的响应函数
+    beforeFileUpload () {
+    },
+    //上传文件,此处为上传图片
+    uploadFile (param) {
+      const formData = new FormData()
+      let config = {
+        //添加请求头
+        headers: {'Content-Type': 'multipart/form-data'},
+      }
+      formData.append('file', param.file)
+      Http.upload(Apis.FILE.UPLOAD_IMAGE.replace('{userId}', this.user.userVO.id), formData, config).then((res) => {
+        console.log('上传成功')
+        this.authentication.agencyPhoto = res.data
+        console.log(res.data)
+        notify('success', '上传成功')
+        this.$refs['authentication'].validateField('agencyPhoto');
+      }).catch(error => {
+        notify('error', error.data)
+      })
+    },
+    //设置服务类型
+    setServiceTypes () {
+      getAllServiceTypes().then((res) => {
+        this.serviceTypes = res
+      }).catch((error) => {
+        notify('error', '机构能力加载失败')
+      })
+    },
+    //设置机构资源类型
+    setResourceTypes () {
+      this.resourceTypes = getAllAgencyResourceTypes()
+    },
+    //添加一项测评机构资源
+    addAgencyResource () {
+      const tmpResource = {
+        id: this.authentication.evaluationAgencyResourceList.length,
+        type: this.resourceTypes[0],
+        name: '',
+        totalNum: 0,
+        availableNum: 0,
+      }
+      this.authentication.evaluationAgencyResourceList.push(tmpResource)
+    },
+    //删除一项测评机构资源
+    removeAgencyResource (id) {
+      this.authentication.evaluationAgencyResourceList.splice(id, 1)
+      for (var i = 0; i < this.authentication.evaluationAgencyResourceList.length; i++) {
+        this.authentication.evaluationAgencyResourceList[i].id = i
+      }
+    },
+    //检测测评机构资源填写是否有效
+    checkAgencyResourceVaild () {
+      if (this.authentication.evaluationAgencyResourceList.length === 0) {
+        return true
+      }
+      for (var i = 0; i < this.authentication.evaluationAgencyResourceList.length; i++) {
+        const item = this.authentication.evaluationAgencyResourceList[i]
+        if (item.type === '') {
+          notify('error', '资源类型不能为空')
+          return false
+        }
+        if (item.name === '') {
+          notify('error', '资源名称不能为空')
+          return false
+        }
+        if (item.totalNum < item.availableNum) {
+          notify('error', '资源总数量不能低于可用数量')
+          return false
+        }
+      }
+      return true
+    },
+    //
+    setUserInfo () {
+      this.user = storageGet('user')
+    },
+    //
+    showLoading () {
+      this.loading = true
+    },
+    hideLoading () {
+      this.loading = false
+    },
+    submitSuccess () {
+
+    },
+    sendBusMessage () {
+      this.$root.$emit('user', this.user)
+    },
+    checkNumber (value) {
+      return /^\d+$/.test(value)
+    },
+  },
+  created: function () {
+  }
+}
+</script>
+
+<style scoped>
+  .el-radio {
+    margin: 10px 20px 10px 0;
+  }
+
+  .el-form-item /deep/ .el-tabs__content {
+    max-height: 120px !important;
+    overflow: auto;
+  }
+
+  .el-row {
+    margin-bottom: 10px;
+  }
+
+  .el-input {
+    width: 400px;
+  }
+
+  .avatar-uploader .el-upload {
+    border: 1px dashed #d9d9d9;
+    border-radius: 6px;
+    cursor: pointer;
+    position: relative;
+    overflow: hidden;
+  }
+
+  .avatar-uploader .el-upload:hover {
+    border-color: #409EFF;
+  }
+
+  .avatar-uploader-icon {
+    border: 1px dashed #d9d9d9;
+    border-radius: 6px;
+    font-size: 28px;
+    color: #8c939d;
+    width: 176px;
+    height: 178px;
+    line-height: 178px;
+    text-align: center;
+  }
+
+  .avatar-uploader-icon:hover {
+    border-color: #409EFF;
+  }
+
+  .avatar {
+    width: 178px;
+    height: 178px;
+    display: block;
+  }
+</style>

+ 429 - 0
src/components/authen/AgencyAuthenticationCreate.vue

@@ -0,0 +1,429 @@
+<template>
+  <div class="create-container">
+    <div class="create-body" v-loading="loading">
+      <div class="title">测评机构认证</div>
+      <el-form :model="authentication" :rules="rules" ref="authentication" label-width="12%" class="demo-report">
+        <el-form-item prop="agencyPhoto" label="机构logo">
+          <el-upload
+            class="avatar-uploader"
+            action=""
+            :show-file-list="false"
+            :http-request="uploadFile"
+            :before-upload="beforeFileUpload">
+            <img v-if="authentication.agencyPhoto" :src="authentication.agencyPhoto" class="avatar">
+            <i v-else class="el-icon-plus avatar-uploader-icon"></i>
+          </el-upload>
+          <!--<div v-if="!isModifyMode">-->
+          <!--<span v-if="authentication.photo==null">暂无文件</span>-->
+          <!--<a :href="authentication.photo" v-if="authentication.photo!=null"><i class="fa fa-file-text-o"></i>-->
+          <!--{{authentication.photo}}</a>-->
+          <!--</div>-->
+        </el-form-item>
+        <el-form-item label="机构名称" prop="evaluationAgencyName">
+          <el-input size="small" v-if="isModifyMode" v-model="authentication.evaluationAgencyName"></el-input>
+          <!--<span v-if="!isModifyMode">{{authentication.name}}</span>-->
+        </el-form-item>
+        <!--<el-form-item label="机构电话" prop="name">-->
+        <!--<el-input v-if="isModifyMode" v-model="authentication.mobile"></el-input>-->
+        <!--&lt;!&ndash;<span v-if="!isModifyMode">{{authentication.name}}</span>&ndash;&gt;-->
+        <!--</el-form-item>-->
+        <el-form-item label="银行卡账户" prop="bankAccount">
+          <el-input size="small" v-if="isModifyMode" v-model="authentication.bankAccount"></el-input>
+          <!--<span v-if="!isModifyMode">{{authentication.bankAccount}}</span>-->
+        </el-form-item>
+        <el-form-item label="地址" prop="address">
+          <el-input size="small" v-if="isModifyMode" v-model="authentication.address"></el-input>
+          <!--<span v-if="!isModifyMode">{{authentication.address}}</span>-->
+        </el-form-item>
+        <el-form-item label="测评机构能力" prop="evaluationAgencyAbilityList">
+          <el-checkbox-group v-if="isModifyMode" v-model="authentication.evaluationAgencyAbilityList">
+            <span v-for="(item,index) in serviceTypes" :key="index">
+              <el-checkbox :label="item" name="type">{{item}}&nbsp;&nbsp;&nbsp;&nbsp;</el-checkbox>
+            </span>
+          </el-checkbox-group>
+          <!--<span v-if="!isModifyMode">{{authentication.ability}}</span>-->
+        </el-form-item>
+        <el-form-item label="测评机构资源" prop="evaluationAgencyResourceList">
+          <span v-for="item in authentication.evaluationAgencyResourceList" :key="item.id">
+            资源类型:&nbsp;<el-select size="small" v-model="item.type" placeholder="请选择"
+                                  style="width: 150px;margin-bottom: 10px"
+                                  :value="item.type">
+              <el-option
+                v-for="item in resourceTypes"
+                :key="item"
+                :label="item"
+                :value="item">
+              </el-option>
+            </el-select>
+            资源名称:&nbsp;<el-input size="small" v-model="item.name" style="width: 150px"></el-input>
+            总量:&nbsp;<el-input-number size="small" :min="0" v-model="item.totalNum"></el-input-number>
+            可用数量:&nbsp;<el-input-number size="small" :min="0" :max="item.totalNum"
+                                        v-model="item.availableNum"></el-input-number>
+            <el-button size="small" type="danger" icon="el-icon-delete"
+                       @click="removeAgencyResource(item.id)"></el-button>
+            <br/>
+          </span>
+          <el-button type="primary" icon="el-icon-circle-plus" plain size="small" @click="addAgencyResource">添加资源
+          </el-button>
+          <!--<span v-if="!isModifyMode">{{authentication.resource}}</span>-->
+        </el-form-item>
+
+        <!--<el-form-item v-if="!isModifyMode">-->
+        <!--<div class="btn btn-medium btn-info" @click="modifyInfo()">修改</div>-->
+        <!--<div class="btn btn-medium" @click="cancelModify()">返回</div>-->
+        <!--</el-form-item>-->
+        <el-form-item v-if="isModifyMode">
+          <el-button type="primary" size="small" @click="submitInfo()">提交</el-button>
+          <!--<div  class="btn btn-primary btn-info" @click="submitInfo()">提交</div>-->
+          <!--<div class="btn btn-primary" @click="cancelModify()">取消</div>-->
+        </el-form-item>
+      </el-form>
+    </div>
+  </div>
+</template>
+
+<script>
+import Http from '@/js/http'
+import Apis from '@/js/api'
+import {notify} from '@/constants/index'
+import {
+  getAllAgencyResourceTypes,
+  getAllServiceTypes,
+  getCurrentUser,
+  getRolesPermissions,
+  storageGet,
+  storageSave,
+  uploadAgencyAuthenticationInfo
+} from '@/js/index'
+
+export default {
+  name: 'AgencyAuthenticationCreate',
+  data () {
+    return {
+      userId: 0,
+      user: {},
+      loading: false,
+      isModifyMode: true,
+      resourceTypes: [],
+      serviceTypes: [],
+      authentication: {
+        mobile: '',
+        evaluationAgencyName: '',
+        bankAccount: '',
+        address: '',
+        evaluationAgencyAbilityList: [],
+        evaluationAgencyResourceList: [],
+        photo: [],
+        agencyPhoto: '',
+      },
+      rules: {
+        // agencyPhoto: [
+        //   {required: true, message: '请输入机构名称', trigger: 'blur'},
+        //   { min: 3, max: 50, message: "机构名称长度在 3 到 50 个字符", trigger: "blur" }
+        // ],
+        evaluationAgencyName: [
+          {required: true, message: '请输入机构名称', trigger: 'blur'},
+          {min: 3, max: 50, message: '机构名称长度在 3 到 50 个字符', trigger: 'blur'}
+        ],
+        bankAccount: [
+          {required: true, message: '请输入银行卡账户', trigger: 'blur'},
+          {
+            validator: (rule, value, callback) => {
+              if (!this.checkNumber(value)) {
+                callback(new Error('银行卡账户输入有误'))
+              } else {
+                callback()
+              }
+            }, trigger: 'blur'
+          },
+        ],
+        address: [
+          {required: true, message: '请输入地址', trigger: 'blur'}
+        ],
+        evaluationAgencyAbilityList: [
+          {
+            type: 'array',
+            required: true,
+            message: '请至少选择一种服务类型',
+            trigger: 'change'
+          }
+        ],
+        evaluationAgencyResourceList: [
+          {
+            validator: (rule, value, callback) => {
+              var isError = false
+              if (value == null || value.length == 0) {
+                callback(new Error('机构资源不可为空'))
+              } else {
+                for (var i = 0; i < value.length; i++) {
+                  if (value[i].name == '') {
+                    isError = true
+                    break
+                  }
+                }
+              }
+              if (isError) {
+                callback(new Error('资源名称不可为空'))
+              } else {
+                callback()
+              }
+            }, trigger: 'blur'
+          },
+        ],
+        agencyPhoto: [
+          {
+            validator: (rule, value, callback) => {
+              if (value == null || value == '') {
+                callback(new Error('机构logo不可为空'))
+              } else {
+                callback()
+              }
+            }, trigger: 'blur'
+          },
+        ]
+
+      }
+    }
+  },
+  mounted () {
+    this.$nextTick(() => {
+      this.init()
+    })
+  },
+  methods: {
+    //初始化数据
+    init () {
+      this.setServiceTypes()
+      this.setResourceTypes()
+      this.setUserInfo()
+    },
+    //加载数据
+    loadData: function () {
+    },
+    //表单进入可编辑状态,可修改表单,不再使用
+    modifyInfo () {
+      this.isModifyMode = true
+    },
+    //提交认证信息
+    submitInfo () {
+      //this.isModifyMode = false
+      this.$refs['authentication'].validate(valid => {
+        if (valid) {
+          this.showLoading()
+          const newAuthentication = {
+            userId: this.user.userVO.id,
+            evaluationAgencyName: this.authentication.evaluationAgencyName,
+            bankAccount: this.authentication.bankAccount,
+            address: this.authentication.address,
+            evaluationAgencyAbilityList: this.authentication.evaluationAgencyAbilityList,
+            evaluationAgencyResourceList: this.authentication.evaluationAgencyResourceList,
+            agencyPhoto: this.authentication.agencyPhoto,
+          }
+          console.log(newAuthentication)
+          uploadAgencyAuthenticationInfo(this.user.userVO.id, newAuthentication, this.submitInfoSuccess, this.submitInfoFail)
+        } else {
+          notify('error', '表单填写错误!')
+          return false
+        }
+      })
+    },
+    submitInfoSuccess (res) {
+      console.log(res)
+      getCurrentUser().then(res => {
+        storageSave('user', res)
+        this.user = res
+        this.sendBusMessage()
+        //this.rolesPermissions = getRolesPermissions(res.roleList)
+        storageSave('rolesPermissions', getRolesPermissions(res.roleList))
+        this.hideLoading()
+        this.$alert('认证信息提交成功,将于3个工作日内审核完成', '提交成功', {
+          confirmButtonText: '确定',
+          callback: action => {
+            this.$router.push({
+              name: 'AgencyAuthentication',
+              params: {userId: this.user.userVO.id}
+            })
+          }
+        });
+      }).catch((error) => {
+        this.hideLoading()
+        notify('error', '重新获取用户信息失败:' + error.data)
+      })
+
+    },
+    submitInfoFail (error) {
+      this.hideLoading()
+      notify('error', error.data)
+    },
+    //取消修改表单,表单进入不可编辑状态,不再使用
+    cancelModify () {
+      this.isModifyMode = false
+    },
+    //上传文件时移除文件的响应函数
+    handleRemove (file, fileList) {
+      console.log(file, fileList)
+    },
+    //添加文件时的响应函数
+    handleExceed (files, fileList) {
+      this.$message.warning(
+        `当前限制选择 1 个文件,本次选择了 ${
+          files.length
+          } 个文件,共选择了 ${files.length + fileList.length} 个文件`
+      )
+    },
+    //移除文件前的响应函数
+    beforeRemove (file, fileList) {
+      //return this.$confirm(`确定移除 ${file.name}?`)
+    },
+    //文件上传前的响应函数
+    beforeFileUpload () {
+    },
+    //上传文件,此处为上传图片
+    uploadFile (param) {
+      this.showLoading()
+      const formData = new FormData()
+      let config = {
+        //添加请求头
+        headers: {'Content-Type': 'multipart/form-data'},
+      }
+      formData.append('file', param.file)
+      Http.upload(Apis.FILE.UPLOAD_IMAGE.replace('{userId}', this.user.userVO.id), formData, config).then((res) => {
+        this.hideLoading()
+        this.authentication.agencyPhoto = res.data
+        console.log(res.data)
+        notify('success', '上传成功')
+        this.$refs['authentication'].validateField('agencyPhoto');
+      }).catch(error => {
+        this.hideLoading()
+        notify('error', error.data)
+      })
+    },
+    //设置服务类型
+    setServiceTypes () {
+      getAllServiceTypes().then((res) => {
+        this.serviceTypes = res
+      }).catch((error) => {
+        notify('error', '机构能力加载失败')
+      })
+    },
+    //设置机构资源类型
+    setResourceTypes () {
+      this.resourceTypes = getAllAgencyResourceTypes()
+    },
+    //添加一项测评机构资源
+    addAgencyResource () {
+      const tmpResource = {
+        id: this.authentication.evaluationAgencyResourceList.length,
+        type: this.resourceTypes[0],
+        name: '',
+        totalNum: 0,
+        availableNum: 0,
+      }
+      this.authentication.evaluationAgencyResourceList.push(tmpResource)
+    },
+    //删除一项测评机构资源
+    removeAgencyResource (id) {
+      this.authentication.evaluationAgencyResourceList.splice(id, 1)
+      for (var i = 0; i < this.authentication.evaluationAgencyResourceList.length; i++) {
+        this.authentication.evaluationAgencyResourceList[i].id = i
+      }
+    },
+    //检测测评机构资源填写是否有效
+    checkAgencyResourceVaild () {
+      if (this.authentication.evaluationAgencyResourceList.length === 0) {
+        return true
+      }
+      for (var i = 0; i < this.authentication.evaluationAgencyResourceList.length; i++) {
+        const item = this.authentication.evaluationAgencyResourceList[i]
+        if (item.type === '') {
+          notify('error', '资源类型不能为空')
+          return false
+        }
+        if (item.name === '') {
+          notify('error', '资源名称不能为空')
+          return false
+        }
+        if (item.totalNum < item.availableNum) {
+          notify('error', '资源总数量不能低于可用数量')
+          return false
+        }
+      }
+      return true
+    },
+    //
+    setUserInfo () {
+      this.user = storageGet('user')
+    },
+    //
+    showLoading () {
+      this.loading = true
+    },
+    hideLoading () {
+      this.loading = false
+    },
+    submitSuccess () {
+
+    },
+    sendBusMessage () {
+      this.$root.$emit('user', this.user)
+    },
+    checkNumber (value) {
+      return /^\d+$/.test(value)
+    },
+  },
+  created: function () {
+  }
+}
+</script>
+
+<style scoped>
+  .el-radio {
+    margin: 10px 20px 10px 0;
+  }
+
+  .el-form-item /deep/ .el-tabs__content {
+    max-height: 120px !important;
+    overflow: auto;
+  }
+
+  .el-row {
+    margin-bottom: 10px;
+  }
+
+  .el-input {
+    width: 400px;
+  }
+
+  .avatar-uploader .el-upload {
+    border: 1px dashed #d9d9d9;
+    border-radius: 6px;
+    cursor: pointer;
+    position: relative;
+    overflow: hidden;
+  }
+
+  .avatar-uploader .el-upload:hover {
+    border-color: #409EFF;
+  }
+
+  .avatar-uploader-icon {
+    border: 1px dashed #d9d9d9;
+    border-radius: 6px;
+    font-size: 28px;
+    color: #8c939d;
+    width: 176px;
+    height: 178px;
+    line-height: 178px;
+    text-align: center;
+  }
+
+  .avatar-uploader-icon:hover {
+    border-color: #409EFF;
+  }
+
+  .avatar {
+    width: 178px;
+    height: 178px;
+    display: block;
+  }
+</style>

+ 0 - 198
src/components/authen/Authentication.vue

@@ -1,198 +0,0 @@
-<template>
-  <div class="create-container">
-    <div class="create-body">
-      <div class="title">测评机构认证</div>
-      <el-form :model="authentication" :rules="rules" ref="authentication" label-width="12%" class="demo-report">
-
-        <el-form-item label="机构名称" prop="name">
-          <el-input v-if="isModifyMode" v-model="authentication.name"></el-input>
-          <!--<span v-if="!isModifyMode">{{authentication.name}}</span>-->
-        </el-form-item>
-        <el-form-item label="机构电话" prop="name">
-          <el-input v-if="isModifyMode" v-model="authentication.mobile"></el-input>
-          <!--<span v-if="!isModifyMode">{{authentication.name}}</span>-->
-        </el-form-item>
-        <el-form-item label="银行卡账户" prop="name">
-          <el-input v-if="isModifyMode" v-model="authentication.bankAccount"></el-input>
-          <!--<span v-if="!isModifyMode">{{authentication.bankAccount}}</span>-->
-        </el-form-item>
-        <el-form-item label="地址" prop="name">
-          <el-input v-if="isModifyMode" v-model="authentication.address"></el-input>
-          <!--<span v-if="!isModifyMode">{{authentication.address}}</span>-->
-        </el-form-item>
-        <el-form-item label="测评机构能力" prop="name">
-          <el-input v-if="isModifyMode" v-model="authentication.ability"></el-input>
-          <!--<span v-if="!isModifyMode">{{authentication.ability}}</span>-->
-        </el-form-item>
-        <el-form-item label="测评机构资源" prop="name">
-          <el-input v-if="isModifyMode" v-model="authentication.resource"></el-input>
-          <!--<span v-if="!isModifyMode">{{authentication.resource}}</span>-->
-        </el-form-item>
-        <el-form-item prop="file" label="头像">
-          <el-upload
-            v-if="isModifyMode"
-            drag
-            class="upload-demo"
-            action="https://jsonplaceholder.typicode.com/posts/"
-            :on-remove="handleRemove"
-            :before-remove="beforeRemove"
-            multiple
-            :limit="1"
-            :show-file-list="false"
-            :on-exceed="handleExceed"
-            :before-upload="beforeFileUpload"
-            :http-request="uploadFile"
-            :file-list="authentication.photo"
-          >
-            <i class="el-icon-upload"></i>
-            <div class="el-upload__text">
-              将文件拖到此处,或
-              <em>点击上传</em>
-            </div>
-            <div class="el-upload__tip" slot="tip">请上传头像</div>
-          </el-upload>
-          <!--<div v-if="!isModifyMode">-->
-          <!--<span v-if="authentication.photo==null">暂无文件</span>-->
-          <!--<a :href="authentication.photo" v-if="authentication.photo!=null"><i class="fa fa-file-text-o"></i>-->
-          <!--{{authentication.photo}}</a>-->
-          <!--</div>-->
-        </el-form-item>
-
-        <!--<el-form-item v-if="!isModifyMode">-->
-        <!--<div class="btn btn-medium btn-info" @click="modifyInfo()">修改</div>-->
-        <!--<div class="btn btn-medium" @click="cancelModify()">返回</div>-->
-        <!--</el-form-item>-->
-        <el-form-item v-if="isModifyMode">
-          <div class="btn btn-primary btn-info" @click="submitInfo()">提交</div>
-          <!--<div class="btn btn-primary" @click="cancelModify()">取消</div>-->
-        </el-form-item>
-      </el-form>
-    </div>
-  </div>
-</template>
-
-<script>
-import Http from '@/js/http'
-import Apis from '@/js/api'
-import {notify} from '@/constants/index'
-
-export default {
-  name: 'Authentication',
-  data () {
-    return {
-      userId: 0,
-      isModifyMode: true,
-      authentication: {
-        mobile: '',
-        name: '',
-        bankAccount: '',
-        address: '',
-        ability: '',
-        resource: '',
-        photo: [],
-        photoUrl: '',
-      },
-      rules: {
-        // name: [
-        //   {required: true, message: '请输入报告名称', trigger: 'blur'}
-        //   // { min: 3, max: 5, message: "长度在 3 到 5 个字符", trigger: "blur" }
-        // ],
-        // abstract: [
-        //   {
-        //     required: true,
-        //     message: '请输入摘要信息',
-        //     trigger: 'change'
-        //   }
-        // ],
-        // type: [
-        //   {required: true, message: '请选择报告类型', trigger: 'change'}
-        // ],
-        // conclusion: [
-        //   {required: true, message: '请输入报告结论', trigger: 'blur'}
-        // ]
-      }
-    }
-  },
-  methods: {
-    //加载数据
-    loadData: function () {
-    },
-    modifyInfo () {
-      this.isModifyMode = true
-    },
-    submitInfo () {
-      //this.isModifyMode = false
-      const newAuthentication = {
-        mobile: this.authentication.mobile,
-        evaluationAgencyName: this.authentication.name,
-        bankAccount: this.authentication.bankAccount,
-        address: this.authentication.address,
-        abilities: this.authentication.ability,
-        resources: this.authentication.resource,
-        agencyPhoto: this.authentication.photoUrl,
-      }
-      Http.post(Apis.USER.AGENCY_AUTHENTICATION.replace('{userId}', 3), newAuthentication).then((res) => {
-        console.log(res)
-        notify('success', '测评机构成功')
-      }).catch(error => {
-        notify('error', error.data.msg)
-      })
-    },
-    cancelModify () {
-      this.isModifyMode = false
-    },
-    handleRemove (file, fileList) {
-      console.log(file, fileList)
-    },
-    handleExceed (files, fileList) {
-      this.$message.warning(
-        `当前限制选择 1 个文件,本次选择了 ${
-          files.length
-          } 个文件,共选择了 ${files.length + fileList.length} 个文件`
-      )
-    },
-    beforeRemove (file, fileList) {
-      //return this.$confirm(`确定移除 ${file.name}?`)
-    },
-    beforeFileUpload () {
-    },
-    uploadFile (param) {
-      const formData = new FormData()
-      let config = {
-        //添加请求头
-        headers: {'Content-Type': 'multipart/form-data'},
-      }
-      formData.append('file', param.file)
-      Http.upload(Apis.FILE.UPLOAD_IMAGE.replace('{userId}', 3), formData, config).then((res) => {
-        console.log('上传成功')
-        this.authentication.photoUrl = res.data
-        console.log(res.data)
-        notify('success', '上传成功')
-      }).catch(error => {
-        notify('error', error.data.msg)
-      })
-    }
-  },
-  created: function () {
-  }
-}
-</script>
-
-<style scoped>
-  .el-radio {
-    margin: 10px 20px 10px 0;
-  }
-
-  .el-form-item /deep/ .el-tabs__content {
-    max-height: 120px !important;
-    overflow: auto;
-  }
-
-  .el-row {
-    margin-bottom: 10px;
-  }
-
-  .el-input {
-    width: 400px;
-  }
-</style>

+ 77 - 0
src/components/authen/AuthenticationIndex.vue

@@ -0,0 +1,77 @@
+<template>
+  <div class="create-container">
+    <div class="create-body">
+      <div class="title">选择认证类型</div>
+      <el-row type="flex" justify="center" align="middle" style="margin-top: 100px;margin-bottom: 100px;" :gutter="50">
+        <el-col :span="6">
+          <el-card :body-style="{ padding: '0px' }" style="cursor: pointer;">
+            <i class="el-icon-user-solid image" style="color:#909399" @click="toIndividualAuthentication"></i>
+            <div style="text-align: center;font-size: 12px"><span>认证为个人用户,可以创建项目</span></div>
+            <div @click="toIndividualAuthentication" style="padding: 14px;text-align: center;font-size: 20px">
+              <span>个人认证</span>
+            </div>
+          </el-card>
+        </el-col>
+        <el-col :span="6">
+          <el-card :body-style="{ padding: '0px' }" style="cursor: pointer;">
+            <i class="el-icon-s-cooperation image" style="color:#909399" @click="toEnterpriseAuthentication"></i>
+            <div style="text-align: center;font-size: 12px"><span>认证为企业用户,可以创建项目</span></div>
+            <div @click="toEnterpriseAuthentication" style="padding: 14px;text-align: center;font-size: 20px">
+              <span>企业认证</span>
+            </div>
+          </el-card>
+        </el-col>
+        <el-col :span="6">
+          <el-card :body-style="{ padding: '0px' }" style="cursor: pointer;">
+            <i class="el-icon-s-tools image" style="color:#909399;" @click="toAgencyAuthentication"></i>
+            <div style="text-align: center;font-size: 12px"><span>认证为测评机构,可以接受任务</span></div>
+            <div @click="toAgencyAuthentication" style="padding: 14px;text-align: center;font-size: 20px">
+              <span>机构认证</span>
+            </div>
+          </el-card>
+        </el-col>
+      </el-row>
+
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'AuthenticationIndex',
+  data () {
+    return {}
+  },
+  methods: {
+    test () {
+      console.log('click')
+    },
+    toIndividualAuthentication () {
+      this.$router.push({
+        name: 'IndividualAuthenticationCreate',
+        // params: {projectId: projectId, taskId: taskId}
+      })
+    },
+    toEnterpriseAuthentication () {
+      this.$router.push({
+        name: 'EnterpriseAuthenticationCreate',
+        // params: {projectId: projectId, taskId: taskId}
+      })
+    },
+    toAgencyAuthentication () {
+      this.$router.push({
+        name: 'AgencyAuthenticationCreate',
+        // params: {projectId: projectId, taskId: taskId}
+      })
+    }
+  }
+}
+</script>
+
+<style scoped>
+  .image {
+    font-size: 150px;
+    text-align: center;
+    display: block;
+  }
+</style>

+ 362 - 0
src/components/authen/AuthenticationManage.vue

@@ -0,0 +1,362 @@
+<template>
+  <div class="create-container" v-loading="loading">
+    <div class="create-body">
+      <div class="title">审核认证信息</div>
+      <el-table
+        :data="handlingAuthList"
+        :row-class-name="rowClassName"
+        stripe
+        style="width: 100%">
+        <el-table-column prop="id" label="编号">
+          <template slot-scope="scope">
+            <span>{{scope.row.id}}</span>
+          </template>
+        </el-table-column>
+        <el-table-column prop="userInfo" label="用户信息">
+          <template slot-scope="scope">
+            <span style="cursor: pointer">
+              <el-link type="primary">{{scope.row.userName}}</el-link>
+            </span>
+          </template>
+        </el-table-column>
+        <el-table-column prop="type" label="认证类型">
+          <template slot-scope="scope">
+            <span>
+              <el-tag v-if="scope.row.type=='personal'" type="success">个人</el-tag>
+              <el-tag v-if="scope.row.type=='agency'">机构</el-tag>
+              <el-tag v-if="scope.row.type=='enterprise'" type="warning">企业</el-tag>
+            </span>
+          </template>
+        </el-table-column>
+        <el-table-column prop="detail" label="认证详情">
+          <template slot-scope="scope">
+            <el-link type="primary" @click="handleAuthDetail(scope.row.userId,scope.row.type)">认证详情</el-link>
+          </template>
+        </el-table-column>
+        <el-table-column prop="status" label="认证状态">
+          <template slot-scope="scope">
+            <span>
+              <el-tag :type="scope.row.authStatus.style">{{scope.row.authStatus.text}}</el-tag>
+            </span>
+          </template>
+        </el-table-column>
+        <el-table-column prop="date" label="申请时间" width="180">
+          <template slot-scope="scope">
+            <span>{{reformTime(new Date(scope.row.applytime))}}</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="操作" width="180">
+          <template slot-scope="scope">
+            <el-button type="primary" size="mini" @click="handleAuthenticationPass(scope.row.userId,scope.row.type)">
+              通过
+            </el-button>
+            <el-button type="danger" size="mini" @click="handleAuthenticationReject(scope.row.userId,scope.row.type)">
+              驳回
+            </el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      <el-dialog title="认证详情" :visible.sync="showDialog" center width="40%">
+        <el-form :model="authInfoDetail" label-width="120px" label-position="right">
+          <el-form-item label="类型:">
+            <span>
+              <el-tag v-if="authInfoDetail.type=='personal'" type="success">个人</el-tag>
+              <el-tag v-if="authInfoDetail.type=='agency'">机构</el-tag>
+              <el-tag v-if="authInfoDetail.type=='enterprise'" type="warning">企业</el-tag>
+            </span>
+          </el-form-item>
+          <el-form-item label="姓名:" v-if="authInfoDetail.type == 'personal'">
+            <span>{{authInfoDetail.realName}}</span>
+          </el-form-item>
+          <el-form-item label="身份证号:" v-if="authInfoDetail.type == 'personal'">
+            <span>{{authInfoDetail.IDCard}}</span>
+          </el-form-item>
+          <el-form-item label="身份证照:" v-if="authInfoDetail.type == 'personal'">
+            <span>
+              <el-image
+                style="width: 100px;"
+                :src="authInfoDetail.IDCardPhoto"
+                fit="scale-down"></el-image>
+            </span>
+          </el-form-item>
+          <el-form-item label="银行账号:">
+            <span>{{authInfoDetail.bankAccount}}</span>
+          </el-form-item>
+          <el-form-item label="地址:">
+            <span>{{authInfoDetail.address}}</span>
+          </el-form-item>
+          <el-form-item label="申请时间:">
+            <span>{{reformTime(new Date(authInfoDetail.applyTime))}}</span>
+          </el-form-item>
+
+          <el-form-item label="企业名称:" v-if="authInfoDetail.type == 'enterprise'">
+            <span>{{authInfoDetail.enterpriseName}}</span>
+          </el-form-item>
+          <el-form-item label="法人姓名:" v-if="authInfoDetail.type == 'enterprise'">
+            <span>{{authInfoDetail.legalPersonName}}</span>
+          </el-form-item>
+          <el-form-item label="营业执照:" v-if="authInfoDetail.type == 'enterprise'">
+            <span>
+              <el-image
+                style="width: 100px;"
+                :src="authInfoDetail.businessLicensePhoto"
+                fit="scale-down"></el-image>
+            </span>
+          </el-form-item>
+          <el-form-item label="统一社会信用代码:" v-if="authInfoDetail.type == 'enterprise'">
+            <span>{{authInfoDetail.unifiedSocialCreditCode}}</span>
+          </el-form-item>
+
+          <el-form-item label="机构名称:" v-if="authInfoDetail.type == 'agency'">
+            <span>{{authInfoDetail.evaluationAgencyName}}</span>
+          </el-form-item>
+          <el-form-item label="机构能力:" v-if="authInfoDetail.type == 'agency'">
+            <span>{{authInfoDetail.evaluationAgencyAbilityList}}</span>
+          </el-form-item>
+          <el-form-item label="机构资源:" v-if="authInfoDetail.type == 'agency'">
+            <span>{{authInfoDetail.evaluationAgencyResourceList}}</span>
+          </el-form-item>
+          <el-form-item label="机构Logo:" v-if="authInfoDetail.type == 'agency'">
+            <span>
+              <el-image
+                style="width: 100px;"
+                :src="authInfoDetail.agencyPhoto"
+                fit="scale-down"></el-image>
+            </span>
+          </el-form-item>
+        </el-form>
+        <div slot="footer" class="dialog-footer">
+          <el-button type="info" size="mini" @click="hideAuthDialog()">返回</el-button>
+
+          <el-button type="danger" size="mini"
+                     @click="handleAuthenticationReject(authInfoDetail.userId,authInfoDetail.type)">驳回
+          </el-button>
+
+          <el-button type="primary" size="mini"
+                     @click="handleAuthenticationPass(authInfoDetail.userId,authInfoDetail.type)">通过
+          </el-button>
+        </div>
+      </el-dialog>
+      <!--<el-pagination-->
+      <!--:page-size="20"-->
+      <!--hide-on-single-page-->
+      <!--:pager-count="5"-->
+      <!--:current-page.sync="currentPage"-->
+      <!--layout="prev, pager, next"-->
+      <!--@current-change="handleCurrentChange"-->
+      <!--:total="100">-->
+      <!--</el-pagination>-->
+    </div>
+  </div>
+</template>
+
+<script>
+    import {
+        checkPassAuth,
+        checkRejectAuth,
+        getAllHandledAuthInfo,
+        getAllHandlingAuthInfo,
+        getCurrentAgencyAuthInfo,
+        getCurrentEnterpriseAuthInfo,
+        getCurrentIndividualAuthenInfo,
+        getFormalTimeFromDate
+    } from '@/js/index'
+    import {notify} from '@/constants/index'
+
+    export default {
+        name: 'AuthenticationManage',
+        data () {
+            return {
+                currentPage: 1,
+                loading: false,
+                showDialog: false,
+                authenticationStatusUntreated: '审核中',
+                authenticationStatusPass: '审核通过',
+                authenticationStatusReject: '审核未通过',
+                handlingAuthList: [],
+                handledAuthList: [],
+                authInfoDetail: {
+                    userId: '',
+                    type: '',
+                    realName: '',
+                    IDCard: '',
+                    IDCardPhoto: '',
+                    bankAccount: '',
+                    address: '',
+                    applyTime: '',
+
+                    enterpriseName: '',
+                    legalPersonName: '',
+                    businessLicensePhoto: '',
+                    unifiedSocialCreditCode: '',
+
+                    evaluationAgencyName: '',
+                    evaluationAgencyAbilityList: [],
+                    evaluationAgencyResourceList: [],
+                    agencyPhoto: '',
+                    updateTime: '',
+                    expireTime: ''
+                }
+            }
+        },
+        mounted () {
+            this.$nextTick(() => {
+                this.init()
+            })
+        },
+        methods: {
+            init () {
+                this.getHandlingAuthList()
+                this.getHandledAuthList()
+            },
+            //获取所有未认证信息
+            getHandlingAuthList () {
+                this.showLoading()
+                getAllHandlingAuthInfo(this.getHandlingAuthListSuccess, this.getHandlingAuthListFail)
+            },
+            //获取所有已认证信息
+            getHandlingAuthListSuccess (res) {
+                this.handlingAuthList = res
+                this.hideLoading()
+            },
+            getHandlingAuthListFail (error) {
+                this.hideLoading()
+                notify('error', '获取认证信息失败:' + error.data)
+            },
+            getHandledAuthList () {
+                this.showLoading()
+                getAllHandledAuthInfo(this.getHandledAuthListSuccess, this.getHandledAuthListFail)
+            },
+            getHandledAuthListSuccess (res) {
+                this.handledAuthList = res
+                this.hideLoading()
+            },
+            getHandledAuthListFail (error) {
+                this.hideLoading()
+                notify('error', '获取已认证信息失败:' + error.data)
+            },
+            handleCurrentChange (param) {
+                console.log(param)
+            },
+            handleAuthenticationPass (userId, type) {
+                this.showLoading()
+                checkPassAuth(type, userId, this.handleAuthenticationPassSuccess, this.handleAuthenticationPassFail)
+                // item.status = this.authenticationStatusPass
+                // console.log('通过')
+            },
+            handleAuthenticationPassSuccess (res) {
+                this.hideLoading()
+                this.getHandlingAuthList()
+                console.log(res)
+            },
+            handleAuthenticationPassFail (error) {
+                this.hideLoading()
+                console.log(error)
+                notify('error', '通过失败:' + error.data)
+            },
+            handleAuthenticationReject (userId, type) {
+                this.$prompt('请输入驳回本申请的原因', '提示', {
+                    confirmButtonText: '确定',
+                    cancelButtonText: '取消',
+                }).then((event) => {
+                    const explain = event.value
+                    console.log(explain)
+                    this.showLoading()
+                    const data = {
+                        explain: event.value
+                    }
+                    checkRejectAuth(type, userId, data, this.handleAuthenticationRejectSuccess, this.handleAuthenticationRejectFail)
+                }).catch(() => {
+                })
+            },
+            handleAuthenticationRejectSuccess (res) {
+                this.hideLoading()
+                this.getHandlingAuthList()
+                notify('success', '驳回成功')
+                console.log(res)
+            },
+            handleAuthenticationRejectFail (error) {
+                this.hideLoading()
+                console.log(error)
+                notify('error', '拒绝失败:' + error.data)
+            },
+            handleAuthDetail (userId, type) {
+                this.authInfoDetail.userId = userId
+                this.authInfoDetail.type = type
+                this.getAuthInfo(userId, type)
+            },
+            showLoading () {
+                this.loading = true
+            },
+            hideLoading () {
+                this.loading = false
+            },
+            reformTime (date) {
+                return getFormalTimeFromDate(date)
+            },
+            rowClassName ({row, rowIndex}) {
+                //把每一行的索引放进row.id
+                row.id = rowIndex + 1
+            },
+            showAuthDialog () {
+                this.showDialog = true
+            },
+            hideAuthDialog () {
+                this.showDialog = false
+            },
+            getAuthInfo (userId, type) {
+                this.showLoading()
+                if (type == 'personal') {
+                    getCurrentIndividualAuthenInfo(userId, this.getCurrentIndividualAuthenInfoSuccess, this.getCurrentIndividualAuthenInfoFail)
+                } else if (type == 'enterprise') {
+                    getCurrentEnterpriseAuthInfo(userId, this.getCurrentEnterpriseAuthInfoSuccess, this.getCurrentEnterpriseAuthInfoFail)
+                } else if (type == 'agency') {
+                    getCurrentAgencyAuthInfo(userId, this.getCurrentAgencyAuthInfoSuccess, this.getCurrentAgencyAuthInfoFail)
+                }
+            },
+            getCurrentIndividualAuthenInfoSuccess (res) {
+                this.hideLoading()
+                console.log(res)
+                this.authInfoDetail.realName = res.realName
+                this.authInfoDetail.IDCard = res.idcard
+                this.authInfoDetail.IDCardPhoto = res.idcardPhoto
+                this.authInfoDetail.bankAccount = res.bankAccount
+                this.authInfoDetail.address = res.address
+                this.authInfoDetail.applyTime = res.applyTime
+                this.showAuthDialog()
+                console.log(res)
+
+            },
+            getCurrentIndividualAuthenInfoFail (error) {
+                this.hideLoading()
+                notify('error', '获取个人认证信息出错:' + error.data)
+            },
+            getCurrentEnterpriseAuthInfoSuccess () {
+                this.hideLoading()
+                this.authInfoDetail.enterpriseName = res.enterpriseName
+                this.authInfoDetail.legalPersonName = res.legalPersonName
+                this.authInfoDetail.businessLicensePhoto = res.businessLicensePhoto
+            },
+            getCurrentEnterpriseAuthInfoFail () {
+                this.hideLoading()
+                notify('error', '获取企业认证信息出错:' + error.data)
+            },
+            getCurrentAgencyAuthInfoSuccess () {
+                this.hideLoading()
+                this.authInfoDetail.evaluationAgencyName = res.evaluationAgencyName
+                this.authInfoDetail.evaluationAgencyAbilityList = res.evaluationAgencyAbilityList
+                this.authInfoDetail.evaluationAgencyResourceList = res.evaluationAgencyResourceList
+                this.authInfoDetail.agencyPhoto = res.agencyPhoto
+                this.authInfoDetail.updateTime = res.updateTime
+            },
+            getCurrentAgencyAuthInfoFail () {
+                this.hideLoading()
+                notify('error', '获取机构认证信息出错:' + error.data)
+            }
+        }
+    }
+</script>
+
+<style scoped>
+
+</style>

+ 360 - 0
src/components/authen/EnterpriseAuthentication.vue

@@ -0,0 +1,360 @@
+<template>
+  <div class="create-container">
+    <div class="create-body" v-loading="loading">
+      <div class="title">企业信息认证</div>
+      <el-form :model="authentication" :rules="rules" ref="authentication" label-width="15%" class="demo-report">
+        <el-form-item label="公司名" prop="enterpriseName">
+          <el-input v-if="isModifyMode" v-model="authentication.enterpriseName"></el-input>
+          <span v-if="!isModifyMode">{{authentication.enterpriseName}}</span>
+        </el-form-item>
+        <el-form-item label="公司营业执照" prop="businessLicensePhoto">
+          <el-upload
+            v-if="isModifyMode"
+            class="avatar-uploader"
+            action="https://jsonplaceholder.typicode.com/posts/"
+            :show-file-list="false"
+            :http-request="uploadFile"
+            :before-upload="beforeFileUpload">
+            <img v-if="authentication.businessLicensePhoto" :src="authentication.businessLicensePhoto" class="avatar">
+            <i v-else class="el-icon-plus avatar-uploader-icon"></i>
+          </el-upload>
+          <span v-if="!isModifyMode">
+          <el-image
+            style="width: 100px;"
+            :src="authentication.businessLicensePhoto"
+            fit="scale-down"></el-image>
+        </span>
+          <!--<div v-if="!isModifyMode">-->
+          <!--<span v-if="authentication.photo==null">暂无文件</span>-->
+          <!--<a :href="authentication.photo" v-if="authentication.photo!=null"><i class="fa fa-file-text-o"></i>-->
+          <!--{{authentication.photo}}</a>-->
+          <!--</div>-->
+        </el-form-item>
+        <el-form-item v-if="!isModifyMode" label="认证状态" prop="name">
+          <el-tag :type="authentication.authStatus.style">{{authentication.authStatus.text}}</el-tag>
+        </el-form-item>
+        <el-form-item v-if="!isModifyMode && authentication.authStatus.text == '认证失败'" label="失败原因" prop="name">
+          <el-link v-if="authentication.explain!=null&&authentication.explain!=''" type="danger" disabled>
+            {{authentication.explain}}
+          </el-link>
+          <el-link v-if="authentication.explain==null || authentication.explain==''" type="danger" disabled>管理员未填写
+          </el-link>
+        </el-form-item>
+        <el-form-item label="公司法人姓名" prop="legalPersonName">
+          <el-input v-if="isModifyMode" v-model="authentication.legalPersonName"></el-input>
+          <span v-if="!isModifyMode">{{authentication.legalPersonName}}</span>
+        </el-form-item>
+        <el-form-item label="对公账户" prop="bankAccount">
+          <el-input v-if="isModifyMode" v-model="authentication.bankAccount"></el-input>
+          <span v-if="!isModifyMode">{{authentication.bankAccount}}</span>
+        </el-form-item>
+        <el-form-item label="统一社会信用代码" prop="unifiedSocialCreditCode">
+          <el-input v-if="isModifyMode" v-model="authentication.unifiedSocialCreditCode"></el-input>
+          <span v-if="!isModifyMode">{{authentication.unifiedSocialCreditCode}}</span>
+        </el-form-item>
+        <el-form-item label="公司地址" prop="address">
+          <el-input v-if="isModifyMode" v-model="authentication.address"></el-input>
+          <span v-if="!isModifyMode">{{authentication.address}}</span>
+        </el-form-item>
+
+        <el-form-item v-if="!isModifyMode">
+          <div class="btn btn-medium btn-info" @click="modifyInfo()">修改</div>
+        </el-form-item>
+        <el-form-item v-if="isModifyMode">
+          <div class="btn btn-primary btn-info" @click="updateAuthInfo()">提交</div>
+          <div class="btn btn-primary" @click="cancelModify()">取消</div>
+        </el-form-item>
+      </el-form>
+    </div>
+  </div>
+</template>
+
+<script>
+import Http from '@/js/http'
+import Apis from '@/js/api'
+import {notify} from '@/constants/index'
+import {
+  defaultValue,
+  getCurrentEnterpriseAuthInfo,
+  getCurrentUser,
+  getRolesPermissions,
+  storageGet,
+  storageSave,
+  updateEnterpriseAuthInfo
+} from '@/js/index'
+
+export default {
+  name: 'EnterpriseAuthentication',
+  data () {
+    return {
+      userId: 0,
+      user: {},
+      isModifyMode: false,
+      loading: false,
+      authentication: {
+        enterpriseName: '',
+        legalPersonName: '',
+        bankAccount: '',
+        businessLicensePhoto: defaultValue.image,
+        unifiedSocialCreditCode: '',
+        address: '',
+        authStatus: {text:"审核中", style:"warning"},
+        explain: ''
+      },
+        rules: {
+            enterpriseName: [
+                {required: true, message: '请输入公司名称', trigger: 'blur'},
+                {min: 3, max: 50, message: '机构名称长度在 3 到 50 个字符', trigger: 'blur'}
+            ],
+            businessLicensePhoto: [
+                {
+                    validator: (rule, value, callback) => {
+                        if (value == null || value == '') {
+                            callback(new Error('公司营业执照不能为空'))
+                        } else {
+                            callback()
+                        }
+                    },
+                    trigger: 'blur'
+                },
+            ],
+            legalPersonName: [
+                {required: true, message: '请输入公司法人姓名', trigger: 'blur'}
+            ],
+            bankAccount: [
+                {required: true, message: '请输入对公账户', trigger: 'blur'},
+                {
+                    validator: (rule, value, callback) => {
+                        if (!this.checkNumber(value)) {
+                            callback(new Error('对公账户输入有误'))
+                        } else {
+                            callback()
+                        }
+                    }, trigger: 'blur'
+                },
+            ],
+            unifiedSocialCreditCode: [
+                {required: true, message: '请输入统一社会信用代码', trigger: 'blur'},
+                {
+                    validator: (rule, value, callback) => {
+                        if (!this.checkNumberAndWord(value)) {
+                            callback(new Error('统一社会信用代码输入有误'))
+                        } else {
+                            callback()
+                        }
+                    }, trigger: 'blur'
+                },
+            ],
+            address: [
+                {required: true, message: '请输入公司地址', trigger: 'blur'}
+            ]
+        }
+    }
+  },
+  mounted () {
+    this.$nextTick(() => {
+      this.init()
+    })
+  },
+  methods: {
+    //初始化数据
+    init () {
+      this.setUserInfo()
+      this.getAuthInfo()
+    },
+    //加载数据
+    getAuthInfo () {
+      this.showLoading()
+      getCurrentEnterpriseAuthInfo(this.user.userVO.id, this.getAuthInfoSuccess, this.getAuthInfoFail)
+    },
+    getAuthInfoSuccess (res) {
+        this.hideLoading()
+      this.authentication.enterpriseName = res.enterpriseName == null ? '暂未填写' : res.enterpriseName
+      this.authentication.legalPersonName = res.legalPersonName == null ? '暂未填写' : res.legalPersonName
+      this.authentication.businessLicensePhoto = res.businessLicensePhoto == null ? defaultValue.image : res.businessLicensePhoto
+      this.authentication.unifiedSocialCreditCode = res.unifiedSocialCreditCode == null ? '暂未填写' : res.unifiedSocialCreditCode
+      this.authentication.bankAccount = res.bankAccount == null ? '暂未填写' : res.bankAccount
+      this.authentication.address = res.address == null ? '暂未填写' : res.address
+      this.authentication.authStatus = res.authStatus
+      this.authentication.explain = res.explain
+      console.log(this.authentication)
+    },
+    getAuthInfoFail (error) {
+      this.hideLoading()
+      notify('error', '加载认证信息失败:' + error.data)
+    },
+    //表单进入可编辑状态,可修改表单,不再使用
+    modifyInfo () {
+      this.isModifyMode = true
+    },
+    //提交认证信息
+    updateAuthInfo () {
+      //this.isModifyMode = false
+      this.$refs['authentication'].validate(valid => {
+          if (valid) {
+              this.showLoading()
+              const newAuthentication = {
+                  userId: this.user.userVO.id,
+                  enterpriseName: this.authentication.enterpriseName,
+                  legalPersonName: this.authentication.legalPersonName,
+                  businessLicensePhoto: this.authentication.businessLicensePhoto,
+                  unifiedSocialCreditCode: this.authentication.unifiedSocialCreditCode,
+                  bankAccount: this.authentication.bankAccount,
+                  address: this.authentication.address,
+              }
+              updateEnterpriseAuthInfo(this.user.userVO.id, newAuthentication, this.updateAuthInfoSuccess, this.updateAuthInfoFail)
+          } else {
+              notify('error', '表单填写错误!')
+              return false
+          }
+      })
+
+    },
+    updateAuthInfoSuccess (res) {
+      this.hideLoading()
+      this.cancelModify()
+      console.log(res)
+      this.authentication.enterpriseName = res.enterpriseName == null ? '暂未填写' : res.enterpriseName
+      this.authentication.legalPersonName = res.legalPersonName == null ? '暂未填写' : res.legalPersonName
+      this.authentication.businessLicensePhoto = res.businessLicensePhoto == null ? defaultValue.image : res.businessLicensePhoto
+      this.authentication.unifiedSocialCreditCode = res.unifiedSocialCreditCode == null ? '暂未填写' : res.unifiedSocialCreditCode
+      this.authentication.bankAccount = res.bankAccount == null ? '暂未填写' : res.bankAccount
+      this.authentication.address = res.address == null ? '暂未填写' : res.address
+      notify('success', '认证信息修改成功,正在为您刷新用户信息')
+      getCurrentUser().then(res => {
+        storageSave('user', res)
+        this.user = res
+        this.sendBusMessage()
+        //this.rolesPermissions = getRolesPermissions(res.roleList)
+        storageSave('rolesPermissions', getRolesPermissions(res.roleList))
+        this.hideLoading()
+        notify('success', '用户信息刷新成功')
+      }).catch((error) => {
+        this.hideLoading()
+        notify('error', '重新获取用户信息失败:' + error.data)
+      })
+    },
+    updateAuthInfoFail (error) {
+      this.hideLoading()
+      notify('error', error.data)
+    },
+    //取消修改表单,表单进入不可编辑状态,不再使用
+    cancelModify () {
+      this.isModifyMode = false
+    },
+    //上传文件时移除文件的响应函数
+    handleRemove (file, fileList) {
+      console.log(file, fileList)
+    },
+    //添加文件时的响应函数
+    handleExceed (files, fileList) {
+      this.$message.warning(
+        `当前限制选择 1 个文件,本次选择了 ${
+          files.length
+          } 个文件,共选择了 ${files.length + fileList.length} 个文件`
+      )
+    },
+    //移除文件前的响应函数
+    beforeRemove (file, fileList) {
+      //return this.$confirm(`确定移除 ${file.name}?`)
+    },
+    //文件上传前的响应函数
+    beforeFileUpload () {
+    },
+    //上传文件,此处为上传图片
+    uploadFile (param) {
+      this.showLoading();
+      const formData = new FormData()
+      let config = {
+        //添加请求头
+        headers: {'Content-Type': 'multipart/form-data'},
+      }
+      formData.append('file', param.file)
+      Http.upload(Apis.FILE.UPLOAD_IMAGE.replace('{userId}', this.user.userVO.id), formData, config).then((res) => {
+        this.hideLoading();
+        console.log('上传成功')
+        this.authentication.businessLicensePhoto = res.data
+        console.log(res.data)
+        notify('success', '上传成功')
+      }).catch(error => {
+        this.hideLoading();
+        notify('error', error.data)
+      })
+    },
+    //
+    setUserInfo () {
+      this.user = storageGet('user')
+    },
+    //测试用函数
+    test () {
+
+    },
+    showLoading () {
+      this.loading = true
+    },
+    hideLoading () {
+      this.loading = false
+    },
+    sendBusMessage () {
+      this.$root.$emit('user', this.user)
+    },
+    checkNumber(value){
+        return /^\d+$/.test(value);
+    },
+    checkNumberAndWord(value){
+        return /^[^_IOZSVa-z\W]{2}\d{6}[^_IOZSVa-z\W]{10}$/g.test(value) || /^[A-Za-z0-9]\w{14}$/g.test(value);
+    }
+  },
+}
+</script>
+<style scoped>
+  .el-radio {
+    margin: 10px 20px 10px 0;
+  }
+
+  .el-form-item /deep/ .el-tabs__content {
+    max-height: 120px !important;
+    overflow: auto;
+  }
+
+  .el-row {
+    margin-bottom: 10px;
+  }
+
+  .el-input {
+    width: 400px;
+  }
+
+  .avatar-uploader .el-upload {
+    border: 1px dashed #d9d9d9;
+    border-radius: 6px;
+    cursor: pointer;
+    position: relative;
+    overflow: hidden;
+  }
+
+  .avatar-uploader .el-upload:hover {
+    border-color: #409EFF;
+  }
+
+  .avatar-uploader-icon {
+    border: 1px dashed #d9d9d9;
+    border-radius: 6px;
+    font-size: 28px;
+    color: #8c939d;
+    width: 176px;
+    height: 178px;
+    line-height: 178px;
+    text-align: center;
+  }
+
+  .avatar-uploader-icon:hover {
+    border-color: #409EFF;
+  }
+
+  .avatar {
+    width: 178px;
+    height: 178px;
+    display: block;
+  }
+</style>

+ 332 - 0
src/components/authen/EnterpriseAuthenticationCreate.vue

@@ -0,0 +1,332 @@
+<template>
+  <div class="create-container" v-loading="loading">
+    <div class="create-body">
+      <div class="title">企业信息认证</div>
+      <el-form :model="authentication" :rules="rules" ref="authentication" label-width="15%" class="demo-report">
+        <el-form-item label="公司名" prop="enterpriseName">
+          <el-input size="small" v-if="isModifyMode" v-model="authentication.enterpriseName"></el-input>
+          <!--<span v-if="!isModifyMode">{{authentication.name}}</span>-->
+        </el-form-item>
+        <el-form-item label="公司营业执照" prop="businessLicensePhoto">
+          <el-upload
+            class="avatar-uploader"
+            action="https://jsonplaceholder.typicode.com/posts/"
+            :show-file-list="false"
+            :http-request="uploadFile"
+            :before-upload="beforeFileUpload">
+            <img v-if="authentication.businessLicensePhoto" :src="authentication.businessLicensePhoto" class="avatar">
+            <i v-else class="el-icon-plus avatar-uploader-icon"></i>
+          </el-upload>
+          <!--<div v-if="!isModifyMode">-->
+          <!--<span v-if="authentication.photo==null">暂无文件</span>-->
+          <!--<a :href="authentication.photo" v-if="authentication.photo!=null"><i class="fa fa-file-text-o"></i>-->
+          <!--{{authentication.photo}}</a>-->
+          <!--</div>-->
+        </el-form-item>
+        <el-form-item label="公司法人姓名" prop="legalPersonName">
+          <el-input size="small" v-if="isModifyMode" v-model="authentication.legalPersonName"></el-input>
+          <!--<span v-if="!isModifyMode">{{authentication.name}}</span>-->
+        </el-form-item>
+        <el-form-item label="对公账户" prop="bankAccount">
+          <el-input size="small" v-if="isModifyMode" v-model="authentication.bankAccount"></el-input>
+          <!--<span v-if="!isModifyMode">{{authentication.name}}</span>-->
+        </el-form-item>
+        <el-form-item label="统一社会信用代码" prop="unifiedSocialCreditCode">
+          <el-input size="small" v-if="isModifyMode" v-model="authentication.unifiedSocialCreditCode"></el-input>
+          <!--<span v-if="!isModifyMode">{{authentication.bankAccount}}</span>-->
+        </el-form-item>
+        <el-form-item label="公司地址" prop="address">
+          <el-input size="small" v-if="isModifyMode" v-model="authentication.address"></el-input>
+          <!--<span v-if="!isModifyMode">{{authentication.address}}</span>-->
+        </el-form-item>
+
+        <!--<el-form-item v-if="!isModifyMode">-->
+        <!--<div class="btn btn-medium btn-info" @click="modifyInfo()">修改</div>-->
+        <!--<div class="btn btn-medium" @click="cancelModify()">返回</div>-->
+        <!--</el-form-item>-->
+        <el-form-item v-if="isModifyMode">
+          <div class="btn btn-primary btn-info" @click="submitInfo()">提交</div>
+          <!--<div class="btn btn-primary" @click="cancelModify()">取消</div>-->
+        </el-form-item>
+      </el-form>
+    </div>
+  </div>
+</template>
+
+<script>
+import Http from '@/js/http'
+import Apis from '@/js/api'
+import {notify} from '@/constants/index'
+import {
+  getCurrentUser,
+  getRolesPermissions,
+  storageGet,
+  storageSave,
+  uploadEnterpriseAuthenticationInfo
+} from '@/js/index'
+
+export default {
+  name: 'EnterpriseAuthenticationCreate',
+  data () {
+    return {
+      userId: 0,
+      user: {},
+      isModifyMode: true,
+      loading: false,
+      authentication: {
+        enterpriseName: '',
+        legalPersonName: '',
+        bankAccount: '',
+        businessLicensePhoto: '',
+        unifiedSocialCreditCode: '',
+        address: ''
+      },
+      rules: {
+        enterpriseName: [
+          {required: true, message: '请输入公司名称', trigger: 'blur'},
+          {min: 3, max: 50, message: '机构名称长度在 3 到 50 个字符', trigger: 'blur'}
+        ],
+        businessLicensePhoto: [
+          {
+            validator: (rule, value, callback) => {
+              console.log(value)
+              if (value == null || value == '') {
+                callback(new Error('公司营业执照不能为空'))
+              } else {
+                callback()
+              }
+            },
+            trigger: 'blue'
+          },
+        ],
+        legalPersonName: [
+          {required: true, message: '请输入公司法人姓名', trigger: 'blur'}
+        ],
+        bankAccount: [
+          {required: true, message: '请输入对公账户', trigger: 'blur'},
+          {
+            validator: (rule, value, callback) => {
+              if (!this.checkNumber(value)) {
+                callback(new Error('对公账户输入有误'))
+              } else {
+                callback()
+              }
+            },
+            trigger: 'blur'
+          },
+        ],
+        unifiedSocialCreditCode: [
+          {required: true, message: '请输入统一社会信用代码', trigger: 'blur'},
+          {
+            validator: (rule, value, callback) => {
+              if (!this.checkNumberAndWord(value)) {
+                callback(new Error('统一社会信用代码输入有误'))
+              } else {
+                callback()
+              }
+            }, trigger: 'blur'
+          },
+        ],
+        address: [
+          {required: true, message: '请输入公司地址', trigger: 'blur'}
+        ]
+      }
+    }
+  },
+  mounted () {
+    this.$nextTick(() => {
+      this.init()
+    })
+  },
+  methods: {
+    //初始化数据
+    init () {
+      this.setUserInfo()
+    },
+    //加载数据
+    loadData: function () {
+    },
+    //表单进入可编辑状态,可修改表单,不再使用
+    modifyInfo () {
+      this.isModifyMode = true
+    },
+    //提交认证信息
+    submitInfo () {
+      //this.isModifyMode = false
+      this.$refs['authentication'].validate(valid => {
+        if (valid) {
+          this.showLoading()
+          const newAuthentication = {
+            userId: this.user.userVO.id,
+            enterpriseName: this.authentication.enterpriseName,
+            legalPersonName: this.authentication.legalPersonName,
+            businessLicensePhoto: this.authentication.businessLicensePhoto,
+            unifiedSocialCreditCode: this.authentication.unifiedSocialCreditCode,
+            bankAccount: this.authentication.bankAccount,
+            address: this.authentication.address,
+          }
+          uploadEnterpriseAuthenticationInfo(this.user.userVO.id, newAuthentication, this.submitInfoSuccess, this.submitInfoFail)
+        } else {
+          notify('error', '表单填写错误!')
+          return false
+        }
+      })
+    },
+    submitInfoSuccess (res) {
+      // this.hideLoading()
+      console.log(res)
+      getCurrentUser().then(res => {
+        storageSave('user', res)
+        this.user = res
+        this.sendBusMessage()
+        //this.rolesPermissions = getRolesPermissions(res.roleList)
+        storageSave('rolesPermissions', getRolesPermissions(res.roleList))
+        this.hideLoading()
+        //notify('success', '用户信息刷新成功')
+        this.$alert('认证信息提交成功,将于3个工作日内审核完成', '提交成功', {
+          confirmButtonText: '确定',
+          callback: action => {
+            this.$router.push({
+              name: 'EnterpriseAuthentication',
+              params: {userId: this.user.userVO.id}
+            })
+          }
+        });
+
+        // .catch(_ => {
+        //   this.$router.push({
+        //     name: 'EnterpriseAuthentication',
+        //     params: {userId: this.user.userVO.id}
+        //   })
+        // })
+      }).catch((error) => {
+        this.hideLoading()
+        notify('error', '重新获取用户信息失败:' + error.data)
+      })
+
+    },
+    submitInfoFail (error) {
+      this.hideLoading()
+      notify('error', error.data)
+    },
+    //取消修改表单,表单进入不可编辑状态,不再使用
+    cancelModify () {
+      this.isModifyMode = false
+    },
+    //上传文件时移除文件的响应函数
+    handleRemove (file, fileList) {
+      console.log(file, fileList)
+    },
+    //添加文件时的响应函数
+    handleExceed (files, fileList) {
+      this.$message.warning(
+        `当前限制选择 1 个文件,本次选择了 ${
+          files.length
+          } 个文件,共选择了 ${files.length + fileList.length} 个文件`
+      )
+    },
+    //移除文件前的响应函数
+    beforeRemove (file, fileList) {
+      //return this.$confirm(`确定移除 ${file.name}?`)
+    },
+    //文件上传前的响应函数
+    beforeFileUpload () {
+    },
+    //上传文件,此处为上传图片
+    uploadFile (param) {
+      this.showLoading()
+      const formData = new FormData()
+      let config = {
+        //添加请求头
+        headers: {'Content-Type': 'multipart/form-data'},
+      }
+      formData.append('file', param.file)
+      Http.upload(Apis.FILE.UPLOAD_IMAGE.replace('{userId}', this.user.userVO.id), formData, config).then((res) => {
+        this.hideLoading()
+        console.log('上传成功')
+        this.authentication.businessLicensePhoto = res.data
+        console.log(res.data)
+        notify('success', '上传成功')
+        this.$refs['authentication'].validateField('businessLicensePhoto')
+      }).catch(error => {
+        this.hideLoading()
+        notify('error', error.data)
+      })
+    },
+    //
+    setUserInfo () {
+      this.user = storageGet('user')
+    },
+    //测试用函数
+    test () {
+
+    },
+    showLoading () {
+      this.loading = true
+    },
+    hideLoading () {
+      this.loading = false
+    },
+    sendBusMessage () {
+      this.$root.$emit('user', this.user)
+    },
+    checkNumber (value) {
+      return /^\d+$/.test(value)
+    },
+    checkNumberAndWord (value) {
+      return /^[^_IOZSVa-z\W]{2}\d{6}[^_IOZSVa-z\W]{10}$/g.test(value) || /^[A-Za-z0-9]\w{14}$/g.test(value)
+    }
+  },
+}
+</script>
+<style scoped>
+  .el-radio {
+    margin: 10px 20px 10px 0;
+  }
+
+  .el-form-item /deep/ .el-tabs__content {
+    max-height: 120px !important;
+    overflow: auto;
+  }
+
+  .el-row {
+    margin-bottom: 10px;
+  }
+
+  .el-input {
+    width: 400px;
+  }
+
+  .avatar-uploader .el-upload {
+    border: 1px dashed #d9d9d9;
+    border-radius: 6px;
+    cursor: pointer;
+    position: relative;
+    overflow: hidden;
+  }
+
+  .avatar-uploader .el-upload:hover {
+    border-color: #409EFF;
+  }
+
+  .avatar-uploader-icon {
+    border: 1px dashed #d9d9d9;
+    border-radius: 6px;
+    font-size: 28px;
+    color: #8c939d;
+    width: 176px;
+    height: 178px;
+    line-height: 178px;
+    text-align: center;
+  }
+
+  .avatar-uploader-icon:hover {
+    border-color: #409EFF;
+  }
+
+  .avatar {
+    width: 178px;
+    height: 178px;
+    display: block;
+  }
+</style>

+ 349 - 0
src/components/authen/IndividualAuthentication.vue

@@ -0,0 +1,349 @@
+<template>
+  <div class="create-container" v-loading="loading">
+    <div class="create-body">
+      <div class="title">个人信息认证</div>
+      <el-form :model="authentication" :rules="rules" ref="authentication" label-width="12%" class="demo-report">
+        <el-form-item label="姓名" prop="realName">
+          <el-input v-if="isModifyMode" v-model="authentication.realName"></el-input>
+          <span v-if="!isModifyMode">{{authentication.realName}}</span>
+        </el-form-item>
+        <el-form-item prop="IDCardPhoto" label="手持身份证照片">
+          <el-upload
+            v-if="isModifyMode"
+            class="avatar-uploader"
+            action=""
+            :show-file-list="false"
+            :http-request="uploadFile"
+            :before-upload="beforeFileUpload">
+            <img v-if="authentication.IDCardPhoto" :src="authentication.IDCardPhoto" class="avatar">
+            <i v-else class="el-icon-plus avatar-uploader-icon"></i>
+          </el-upload>
+          <span v-if="!isModifyMode">
+          <el-image
+            style="width: 100px;"
+            :src="authentication.IDCardPhoto"
+            fit="scale-down"></el-image>
+        </span>
+        </el-form-item>
+        <el-form-item label="身份证号" prop="IDCard">
+          <el-input v-if="isModifyMode" v-model="authentication.IDCard"></el-input>
+          <span v-if="!isModifyMode">{{authentication.IDCard}}</span>
+        </el-form-item>
+        <el-form-item v-if="!isModifyMode" label="认证状态" prop="name">
+          <el-tag :type="authentication.authStatus.style">{{authentication.authStatus.text}}</el-tag>
+        </el-form-item>
+        <el-form-item v-if="!isModifyMode && authentication.authStatus.text == '认证失败'" label="失败原因" prop="name">
+          <el-link v-if="authentication.explain!=null&&authentication.explain!=''" type="danger" disabled>
+            {{authentication.explain}}
+          </el-link>
+          <el-link v-if="authentication.explain==null || authentication.explain==''" type="danger" disabled>管理员未填写
+          </el-link>
+        </el-form-item>
+        <el-form-item label="银行卡账户" prop="bankAccount">
+          <el-input v-if="isModifyMode" v-model="authentication.bankAccount"></el-input>
+          <span v-if="!isModifyMode">{{authentication.bankAccount}}</span>
+        </el-form-item>
+        <el-form-item label="地址" prop="address">
+          <el-input v-if="isModifyMode" v-model="authentication.address"></el-input>
+          <span v-if="!isModifyMode">{{authentication.address}}</span>
+        </el-form-item>
+
+        <el-form-item v-if="!isModifyMode">
+          <div v-if="authentication.authStatus.text!='认证通过'" class="btn btn-medium btn-info" @click="modifyInfo()">修改
+          </div>
+        </el-form-item>
+        <el-form-item v-if="isModifyMode">
+          <div class="btn btn-primary btn-info" @click="updateAuthInfo()">提交</div>
+          <div class="btn btn-primary" @click="cancelModify()">取消</div>
+        </el-form-item>
+      </el-form>
+    </div>
+  </div>
+</template>
+
+<script>
+import Http from '@/js/http'
+import Apis from '@/js/api'
+import {notify} from '@/constants/index'
+import {
+  defaultValue,
+  getAllAgencyResourceTypes,
+  getAllServiceTypes,
+  getCurrentIndividualAuthenInfo,
+  getCurrentUser,
+  getProvinceCodeByProvinceName,
+  getProvinceNameByProvinceCode,
+  getRolesPermissions,
+  storageGet,
+  storageSave,
+  updateIndividualAuthInfo
+} from '@/js/index'
+
+export default {
+  name: 'IndividualAuthentication',
+  data () {
+    return {
+      userId: 0,
+      user: {},
+      loading: false,
+      isModifyMode: false,
+      authentication: {
+        IDCardPhoto: defaultValue.image,
+        realName: '',
+        IDCard: '',
+        bankAccount: '',
+        address: '',
+        authStatus: {},
+        explain: ''
+      },
+      rules: {
+        IDCard: [
+          {required: true, message: '请输入身份证号', trigger: 'blur'},
+          {min: 18, max: 18, message: '身份证号输入有误', trigger: 'blur'}
+        ],
+        realName: [
+          {required: true, message: '请输入身份证上的姓名', trigger: 'blur'},
+        ],
+        IDCardPhoto: [
+            {
+                validator: (rule, value, callback) => {
+                    console.log(value);
+                    if (value == null || value == '') {
+                        callback(new Error('手持身份证照片不能为空'))
+                    } else {
+                        callback()
+                    }
+                },
+                trigger: 'blue'
+            },
+        ],
+        bankAccount: [
+          {required: true, message: '请输入银行卡账户', trigger: 'blur'},
+          {
+              validator: (rule, value, callback) => {
+                  if (!this.checkNumber(value)) {
+                      callback(new Error('对银行卡账户有误'))
+                  } else {
+                      callback()
+                  }
+              }, trigger: 'blur'
+          },
+        ],
+        address: [
+          {required: true, message: '请输入地址', trigger: 'blur'}
+        ],
+
+      }
+    }
+  },
+  mounted () {
+    this.$nextTick(() => {
+      this.init()
+    })
+  },
+  watch: {
+    // authentication (val) {
+    //   this.authentication = val
+    // },
+    deep: true
+  },
+  methods: {
+    //初始化数据
+    init () {
+      this.setUserInfo()
+      this.getAuthInfo()
+    },
+    //加载数据
+    getAuthInfo () {
+      this.showLoading()
+      getCurrentIndividualAuthenInfo(this.user.userVO.id, this.getAuthInfoSuccess, this.getAuthInfoFail)
+    },
+    getAuthInfoSuccess (res) {
+      this.hideLoading()
+      this.authentication.IDCardPhoto = res.idcardPhoto == null ? defaultValue.image : res.idcardPhoto
+      this.authentication.realName = res.realName == null ? '暂未填写' : res.realName
+      this.authentication.IDCard = res.idcard == null ? '暂未填写' : res.idcard
+      this.authentication.bankAccount = res.bankAccount == null ? '暂未填写' : res.bankAccount
+      this.authentication.address = res.address == null ? '暂未填写' : res.address
+      this.authentication.authStatus = res.authStatus
+      this.authentication.explain = res.explain
+      console.log(this.authentication)
+    },
+    getAuthInfoFail (error) {
+      this.hideLoading()
+      notify('error', '加载认证信息失败:' + error.data)
+    },
+    //表单进入可编辑状态,可修改表单
+    modifyInfo () {
+      this.isModifyMode = true
+    },
+    //提交认证信息
+    updateAuthInfo () {
+      //this.isModifyMode = false
+
+      this.$refs['authentication'].validate(valid => {
+        if (valid) {
+          this.showLoading()
+          const newAuthentication = {
+            userId: this.user.userVO.id,
+            realName: this.authentication.realName,
+            bankAccount: this.authentication.bankAccount,
+            address: this.authentication.address,
+            IDCardPhoto: this.authentication.IDCardPhoto,
+            IDCard: this.authentication.IDCard,
+          }
+          //console.log(newAuthentication)
+          updateIndividualAuthInfo(this.user.userVO.id, newAuthentication, this.updateAuthInfoSuccess, this.updateAuthInfoFail)
+        } else {
+          notify('error', '表单填写错误!')
+          return false
+        }
+      })
+
+    },
+    updateAuthInfoSuccess (res) {
+      this.hideLoading()
+      this.authentication.IDCardPhoto = res.idcardPhoto == null ? defaultValue.image : res.idcardPhoto
+      this.authentication.realName = res.realName == null ? '暂未填写' : res.realName
+      this.authentication.IDCard = res.idcard == null ? '暂未填写' : res.idcard
+      this.authentication.bankAccount = res.bankAccount == null ? '暂未填写' : res.bankAccount
+      this.authentication.address = res.address == null ? '暂未填写' : res.address
+      this.cancelModify()
+      notify('success', '认证信息修改成功,正在为您刷新用户信息')
+      getCurrentUser().then(res => {
+        storageSave('user', res)
+        this.user = res
+        this.sendBusMessage()
+        //this.rolesPermissions = getRolesPermissions(res.roleList)
+        storageSave('rolesPermissions', getRolesPermissions(res.roleList))
+        this.hideLoading()
+        notify('success', '用户信息刷新成功')
+      }).catch((error) => {
+        this.hideLoading()
+        notify('error', '重新获取用户信息失败:' + error.data)
+      })
+    },
+    updateAuthInfoFail (error) {
+      this.hideLoading()
+      notify('error', error.data)
+    },
+    //取消修改表单,表单进入不可编辑状态,不再使用
+    cancelModify () {
+      this.getAuthInfo()
+      this.isModifyMode = false
+    },
+    //上传文件时移除文件的响应函数
+    handleRemove (file, fileList) {
+      console.log(file, fileList)
+    },
+    //添加文件时的响应函数
+    handleExceed (files, fileList) {
+      this.$message.warning(
+        `当前限制选择 1 个文件,本次选择了 ${
+          files.length
+          } 个文件,共选择了 ${files.length + fileList.length} 个文件`
+      )
+    },
+    //移除文件前的响应函数
+    beforeRemove (file, fileList) {
+      //return this.$confirm(`确定移除 ${file.name}?`)
+    },
+    //文件上传前的响应函数
+    beforeFileUpload () {
+    },
+    //上传文件,此处为上传图片
+    uploadFile (param) {
+      this.showLoading()
+      const formData = new FormData()
+      let config = {
+        //添加请求头
+        headers: {'Content-Type': 'multipart/form-data'},
+      }
+      formData.append('file', param.file)
+      Http.upload(Apis.FILE.UPLOAD_IMAGE.replace('{userId}', this.user.userVO.id), formData, config).then((res) => {
+        this.hideLoading()
+        console.log('上传成功')
+        this.authentication.IDCardPhoto = res.data
+        console.log(res.data)
+        notify('success', '上传成功')
+        this.$refs['authentication'].validateField('IDCardPhoto');
+
+      }).catch(error => {
+        this.hideLoading()
+        notify('error', error.data)
+      })
+    },
+    //
+    setUserInfo () {
+      this.user = storageGet('user')
+    },
+    //
+    showLoading () {
+      this.loading = true
+    },
+    hideLoading () {
+      this.loading = false
+    },
+    sendBusMessage () {
+      this.$root.$emit('user', this.user)
+    },
+    checkNumber(value){
+        return /^\d+$/.test(value);
+    },
+  },
+  created: function () {
+  }
+}
+</script>
+
+<style scoped>
+  .el-radio {
+    margin: 10px 20px 10px 0;
+  }
+
+  .el-form-item /deep/ .el-tabs__content {
+    max-height: 120px !important;
+    overflow: auto;
+  }
+
+  .el-row {
+    margin-bottom: 10px;
+  }
+
+  .el-input {
+    width: 400px;
+  }
+
+  .avatar-uploader .el-upload {
+    border: 1px dashed #d9d9d9;
+    border-radius: 6px;
+    cursor: pointer;
+    position: relative;
+    overflow: hidden;
+  }
+
+  .avatar-uploader .el-upload:hover {
+    border-color: #409EFF;
+  }
+
+  .avatar-uploader-icon {
+    border: 1px dashed #d9d9d9;
+    border-radius: 6px;
+    font-size: 28px;
+    color: #8c939d;
+    width: 176px;
+    height: 178px;
+    line-height: 178px;
+    text-align: center;
+  }
+
+  .avatar-uploader-icon:hover {
+    border-color: #409EFF;
+  }
+
+  .avatar {
+    width: 178px;
+    height: 178px;
+    display: block;
+  }
+</style>

+ 307 - 0
src/components/authen/IndividualAuthenticationCreate.vue

@@ -0,0 +1,307 @@
+<template>
+  <div class="create-container" v-loading="loading">
+    <div class="create-body">
+      <div class="title">个人信息认证</div>
+      <el-form :model="authentication" :rules="rules" ref="authentication" label-width="12%" class="demo-report">
+        <el-form-item label="姓名" prop="realName">
+          <el-input size="small" v-if="isModifyMode" v-model="authentication.realName"></el-input>
+          <!--<span v-if="!isModifyMode">{{authentication.name}}</span>-->
+        </el-form-item>
+        <el-form-item prop="IDCardPhoto" label="手持身份证照片">
+          <el-upload
+            class="avatar-uploader"
+            action=""
+            :show-file-list="false"
+            :http-request="uploadFile"
+            :before-upload="beforeFileUpload">
+            <img v-if="authentication.IDCardPhoto" :src="authentication.IDCardPhoto" class="avatar">
+            <i v-else class="el-icon-plus avatar-uploader-icon"></i>
+          </el-upload>
+          <!--<div v-if="!isModifyMode">-->
+          <!--<span v-if="authentication.photo==null">暂无文件</span>-->
+          <!--<a :href="authentication.photo" v-if="authentication.photo!=null"><i class="fa fa-file-text-o"></i>-->
+          <!--{{authentication.photo}}</a>-->
+          <!--</div>-->
+        </el-form-item>
+        <el-form-item label="身份证号" prop="IDCard">
+          <el-input size="small" v-if="isModifyMode" v-model="authentication.IDCard"></el-input>
+          <!--<span v-if="!isModifyMode">{{authentication.name}}</span>-->
+        </el-form-item>
+
+        <el-form-item label="银行卡账户" prop="bankAccount">
+          <el-input size="small" v-if="isModifyMode" v-model="authentication.bankAccount"></el-input>
+          <!--<span v-if="!isModifyMode">{{authentication.bankAccount}}</span>-->
+        </el-form-item>
+        <el-form-item label="地址" prop="address">
+          <el-input size="small" v-if="isModifyMode" v-model="authentication.address"></el-input>
+          <!--<span v-if="!isModifyMode">{{authentication.address}}</span>-->
+        </el-form-item>
+
+        <!--<el-form-item v-if="!isModifyMode">-->
+        <!--<div class="btn btn-medium btn-info" @click="modifyInfo()">修改</div>-->
+        <!--<div class="btn btn-medium" @click="cancelModify()">返回</div>-->
+        <!--</el-form-item>-->
+        <el-form-item v-if="isModifyMode">
+          <div class="btn btn-primary btn-info" @click="submitInfo()">提交</div>
+          <!--<div class="btn btn-primary" @click="cancelModify()">取消</div>-->
+        </el-form-item>
+      </el-form>
+    </div>
+  </div>
+</template>
+
+<script>
+import Http from '@/js/http'
+import Apis from '@/js/api'
+import {notify} from '@/constants/index'
+import {
+  getAllAgencyResourceTypes,
+  getAllServiceTypes,
+  getCurrentUser,
+  getProvinceCodeByProvinceName,
+  getProvinceNameByProvinceCode,
+  getRolesPermissions,
+  storageGet,
+  storageSave,
+  uploadIndividualAuthenticationInfo,
+} from '@/js/index'
+
+export default {
+  name: 'IndividualAuthenticationCreate',
+  data () {
+    return {
+      userId: 0,
+      user: {},
+      isModifyMode: true,
+      loading: false,
+      authentication: {
+        IDCardPhoto: '',
+        realName: '',
+        IDCard: '',
+        bankAccount: '',
+        address: '',
+      },
+      rules: {
+        IDCard: [
+          {required: true, message: '请输入身份证号', trigger: 'blur'},
+          {min: 18, max: 18, message: '身份证号输入有误', trigger: 'blur'}
+        ],
+        realName: [
+          {required: true, message: '请输入身份证上的姓名', trigger: 'blur'},
+        ],
+        IDCardPhoto: [
+            {
+                validator: (rule, value, callback) => {
+                    console.log(value);
+                    if (value == null || value == '') {
+                        callback(new Error('手持身份证照片不能为空'))
+                    } else {
+                        callback()
+                    }
+                },
+                trigger: 'blue'
+            },
+        ],
+        bankAccount: [
+          {required: true, message: '请输入银行卡账户', trigger: 'blur'},
+          {
+              validator: (rule, value, callback) => {
+                  if (!this.checkNumber(value)) {
+                      callback(new Error('银行卡账户输入有误'))
+                  } else {
+                      callback()
+                  }
+              }, trigger: 'blur'
+          },
+        ],
+        address: [
+          {required: true, message: '请输入地址', trigger: 'blur'}
+        ],
+
+      }
+    }
+  },
+  mounted () {
+    this.$nextTick(() => {
+      this.init()
+    })
+  },
+  methods: {
+    //初始化数据
+    init () {
+      this.setUserInfo()
+    },
+    //加载数据
+    loadData: function () {
+    },
+    //表单进入可编辑状态,可修改表单,不再使用
+    modifyInfo () {
+      this.isModifyMode = true
+    },
+    //提交认证信息
+    submitInfo () {
+      //this.isModifyMode = false
+      this.$refs['authentication'].validate(valid => {
+        if (valid) {
+          this.showLoading()
+          const newAuthentication = {
+            userId: this.user.userVO.id,
+            realName: this.authentication.realName,
+            IDCard: this.authentication.IDCard,
+            IDCardPhoto: this.authentication.IDCardPhoto,
+            bankAccount: this.authentication.bankAccount,
+            address: this.authentication.address
+          }
+          uploadIndividualAuthenticationInfo(this.user.userVO.id, newAuthentication, this.submitInfoSuccess, this.submitInfoFail)
+
+        } else {
+          notify('error', '表单填写错误!')
+          return false
+        }
+      })
+    },
+    submitInfoSuccess (res) {
+      console.log(res)
+      getCurrentUser().then(res => {
+        storageSave('user', res)
+        this.user = res
+        //this.rolesPermissions = getRolesPermissions(res.roleList)
+        storageSave('rolesPermissions', getRolesPermissions(res.roleList))
+        this.hideLoading()
+        //notify('success', '用户信息刷新成功')
+        this.sendBusMessage()
+        this.$alert('认证信息提交成功,将于3个工作日内审核完成', '提交成功', {
+          confirmButtonText: '确定',
+          callback: action => {
+            this.$router.push({
+              name: 'IndividualAuthentication',
+              params: {userId: this.user.userVO.id}
+            })
+          }
+        });
+      }).catch((error) => {
+        this.hideLoading()
+        notify('error', '重新获取用户信息失败:' + error.data)
+      })
+    },
+    submitInfoFail (error) {
+      this.hideLoading()
+      notify('error', error.data)
+    },
+    //取消修改表单,表单进入不可编辑状态,不再使用
+    cancelModify () {
+      this.isModifyMode = false
+    },
+    //上传文件时移除文件的响应函数
+    handleRemove (file, fileList) {
+      console.log(file, fileList)
+    },
+    //添加文件时的响应函数
+    handleExceed (files, fileList) {
+      this.$message.warning(
+        `当前限制选择 1 个文件,本次选择了 ${
+          files.length
+          } 个文件,共选择了 ${files.length + fileList.length} 个文件`
+      )
+    },
+    //移除文件前的响应函数
+    beforeRemove (file, fileList) {
+      //return this.$confirm(`确定移除 ${file.name}?`)
+    },
+    //文件上传前的响应函数
+    beforeFileUpload () {
+    },
+    //上传文件,此处为上传图片
+    uploadFile (param) {
+      this.showLoading()
+      const formData = new FormData()
+      let config = {
+        //添加请求头
+        headers: {'Content-Type': 'multipart/form-data'},
+      }
+      formData.append('file', param.file)
+      Http.upload(Apis.FILE.UPLOAD_IMAGE.replace('{userId}', this.user.userVO.id), formData, config).then((res) => {
+        this.hideLoading()
+        console.log('上传成功')
+        this.authentication.IDCardPhoto = res.data
+        console.log(res.data)
+        notify('success', '上传成功')
+        this.$refs['authentication'].validateField('IDCardPhoto');
+      }).catch(error => {
+        this.hideLoading()
+        notify('error', error.data)
+      })
+    },
+    //
+    setUserInfo () {
+      this.user = storageGet('user')
+    },
+    showLoading () {
+      this.loading = true
+    },
+    hideLoading () {
+      this.loading = false
+    },
+    sendBusMessage () {
+      this.$root.$emit('user', this.user)
+    },
+    checkNumber(value){
+        return /^\d+$/.test(value);
+    },
+  },
+  created: function () {
+  }
+}
+</script>
+
+<style scoped>
+  .el-radio {
+    margin: 10px 20px 10px 0;
+  }
+
+  .el-form-item /deep/ .el-tabs__content {
+    max-height: 120px !important;
+    overflow: auto;
+  }
+
+  .el-row {
+    margin-bottom: 10px;
+  }
+
+  .el-input {
+    width: 400px;
+  }
+
+  .avatar-uploader .el-upload {
+    border: 1px dashed #d9d9d9;
+    border-radius: 6px;
+    cursor: pointer;
+    position: relative;
+    overflow: hidden;
+  }
+
+  .avatar-uploader .el-upload:hover {
+    border-color: #409EFF;
+  }
+
+  .avatar-uploader-icon {
+    border: 1px dashed #d9d9d9;
+    border-radius: 6px;
+    font-size: 28px;
+    color: #8c939d;
+    width: 176px;
+    height: 178px;
+    line-height: 178px;
+    text-align: center;
+  }
+
+  .avatar-uploader-icon:hover {
+    border-color: #409EFF;
+  }
+
+  .avatar {
+    width: 178px;
+    height: 178px;
+    display: block;
+  }
+</style>

+ 270 - 60
src/components/cheat/AgencyAdd.vue

@@ -2,36 +2,60 @@
   <div class="create-container">
     <div class="create-body">
       <div class="title">添加机构</div>
-      <el-form :model="agency" :rules="rules" ref="agency" label-width="12%" class="demo-report">
+      <el-form v-loading="loading" :model="agency" :rules="rules" ref="agency" label-width="12%" class="demo-report">
         <el-form-item label="机构名称" prop="name">
-          <el-input v-if="isModifyMode" v-model="agency.name"></el-input>
+          <el-input size="small" v-if="isModifyMode" v-model="agency.name"></el-input>
           <!--<span v-if="!isModifyMode">{{agency.name}}</span>-->
         </el-form-item>
-        <el-form-item label="机构电话" prop="name">
+        <el-form-item size="small" label="机构电话" prop="mobile">
           <el-input v-if="isModifyMode" v-model="agency.mobile"></el-input>
           <!--<span v-if="!isModifyMode">{{agency.name}}</span>-->
         </el-form-item>
-        <el-form-item label="机构邮箱" prop="name">
+        <el-form-item size="small" label="机构邮箱" prop="email">
           <el-input v-if="isModifyMode" v-model="agency.email"></el-input>
           <!--<span v-if="!isModifyMode">{{agency.name}}</span>-->
         </el-form-item>
-        <el-form-item label="银行卡账户" prop="name">
+        <el-form-item size="small" label="银行卡账户" prop="bankAccount">
           <el-input v-if="isModifyMode" v-model="agency.bankAccount"></el-input>
           <!--<span v-if="!isModifyMode">{{agency.bankAccount}}</span>-->
         </el-form-item>
-        <el-form-item label="地址" prop="name">
+        <el-form-item size="small" label="地址" prop="address">
           <el-input v-if="isModifyMode" v-model="agency.address"></el-input>
           <!--<span v-if="!isModifyMode">{{agency.address}}</span>-->
         </el-form-item>
-        <el-form-item label="测评机构能力" prop="name">
-          <el-input v-if="isModifyMode" v-model="agency.ability"></el-input>
+        <el-form-item label="测评机构能力" prop="evaluationAgencyAbilityList">
+          <el-checkbox-group v-if="isModifyMode" v-model="agency.evaluationAgencyAbilityList">
+            <span v-for="(item,index) in serviceTypes" :key="index">
+              <el-checkbox :label="item"
+                           name="evaluationAgencyAbilityList">{{item}}&nbsp;&nbsp;&nbsp;&nbsp;</el-checkbox>
+            </span>
+          </el-checkbox-group>
           <!--<span v-if="!isModifyMode">{{agency.ability}}</span>-->
         </el-form-item>
-        <el-form-item label="测评机构资源" prop="name">
-          <el-input v-if="isModifyMode" v-model="agency.resource"></el-input>
-          <!--<span v-if="!isModifyMode">{{agency.resource}}</span>-->
+        <el-form-item label="测评机构资源" prop="evaluationAgencyResourceList">
+          <span v-for="item in agency.evaluationAgencyResourceList" :key="item.id">
+            资源类型:&nbsp;<el-select size="small" v-model="item.type" placeholder="请选择"
+                                  style="width: 15%;margin-bottom: 10px"
+                                  :value="item.type">
+              <el-option
+                v-for="item in resourceTypes"
+                :key="item"
+                :label="item"
+                :value="item">
+              </el-option>
+            </el-select>
+            资源名称:&nbsp;<el-input size="small" v-model="item.name" style="width: 15%"></el-input>
+            总量:&nbsp;<el-input-number size="small" :min="0" v-model="item.totalNum"></el-input-number>
+            可用数量:&nbsp;<el-input-number size="small" :min="0" :max="item.totalNum"
+                                        v-model="item.availableNum"></el-input-number>
+            <el-button size="small" type="danger" icon="el-icon-delete"
+                       @click="removeAgencyResource(item.id)"></el-button>
+            <br/>
+          </span>
+          <el-button type="primary" icon="el-icon-circle-plus" plain size="mini" @click="addAgencyResource">添加资源
+          </el-button>
         </el-form-item>
-        <el-form-item prop="file" label="头像">
+        <el-form-item prop="photoUrl" label="机构logo">
           <el-upload
             v-if="isModifyMode"
             class="avatar-uploader"
@@ -111,85 +135,196 @@
 import Http from '@/js/http'
 import Apis from '@/js/api'
 import {notify} from '@/constants/index'
+import {getAllAbilities, getAllAgencyResourceTypes, storageGet} from '@/js/index'
 
 export default {
   name: 'AgencyAdd',
   data () {
     return {
+      user: {},
       userId: 0,
+      loading: false,
       isModifyMode: true,
       dialogVisible: false,
+      serviceTypes: [],
+      resourceTypes: [],
       agency: {
         mobile: '',
         email: '',
         name: '',
         bankAccount: '',
         address: '',
-        ability: '',
-        resource: '',
+        evaluationAgencyAbilityList: [],
+        evaluationAgencyResourceList: [
+          {
+            id: 0,
+            type: '',
+            name: '',
+            totalNum: 0,
+            availableNum: 0,
+          }
+        ],
+        professionalsCount: 0,
+        professionalsFreeCount: 0,
+        serversCount: 0,
+        serversFreeCount: 0,
+        devicesCount: 0,
+        devicesFreeCount: 0,
         photo: [],
         photoUrl: '',
         password: '',
         username: '',
       },
       rules: {
-        // name: [
-        //   {required: true, message: '请输入报告名称', trigger: 'blur'}
-        //   // { min: 3, max: 5, message: "长度在 3 到 5 个字符", trigger: "blur" }
-        // ],
-        // abstract: [
-        //   {
-        //     required: true,
-        //     message: '请输入摘要信息',
-        //     trigger: 'change'
-        //   }
-        // ],
-        // type: [
-        //   {required: true, message: '请选择报告类型', trigger: 'change'}
-        // ],
-        // conclusion: [
-        //   {required: true, message: '请输入报告结论', trigger: 'blur'}
-        // ]
-      }
+        name: [
+          {required: true, message: '请输入测评机构名称', trigger: 'blur'}
+          // { min: 3, max: 5, message: "长度在 3 到 5 个字符", trigger: "blur" }
+        ],
+        mobile: [
+          {required: true, message: '请输入手机号', trigger: 'blur'}
+          // { min: 3, max: 5, message: "长度在 3 到 5 个字符", trigger: "blur" }
+        ],
+        email: [
+          {required: true, message: '请输入邮箱地址', trigger: 'blur'}
+          // { min: 3, max: 5, message: "长度在 3 到 5 个字符", trigger: "blur" }
+        ],
+        bankAccount: [
+          {required: true, message: '请输入银行卡账户', trigger: 'blur'},
+          {
+            validator: (rule, value, callback) => {
+              if (!this.checkNumber(value)) {
+                callback(new Error('银行卡账户输入有误'))
+              } else {
+                callback()
+              }
+            }, trigger: 'blur'
+          },
+        ],
+        address: [
+          {required: true, message: '请输入机构地址', trigger: 'blur'}
+          // { min: 3, max: 5, message: "长度在 3 到 5 个字符", trigger: "blur" }
+        ],
+        evaluationAgencyAbilityList: [
+          {type: 'array', required: true, message: '请至少选择一个机构能力', trigger: 'change'}
+          // { min: 3, max: 5, message: "长度在 3 到 5 个字符", trigger: "blur" }
+        ],
+        evaluationAgencyResourceList: [
+          {
+            validator: (rule, value, callback) => {
+              var isError = false
+              if (value == null || value.length == 0) {
+                callback(new Error('机构资源不可为空'))
+              } else {
+                for (var i = 0; i < value.length; i++) {
+                  if (value[i].name == '') {
+                    isError = true
+                    break
+                  }
+                }
+              }
+              if (isError) {
+                callback(new Error('资源名称不可为空'))
+              } else {
+                callback()
+              }
+            }, trigger: 'blur'
+          },
+        ],
+        photoUrl: [
+          {
+            validator: (rule, value, callback) => {
+              if (value == null || value == '') {
+                callback(new Error('机构logo不可为空'))
+              } else {
+                callback()
+              }
+            }, trigger: 'blur'
+          },
+        ]
+      },
+      tableData: [{
+        date: '2016-05-02',
+        name: '王小虎',
+        address: '上海市普陀区金沙江路 1518 弄'
+      }, {
+        date: '2016-05-04',
+        name: '王小虎',
+        address: '上海市普陀区金沙江路 1517 弄'
+      }, {
+        date: '2016-05-01',
+        name: '王小虎',
+        address: '上海市普陀区金沙江路 1519 弄'
+      }, {
+        date: '2016-05-03',
+        name: '王小虎',
+        address: '上海市普陀区金沙江路 1516 弄'
+      }]
     }
   },
+  mounted () {
+    this.$nextTick(() => {
+      this.init()
+    })
+  },
   methods: {
+    //初始化
+    init () {
+      this.setServiceTypes()
+      this.setResourceTypes()
+      this.setUserInfo()
+    },
     //加载数据
     loadData: function () {
     },
+    //表单进入可编辑状态,可修改表单,不再使用
     modifyInfo () {
       this.isModifyMode = true
     },
+    //提交表单
     submitInfo () {
       //this.showDialog()
-      const newAgency = {
-        mobile: this.agency.mobile,
-        evaluationAgencyName: this.agency.name,
-        bankAccount: this.agency.bankAccount,
-        address: this.agency.address,
-        abilities: this.agency.ability,
-        resources: this.agency.resource,
-        agencyPhoto: this.agency.photoUrl,
-        email: this.agency.email
-      }
-      Http.post(Apis.USER.ADD_AGENCY, newAgency).then((res) => {
-        // console.log(res)
-        // console.log(res.data)
-        res = res.data
-        this.agency.password = res.userVO.password
-        this.agency.username = res.userVO.userName
-        this.agency.mobile = res.userVO.mobileNum
-        this.showDialog()
-      }).catch(error => {
-        notify('error', error.data.msg)
+
+      this.$refs['agency'].validate(valid => {
+        if (valid) {
+          this.showLoading()
+          const newAgency = {
+            mobile: this.agency.mobile,
+            evaluationAgencyName: this.agency.name,
+            bankAccount: this.agency.bankAccount,
+            address: this.agency.address,
+            evaluationAgencyAbilityList: this.agency.evaluationAgencyAbilityList,
+            evaluationAgencyResourceList: this.agency.evaluationAgencyResourceList,
+            agencyPhoto: this.agency.photoUrl,
+            email: this.agency.email
+          }
+          Http.post(Apis.USER.ADD_AGENCY, newAgency).then((res) => {
+            this.hideLoading()
+            console.log(res)
+            // console.log(res.data)
+            //res = res.data
+            this.agency.password = res.userVO.password
+            this.agency.username = res.userVO.userName
+            this.agency.mobile = res.userVO.mobile
+            this.showDialog()
+          }).catch(error => {
+            this.hideLoading()
+            notify('error', error.data)
+          })
+        } else {
+          notify('error', '表单填写错误!')
+          return false
+        }
       })
     },
+    //取消修改表单,表单进入不可编辑状态,不再使用
     cancelModify () {
       this.isModifyMode = false
     },
+    //上传文件时移除文件的响应函数
     handleRemove (file, fileList) {
       console.log(file, fileList)
     },
+    //添加文件时的响应函数
     handleExceed (files, fileList) {
       this.$message.warning(
         `当前限制选择 1 个文件,本次选择了 ${
@@ -197,11 +332,14 @@ export default {
           } 个文件,共选择了 ${files.length + fileList.length} 个文件`
       )
     },
+    //移除文件前的响应函数
     beforeRemove (file, fileList) {
-      return this.$confirm(`确定移除 ${file.name}?`)
+      //return this.$confirm(`确定移除 ${file.name}?`)
     },
+    //文件上传前的响应函数
     beforeFileUpload () {
     },
+    //上传文件,此处为上传图片
     uploadFile (param) {
       const formData = new FormData()
       let config = {
@@ -209,16 +347,17 @@ export default {
         headers: {'Content-Type': 'multipart/form-data'},
       }
       formData.append('file', param.file)
-      Http.upload(Apis.FILE.UPLOAD_IMAGE.replace('{userId}', 3), formData, config).then((res) => {
+      //console.log(JSON.parse(this.user).userVO)
+      Http.upload(Apis.FILE.UPLOAD_IMAGE.replace('{userId}', this.user.userVO.id), formData, config).then((res) => {
         this.agency.photoUrl = res.data
         console.log(res.data)
         notify('success', '上传成功')
-        sessionStorage.setItem('file', 'qweqewqweqweqweqew')
-        sessionStorage.getItem('file')
+        this.$refs['agency'].validateField('photoUrl');
       }).catch(error => {
-        notify('error', error.data.msg)
+        notify('error', error.data)
       })
     },
+    //关闭对话框时的响应函数
     handleDialogClose (done) {
       this.$confirm('确认退出?退出前请记录下登录账号和密码,否则无法找回!!!')
         .then(_ => {
@@ -228,13 +367,16 @@ export default {
         .catch(_ => {
         })
     },
+    //弹出对话框
     showDialog () {
       this.dialogVisible = true
     },
+    //隐藏对话框
     hideDialog () {
       this.dialogVisible = false
       this.resetForm()
     },
+    //TODO 跳转到登录页面
     toLogin () {
       this.hideDialog()
       this.$router.push({
@@ -242,6 +384,7 @@ export default {
         // params: {projectId: projectId, taskId: taskId}
       })
     },
+    //重置表单
     resetForm () {
       this.agency = {
         mobile: '',
@@ -249,14 +392,77 @@ export default {
         name: '',
         bankAccount: '',
         address: '',
-        ability: '',
-        resource: '',
+        evaluationAgencyAbilityList: '',
+        evaluationAgencyResourceList: '',
         photo: [],
         photoUrl: '',
         password: '',
         username: '',
       }
-    }
+    },
+    //设置服务类型
+    setServiceTypes () {
+      this.serviceTypes = getAllAbilities()
+    },
+    //添加一项测评机构资源
+    addAgencyResource () {
+      const tmpResource = {
+        id: this.agency.evaluationAgencyResourceList.length,
+        type: this.resourceTypes[0],
+        name: '',
+        totalNum: 0,
+        availableNum: 0,
+      }
+      this.agency.evaluationAgencyResourceList.push(tmpResource)
+    },
+    //删除一项测评机构资源
+    removeAgencyResource (id) {
+      this.agency.evaluationAgencyResourceList.splice(id, 1)
+      for (var i = 0; i < this.agency.evaluationAgencyResourceList.length; i++) {
+        this.agency.evaluationAgencyResourceList[i].id = i
+      }
+    },
+    //设置测评机构资源类型
+    setResourceTypes () {
+      this.resourceTypes = getAllAgencyResourceTypes()
+    },
+    //检测测评机构资源填写是否有效
+    checkAgencyResourceVaild () {
+      if (this.agency.evaluationAgencyResourceList.length === 0) {
+        return true
+      }
+      for (var i = 0; i < this.agency.evaluationAgencyResourceList.length; i++) {
+        const item = this.agency.evaluationAgencyResourceList[i]
+        if (item.type === '') {
+          notify('error', '资源类型不能为空')
+          return false
+        }
+        if (item.name === '') {
+          notify('error', '资源名称不能为空')
+          return false
+        }
+        if (item.totalNum < item.availableNum) {
+          notify('error', '资源总数量不能低于可用数量')
+          return false
+        }
+      }
+      return true
+    },
+    //获取用户信息
+    setUserInfo () {
+      this.user = storageGet('user')
+    },
+    //显示loading
+    showLoading () {
+      this.loading = true
+    },
+    //隐藏loading
+    hideLoading () {
+      this.loading = false
+    },
+    checkNumber (value) {
+      return /^\d+$/.test(value)
+    },
   },
   created: function () {
   }
@@ -312,4 +518,8 @@ export default {
     height: 178px;
     display: block;
   }
+
+  .el-input-number {
+    width: 150px;
+  }
 </style>

+ 343 - 0
src/components/cheat/AgencyDetail.vue

@@ -0,0 +1,343 @@
+<template>
+  <div class="create-container">
+    <div class="create-body">
+      <div class="title">修改能力和资源</div>
+      <el-form v-loading="loading" :model="agency" :rules="rules" ref="agency" label-width="12%" class="demo-report">
+        <el-form-item prop="file" label="机构logo">
+          <span>
+          <el-image
+            style="width: 100px;"
+            :src="agency.agencyPhoto"
+            fit="scale-down"></el-image>
+        </span>
+        </el-form-item>
+        <el-form-item label="机构名称" prop="name">
+          <!--<el-input size="small" v-if="isModifyMode" v-model="agency.name"></el-input>-->
+          <span>{{agency.evaluationAgencyName}}</span>
+        </el-form-item>
+        <el-form-item size="small" label="机构账户" prop="bankAccount">
+          <!--<el-input v-if="isModifyMode" v-model="agency.bankAccount"></el-input>-->
+          <span>{{agency.bankAccount}}</span>
+        </el-form-item>
+        <el-form-item size="small" label="机构地址" prop="address">
+          <!--<el-input v-if="isModifyMode" v-model="agency.address"></el-input>-->
+          <span>{{agency.address}}</span>
+        </el-form-item>
+        <el-form-item label="机构能力" prop="evaluationAgencyAbilityList">
+          <el-checkbox-group v-if="isModifyMode" v-model="agency.evaluationAgencyAbilityList">
+            <span v-for="(item,index) in serviceTypes" :key="index">
+              <el-checkbox :label="item"
+                           name="evaluationAgencyAbilityList">{{item}}&nbsp;&nbsp;&nbsp;&nbsp;</el-checkbox>
+            </span>
+          </el-checkbox-group>
+          <span v-if="!isModifyMode">
+            <span v-for="(item,index) in agency.evaluationAgencyAbilityList" :key="index">
+              <el-tag>{{item}}</el-tag>&nbsp;
+            </span>
+          </span>
+        </el-form-item>
+        <el-form-item label="机构资源" prop="evaluationAgencyResourceList">
+          <span v-if="isModifyMode" v-for="item in agency.evaluationAgencyResourceList" :key="item.id">
+            资源类型:&nbsp;<el-select size="small" v-model="item.type" placeholder="请选择"
+                                  style="width: 15%;margin-bottom: 10px"
+                                  :value="item.type">
+              <el-option
+                v-for="item in resourceTypes"
+                :key="item"
+                :label="item"
+                :value="item">
+              </el-option>
+            </el-select>
+            资源名称:&nbsp;<el-input size="small" v-model="item.name" style="width: 15%" prop="resourceName"></el-input>
+            总量:&nbsp;<el-input-number size="small" :min="0" v-model="item.totalNum"></el-input-number>
+            可用数量:&nbsp;<el-input-number size="small" :min="0" :max="item.totalNum"
+                                        v-model="item.availableNum"></el-input-number>
+            <el-button size="small" type="danger" icon="el-icon-delete"
+                       @click="removeAgencyResource(item.id)"></el-button>
+            <br/>
+          </span>
+          <el-button v-if="isModifyMode" type="primary" icon="el-icon-circle-plus" plain size="mini"
+                     @click="addAgencyResource">添加资源
+          </el-button>
+          <span v-if="!isModifyMode" v-for="item in agency.evaluationAgencyResourceList" :key="item.id">
+            资源类型:{{item.type}};&nbsp;&nbsp;资源名称:{{item.name}};&nbsp;&nbsp;资源总量:{{item.totalNum}};&nbsp;&nbsp;可用资源:{{item.availableNum}}<br/>
+          </span>
+        </el-form-item>
+
+        <!--<el-form-item v-if="!isModifyMode">-->
+        <!--<div class="btn btn-medium btn-info" @click="modifyInfo()">修改</div>-->
+        <!--<div class="btn btn-medium" @click="cancelModify()">返回</div>-->
+        <!--</el-form-item>-->
+        <el-form-item>
+          <el-button v-if="isModifyMode" type="primary" size="small" @click="submitInfo()">提交</el-button>
+          <el-button v-if="isModifyMode" type="info" size="small" @click="cancelModify()">取消</el-button>
+          <el-button v-if="!isModifyMode" type="primary" size="small" @click="modifyInfo()">修改</el-button>
+          <!--<div class="btn btn-primary" @click="cancelModify()">取消</div>-->
+        </el-form-item>
+      </el-form>
+    </div>
+  </div>
+</template>
+
+<script>
+import {notify} from '@/constants/index'
+import {
+  getAllAbilities,
+  getAllAgencyResourceTypes,
+  getCurrentAgencyAuthInfo,
+  storageGet,
+  updateAgencyResourceAndAbility
+} from '@/js/index'
+
+export default {
+  name: 'Agency',
+  data () {
+    return {
+      user: {},
+      userId: 0,
+      loading: false,
+      isModifyMode: false,
+      dialogVisible: false,
+      serviceTypes: [],
+      resourceTypes: [],
+      agency: {
+        evaluationAgencyName: '',
+        bankAccount: '',
+        address: '',
+        evaluationAgencyAbilityList: [],
+        evaluationAgencyResourceList: [
+          {
+            id: 0,
+            type: '',
+            name: '',
+            totalNum: 0,
+            availableNum: 0,
+          }
+        ],
+        agencyPhoto: '',
+      },
+      rules: {
+        evaluationAgencyAbilityList: [
+          {type: 'array', required: true, message: '请至少选择一个机构能力', trigger: 'change'}
+          // { min: 3, max: 5, message: "长度在 3 到 5 个字符", trigger: "blur" }
+        ],
+        evaluationAgencyResourceList: [
+          {
+            validator: (rule, value, callback) => {
+              var isError = false
+              if (value == null || value.length == 0){
+                callback(new Error('机构资源不可为空'))
+              } else {
+                for (var i = 0; i < value.length; i++) {
+                  if (value[i].name == '') {
+                    isError = true
+                    break
+                  }
+                }
+              }
+              if (isError) {
+                callback(new Error('资源名称不可为空'))
+              } else {
+                callback()
+              }
+            }, trigger: 'blur'
+          },
+        ],
+        resourceName: [
+          {required: true, message: '请输入地址', trigger: 'blur'}
+        ]
+      },
+    }
+  },
+  mounted () {
+    this.$nextTick(() => {
+      this.init()
+    })
+  },
+  methods: {
+    //初始化
+    init () {
+      this.setServiceTypes()
+      this.setResourceTypes()
+      this.setUserInfo()
+      this.getAgencyInfo()
+    },
+    getAgencyInfo () {
+      this.showLoading()
+      getCurrentAgencyAuthInfo(this.user.userVO.id, this.getAgencyInfoSuccess, this.getAgencyInfoFail)
+    },
+    getAgencyInfoSuccess (res) {
+      this.hideLoading()
+      this.agency.evaluationAgencyName = res.evaluationAgencyName
+      this.agency.bankAccount = res.bankAccount
+      this.agency.address = res.address
+      this.agency.evaluationAgencyAbilityList = res.evaluationAgencyAbilityList
+      this.agency.evaluationAgencyResourceList = res.evaluationAgencyResourceList
+      this.agency.agencyPhoto = res.agencyPhoto
+    },
+    getAgencyInfoFail (error) {
+      this.hideLoading()
+      notify('error', '获取机构信息失败:' + error.data)
+    },
+    //表单进入可编辑状态,可修改表单,不再使用
+    modifyInfo () {
+      this.isModifyMode = true
+    },
+    //提交表单
+    submitInfo () {
+      this.$refs['agency'].validate(valid => {
+        if (valid) {
+          this.showLoading()
+          const data = {
+            evaluationAgencyAbilityList: this.agency.evaluationAgencyAbilityList,
+            evaluationAgencyResourceList: this.agency.evaluationAgencyResourceList
+          }
+          updateAgencyResourceAndAbility(this.user.userVO.id, data, this.submitInfoSuccess, this.submitInfoFail)
+        } else {
+          notify('error', '表单填写错误!')
+          return false
+        }
+      })
+    },
+    submitInfoSuccess (res) {
+      this.hideLoading()
+      notify('success', '修改成功')
+      this.cancelModify()
+    },
+    submitInfoFail (error) {
+      this.hideLoading()
+      notify('error', '修改资源能力失败:' + error.data)
+    },
+    //取消修改表单,表单进入不可编辑状态,不再使用
+    cancelModify () {
+      this.isModifyMode = false
+      this.getAgencyInfo()
+    },
+    //TODO 跳转到登录页面
+    toLogin () {
+      this.hideDialog()
+      this.$router.push({
+        name: 'Home',
+        // params: {projectId: projectId, taskId: taskId}
+      })
+    },
+    //设置服务类型
+    setServiceTypes () {
+      this.serviceTypes = getAllAbilities()
+    },
+    //添加一项测评机构资源
+    addAgencyResource () {
+      const tmpResource = {
+        id: this.agency.evaluationAgencyResourceList.length,
+        type: this.resourceTypes[0],
+        name: '',
+        totalNum: 0,
+        availableNum: 0,
+      }
+      this.agency.evaluationAgencyResourceList.push(tmpResource)
+    },
+    //删除一项测评机构资源
+    removeAgencyResource (id) {
+      this.agency.evaluationAgencyResourceList.splice(id, 1)
+      for (var i = 0; i < this.agency.evaluationAgencyResourceList.length; i++) {
+        this.agency.evaluationAgencyResourceList[i].id = i
+      }
+    },
+    //设置测评机构资源类型
+    setResourceTypes () {
+      this.resourceTypes = getAllAgencyResourceTypes()
+    },
+    //检测测评机构资源填写是否有效
+    checkAgencyResourceVaild () {
+      if (this.agency.evaluationAgencyResourceList.length === 0) {
+        return true
+      }
+      for (var i = 0; i < this.agency.evaluationAgencyResourceList.length; i++) {
+        const item = this.agency.evaluationAgencyResourceList[i]
+        if (item.type === '') {
+          notify('error', '资源类型不能为空')
+          return false
+        }
+        if (item.name === '') {
+          notify('error', '资源名称不能为空')
+          return false
+        }
+        if (item.totalNum < item.availableNum) {
+          notify('error', '资源总数量不能低于可用数量')
+          return false
+        }
+      }
+      return true
+    },
+    //获取用户信息
+    setUserInfo () {
+      this.user = storageGet('user')
+    },
+    //显示loading
+    showLoading () {
+      this.loading = true
+    },
+    //隐藏loading
+    hideLoading () {
+      this.loading = false
+    }
+  },
+  created: function () {
+  }
+}
+</script>
+
+<style scoped>
+  .el-radio {
+    margin: 10px 20px 10px 0;
+  }
+
+  .el-form-item /deep/ .el-tabs__content {
+    max-height: 120px !important;
+    overflow: auto;
+  }
+
+  .el-row {
+    margin-bottom: 10px;
+  }
+
+  .el-input {
+    width: 400px;
+  }
+
+  .avatar-uploader .el-upload {
+    border: 1px dashed #d9d9d9;
+    border-radius: 6px;
+    cursor: pointer;
+    position: relative;
+    overflow: hidden;
+  }
+
+  .avatar-uploader .el-upload:hover {
+    border-color: #409EFF;
+  }
+
+  .avatar-uploader-icon {
+    font-size: 28px;
+    color: #8c939d;
+    width: 178px;
+    height: 178px;
+    line-height: 178px;
+    text-align: center;
+    border: 1px dashed #d9d9d9;
+    border-radius: 6px;
+    cursor: pointer;
+    position: relative;
+    overflow: hidden;
+  }
+
+  .avatar {
+    width: 178px;
+    height: 178px;
+    display: block;
+  }
+
+  .el-input-number {
+    width: 150px;
+  }
+</style>

+ 187 - 72
src/components/cheat/ProjectAdd.vue

@@ -1,6 +1,6 @@
 <template>
   <div class="create-container">
-    <div class="create-body">
+    <div class="create-body" v-loading="loading">
       <div class="title">创建项目</div>
       <el-tabs tabPosition="top" type="card">
         <el-tab-pane label="单个创建项目">
@@ -27,9 +27,9 @@
             </el-form-item>
             <el-form-item label="平台" prop="platform">
               <el-checkbox-group v-if="isModifyMode" v-model="project.platform">
-                <el-checkbox label="0">IOS</el-checkbox>
-                <el-checkbox label="1">ANDROID</el-checkbox>
-                <el-checkbox label="2">WEB</el-checkbox>
+                <span v-for="(item,index) in platforms" :key="index">
+              <el-checkbox :label="item">{{ item }}&nbsp;&nbsp;&nbsp;&nbsp;</el-checkbox>
+            </span>
               </el-checkbox-group>
               <!--<span-->
               <!--v-if="!isModifyMode"-->
@@ -39,20 +39,16 @@
             </el-form-item>
             <el-form-item label="服务类型" prop="type">
               <el-checkbox-group v-if="isModifyMode" v-model="project.type">
-                <el-checkbox label="0" name="type">{{serviceType[0]}}</el-checkbox>
-                <el-checkbox label="1" name="type">{{serviceType[1]}}</el-checkbox>
-                <el-checkbox label="2" name="type">{{serviceType[2]}}</el-checkbox>
-                <el-checkbox label="3" name="type">{{serviceType[3]}}</el-checkbox>
-                <el-checkbox label="4" name="type">{{serviceType[4]}}</el-checkbox>
-                <el-checkbox label="5" name="type">{{serviceType[5]}}</el-checkbox>
-                <el-checkbox label="6" name="type">{{serviceType[6]}}</el-checkbox>
+            <span v-for="(item,index) in serviceType" :key="index">
+              <el-checkbox :label="item" name="type">{{item}}&nbsp;&nbsp;&nbsp;&nbsp;</el-checkbox>
+            </span>
               </el-checkbox-group>
-              <!--<span v-if="!isModifyMode" class="badge" v-for="item in project.type">{{serviceType[item]}}</span>-->
             </el-form-item>
             <el-form-item prop="file" label="项目需求文档">
               <el-upload
                 v-if="isModifyMode"
                 drag
+                style="width: 400px"
                 class="upload-demo"
                 action=""
                 :on-remove="handleRemove"
@@ -80,6 +76,7 @@
             </el-form-item>
             <el-form-item prop="file" label="项目待测文件">
               <el-upload
+                style="width: 400px"
                 v-if="isModifyMode"
                 drag
                 class="upload-demo"
@@ -98,7 +95,6 @@
                   将文件拖到此处,或
                   <em>点击上传</em>
                 </div>
-                <div class="el-upload__tip" slot="tip">请上传报告文件</div>
               </el-upload>
               <!--<div v-if="!isModifyMode">-->
               <!--<span v-if="project.file==null || project.file.length === 0">暂无文件</span>-->
@@ -131,11 +127,11 @@
         <el-tab-pane label="批量创建项目">
           <el-form :model="project" :rules="rules" ref="project" label-width="12%" class="demo-report">
             <el-form-item prop="file" label="Excel模板文件">
-              <div>
-                <a :href="downloadFile"><i
-                  class="fa fa-file-text-o"></i>
-                  {{downloadFile}}</a>
-              </div>
+              <a :href="downloadFile">
+                <el-link :underline="false" type="primary"><i
+                  class="el-icon-document"></i>下载文档
+                </el-link>
+              </a>
             </el-form-item>
             <el-form-item type="file" prop="file" label="Excel文件">
               <el-upload
@@ -156,7 +152,6 @@
                   将文件拖到此处,或
                   <em>点击上传</em>
                 </div>
-                <div class="el-upload__tip" slot="tip">请上传报告文件</div>
               </el-upload>
               <!--<div v-if="!isModifyMode">-->
               <!--<span v-if="project.file==null">暂无文件</span>-->
@@ -178,37 +173,49 @@
           <el-table
             :data="projectList"
             style="width: auto">
-      <el-table-column
-        prop="projectDetails.name"
-        label="项目名称">
-      </el-table-column>
-            <el-table-column
-              prop="projectDetails.platform"
-              label="项目测试平台">
+            <el-table-column prop="name" label="项目名称">
+              <template slot-scope="scope">
+                <span>{{scope.row.name}}</span>
+              </template>
             </el-table-column>
-            <el-table-column
-              prop="projectDetails.contactName"
-              label="项目联系人">
+            <el-table-column prop="platform" label="项目测试平台">
+              <template slot-scope="scope">
+                <span v-for="item in JSON.parse(scope.row.platform)" :key="item">
+                   <el-tag type="success">{{item}}</el-tag>&nbsp;&nbsp;
+                </span>
+              </template>
             </el-table-column>
-            <el-table-column
-              prop="projectDetails.contactPhone"
-              label="联系方式">
+            <el-table-column prop="linkMan" label="项目联系人">
+              <template slot-scope="scope">
+                <span>{{scope.row.linkMan}}</span>
+              </template>
             </el-table-column>
-            <el-table-column
-              prop="projectDetails.type"
-              label="项目测试类型">
+            <el-table-column prop="linkManMobile" label="联系方式">
+              <template slot-scope="scope">
+                <span>{{scope.row.linkManMobile}}</span>
+              </template>
             </el-table-column>
-            <el-table-column
-              prop="projectDetails.desc"
-              label="项目需求描述">
+            <el-table-column prop="type" label="项目测试类型">
+              <template slot-scope="scope">
+                <span v-for="item in JSON.parse(scope.row.type)" :key="item">
+                   <el-tag type="success">{{item}}</el-tag>&nbsp;&nbsp;
+                </span>
+              </template>
             </el-table-column>
-            <el-table-column
-              prop="projectDetails.desc"
-              label="测试报告内容">
+            <el-table-column prop="description" label="项目需求描述">
+              <template slot-scope="scope">
+                <span>{{scope.row.description}}</span>
+              </template>
             </el-table-column>
-            <el-table-column
-              prop="projectDetails.desc"
-              label="测试报告结论">
+            <el-table-column prop="description" label="测试报告内容">
+              <template slot-scope="scope">
+                <span>{{scope.row.description}}</span>
+              </template>
+            </el-table-column>
+            <el-table-column prop="description" label="测试报告结论">
+              <template slot-scope="scope">
+                <span>{{scope.row.description}}</span>
+              </template>
             </el-table-column>
     </el-table>
         </span>
@@ -228,21 +235,27 @@
 <script>
 import Http from '@/js/http.js'
 import Apis from '@/js/api.js'
-import ServiceType from '@/constants/enum/service-type.js'
-import PlatformType from '@/constants/enum/platform-type.js'
 import {notify} from '@/constants/index'
+import {
+  getAllPlatformTypes,
+  getAllServiceTypes,
+  getGreenChannelAddProjectExcelTemplateFile,
+  storageGet
+} from '@/js/index'
 
 export default {
   name: 'ProjectAdd',
   data () {
     return {
       userId: 0,
+      user: {},
+      loading: false,
       dialogVisible: false,
       isModifyMode: true,
-      serviceType: ServiceType,
-      platform: PlatformType,
+      serviceType: [],
+      platforms: [],
       isFormSubmit: true,
-      downloadFile: '123.xls',
+      downloadFile: '',
       project: {
         name: '',
         description: '',
@@ -422,7 +435,18 @@ export default {
       }]
     }
   },
+  mounted () {
+    this.$nextTick(() => {
+      this.init()
+    })
+  },
   methods: {
+    init () {
+      this.setServiceType()
+      this.setPlatformType()
+      this.setUserInfo()
+      this.setTemplateExcel()
+    },
     //加载数据
     loadData: function () {
     },
@@ -431,8 +455,9 @@ export default {
     },
     submitInfo () {
       //this.isModifyMode = false
+      this.showLoading()
       const newProject = {
-        userId: 3,
+        userId: this.user.userVO.id,
         name: this.project.name,
         description: this.project.description,
         contactName: this.project.contactName,
@@ -445,10 +470,12 @@ export default {
         datetime: this.project.datetime
       }
       Http.post(Apis.PROJECT.ADD_PROJECT, newProject).then((res) => {
-        notify('success', '项目添加成功')
+        this.hideLoading()
+        this.createProjectByFormSuccessConfirm()
         console.log(res)
       }).catch(error => {
-        notify('error', error.data.msg)
+        this.hideLoading()
+        notify('error', error.data)
       })
     },
     // cancelModify () {
@@ -465,25 +492,32 @@ export default {
       )
     },
     beforeRemove (file, fileList) {
-      return this.$confirm(`确定移除 ${file.name}?`)
+      //return this.$confirm(`确定移除 ${file.name}?`)
     },
     beforeFileUpload () {
 
     },
     uploadProjectCreateExcelFile (param) {
+      this.showLoading()
       const formData = new FormData()
       let config = {
         //添加请求头
         headers: {'Content-Type': 'multipart/form-data'},
       }
       formData.append('file', param.file)
-      Http.upload(Apis.PROJECT.ADD_PROJECT_BY_EXCEL, formData, config).then((res) => {
+      Http.upload(Apis.PROJECT.ADD_PROJECT_BY_EXCEL_PRE.replace('{userId}', this.user.userVO.id), formData, config).then((res) => {
         console.log(res)
+        console.log(res.data[0].platform)
+        console.log(typeof res.data[0].platform)
+        console.log(typeof JSON.parse(res.data[0].platform))
+        console.log(JSON.parse(res.data[0].platform))
         this.projectList = res.data
+        this.hideLoading()
         this.showDialog()
         //notify('success', '项目添加成功')
       }).catch(error => {
         notify('error', error)
+        this.hideLoading()
       })
     },
     uploadRequireDoc (param) {
@@ -493,13 +527,13 @@ export default {
         headers: {'Content-Type': 'multipart/form-data'},
       }
       formData.append('file', param.file)
-      Http.upload(Apis.FILE.REQUIREMENT_FILE.replace('{userId}', 3), formData, config).then((res) => {
+      Http.upload(Apis.FILE.REQUIREMENT_FILE.replace('{userId}', this.user.userVO.id), formData, config).then((res) => {
         console.log('上传成功')
         this.project.requireDocUrl = res.data
         console.log(res.data)
         notify('success', '上传成功')
       }).catch(error => {
-        notify('error', error.data.msg)
+        notify('error', error.data)
       })
     },
     uploadApkFile (param) {
@@ -509,39 +543,120 @@ export default {
         headers: {'Content-Type': 'multipart/form-data'},
       }
       formData.append('file', param.file)
-      Http.upload(Apis.FILE.APK.replace('{userId}', 3), formData, config).then((res) => {
+      Http.upload(Apis.FILE.APK.replace('{userId}', this.user.userVO.id), formData, config).then((res) => {
         console.log('上传成功')
         this.project.fileUrl = res.data
         console.log(res)
         notify('success', '上传成功')
       }).catch(error => {
-        notify('error', error.data.msg)
+        notify('error', error.data)
       })
     },
     handleDialogClose (done) {
-      this.$confirm('确认退出?退出前请记录下登录账号和密码,否则无法找回!!!')
-        .then(_ => {
-          //done()
-          this.hideDialog()
-        })
-        .catch(_ => {
-        })
+      this.hideDialog()
+      this.project.excelFile = []
+      // this.$confirm('确认退出?退出前请记录下登录账号和密码,否则无法找回!!!')
+      //   .then(_ => {
+      //     //done()
+      //     this.hideDialog()
+      //   })
+      //   .catch(_ => {
+      //   })
     },
     ensureSubmitExcel () {
-      notify('success', '添加成功')
-      // Http.post('',this.projectList).then((res)=>{
-      //
-      // }).catch((error)=>{
-      //
-      // })
+      this.hideDialog()
+      this.showLoading()
+      Http.post(Apis.PROJECT.ADD_PROJECT_BY_EXCEL, this.projectList).then((res) => {
+        notify('success', '添加成功')
+        this.hideLoading()
+      }).catch((error) => {
+        notify('error', error.data)
+        this.hideLoading()
+      })
     },
     showDialog () {
       this.dialogVisible = true
     },
     hideDialog () {
       this.dialogVisible = false
-      this.resetForm()
+      //this.resetForm()
+    },
+    setServiceType () {
+      getAllServiceTypes().then((res) => {
+        this.serviceType = res
+      }).catch((error) => {
+        notify('error', '获取服务类型出错')
+      })
+    },
+    setPlatformType () {
+      this.platforms = getAllPlatformTypes()
+    },
+    createProjectByFormSuccessConfirm () {
+      this.$confirm('项目创建成功,是否跳转至主页?', '提示', {
+        confirmButtonText: '跳转至主页',
+        cancelButtonText: '继续创建项目',
+        type: 'success'
+      }).then(() => {
+        this.$router.push({
+          name: 'Home',
+          // params: {projectId: projectId, taskId: taskId}
+        })
+        // this.$message({
+        //   type: 'success',
+        //   message: '删除成功!'
+        // });
+      }).catch(() => {
+        this.resetForm()
+        // this.$message({
+        //   type: 'info',
+        //   message: '已取消删除'
+        // });
+      })
     },
+    resetForm () {
+      this.project = {
+        name: '',
+        description: '',
+        contactName: '',
+        contactPhone: '',
+        platform: [],
+        type: [],
+        requireDoc: [],
+        requireDocUrl: '',
+        file: [],
+        fileUrl: '',
+        excelFile: [],
+        excelFileUrl: '',
+        price: '',
+        datetime: ''
+      }
+    },
+    setUserInfo () {
+      this.user = storageGet('user')
+    },
+    setTemplateExcel () {
+      this.showLoading()
+      getGreenChannelAddProjectExcelTemplateFile(this.setTemplateExcelSuccess, this.setTemplateExcelFail)
+    },
+    setTemplateExcelSuccess (res) {
+      this.hideLoading()
+      this.downloadFile = res.fileUrl
+    },
+    setTemplateExcelFail (error) {
+      this.hideLoading()
+      notify('error', '加载模板文件失败:' + error.data)
+    },
+    showLoading () {
+      this.loading = true
+    },
+    hideLoading () {
+      this.loading = false
+    }
+  },
+  watch: {
+    serviceType (val) {
+      this.serviceType = val
+    }
   },
   created: function () {
   }

+ 561 - 25
src/components/commons/Header.vue

@@ -1,23 +1,47 @@
 <template>
-  <nav class="navbar">
-    <div class="container">
-      <div class="navbar-translate">
-        <a class="navbar-brand">众测</a>
-        <button
-          type="button"
-          data-toggle="collapse"
-          aria-expanded="false"
-          aria-label="Toggle navigation"
-          @click="openNavBarFunc"
-          v-bind:class="['navbar-toggler',{ 'open-fixed': openNavBar}]"
-        >
-          <span class="navbar-toggler-icon"></span>
-          <span class="navbar-toggler-icon"></span>
-          <span class="navbar-toggler-icon"></span>
-        </button>
+  <nav class="navbar" v-loading.fullscreen.lock="fullScreenLoading">
+    <div class="container" style="min-width: 1100px">
+      <!--<div class="navbar-translate" style="text-align: center;vertical-align: middle;">-->
+      <!--<span>-->
+      <!--<a href="javascript:;">-->
+      <!--<img :src="defaultValue.image" style="height: 50px;object-fit: contain;" >-->
+      <!--</a>-->
+      <!--</span>-->
+      <!--<span  style="margin-bottom: 20px"><a style="font-size: 25px">众测</a></span>-->
+      <!--<button-->
+      <!--type="button"-->
+      <!--data-toggle="collapse"-->
+      <!--aria-expanded="false"-->
+      <!--aria-label="Toggle navigation"-->
+      <!--@click="openNavBarFunc"-->
+      <!--v-bind:class="['navbar-toggler',{ 'open-fixed': openNavBar}]"-->
+      <!--&gt;-->
+      <!--<span class="navbar-toggler-icon"></span>-->
+      <!--<span class="navbar-toggler-icon"></span>-->
+      <!--<span class="navbar-toggler-icon"></span>-->
+      <!--</button>-->
+      <!--</div>-->
+      <div>
+        <ul class="navbar-nav ml-auto">
+          <li class="dropdown nav-item">
+            <router-link to="/home">
+              <a data-toggle="dropdown">
+                <img style="height: 50px;padding-top: 10px" :src="defaultValue.image">
+              </a>
+            </router-link>
+          </li>
+          <li class="dropdown nav-item">
+            <router-link to="/home">
+              <a class="dropdown-toggle nav-link" data-toggle="dropdown">
+                <span style="font-size: 20px">群智众测平台</span>
+              </a>
+            </router-link>
+          </li>
+        </ul>
       </div>
-      <div class="collapse navbar-collapse" v-bind:style="{right:openNavBar?'230px':'0'}">
+      <div style="margin-left: 0; flex: auto">
         <ul class="navbar-nav ml-auto">
+
           <li class="dropdown nav-item">
             <router-link to="/home">
               <a class="dropdown-toggle nav-link" data-toggle="dropdown">
@@ -34,13 +58,24 @@
               </a>
             </router-link>
           </li>
+
+        </ul>
+      </div>
+      <div>
+        <ul class="navbar-nav ml-auto">
+
           <li class="dropdown nav-item">
-            <router-link to="/mine">
+            <router-link v-if="isLogin" to="/mine">
               <a class="dropdown-toggle nav-link" data-toggle="dropdown">
                 <img class="icon" src="@/assets/img/mine_icon.svg">
                 <span>我的众测</span>
               </a>
             </router-link>
+            <a v-if="!isLogin" class="dropdown-toggle nav-link" data-toggle="dropdown"
+               :href="loginUrl">
+              <img class="icon" src="@/assets/img/mine_icon.svg">
+              <span>登录</span>
+            </a>
             <div class="dropdown-menu dropdown-with-icons">
               <a href="./sections.html#headers" class="dropdown-item">
                 <i class="material-icons"></i> Headers
@@ -50,40 +85,541 @@
               </a>
             </div>
           </li>
+          <li class="dropdown nav-item" style="margin-left: 50px">
+            <router-link v-if="isLogin" to="/mine">
+              <a data-toggle="dropdown">
+                <img class="user-img" :src="defaultValue.image">
+              </a>
+            </router-link>
+          </li>
+          <el-dropdown v-if="isLogin">
+            <span class="dropdown-toggle nav-link el-dropdown-link">{{user.userVO.name}}<i
+              class="el-icon-arrow-down el-icon--right"></i>
+            </span>
+            <el-dropdown-menu slot="dropdown">
+              <el-dropdown-item v-if="rolesPermissions.isSystemAdministrator">
+                <router-link :to="{ name: 'AuthenticationManage'}">
+                  <el-link icon="el-icon-view" :underline="false">
+                    审核认证信息
+                  </el-link>
+                </router-link>
+              </el-dropdown-item>
+              <el-dropdown-item v-if="user.authStatus.text == '审核通过' && user.userVO.authType=='agency'">
+                <router-link :to="{ name: 'Agency',params:{userId:user.userVO.id}}">
+                  <el-link icon="el-icon-edit" :underline="false">
+                    修改机构信息
+                  </el-link>
+                </router-link>
+              </el-dropdown-item>
+              <el-dropdown-item v-if="user.authStatus.text == '未实名认证' && !rolesPermissions.isSystemAdministrator">
+                <router-link :to="{ name: 'AuthenticationIndex'}">
+                  <el-link type="info" icon="el-icon-warning-outline" :underline="false">
+                    未实名认证
+                  </el-link>
+                </router-link>
+              </el-dropdown-item>
+              <el-dropdown-item v-if="user.authStatus.text == '认证审核中'" @click.native="handleClickAuthChecking()">
+                <el-link type="warning" icon="el-icon-loading" :underline="false">
+                  认证审核中
+                </el-link>
+              </el-dropdown-item>
+              <el-dropdown-item @click.native="handleClickAuthPass()" v-if="user.authStatus.text == '审核通过'">
+                <el-link type="primary" icon="el-icon-check" :underline="false">
+                  已认证
+                </el-link>
+              </el-dropdown-item>
+              <el-dropdown-item @click.native="handleClickAuthReject()" v-if="user.authStatus.text == '审核未通过'">
+                <el-link type="danger" icon="el-icon-close" :underline="false">
+                  认证失败
+                </el-link>
+              </el-dropdown-item>
+              <el-dropdown-item divided @click.native="userLogout()">登出</el-dropdown-item>
+            </el-dropdown-menu>
+          </el-dropdown>
+          <el-dialog title="认证信息审核中" :visible.sync="isShowAuthCheckingDialog" width="40%"
+                     :before-close="hideAuthCheckingDialog" center>
+            <span>
+              <el-card v-if="authInfo.type" class="box-card">
+                <div slot="header" class="clearfix">
+                  <span>认证信息</span>
+                </div>
+                <div class="text item">
+                  <ul v-if="authInfo.type=='个人'" style="list-style-type:none">
+                    <li>认证类型:{{authInfo.type}}认证</li>
+                    <li>认证姓名:{{authInfo.realName}}</li>
+                    <li>认证账户:{{authInfo.bankAccount}}</li>
+                    <li>认证地址:{{authInfo.address}}</li>
+                    <li>申请时间:{{authInfo.createTime}}</li>
+                    <li>认证状态:{{authInfo.status}}</li>
+                    <li>失败原因:{{authInfo.rejectReason}}</li>
+                  </ul>
+
+                  <ul v-if="authInfo.type=='机构'" style="list-style-type:none">
+                    <li>认证类型:{{authInfo.type}}认证</li>
+                    <li>认证姓名:{{authInfo.evaluationAgencyName}}</li>
+                    <li>认证账户:{{authInfo.bankAccount}}</li>
+                    <li>认证地址:{{authInfo.address}}</li>
+                    <li>申请时间:{{authInfo.createTime}}</li>
+                    <li>认证状态:{{authInfo.status}}</li>
+                    <li>失败原因:{{authInfo.rejectReason}}</li>
+                  </ul>
+
+                  <ul v-if="authInfo.type=='企业'" style="list-style-type:none">
+                    <li>认证类型:{{authInfo.type}}认证</li>
+                    <li>认证企业名称:{{authInfo.companyName}}</li>
+                    <li>认证法人姓名:{{authInfo.legalPersonName}}</li>
+                    <li>认证账户:{{authInfo.bankAccount}}</li>
+                    <li>统一信用代码:{{authInfo.unifiedSocialCreditCode}}</li>
+                    <li>认证地址:{{authInfo.address}}</li>
+                    <li>申请时间:{{authInfo.createTime}}</li>
+                    <li>认证状态:{{authInfo.status}}</li>
+                    <li>失败原因:{{authInfo.rejectReason}}</li>
+                  </ul>
+                </div>
+              </el-card>
+            </span>
+            <span slot="footer" class="dialog-footer">
+              <el-button size="mini" @click="hideAuthCheckingDialog">返回</el-button>
+              <el-button size="mini" type="danger" @click="deleteOldAuthInfo">放弃认证</el-button>
+              <el-button size="mini" type="primary" @click="handleUpdateAuthInfo">重新认证</el-button>
+            </span>
+          </el-dialog>
+          <el-dialog title="认证成功" :visible.sync="isShowAuthPassDialog" width="40%" :before-close="hideAuthPassDialog"
+                     center>
+            <span>
+              <el-card v-if="authInfo.type" class="box-card">
+                <div slot="header" class="clearfix">
+                  <span>认证信息</span>
+                </div>
+                <div class="text item">
+                  <ul v-if="authInfo.type=='个人'" style="list-style-type:none">
+                    <li>认证类型:{{authInfo.type}}认证</li>
+                    <li>认证姓名:{{authInfo.realName}}</li>
+                    <li>认证账户:{{authInfo.bankAccount}}</li>
+                    <li>认证地址:{{authInfo.address}}</li>
+                    <li>申请时间:{{authInfo.createTime}}</li>
+                    <li>认证状态:{{authInfo.status}}</li>
+                    <li>失败原因:{{authInfo.rejectReason}}</li>
+                  </ul>
+
+                  <ul v-if="authInfo.type=='机构'" style="list-style-type:none">
+                    <li>认证类型:{{authInfo.type}}认证</li>
+                    <li>认证姓名:{{authInfo.evaluationAgencyName}}</li>
+                    <li>认证账户:{{authInfo.bankAccount}}</li>
+                    <li>认证地址:{{authInfo.address}}</li>
+                    <li>申请时间:{{authInfo.createTime}}</li>
+                    <li>认证状态:{{authInfo.status}}</li>
+                    <li>失败原因:{{authInfo.rejectReason}}</li>
+                  </ul>
+
+                  <ul v-if="authInfo.type=='企业'" style="list-style-type:none">
+                    <li>认证类型:{{authInfo.type}}认证</li>
+                    <li>认证企业名称:{{authInfo.companyName}}</li>
+                    <li>认证法人姓名:{{authInfo.legalPersonName}}</li>
+                    <li>认证账户:{{authInfo.bankAccount}}</li>
+                    <li>统一信用代码:{{authInfo.unifiedSocialCreditCode}}</li>
+                    <li>认证地址:{{authInfo.address}}</li>
+                    <li>申请时间:{{authInfo.createTime}}</li>
+                    <li>认证状态:{{authInfo.status}}</li>
+                    <li>失败原因:{{authInfo.rejectReason}}</li>
+                  </ul>
+                </div>
+              </el-card>
+            </span>
+            <span slot="footer" class="dialog-footer">
+              <el-button size="mini" @click="hideAuthPassDialog">返回</el-button>
+            </span>
+          </el-dialog>
+          <el-dialog title="认证失败" :visible.sync="isShowAuthRejectDialog" width="40%"
+                     :before-close="hideAuthRejectDialog"
+                     center>
+            <span>
+              <el-card v-if="authInfo.type" class="box-card">
+                <div slot="header" class="clearfix">
+                  <span>认证信息</span>
+                </div>
+                <div class="text item">
+                  <ul v-if="authInfo.type=='个人'" style="list-style-type:none">
+                    <li>认证类型:{{authInfo.type}}认证</li>
+                    <li>认证姓名:{{authInfo.realName}}</li>
+                    <li>认证账户:{{authInfo.bankAccount}}</li>
+                    <li>认证地址:{{authInfo.address}}</li>
+                    <li>申请时间:{{authInfo.createTime}}</li>
+                    <li>认证状态:{{authInfo.status}}</li>
+                    <li>失败原因:{{authInfo.rejectReason}}</li>
+                  </ul>
+
+                  <ul v-if="authInfo.type=='机构'" style="list-style-type:none">
+                    <li>认证类型:{{authInfo.type}}认证</li>
+                    <li>认证姓名:{{authInfo.evaluationAgencyName}}</li>
+                    <li>认证账户:{{authInfo.bankAccount}}</li>
+                    <li>认证地址:{{authInfo.address}}</li>
+                    <li>申请时间:{{authInfo.createTime}}</li>
+                    <li>认证状态:{{authInfo.status}}</li>
+                    <li>失败原因:{{authInfo.rejectReason}}</li>
+                  </ul>
+
+                  <ul v-if="authInfo.type=='企业'" style="list-style-type:none">
+                    <li>认证类型:{{authInfo.type}}认证</li>
+                    <li>认证企业名称:{{authInfo.companyName}}</li>
+                    <li>认证法人姓名:{{authInfo.legalPersonName}}</li>
+                    <li>认证账户:{{authInfo.bankAccount}}</li>
+                    <li>统一信用代码:{{authInfo.unifiedSocialCreditCode}}</li>
+                    <li>认证地址:{{authInfo.address}}</li>
+                    <li>申请时间:{{authInfo.createTime}}</li>
+                    <li>认证状态:{{authInfo.status}}</li>
+                    <li>失败原因:{{authInfo.rejectReason}}</li>
+                  </ul>
+                </div>
+              </el-card>
+            </span>
+            <span slot="footer" class="dialog-footer">
+              <el-button size="mini" @click="hideAuthRejectDialog">返回</el-button>
+              <el-button size="mini" type="danger" @click="deleteOldAuthInfo">放弃认证</el-button>
+              <el-button size="mini" type="primary" @click="handleUpdateAuthInfo">修改认证信息</el-button>
+            </span>
+          </el-dialog>
+          <!--<li class="dropdown nav-item">-->
+          <!--<router-link v-if="isLogin" to="/mine">-->
+          <!--<a class="dropdown-toggle nav-link" data-toggle="dropdown">-->
+          <!--<span>{{user.userVO.name}}</span>-->
+          <!--</a>-->
+          <!--</router-link>-->
+          <!--</li>-->
+          <!--<li class="dropdown nav-item">-->
+          <!--<router-link v-if="isLogin" to="/mine">-->
+          <!--<div style="margin-top: 5px;margin-right: 20px">-->
+          <!--<el-tooltip class="item" effect="dark" content="认证成功" placement="bottom">-->
+          <!--<el-link type="info" disabled icon="el-icon-warning-outline">已认证</el-link>-->
+          <!--</el-tooltip>-->
+          <!--</div>-->
+          <!--</router-link>-->
+          <!--</li>-->
+          <!--<li class="dropdown nav-item">-->
+          <!--<router-link v-if="isLogin" to="/mine">-->
+          <!--<div style="margin-top: 5px;margin-right: 20px">-->
+          <!--<el-tooltip class="item" effect="dark" content="点击进行认证" placement="bottom">-->
+          <!--<el-link type="danger" icon="el-icon-warning-outline">未实名认证</el-link>-->
+          <!--</el-tooltip>-->
+          <!--</div>-->
+          <!--</router-link>-->
+          <!--</li>-->
+          <!--<li>-->
+          <!--<a v-if="isLogin" class="dropdown-toggle nav-link" data-toggle="dropdown" href="#" @click="userLogout()">-->
+          <!--<span>登出</span>-->
+          <!--</a>-->
+          <!--</li>-->
         </ul>
       </div>
     </div>
+
   </nav>
 </template>
 
 <script>
+import {
+  defaultValue,
+  deleteAuthInfo,
+  getCurrentAgencyAuthInfo,
+  getCurrentEnterpriseAuthInfo,
+  getCurrentIndividualAuthenInfo,
+  getCurrentUser,
+  getRolesPermissions,
+  logout,
+  storageGet,
+  storageSave
+} from '@/js/index'
+import {notify} from '@/constants/index'
 
 export default {
   name: 'header-container',
   data () {
     return {
+      user: {},
+      fullScreenLoading: true,
+      loginUrl: process.env.LOGIN_URL,
+      authInfo: {},
+      isShowAuthCheckingDialog: false,
+      isShowAuthRejectDialog: false,
+      isShowAuthPassDialog: false,
+      //loading: true,
       openNavBar: false,
+      defaultValue: defaultValue,
       userIdentity: '',
+      isLogin: false,
+      rolesPermissions: {}
     }
   },
+  mounted () {
+    this.$nextTick(() => {
+
+    })
+  },
+  watch: {
+    'user.authStatus' (val) {
+      this.user.authStatus = val
+      console.log('changed')
+      console.log(this.user.authStatus)
+    },
+    deep: true
+  },
   methods: {
     openNavBarFunc () {
       this.openNavBar = !this.openNavBar
     },
-    getCurrentUser () {
-      // Http.get(Apis.USER.GET_CURRENT_USER).then((res) => {
-      //   sessionStorage.setItem('user', JSON.stringify(res))
+    setCurrUserByHttp () {
+      // getCurrentUser().then((res) => {
+      //   console.log(res)
+      //   storageSave('user', res)
+      //   storageSave('rolesPermissions', getRolesPermissions(res.roleList))
+      //   this.isLogin = true
+      //   this.fullScreenLoading = false
+      // }).catch(error => {
+      //   this.fullScreenLoading = false
+      //   console.log(error)
+      //   if (error.status == 401) {
+      //     notify('warning', error.data)
+      //   } else {
+      //     notify('error', error.data)
+      //   }
+      // })
+    },
+    setUserInfo () {
+      // storageGet('user').then((res)=>{
+      //   if (res == null){
+      //     this.setCurrUserByHttp()
+      //   }else{
+      //     this.fullScreenLoading = false
+      //     this.isLogin = true
+      //   }
+      // }).catch((error)=>{
+      //   this.setCurrUserByHttp()
       // })
+      if (storageGet('user') == null) {
+        storageSave('rolesPermissions', {
+          'isRegionManager': false,
+          'isIndividualUser': false,
+          'isEnterpriseUser': false,
+          'isAgency': false,
+          'isSystemAdministrator': false
+        })
+        console.log('本地没有用户信息,开始加载用户信息')
+        getCurrentUser().then((res) => {
+          console.log(res)
+          storageSave('user', res)
+          this.user = res
+          this.rolesPermissions = getRolesPermissions(res.roleList)
+          storageSave('rolesPermissions', getRolesPermissions(res.roleList))
+          console.log('用户信息加载成功')
+          this.isLogin = true
+          this.fullScreenLoading = false
+        }).catch((error) => {
+          console.log('用户信息加载失败')
+          this.fullScreenLoading = false
+        })
+      } else {
+        this.user = storageGet('user')
+        this.fullScreenLoading = false
+        this.isLogin = true
+      }
+    },
+    getCurrentUserSuccess (res) {
+      console.log(res)
+      storageSave('user', res)
+      this.user = res
+      this.rolesPermissions = getRolesPermissions(res.roleList)
+      storageSave('rolesPermissions', getRolesPermissions(res.roleList))
+      console.log('用户信息加载成功')
+      this.isLogin = true
+      this.fullScreenLoading = false
     },
-    getUserIdentity () {
+    getCurrentUserFail (error) {
+      console.log('用户信息加载失败')
+      this.fullScreenLoading = false
+    },
+    userLogout () {
+      this.isLogin = false
+      logout().then((res) => {
+        this.$router.push({
+          name: 'Index',
+        })
+      })
 
+    },
+    showLoading () {
+      this.fullScreenLoading = true
+    },
+    hideLoading () {
+      this.fullScreenLoading = false
+    },
+    handleClickAuthReject () {
+      if (this.user.userVO.authType == 'agency') {
+        this.$router.push({
+          name: 'AgencyAuthentication',
+          params: {userId: this.user.userVO.id}
+        })
+      }
+      if (this.user.userVO.authType == 'enterprise') {
+        this.$router.push({
+          name: 'EnterpriseAuthentication',
+          params: {userId: this.user.userVO.id}
+        })
+      }
+      if (this.user.userVO.authType == 'personal') {
+        this.$router.push({
+          name: 'IndividualAuthentication',
+          params: {userId: this.user.userVO.id}
+        })
+      }
+
+      //this.getAuthInfo()
+    },
+    handleClickAuthPass () {
+      if (this.user.userVO.authType == 'agency') {
+        this.$router.push({
+          name: 'AgencyAuthentication',
+          params: {userId: this.user.userVO.id}
+        })
+      }
+      if (this.user.userVO.authType == 'enterprise') {
+        this.$router.push({
+          name: 'EnterpriseAuthentication',
+          params: {userId: this.user.userVO.id}
+        })
+      }
+      if (this.user.userVO.authType == 'personal') {
+        this.$router.push({
+          name: 'IndividualAuthentication',
+          params: {userId: this.user.userVO.id}
+        })
+      }
+      //this.getAuthInfo()
+    },
+    handleClickAuthChecking () {
+      //this.getAuthInfo()
+      if (this.user.userVO.authType == 'agency') {
+        this.$router.push({
+          name: 'AgencyAuthentication',
+          params: {userId: this.user.userVO.id}
+        })
+      }
+      if (this.user.userVO.authType == 'enterprise') {
+        this.$router.push({
+          name: 'EnterpriseAuthentication',
+          params: {userId: this.user.userVO.id}
+        })
+      }
+      if (this.user.userVO.authType == 'personal') {
+        this.$router.push({
+          name: 'IndividualAuthentication',
+          params: {userId: this.user.userVO.id}
+        })
+      }
+    },
+    showAuthRejectDialog () {
+      this.isShowAuthRejectDialog = true
+    },
+    showAuthPassDialog () {
+      this.isShowAuthPassDialog = true
+    },
+    showAuthCheckingDialog () {
+      this.isShowAuthCheckingDialog = true
+    },
+    hideAuthRejectDialog () {
+      this.isShowAuthRejectDialog = false
+    },
+    hideAuthPassDialog () {
+      this.isShowAuthPassDialog = false
+    },
+    hideAuthCheckingDialog () {
+      this.isShowAuthCheckingDialog = false
+    },
+    deleteOldAuthInfo () {
+      this.hideAuthCheckingDialog()
+      this.hideAuthRejectDialog()
+      this.hideAuthPassDialog()
+      this.showLoading()
+      deleteAuthInfo().then((res) => {
+        this.hideLoading()
+        notify('success', '成功删除认证信息')
+      }).catch((error) => {
+        this.hideLoading()
+        notify('error', '删除认证信息失败:' + error.data)
+      })
+    },
+    getAuthInfo () {
+      this.showLoading()
+      if (this.user.userVO.authType == 'agency') {
+        getCurrentAgencyAuthInfo(this.user.userVO.id, this.getCurrentAgencyAuthInfoSuccess, this.getCurrentAgencyAuthInfoFail)
+      }
+      if (this.user.userVO.authType == 'personal') {
+        getCurrentIndividualAuthenInfo(this.user.userVO.id, this.getCurrentIndividualAuthenInfoSuccess, this.getCurrentIndividualAuthenInfoFail)
+      }
+      if (this.user.userVO.authType == 'enterprise') {
+        getCurrentEnterpriseAuthInfo(this.user.userVO.id, this.getCurrentEnterpriseAuthInfoSuccess, this.getCurrentEnterpriseAuthInfoFail)
+      }
+    },
+    getCurrentAgencyAuthInfoSuccess () {
+      this.hideLoading()
+    },
+    getCurrentAgencyAuthInfoFail () {
+      this.hideLoading()
+    },
+    getCurrentIndividualAuthenInfoSuccess () {
+      this.hideLoading()
+    },
+    getCurrentIndividualAuthenInfoFail () {
+      this.hideLoading()
+    },
+    getCurrentEnterpriseAuthInfoSuccess () {
+      this.hideLoading()
+    },
+    getCurrentEnterpriseAuthInfoFail () {
+      this.hideLoading()
+    },
+    handleUpdateAuthInfo () {
+      this.hideAuthPassDialog()
+      this.hideAuthRejectDialog()
+      this.hideAuthCheckingDialog()
+      if (this.user.userVO.authType == 'personal') {
+        this.$router.push({
+          name: 'IndividualAuthentication',
+          params: {
+            userId: this.authInfo.userId
+          }
+        })
+      }
+      if (this.authInfo.type == 'enterprise') {
+        this.$router.push({
+          name: 'EnterpriseAuthentication',
+          params: {
+            userId: this.authInfo.userId
+          }
+        })
+      }
+      if (this.authInfo.type == 'agency') {
+        this.$router.push({
+          name: 'AgencyAuthentication',
+          params: {
+            userId: this.authInfo.userId
+          }
+        })
+      }
     }
   },
-  mounted () {
-    this.$nextTick(() => {
-      this.getCurrentUser()
+  created () {
+    var self = this
+    this.$root.$on('user', function (val) {
+      self.user = val
     })
   },
+  beforeMount () {
+    this.setUserInfo()
+    // if (storageGet('user' != null)){
+    //   this.isLogin = true
+    // }
+    console.log(this.isLogin)
+  }
 }
 </script>
 

+ 82 - 18
src/components/commons/ProjectItem.vue

@@ -1,21 +1,49 @@
 <template>
   <div class="project-item-container">
-    <span class="col-xl-2 col-lg-3 col-md-4 col-sm-1">
-      <img class="project-cover" src="@/assets/img/home_ban1.jpg">
-    </span>
-    <span class="project-title col-md-2 col-sm-10">{{project.name}}</span>
-    <span class="project-title col-md-2 col-sm-10">{{project.id}}</span>
-    <span class="col-md-2 col-sm-10">
-      <span
-        v-bind:class="['badge',{ 'ios-platform': item=='IOS','android-platform': item=='ANDROID','web-platform': item=='WEB'}]"
-        v-for="item in project.platform"
-      >{{item}}</span>
-    </span>
-    <span class="col-md-1 col-sm-5">¥{{project.price}}</span>
-    <span class="project-td">
-      <span class="btn btn-medium btn-info" @click="goToProjectDetail(projectId)">查看详情</span>
-    </span>
+    <!--<span class="col-xl-2 col-lg-3 col-md-4 col-sm-1" style="width: 150px">-->
+    <!--<img class="project-cover" src="@/assets/img/home_ban1.jpg">-->
+    <!--</span>-->
+    <!--<span class="project-title col-md-2 col-sm-10" style="width: 150px;font-size: 12px">{{project.name}}</span>-->
+    <!--<span class="project-title col-md-2 col-sm-10" style="width: 10%;font-size: 12px">{{project.id}}</span>-->
+    <!--<span class="col-md-2 col-sm-10" style="width: 10%">-->
+    <!--<span-->
+    <!--style="font-size: 10px;"-->
+    <!--v-bind:class="['badge',{ 'ios-platform': item=='IOS','android-platform': item=='ANDROID','web-platform': item=='WEB'}]"-->
+    <!--v-for="item in project.platform"-->
+    <!--&gt;{{item}}</span>-->
+    <!--</span>-->
+    <!--<span class="col-md-1 col-sm-5" style="width: 10%;font-size: 12px"><div class="badge">¥{{project.budget}}</div></span>-->
+    <!--<span class="project-td" style="width: 15%">-->
+    <!--<span class="btn btn-small btn-info" @click="goToProjectDetail(project.id)">查看详情</span>-->
+    <!--</span>-->
+    <el-row type="flex" align="middle" justify="center" style="font-size: 14px;">
+      <el-col :span="6" type="flex" align="middle" justify="center">
+        <el-badge :value="project.statusVO.text" class="item" :type="project.statusVO.style">
+          <img class="project-cover" src="@/assets/img/home_ban1.jpg">
+        </el-badge>
+      </el-col>
+      <el-col :span="6" type="flex" align="middle" justify="center">{{project.name}}</el-col>
+      <!--<el-col :span="4">{{project.id}}</el-col>-->
+      <el-col :span="6" type="flex" align="middle" justify="center">
+        <span style="font-size: 10px;"
+              v-bind:class="['badge',{ 'ios-platform': item=='IOS','android-platform': item=='ANDROID','web-platform': item=='WEB'}]"
+              v-for="item in project.platform"
+        >{{item}}</span>
+      </el-col>
+      <el-col :span="2" type="flex" align="middle" justify="center">
+        <div class="badge">¥{{project.budget}}</div>
+      </el-col>
+      <el-col :span="4" type="flex" align="middle" justify="center">
+        <el-badge v-if="project.needHandle" is-dot class="item">
+          <span class="btn btn-small btn-info" @click="goToProjectDetail(project.id)">查看详情</span>
+        </el-badge>
+        <span v-if="!project.needHandle" class="btn btn-small btn-info" @click="goToProjectDetail(project.id)">查看详情</span>
+      </el-col>
+    </el-row>
+
+
   </div>
+
 </template>
 
 <script>
@@ -48,9 +76,12 @@ export default {
 
 <style lang="less" scoped>
   .project-item-container {
-    padding: 20px;
+    /*padding: 20px;*/
+    padding-top: 10px;
+    padding-bottom: 10px;
     border: 1px solid #eee;
-    margin: 15px 5px;
+    margin-top: 5px;
+    margin-bottom: 5px;
     span {
       display: inline-block;
     }
@@ -67,6 +98,39 @@ export default {
   }
 
   .project-td {
-    padding: 15px;
+    //padding: 15px;
+  }
+
+  .el-row {
+    margin-bottom: 20px;
+    &:last-child {
+      margin-bottom: 0;
+    }
+  }
+
+  .el-col {
+    border-radius: 4px;
+  }
+
+  .bg-purple-dark {
+    background: #99a9bf;
+  }
+
+  .bg-purple {
+    background: #d3dce6;
+  }
+
+  .bg-purple-light {
+    background: #e5e9f2;
+  }
+
+  .grid-content {
+    border-radius: 4px;
+    min-height: 36px;
+  }
+
+  .row-bg {
+    //padding: 10px 0;
+    background-color: #f9fafc;
   }
 </style>

+ 22 - 25
src/components/commons/TaskItem.vue

@@ -1,24 +1,28 @@
 <template>
   <div class="task-item-container">
-       <span class="col-xl-2 col-lg-3 col-md-4 col-sm-1">
-        <img class="task-cover" src="@/assets/img/home_ban1.jpg">
-      </span>
-    <span class="task-title col-md-2 col-sm-10">{{taskTable.title}}</span>
-    <span class="col-md-1 col-sm-5 ">{{serviceType[taskTable.serviceType]}}</span>
-    <span class="col-md-1 col-sm-5 ">¥{{taskTable.price}}</span>
-    <!--<span class="col-md-1 col-sm-5 ">{{platformType}}</span>-->
-    <span class="col-md-1 col-sm-5 ">{{taskStatus[taskTable.status]}}</span>
-    <span class="task-td">
-       <span class="btn btn-medium btn-info" @click="goToTaskDetail(taskTable.projectId,taskTable.id)">查看详情</span>
-       </span>
-
+    <el-row type="flex" align="middle" justify="center" style="font-size: 14px;">
+      <el-col :span="6" type="flex" align="middle" justify="center">
+        <el-badge :value="taskTable.statusVO.text" class="item" :type="taskTable.statusVO.style">
+          <img class="task-cover" src="@/assets/img/home_ban1.jpg">
+        </el-badge>
+      </el-col>
+      <el-col :span="5" type="flex" align="middle" justify="center">{{taskTable.title}}</el-col>
+      <!--<el-col :span="4">{{project.id}}</el-col>-->
+      <el-col :span="5" type="flex" align="middle" justify="center">{{taskTable.serviceType}}</el-col>
+      <el-col :span="4" type="flex" align="middle" justify="center">
+        <div class="badge" type="flex" align="middle" justify="center">
+          ¥{{taskTable.quotePrice==null?0:taskTable.quotePrice}}
+        </div>
+      </el-col>
+      <el-col :span="4" type="flex" align="middle" justify="center"><span class="btn btn-medium btn-info"
+                                                                          @click="goToTaskDetail(taskTable.projectId,taskTable.id)">查看详情</span>
+      </el-col>
+    </el-row>
   </div>
 </template>
 
 <script>
-import ServiceType from '@/constants/enum/service-type'
 import TaskStatus from '@/constants/enum/task-status'
-import PlatformType from '@/constants/enum/platform-type'
 
 export default {
   name: 'Task-Item',
@@ -29,18 +33,10 @@ export default {
     return {
       taskTable: this.task,
       taskStatus: TaskStatus,//TaskStatus[this.task.status],
-      serviceType: ServiceType,//[this.task.serviceType],
-      platformType: []
     }
   },
   mounted () {
-    this.taskStatus = TaskStatus[this.taskTable.status]
-    this.serviceType = ServiceType[this.taskTable.serviceType]
     let plats = []
-    for (let i in this.taskTable.platform) {
-      plats.push(PlatformType[i])
-    }
-    this.platformType = plats
     //console.log(this.platformType)
   }
   ,
@@ -60,9 +56,10 @@ export default {
 
 <style lang="less" scoped>
   .task-item-container {
-    padding: 20px;
+    padding-top: 10px;
+    padding-bottom: 10px;
     border: 1px solid #eee;
-    margin: 15px 5px;
+    /*margin: 15px 5px;*/
     span {
       display: inline-block;
     }
@@ -79,6 +76,6 @@ export default {
   }
 
   .task-td {
-    padding: 15px;
+    /*padding: 15px;*/
   }
 </style>

File diff suppressed because it is too large
+ 532 - 343
src/components/project/Project.vue


+ 242 - 152
src/components/project/ProjectCreate.vue

@@ -1,65 +1,47 @@
 <template>
-  <div class="create-container">
-    <div class="title h1">申请项目</div>
+  <div class="create-container" v-loading="loading">
+    <div class="title h1">创建项目</div>
     <div class="create-body">
       <el-form :model="project" :rules="rules" ref="project" label-width="12%" class="demo-project">
         <el-form-item label="项目名称" prop="name">
-          <el-input v-model="project.name"></el-input>
+          <el-input size="small" v-model="project.name" placeholder="请输入项目名称"></el-input>
         </el-form-item>
-        <el-form-item label="联系方式" prop="contact">
-          <div>
-            <el-row :gutter="2">
-              <el-col :span="2">
-                <span>联系人</span>
-              </el-col>
-              <el-col :span="10">
-                <el-input v-model="project.contactName" placeholder="请输入联系人姓名"></el-input>
-              </el-col>
-            </el-row>
-            <el-row :gutter="2">
-              <el-col :span="2">
-                <span>联系人电话</span>
-              </el-col>
-              <el-col :span="10">
-                <el-input v-model="project.contactPhone" placeholder="请输入联系人电话"></el-input>
-              </el-col>
-            </el-row>
-          </div>
-        </el-form-item>
-        <el-form-item label="平台" prop="platform">
-          <el-checkbox-group v-model="project.platform">
-            <el-checkbox label="IOS">IOS</el-checkbox>
-            <el-checkbox label="ANDROID">ANDROID</el-checkbox>
-            <el-checkbox label="WEB">WEB</el-checkbox>
-          </el-checkbox-group>
+        <el-form-item label="联系人" prop="contactName">
+          <el-input size="small" v-model="project.contactName" placeholder="请输入联系人姓名"></el-input>
         </el-form-item>
-        <el-form-item label="需求描述" prop="desc">
-          <el-input type="textarea" v-model="project.desc"></el-input>
+        <el-form-item label="手机号" prop="contactPhone">
+          <el-input size="small" v-model="project.contactPhone" placeholder="请输入联系人电话"></el-input>
         </el-form-item>
-        <el-form-item label="价格" prop="price">
-          <el-input type="number" v-model="project.price">
+        <el-form-item label="预算" prop="budget">
+          <el-input size="small" type="number" v-model="project.budget" placeholder="请输入项目预算">
             <template slot="append">¥</template>
           </el-input>
         </el-form-item>
+        <el-form-item label="需求描述" prop="desc">
+          <el-input type="textarea" style="width: 400px" v-model="project.desc"
+                    placeholder="请输入对项目的描述"></el-input>
+        </el-form-item>
+
+        <!--<el-form-item label="价格" prop="price">-->
+        <!--<el-input type="number" v-model="project.price">-->
+        <!--<template slot="append">¥</template>-->
+        <!--</el-input>-->
+        <!--</el-form-item>-->
+        <el-form-item label="平台" prop="platform">
+          <el-checkbox-group v-model="project.platform">
+            <span v-for="(item,index) in platforms" :key="index">
+              <el-checkbox :label="item">{{ item }}&nbsp;&nbsp;&nbsp;&nbsp;</el-checkbox>
+            </span>
+          </el-checkbox-group>
+        </el-form-item>
         <el-form-item label="服务类型" prop="type">
           <el-checkbox-group v-model="project.type">
-            <el-checkbox label="0" name="0">接口测试</el-checkbox>
-            <el-checkbox label="1" name="1">安全漏洞扫描</el-checkbox>
-            <el-checkbox label="2" name="2">风险评估服务</el-checkbox>
-            <el-checkbox label="3" name="3">源代码安全审计服务</el-checkbox>
-            <el-checkbox label="4" name="4">功能测试服务</el-checkbox>
-            <el-checkbox label="5" name="5">性能测试</el-checkbox>
-            <el-checkbox label="6" name="6">功能和易用性测试</el-checkbox>
+            <span v-for="(item,index) in serviceType" :key="index">
+              <el-checkbox :label="item" name="type">{{item}}&nbsp;&nbsp;&nbsp;&nbsp;</el-checkbox>
+            </span>
           </el-checkbox-group>
         </el-form-item>
-        <el-form-item label="用途" prop="usage">
-          <el-input v-model="project.usage"></el-input>
-        </el-form-item>
-        <el-form-item label="预算" prop="budget">
-          <el-input type="number" v-model="project.budget">
-            <template slot="append">¥</template>
-          </el-input>
-        </el-form-item>
+
         <el-form-item label="项目可见性" prop="resource">
           <el-tabs
             :tab-position="tabPosition"
@@ -67,13 +49,9 @@
             style="max-height: 200px;"
           >
             <el-tab-pane :label="resourceType[0]" name="0">
-              <el-radio-group v-model="project.institution">
-                <el-radio
-                  :label="item"
-                  name="type"
-                  v-for="item,index in institutionArray"
-                  :key="index"
-                ></el-radio>
+              <el-radio-group v-model="project.institution" prop="institution">
+                <el-radio :label="item" name="type" v-for="item,index in institutionArray" :key="index">{{item.name}}
+                </el-radio>
               </el-radio-group>
             </el-tab-pane>
             <el-tab-pane :label="resourceType[1]" name="1">
@@ -89,6 +67,7 @@
         </el-form-item>
         <el-form-item label="需求文档" prop="doc">
           <el-upload
+            style="width: 400px"
             drag
             class="upload-demo"
             action=""
@@ -105,12 +84,12 @@
               将文件拖到此处,或
               <em>点击上传</em>
             </div>
-            <div class="el-upload__tip" slot="tip">请上传需求文档</div>
           </el-upload>
         </el-form-item>
         <el-form-item label="安装包" prop="file">
           <el-upload
             drag
+            style="width: 400px"
             class="upload-demo"
             action=""
             :on-remove="handleRemove"
@@ -125,12 +104,12 @@
               将文件拖到此处,或
               <em>点击上传</em>
             </div>
-            <div class="el-upload__tip" slot="tip">只能上传Android或IOS安装包文件</div>
           </el-upload>
         </el-form-item>
         <el-form-item label="项目截止时间" prop="datetime">
           <div class="block">
             <el-date-picker
+              size="small"
               v-model="project.datetime"
               type="datetime"
               placeholder="选择截止时间"
@@ -149,14 +128,20 @@
 </template>
 
 <script>
-import Enum from '@/constants/enum/index'
 import Http from '@/js/http.js'
 import Apis from '@/js/api.js'
 import provincecity from '@/components/commons/ProvinceCity'
 import provinceCityJSON from '@/constants/provinceCity.json'
-import ServiceType from '@/constants/enum/service-type'
 import ResourceType from '@/constants/enum/resource-type'
 import {notify} from '@/constants/index'
+import {
+  checkFileType,
+  getAllInstitutions,
+  getAllPlatformTypes,
+  getAllServiceTypes,
+  getProvinceNameByProvinceCode,
+  storageGet
+} from '@/js/index'
 
 export default {
   name: 'ProjectCreate',
@@ -175,13 +160,15 @@ export default {
       }
     }
     return {
+      user: {},
+      loading: false,
       tabPosition: 'top',
-      institutionArray: Enum.institution,
-      platformType: [],
-      serviceType: ServiceType,
+      institutionArray: [],
+      platforms: [],
+      serviceType: [],
       resourceType: ResourceType,
       project: {
-        userId: 3,
+        userId: 0,
         name: '',
         contactName: '',
         contactPhone: '',
@@ -194,7 +181,7 @@ export default {
         fileUrl: '',
         resource: '0',
         location: {provinceCode: '3200', cityCode: '3201'},
-        institution: '',
+        institution: {},
         datetime: '',
         price: '',
         usage: '',
@@ -228,9 +215,17 @@ export default {
       },
       rules: {
         name: [
-          {required: true, message: '请输入项目名称', trigger: 'blur'}
+          {required: true, message: '请输入项目名称', trigger: 'blur'},
+          {min: 5, max: 50, message: '项目名称长度在 5 到 50 个字符', trigger: 'blur'}
+        ],
+        contactName: [
+          {required: true, message: '请输入联系人姓名', trigger: 'blur'}
           // { min: 3, max: 5, message: "长度在 3 到 5 个字符", trigger: "blur" }
         ],
+        contactPhone: [
+          {required: true, message: '请输入手机号', trigger: 'blur'},
+          //{min: 11, max: 11, message: '请输入正确的手机号', trigger: 'blur'}
+        ],
         type: [
           {
             type: 'array',
@@ -247,15 +242,33 @@ export default {
             trigger: 'change'
           }
         ],
-        desc: [{required: true, message: '请填写活动形式', trigger: 'blur'}],
-        contact: [{validator: validatePass, trigger: 'blur'}],
+        desc: [{required: false, message: '请填写描述', trigger: 'blur'}],
+        //price: [{required: true, message: '请填写价格', trigger: 'blur'}],
+        budget: [
+          {required: true, message: '预算不可为空', trigger: 'blur'},
+          {
+            validator: (rule, value, callback) => {
+              if(value < 0){
+                callback(new Error('请输入不小于0的数'))
+              } else {
+                callback()
+              }
+            }, trigger: 'blur'
+          },
+        ],
         resource: [
+          {required: true},
           {
-            required: true,
-            message: '请选择项目可见性',
-            trigger: 'change'
-          }
-        ]
+            validator: (rule, value, callback) => {
+              if (value == 0 && this.project.institution.id == null) {
+                callback(new Error('定向发布至少要选择一个区域管理员'))
+              } else {
+                callback()
+              }
+            }, trigger: 'change'
+          },
+        ],
+        datetime:[{required: true, message: '截止时间不可为空', trigger: 'blur'}],
       }
     }
   },
@@ -265,24 +278,30 @@ export default {
     })
   },
   watch: {
-    'project.institution' () {
-      if (this.project.institution) {
-        this.$refs.addFormProvince.resetProviceCity()
-        this.project.location = {provinceCode: '', cityCode: ''}
-      }
-    },
-    'project.location' () {
-      if (this.project.location.provinceCode || this.project.location.cityCode) {
-        this.project.institution = ''
-      }
+    serviceType (val) {
+      this.serviceType = val
     },
-    'project.resource' () {
-      if (this.project.resource == '2') {
-        this.$refs.addFormProvince.resetProviceCity()
-        this.project.institution = ''
-        this.project.location = {provinceCode: '', cityCode: ''}
-      }
+    institutionArray (val) {
+      this.institutionArray = val
     },
+    // 'project.institution' () {
+    //   if (this.project.institution) {
+    //     this.$refs.addFormProvince.resetProviceCity()
+    //     this.project.location = {provinceCode: '', cityCode: ''}
+    //   }
+    // },
+    // 'project.location' () {
+    //   if (this.project.location.provinceCode || this.project.location.cityCode) {
+    //     this.project.institution = ''
+    //   }
+    // },
+    // 'project.resource' () {
+    //   if (this.project.resource == '2') {
+    //     this.$refs.addFormProvince.resetProviceCity()
+    //     this.project.institution = ''
+    //     this.project.location = {provinceCode: '', cityCode: ''}
+    //   }
+    // },
     deep: true
   },
   methods: {
@@ -308,54 +327,59 @@ export default {
       }
     },
     init () {
+      this.setServiceType()
+      this.setPlatforms()
+      this.setInstitution()
+      this.setUserInfo()
       // this.project.platform.map(item => {
       //   this.platformType.push(PlatformType[item])
       // })
     },
-    submitForm (formName) {
-      //console.log(this.project)
-      const newProject = {
-        userId: 3,
-        name: this.project.name,
-        type: this.project.type,
-        platform: this.project.platform,
-        desc: this.project.desc,
-        resource: this.project.resource,
-        location: this.project.location,
-        institution: this.project.institution,
-        contactName: this.project.contactName,
-        contactPhone: this.project.contactPhone,
-        doc: this.project.requireDocUrl,
-        file: this.project.fileUrl,
-        budget: this.project.budget,
-        datetime: this.project.datetime,
-        usage: this.project.usage,
-        price: this.project.price
-      }
-      Http.post(Apis.PROJECT.CREATE_PROJECT, newProject).then((res) => {
-        notify('success', '创建成功')
-        if (window.history.length <= 1) {
-          this.$router.push({path: '/'})
-          return false
+    submitForm () {
+      this.$refs['project'].validate(valid => {
+        if (valid) {
+          //console.log(this.project)
+          this.showLoading()
+          const newLocation = getProvinceNameByProvinceCode(this.project.location.provinceCode, this.project.location.cityCode)
+          const newProject = {
+            userId: this.user.userVO.id,
+            name: this.project.name,
+            type: this.project.type,
+            platform: this.project.platform,
+            desc: this.project.desc,
+            resource: this.project.resource,
+            location: newLocation,
+            institution: this.project.institution.id,
+            contactName: this.project.contactName,
+            contactPhone: this.project.contactPhone,
+            doc: this.project.requireDocUrl,
+            file: this.project.fileUrl,
+            budget: this.project.budget,
+            datetime: this.project.datetime,
+            usage: this.project.usage,
+            price: this.project.price
+          }
+          Http.post(Apis.PROJECT.CREATE_PROJECT, newProject).then((res) => {
+            //notify('success', '创建成功')
+            this.hideLoading()
+            this.createProjectSuccess(res.projectDetails.id)
+            // if (window.history.length <= 1) {
+            //   this.$router.push({path: '/'})
+            //   return false
+            // } else {
+            //   this.$router.go(-1)
+            // }
+          }).catch(error => {
+            //console.log(error)
+            notify('error', error.data)
+
+          })
         } else {
-          this.$router.go(-1)
+          console.log(valid)
+          notify('error','表单填写错误!')
+          return false
         }
-      }).catch(error => {
-        //console.log(error)
-        notify('error', error.data.msg)
-
       })
-      // this.$refs[formName].validate(valid => {
-      //   if (valid) {
-      //     Http.post(Apis.PROJECT.CREATE_PROJECT, this.project).then((res) => {
-      //       console.log(res.status)
-      //     })
-      //     //提交 project
-      //   } else {
-      //     console.log('error submit!!')
-      //     return false
-      //   }
-      // })
     },
     resetForm (formName) {
       this.$refs[formName].resetFields()
@@ -376,27 +400,18 @@ export default {
       this.project.budget = ''
     },
     beforeApkUpload (file) {
-      console.log(file)
-      const isAPK = file.type === 'application/vnd.android.package-archive'
-      const isDMG = file.type === 'application/octet-stream'
-
-      if (!isAPK && !isDMG) {
-        this.$message.error('上传安装包只能是 APK 或 DMG 格式!')
-      }
-      return isAPK || isDMG
+      const fileType = ['exe', 'apk', 'dmg']
+      return checkFileType(file, fileType, this.beforeApkUploadError)
+    },
+    beforeApkUploadError () {
+      this.$message.error('上传文件只能是exe,dmg,apk格式!')
     },
     beforeFileUpload (file) {
-      const isPDF = file.type === 'application/pdf'
-      const isDOC = file.type === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
-      const isEXCEL = file.type === 'application/vnd.ms-excel'
-      const isXLS = file.type === 'application/x-xls'
-      const isTXT = file.type === 'text/plain'
-      const isXLSX = file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
-      //console.log(file)
-      if (!(isDOC || isEXCEL || isPDF || isTXT || isXLS || isXLSX)) {
-        this.$message.error('上传文件只能是 PDF 、 DOC 、DOCX 、XLS、TXT、XLSX 格式!')
-      }
-      return isDOC || isEXCEL || isPDF || isTXT || isXLS || isXLSX
+      const fileTypeList = ['pdf', 'xls', 'xlsx', 'doc', 'docx', 'txt']
+      return checkFileType(file, fileTypeList, this.beforeFileUploadError)
+    },
+    beforeFileUploadError () {
+      this.$message.error('上传文件只能是 PDF 、 DOC 、DOCX 、XLS、TXT、XLSX 格式!')
     },
     loadData () {
       Http.get(Apis.PAGE.PROJECT_DETAIL_PAGE).then((res) => {
@@ -417,32 +432,78 @@ export default {
       //return this.$confirm(`确定移除 ${file.name}?`)
     },
     uploadRequireDoc (param) {
+      this.showLoading()
       const formData = new FormData()
       let config = {
         //添加请求头
         headers: {'Content-Type': 'multipart/form-data'},
       }
       formData.append('file', param.file)
-      Http.upload(Apis.FILE.REQUIREMENT_FILE.replace('{userId}', 3), formData, config).then((res) => {
+      Http.upload(Apis.FILE.REQUIREMENT_FILE.replace('{userId}', this.user.userVO.id), formData, config).then((res) => {
         //console.log('上传成功')
+        this.hideLoading()
+        notify('success', '需求文档上传成功')
         this.project.requireDocUrl = res.data
-        console.log(this.project.doc)
+        //console.log(this.project.doc)
         //console.log(res.data)
+      }).catch((error) => {
+        this.hideLoading()
+        notify('error', '需求文档上传失败:' + error.data)
       })
 
     },
     uploadApkFile (param) {
+      this.showLoading()
       const formData = new FormData()
       let config = {
         //添加请求头
         headers: {'Content-Type': 'multipart/form-data'},
       }
       formData.append('file', param.file)
-      Http.upload(Apis.FILE.APK.replace('{userId}', 3), formData, config).then((res) => {
-        console.log('上传成功')
+      Http.upload(Apis.FILE.APK.replace('{userId}', this.user.userVO.id), formData, config).then((res) => {
+        this.hideLoading()
+        notify('success', '文件上传成功')
         this.project.fileUrl = res.data
         console.log(res)
+      }).catch((error) => {
+        this.hideLoading()
+        notify('error', '文件上传失败:' + error.data)
       })
+    },
+    setServiceType () {
+      getAllServiceTypes().then((res) => {
+        this.serviceType = res
+      }).catch((error) => {
+        notify('error', '获取项目服务类型列表失败')
+      })
+    },
+    setPlatforms () {
+      this.platforms = getAllPlatformTypes()
+    },
+    setInstitution () {
+      getAllInstitutions().then((res) => {
+        this.institutionArray = res
+      })
+    },
+    setUserInfo () {
+      this.user = storageGet('user')
+    },
+    createProjectSuccess (projectId) {
+      this.$alert('项目创建成功', '创建成功', {
+        confirmButtonText: '确定',
+        callback: action => {
+          this.$router.push({
+            name: 'Project',
+            params: {projectId: projectId}
+          })
+        }
+      })
+    },
+    showLoading () {
+      this.loading = true
+    },
+    hideLoading () {
+      this.loading = false
     }
   }
 }
@@ -465,5 +526,34 @@ export default {
     max-height: 120px !important;
     overflow: auto;
   }
+
+  .el-input {
+    width: 400px;
+  }
 </style>
 
+<!--<el-form-item label="联系方式" prop="contact">-->
+<!--<div>-->
+<!--<el-row :gutter="2">-->
+<!--<el-col :span="2">-->
+<!--<span>联系人</span>-->
+<!--</el-col>-->
+<!--<el-col :span="10">-->
+<!--<el-input v-model="project.contactName" placeholder="请输入联系人姓名"></el-input>-->
+<!--</el-col>-->
+<!--</el-row>-->
+<!--<el-row :gutter="2">-->
+<!--<el-col :span="2">-->
+<!--<span>联系人电话</span>-->
+<!--</el-col>-->
+<!--<el-col :span="10">-->
+<!--<el-input v-model="project.contactPhone" placeholder="请输入联系人电话"></el-input>-->
+<!--</el-col>-->
+<!--</el-row>-->
+<!--</div>-->
+<!--</el-form-item>-->
+
+
+<!--<el-form-item label="用途" prop="usage">-->
+<!--<el-input v-model="project.usage"></el-input>-->
+<!--</el-form-item>-->

+ 300 - 0
src/components/report/ProjectReport.vue

@@ -0,0 +1,300 @@
+<template>
+  <div class="create-container">
+    <div class="create-body" v-loading="loading">
+      <el-form :model="report" :rules="rules" ref="report" label-width="12%" class="demo-report">
+        <el-form-item label="报告名称" prop="name">
+          <el-input size="small" v-if="isModifyMode" v-model="report.name"></el-input>
+          <span v-if="!isModifyMode">{{report.name}}</span>
+        </el-form-item>
+        <el-form-item label="报告类型" prop="type">
+          <el-radio-group v-if="isModifyMode" v-model="report.type">
+            <span v-for="(item,index) in reportType" :key="index">
+              <el-radio :label="item" name="type">{{item}}</el-radio>
+            </span>
+          </el-radio-group>
+          <span v-if="!isModifyMode" class="badge">{{report.type}}</span>
+        </el-form-item>
+
+        <el-form-item label="测试对象" prop="target">
+          <el-input autosize v-if="isModifyMode" type="textarea" v-model="report.target"></el-input>
+          <span v-if="!isModifyMode">{{report.target}}</span>
+        </el-form-item>
+
+        <el-form-item label="测试内容" prop="content">
+          <el-input autosize v-if="isModifyMode" type="textarea" v-model="report.content"></el-input>
+          <span v-if="!isModifyMode">{{report.content}}</span>
+        </el-form-item>
+        <el-form-item prop="file" label="报告文件">
+          <el-upload
+            style="width: 400px"
+            v-if="isModifyMode"
+            drag
+            class="upload-demo"
+            action=""
+            :on-remove="handleRemove"
+            :before-remove="beforeRemove"
+            multiple
+            :limit="1"
+            :on-exceed="handleExceed"
+            :before-upload="beforeFileUpload"
+            :file-list="report.file"
+            :http-request="uploadReportFile"
+          >
+            <i class="el-icon-upload"></i>
+            <div class="el-upload__text">
+              将文件拖到此处,或
+              <em>点击上传</em>
+            </div>
+            <div class="el-upload__tip" slot="tip">请上传报告文件</div>
+          </el-upload>
+          <div v-if="!isModifyMode">
+            <span v-if="report.fileUrl==null">暂无文件</span>
+            <a :href="report.fileUrl" v-if="report.fileUrl!=null">
+              <el-link :underline="false" type="primary"><i class="el-icon-document"></i>下载文档</el-link>
+            </a>
+          </div>
+        </el-form-item>
+
+        <el-form-item label="结论" prop="conclusion">
+          <el-input autosize v-if="isModifyMode" type="textarea" v-model="report.conclusion"></el-input>
+          <span v-if="!isModifyMode">{{report.conclusion}}</span>
+        </el-form-item>
+        <el-form-item v-if="!isModifyMode">
+          <div class="btn btn-medium btn-info" @click="modifyForm()">修改</div>
+          <div class="btn btn-medium" @click="back()">返回</div>
+        </el-form-item>
+        <el-form-item v-if="isModifyMode">
+          <div class="btn btn-medium btn-info" @click="submitForm('report')">确认修改</div>
+          <div class="btn btn-medium" @click="resetForm('report')">重置</div>
+          <div class="btn btn-medium" @click="cancelCreate('report')">取消</div>
+        </el-form-item>
+      </el-form>
+    </div>
+  </div>
+</template>
+
+<script>
+import Http from '@/js/http.js'
+import Apis from '@/js/api.js'
+import {notify} from '@/constants/index'
+import {getAllReportTypes, storageGet} from '@/js/index'
+
+export default {
+  name: 'ProjectReport',
+  components: {},
+  data () {
+    return {
+      user: {},
+      loading: false,
+      reportId: 0,
+      projectId: '',
+      taskId: '',
+      isModifyMode: false,
+      reportType: [],
+      report: {
+        name: '',
+        type: '',
+        description: '',
+        target: '',
+        content: '',
+        file: [],
+        fileUrl: '',
+        conclusion: ''
+      },
+      rules: {
+        name: [
+          {required: true, message: '任务名称不可为空', trigger: 'blur'},
+          {min: 5, max: 50, message: '报告名称长度在 5 到 50 个字符', trigger: 'blur'}
+        ],
+        type: [
+          {required: true, message: '报告类型不可为空'},
+        ],
+        target: [
+          {required: true, message: '测试对象不可为空', trigger: 'blur'}
+        ],
+        content: [
+          {required: true, message: '测试内容不可为空', trigger: 'blur'}
+        ],
+        conclusion: [
+          {required: true, message: '结论不可为空', trigger: 'blur'}
+        ]
+      }
+    }
+  },
+  mounted () {
+    this.$nextTick(() => {
+      this.init()
+    })
+  },
+  methods: {
+    init () {
+      this.reportId = this.$route.params.reportId
+      this.projectId = this.$route.params.projectId
+      this.taskId = this.$route.params.taskId
+      this.setReportType()
+      this.setUserInfo()
+      this.loadData()
+    },
+    modifyForm () {
+      this.isModifyMode = true
+    },
+    submitForm (formName) {
+      this.$refs['report'].validate(valid => {
+        if (valid) {
+          this.isModifyMode = false
+          this.showLoading()
+          const newReport = {
+            name: this.report.name,
+            scope: this.taskId == null ? 0 : 1,
+            type: this.report.type,
+            dependencyCode: this.taskId == null ? this.projectId : this.taskId,
+            target: this.report.target,
+            content: this.report.content,
+            file: '123.pdf',
+            conclusion: this.report.conclusion
+          }
+          console.log(newReport)
+          Http.put(Apis.REPORT.UPDATE_PROJECT_REPORT.replace('{projectId}', this.projectId).replace('{reportId}', this.reportId), newReport).then((res) => {
+            console.log(res)
+            notify('success', '修改成功')
+            this.hideLoading()
+            this.isModifyMode = false
+          }).catch((error) => {
+            this.hideLoading()
+            notify('error', error.data)
+          })
+          //提交 report
+        } else {
+          notify('error', '表单填写有误')
+          return false
+        }
+      })
+    },
+    resetForm (formName) {
+      this.$refs[formName].resetFields()
+      this.report.name = ''
+      this.report.target = ''
+      this.report.content = ''
+      this.report.file = ''
+      this.report.type = ''
+      this.report.conclusion = ''
+    },
+    cancelCreate () {
+      this.isModifyMode = false
+      //请求 report
+    },
+    handleRemove (file, fileList) {
+      console.log(file, fileList)
+    },
+    handleExceed (files, fileList) {
+      this.$message.warning(
+        `当前限制选择 1 个文件,本次选择了 ${
+          files.length
+          } 个文件,共选择了 ${files.length + fileList.length} 个文件`
+      )
+    },
+    beforeRemove (file, fileList) {
+      //return this.$confirm(`确定移除 ${file.name}?`)
+    },
+    beforeFileUpload (file) {
+      console.log(file)
+      const isPDF = file.type === 'application/pdf'
+      const isDOC = file.type === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
+      const isEXCEL = file.type === 'application/vnd.ms-excel'
+      const isXLS = file.type === 'application/x-xls'
+      const isTXT = file.type === 'text/plain'
+      const isXLSX = file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
+      //console.log(file)
+      if (!(isDOC || isEXCEL || isPDF || isTXT || isXLS || isXLSX)) {
+        this.$message.error('上传文件只能是 PDF 、 DOC 、DOCX 、XLS、TXT、XLSX 格式!')
+      }
+      return isDOC || isEXCEL || isPDF || isTXT || isXLS || isXLSX
+    },
+    back () {
+      this.$router.push({
+        name: 'Project',
+        params: {projectId: this.projectId}
+      })
+    },
+    loadData () {
+      //pro1564487183259
+      //pro1564487183259_task1564487274060
+      //pro1564487183259pro1564487183259_task1564487274060_rep1564488510500
+      this.showLoading()
+      Http.get(Apis.REPORT.GET_PROJECT_REPORT.replace('{projectId}', this.projectId).replace('{reportId}', this.reportId)).then((res) => {
+        this.report.name = res.crowdReportVO.name
+        this.report.crowdTestTaskId = res.crowdReportVO.crowdTestTaskId
+        this.report.scope = res.crowdReportVO.scope
+        this.report.type = res.crowdReportVO.type
+        this.report.description = res.crowdReportVO.description
+        this.report.content = res.crowdReportVO.content
+        this.report.fileUrl = res.crowdReportVO.file
+        this.report.conclusion = res.crowdReportVO.conclusion
+        this.report.target = res.crowdReportVO.target
+        this.hideLoading()
+        //notify('success', '修改成功')
+      }).catch((error) => {
+        this.hideLoading()
+        notify('error', '打开报告失败:' + error.data)
+      })
+    },
+    uploadReportFile (param) {
+      this.showLoading()
+      const formData = new FormData()
+      let config = {
+        //添加请求头
+        headers: {'Content-Type': 'multipart/form-data'},
+      }
+      formData.append('file', param.file)
+      Http.upload(Apis.FILE.UPLOAD_REPORT_FILE.replace('{userId}', this.user.userVO.id), formData, config).then((res) => {
+        console.log('上传成功')
+        this.report.fileUrl = res.data
+        console.log(res)
+        this.hideLoading()
+      }).catch((error) => {
+        this.hideLoading()
+        notify('error', '文件上传失败:' + error.data)
+      })
+    },
+    setReportType () {
+      getAllReportTypes().then((res) => {
+        this.reportType = res
+      }).catch((error) => {
+        notify('error', '加载报告类型失败')
+      })
+    },
+    setUserInfo () {
+      this.user = storageGet('user')
+    },
+    updateReportSuccess () {
+
+    },
+    showLoading () {
+      this.loading = true
+    },
+    hideLoading () {
+      this.loading = false
+    }
+  },
+  watch: {
+    reportType (val) {
+      this.reportType = val
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+  .el-radio {
+    margin: 10px 20px 10px 0;
+  }
+
+  .el-form-item /deep/ .el-tabs__content {
+    max-height: 120px !important;
+    overflow: auto;
+  }
+
+  .el-row {
+    margin-bottom: 10px;
+  }
+</style>

+ 281 - 0
src/components/report/ProjectReportCreate.vue

@@ -0,0 +1,281 @@
+<template>
+  <div class="create-container" v-loading="loading">
+    <div class="title h1">创建报告</div>
+    <div class="create-body">
+      <el-form :model="report" :rules="rules" ref="report" label-width="12%" class="demo-report">
+        <el-form-item label="报告名称" prop="name">
+          <el-input size="small" v-model="report.name"></el-input>
+        </el-form-item>
+        <el-form-item label="报告类型" prop="type">
+          <el-radio-group v-model="report.type">
+            <span v-for="(item,index) in reportType" :key="index">
+              <el-radio :label="item" name="type">{{item}}</el-radio>
+            </span>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label="测试对象" prop="name">
+          <el-input autosize style="width: 400px" type="textarea" v-model="report.target"></el-input>
+        </el-form-item>
+        <el-form-item label="测试内容" prop="name">
+          <el-input autosize style="width: 400px" type="textarea" v-model="report.content"></el-input>
+        </el-form-item>
+        <!--<el-form-item label="摘要" prop="abstract">-->
+        <!--<div>-->
+        <!--<el-row :gutter="2">-->
+        <!--<el-col :span="2">-->
+        <!--<span>测试对象</span>-->
+        <!--</el-col>-->
+        <!--<el-col :span="10">-->
+        <!--<el-input type="textarea" v-model="report.target"></el-input>-->
+        <!--</el-col>-->
+        <!--</el-row>-->
+        <!--<el-row :gutter="2">-->
+        <!--<el-col :span="2">-->
+        <!--<span>测试内容</span>-->
+        <!--</el-col>-->
+        <!--<el-col :span="10">-->
+        <!--<el-input type="textarea" v-model="report.content"></el-input>-->
+        <!--</el-col>-->
+        <!--</el-row>-->
+        <!--</div>-->
+        <!--</el-form-item>-->
+        <el-form-item prop="file" label="报告文件">
+          <el-upload
+            style="width: 400px"
+            drag
+            class="upload-demo"
+            action="https://jsonplaceholder.typicode.com/posts/"
+            :on-remove="handleRemove"
+            :before-remove="beforeRemove"
+            multiple
+            :limit="1"
+            :on-exceed="handleExceed"
+            :before-upload="beforeFileUpload"
+            :file-list="report.file"
+            :http-request="uploadReportFile"
+          >
+            <i class="el-icon-upload"></i>
+            <div class="el-upload__text">
+              将文件拖到此处,或
+              <em>点击上传</em>
+            </div>
+          </el-upload>
+        </el-form-item>
+
+        <el-form-item label="结论" prop="conclusion">
+          <el-input autosize style="width: 400px" type="textarea" v-model="report.conclusion"></el-input>
+        </el-form-item>
+        <el-form-item>
+          <div class="btn btn-medium btn-info" @click="submitForm('report')">提交</div>
+          <div class="btn btn-medium" @click="resetForm('report')">重置</div>
+          <div class="btn btn-medium" @click="cancelCreate('report')">取消</div>
+        </el-form-item>
+      </el-form>
+    </div>
+  </div>
+</template>
+
+<script>
+import Http from '@/js/http.js'
+import Apis from '@/js/api.js'
+import {notify} from '@/constants/index'
+import {getAllReportTypes, storageGet} from '@/js/index'
+
+export default {
+  name: 'ProjectReportCreate',
+  components: {},
+  data () {
+    return {
+      user: {},
+      reportType: [],
+      loading: false,
+      scope: 0,
+      projectId: '',
+      taskId: '',
+      dependencyCode: '',
+      report: {
+        name: '',
+        target: '',
+        content: '',
+        file: [],
+        fileUrl: '',
+        type: '',
+        conclusion: ''
+      },
+      rules: {
+        name: [
+          {required: true, message: '任务名称不可为空', trigger: 'blur'},
+          {min: 5, max: 50, message: '报告名称长度在 5 到 50 个字符', trigger: 'blur'}
+        ],
+        type: [
+          {required: true, message: '报告类型不可为空'},
+        ],
+        target: [
+          {required: true, message: '测试对象不可为空', trigger: 'blur'}
+        ],
+        content: [
+          {required: true, message: '测试内容不可为空', trigger: 'blur'}
+        ],
+        conclusion: [
+          {required: true, message: '结论不可为空', trigger: 'blur'}
+        ]
+      }
+    }
+  },
+  mounted () {
+    this.$nextTick(() => {
+      this.init()
+    })
+  },
+  methods: {
+    init () {
+      this.scope = this.$route.params.scope
+      this.dependencyCode = this.$route.params.dependencyCode
+      this.projectId = this.$route.params.projectId
+      this.taskId = this.$route.params.taskId
+      this.setUserInfo()
+      this.setReportType()
+    },
+    submitForm (formName) {
+      this.$refs['report'].validate(valid => {
+        if (valid) {
+          this.showLoading()
+          const newReport = {
+            name: this.report.name,
+            scope: this.scope,
+            type: this.report.type,
+            dependencyCode: this.dependencyCode,
+            target: this.report.target,
+            content: this.report.content,
+            file: this.report.fileUrl,
+            conclusion: this.report.conclusion
+          }
+          console.log(newReport)
+          Http.post(Apis.REPORT.CREATE_PROJECT_REPORT.replace('{projectId}', this.projectId), newReport).then((res) => {
+            this.hideLoading()
+            this.createReportSuccess(res.crowdReportVO.code)
+          }).catch((error) => {
+            this.hideLoading()
+            notify('error', '报告创建失败:' + error.data)
+          })
+          //提交 report
+        } else {
+          notify('error', '表单填写有误')
+          return false
+        }
+      })
+    },
+    resetForm (formName) {
+      this.$refs[formName].resetFields()
+      this.report.name = ''
+      this.report.abstract.target = ''
+      this.report.abstract.content = ''
+      this.report.file = []
+      this.report.type = ''
+      this.report.conclusion = ''
+    },
+    cancelCreate () {
+      if (window.history.length <= 1) {
+        this.$router.push({path: '/'})
+        return false
+      } else {
+        this.$router.go(-1)
+      }
+    },
+    handleRemove (file, fileList) {
+      console.log(file, fileList)
+    },
+    handleExceed (files, fileList) {
+      this.$message.warning(
+        `当前限制选择 1 个文件,本次选择了 ${
+          files.length
+          } 个文件,共选择了 ${files.length + fileList.length} 个文件`
+      )
+    },
+    beforeRemove (file, fileList) {
+      //return this.$confirm(`确定移除 ${file.name}?`)
+    },
+    beforeFileUpload (file) {
+      console.log(file)
+      const isPDF = file.type === 'application/pdf'
+      const isDOC = file.type === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
+      const isEXCEL = file.type === 'application/vnd.ms-excel'
+      const isXLS = file.type === 'application/x-xls'
+      const isTXT = file.type === 'text/plain'
+      const isXLSX = file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
+      //console.log(file)
+      if (!(isDOC || isEXCEL || isPDF || isTXT || isXLS || isXLSX)) {
+        this.$message.error('上传文件只能是 PDF 、 DOC 、DOCX 、XLS、TXT、XLSX 格式!')
+      }
+      return isDOC || isEXCEL || isPDF || isTXT || isXLS || isXLSX
+    },
+    loadData () {
+    },
+    uploadReportFile (param) {
+      const formData = new FormData()
+      let config = {
+        //添加请求头
+        headers: {'Content-Type': 'multipart/form-data'},
+      }
+      formData.append('file', param.file)
+      Http.upload(Apis.FILE.UPLOAD_REPORT_FILE.replace('{userId}', this.user.userVO.id), formData, config).then((res) => {
+        console.log('上传成功')
+        this.report.fileUrl = res.data
+        console.log(res)
+      })
+    },
+    setReportType () {
+      this.reportType = getAllReportTypes().then((res) => {
+        this.reportType = res
+      }).catch((error) => {
+        notify('error', '获取报告类型列表失败')
+      })
+    },
+    setUserInfo () {
+      this.user = storageGet('user')
+    },
+    createReportSuccess (reportId) {
+      this.$alert('报告创建成功', '创建成功', {
+        confirmButtonText: '确定',
+        callback: action => {
+          this.$router.push({
+            name: 'ProjectReport',
+            params: {reportId: reportId, projectId: this.projectId}
+          })
+        }
+      })
+    },
+    showLoading () {
+      this.loading = true
+    },
+    hideLoading () {
+      this.loading = false
+    }
+  },
+  watch: {
+    reportType (val) {
+      this.reportType = val
+    }
+  }
+
+}
+</script>
+
+<style lang="less" scoped>
+  .el-radio {
+    margin: 10px 20px 10px 0;
+  }
+
+  .el-form-item /deep/ .el-tabs__content {
+    max-height: 120px !important;
+    overflow: auto;
+  }
+
+  .el-row {
+    margin-bottom: 10px;
+  }
+
+  .el-input {
+    width: 400px;
+  }
+</style>

+ 0 - 297
src/components/report/Report.vue

@@ -1,297 +0,0 @@
-<template>
-  <div class="create-container">
-    <div class="create-body">
-      <el-form :model="report" :rules="rules" ref="report" label-width="12%" class="demo-report">
-        <el-form-item label="报告名称" prop="name">
-          <el-input v-if="isModifyMode" v-model="report.name"></el-input>
-          <span v-if="!isModifyMode">{{report.name}}</span>
-        </el-form-item>
-        <el-form-item label="报告类型" prop="type">
-          <el-radio-group v-if="isModifyMode" v-model="report.type">
-            <el-radio :label="0" name="type">{{ serviceType[0] }}</el-radio>
-            <el-radio :label="1" name="type">{{ serviceType[1] }}</el-radio>
-            <el-radio :label="2" name="type">{{ serviceType[2] }}</el-radio>
-            <el-radio :label="3" name="type">{{ serviceType[3] }}</el-radio>
-            <el-radio :label="4" name="type">{{ serviceType[4] }}</el-radio>
-            <el-radio :label="5" name="type">{{ serviceType[5] }}</el-radio>
-          </el-radio-group>
-          <span v-if="!isModifyMode" class="badge">{{serviceType[report.type]}}</span>
-        </el-form-item>
-        <el-form-item label="摘要" prop="abstract">
-          <div>
-            <el-row :gutter="2">
-              <el-col :span="2">
-                <span>测试对象</span>
-              </el-col>
-              <el-col :span="10">
-                <el-input v-if="isModifyMode" type="textarea" v-model="report.target"></el-input>
-                <span v-if="!isModifyMode">{{report.target}}</span>
-              </el-col>
-            </el-row>
-            <el-row :gutter="2">
-              <el-col :span="2">
-                <span>测试内容</span>
-              </el-col>
-              <el-col :span="10">
-                <el-input v-if="isModifyMode" type="textarea" v-model="report.content"></el-input>
-                <span v-if="!isModifyMode">{{report.content}}</span>
-              </el-col>
-            </el-row>
-          </div>
-        </el-form-item>
-        <el-form-item prop="file" label="报告文件">
-          <el-upload
-            v-if="isModifyMode"
-            drag
-            class="upload-demo"
-            action=""
-            :on-remove="handleRemove"
-            :before-remove="beforeRemove"
-            multiple
-            :limit="1"
-            :on-exceed="handleExceed"
-            :before-upload="beforeFileUpload"
-            :file-list="report.file"
-            :http-request="uploadReportFile"
-          >
-            <i class="el-icon-upload"></i>
-            <div class="el-upload__text">
-              将文件拖到此处,或
-              <em>点击上传</em>
-            </div>
-            <div class="el-upload__tip" slot="tip">请上传报告文件</div>
-          </el-upload>
-          <div v-if="!isModifyMode">
-            <span v-if="report.fileUrl==null">暂无文件</span>
-            <a :href="report.fileUrl" v-if="report.fileUrl!=null"><i class="fa fa-file-text-o"></i>
-              {{report.fileUrl}}</a>
-          </div>
-        </el-form-item>
-
-        <el-form-item label="结论" prop="conclusion">
-          <el-input v-if="isModifyMode" type="textarea" v-model="report.conclusion"></el-input>
-          <span v-if="!isModifyMode">{{report.conclusion}}</span>
-        </el-form-item>
-        <el-form-item v-if="!isModifyMode">
-          <div class="btn btn-medium btn-info" @click="modifyForm()">修改</div>
-          <div class="btn btn-medium" @click="back()">返回</div>
-        </el-form-item>
-        <el-form-item v-if="isModifyMode">
-          <div class="btn btn-primary btn-info" @click="submitForm('report')">确认修改</div>
-          <div class="btn btn-primary" @click="resetForm('report')">重置</div>
-          <div class="btn btn-primary" @click="cancelCreate('report')">取消</div>
-        </el-form-item>
-      </el-form>
-    </div>
-  </div>
-</template>
-
-<script>
-import Http from '@/js/http.js'
-import Apis from '@/js/api.js'
-import ServiceType from '@/constants/enum/service-type'
-import {notify} from '@/constants/index'
-export default {
-  name: 'Report-Create',
-  components: {},
-  data () {
-    return {
-      reportId: 0,
-      projectId: '',
-      taskId: '',
-      isModifyMode: false,
-      serviceType: ServiceType,
-      report: {
-        name: '',
-        type: '',
-        description: '',
-        target: '',
-        content: '',
-        file: [],
-        fileUrl: '',
-        conclusion: ''
-      },
-      rules: {
-        // name: [
-        //   {required: true, message: '请输入报告名称', trigger: 'blur'}
-        //   // { min: 3, max: 5, message: "长度在 3 到 5 个字符", trigger: "blur" }
-        // ],
-        // abstract: [
-        //   {
-        //     required: true,
-        //     message: '请输入摘要信息',
-        //     trigger: 'change'
-        //   }
-        // ],
-        // type: [
-        //   {required: true, message: '请选择报告类型', trigger: 'change'}
-        // ],
-        // conclusion: [
-        //   {required: true, message: '请输入报告结论', trigger: 'blur'}
-        // ]
-      }
-    }
-  },
-  mounted () {
-    this.$nextTick(() => {
-      this.init()
-    })
-  },
-  methods: {
-    init () {
-      this.reportId = this.$route.params.reportId
-      this.projectId = this.$route.params.projectId
-      this.taskId = this.$route.params.taskId
-      this.loadData()
-    },
-    modifyForm () {
-      this.isModifyMode = true
-    },
-    submitForm (formName) {
-      const newReport = {
-        name: this.report.name,
-        scope: this.taskId == null ? 0 : 1,
-        type: this.report.type,
-        dependencyCode: this.taskId == null ? this.projectId : this.taskId,
-        target: this.report.target,
-        content: this.report.content,
-        file: '123.pdf',
-        conclusion: this.report.conclusion
-      }
-      console.log(newReport)
-      if (this.taskId == null) {
-        Http.put(Apis.REPORT.UPDATE_PROJECT_REPORT.replace('{projectId}', this.projectId).replace('{reportId}', this.reportId), newReport).then((res) => {
-          console.log(res)
-        })
-      } else {
-        Http.put(Apis.REPORT.UPDATE_TASK_REPORT.replace('{projectId}', this.projectId).replace('{taskId}', this.taskId).replace('{reportId}', this.reportId), newReport).then((res) => {
-          console.log(res)
-        })
-      }
-      // this.$refs[formName].validate(valid => {
-      //   if (valid) {
-      //     this.isModifyMode = false
-      //
-      //     //提交 report
-      //   } else {
-      //     console.log('error submit!!')
-      //     return false
-      //   }
-      // })
-    },
-    resetForm (formName) {
-      this.$refs[formName].resetFields()
-      this.report.name = ''
-      this.report.target = ''
-      this.report.content = ''
-      this.report.file = ''
-      this.report.type = ''
-      this.report.conclusion = ''
-    },
-    cancelCreate () {
-      this.isModifyMode = false
-      //请求 report
-    },
-    handleRemove (file, fileList) {
-      console.log(file, fileList)
-    },
-    handleExceed (files, fileList) {
-      this.$message.warning(
-        `当前限制选择 1 个文件,本次选择了 ${
-          files.length
-          } 个文件,共选择了 ${files.length + fileList.length} 个文件`
-      )
-    },
-    beforeRemove (file, fileList) {
-      //return this.$confirm(`确定移除 ${file.name}?`)
-    },
-    beforeFileUpload (file) {
-      console.log(file)
-      const isPDF = file.type === 'application/pdf'
-      const isDOC = file.type === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
-      const isEXCEL = file.type === 'application/vnd.ms-excel'
-      const isXLS = file.type === 'application/x-xls'
-      const isTXT = file.type === 'text/plain'
-      const isXLSX = file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
-      //console.log(file)
-      if (!(isDOC || isEXCEL || isPDF || isTXT || isXLS || isXLSX)) {
-        this.$message.error('上传文件只能是 PDF 、 DOC 、DOCX 、XLS、TXT、XLSX 格式!')
-      }
-      return isDOC || isEXCEL || isPDF || isTXT || isXLS || isXLSX
-    },
-    back () {
-      if (window.history.length <= 1) {
-        this.$router.push({path: '/'})
-        return false
-      } else {
-        this.$router.go(-1)
-      }
-    },
-    loadData () {
-      //pro1564487183259
-      //pro1564487183259_task1564487274060
-      //pro1564487183259pro1564487183259_task1564487274060_rep1564488510500
-      console.log('***')
-      console.log(this.projectId)
-      console.log(this.taskId)
-      console.log(this.reportId)
-      console.log('***')
-      if (this.taskId == null) {
-        Http.get(Apis.REPORT.GET_PROJECT_REPORT.replace('{projectId}', this.projectId).replace('{reportId}', this.reportId)).then((res) => {
-          console.log(res)
-          this.report.name = res.crowdReportVO.name
-          this.report.crowdTestTaskId = res.crowdReportVO.crowdTestTaskId
-          this.report.scope = res.crowdReportVO.scope
-          this.report.type = res.crowdReportVO.type
-          this.report.description = res.crowdReportVO.description
-          this.report.content = res.crowdReportVO.content
-          this.report.fileUrl = res.crowdReportVO.file
-          this.report.conclusion = res.crowdReportVO.conclusion
-          this.report.target = res.crowdReportVO.target
-        })
-      } else {
-        Http.get(Apis.REPORT.GET_TASK_REPORT.replace('{projectId}', this.projectId).replace('{taskId}', this.taskId).replace('{reportId}', this.reportId)).then((res) => {
-          console.log(res)
-          this.report.name = res.crowdReportVO.name
-          this.report.crowdTestTaskId = res.crowdReportVO.crowdTestTaskId
-          this.report.scope = res.crowdReportVO.scope
-          this.report.type = res.crowdReportVO.type
-          this.report.description = res.crowdReportVO.description
-          this.report.content = res.crowdReportVO.content
-          this.report.fileUrl = res.crowdReportVO.file
-          this.report.conclusion = res.crowdReportVO.conclusion
-          this.report.target = res.crowdReportVO.target
-        })
-      }
-    },
-    uploadReportFile (param) {
-      const formData = new FormData()
-      let config = {
-        //添加请求头
-        headers: {'Content-Type': 'multipart/form-data'},
-      }
-      formData.append('file', param.file)
-      Http.upload(Apis.FILE.UPLOAD_REPORT_FILE.replace('{userId}', 3), formData, config).then((res) => {
-        console.log('上传成功')
-        this.report.fileUrl = res.data
-        console.log(res)
-      })
-    }
-  }
-}
-</script>
-
-<style lang="less" scoped>
-  .el-radio {
-    margin: 10px 20px 10px 0;
-  }
-
-  .el-form-item /deep/ .el-tabs__content {
-    max-height: 120px !important;
-    overflow: auto;
-  }
-
-  .el-row {
-    margin-bottom: 10px;
-  }
-</style>

+ 23 - 15
src/components/report/ReportList.vue

@@ -12,13 +12,13 @@
     <el-table :showHeader="true" :data="reportList" style="width: 100%">
       <el-table-column prop="type" label="报告类型" title="报告类型">
         <template slot-scope="scope">
-          <span class="badge">{{serviceType[scope.row.type]}}</span>
+          <span class="badge">{{scope.row.type}}</span>
         </template>
       </el-table-column>
       <el-table-column prop="file" sortable label="报告文件">
         <template slot-scope="scope">
-          <span v-if="scope.row.content==null">暂无文件</span>
-          <a :href="scope.row.content" v-if="scope.row.content!=0" target="_blank"><i
+          <span v-if="scope.row.content==null || scope.row.content==''">暂无文件</span>
+          <a :href="scope.row.file" v-if="scope.row.content!=null" target="_blank"><i
             class="fa fa-file-text-o"></i> {{scope.row.content}}</a>
         </template>
       </el-table-column>
@@ -33,8 +33,6 @@
 </template>
 <script>
 
-import ServiceType from '../../constants/enum/service-type'
-
 export default {
   name: 'report-list',
   props: {
@@ -45,22 +43,32 @@ export default {
   data () {
     return {
       editIndex: -1,
-      serviceType: ServiceType,
-      reportList: this.reports,
+      reportList: this.reports == null ? [] : this.reports,
       pid: this.projectId,
       tid: this.taskId,
     }
   },
   methods: {
     handleEdit (index, row) {
-      this.$router.push({
-        name: 'Report',
-        params: {
-          reportId: row.code,
-          projectId: this.pid,
-          taskId: this.tid
-        }
-      })
+      if (this.tid == null) {
+        this.$router.push({
+          name: 'ProjectReport',
+          params: {
+            reportId: row.code,
+            projectId: this.pid
+          }
+        })
+      } else {
+        this.$router.push({
+          name: 'TaskReport',
+          params: {
+            reportId: row.code,
+            projectId: this.pid,
+            taskId: this.tid
+          }
+        })
+      }
+
       // this.editIndex = index;
     },
     handleDelete (index, row) {

+ 300 - 0
src/components/report/TaskReport.vue

@@ -0,0 +1,300 @@
+<template>
+  <div class="create-container">
+    <div class="create-body" v-loading="loading">
+      <el-form :model="report" :rules="rules" ref="report" label-width="12%" class="demo-report">
+        <el-form-item label="报告名称" prop="name">
+          <el-input size="small" v-if="isModifyMode" v-model="report.name"></el-input>
+          <span v-if="!isModifyMode">{{report.name}}</span>
+        </el-form-item>
+        <el-form-item label="报告类型" prop="type">
+          <el-radio-group v-if="isModifyMode" v-model="report.type">
+            <span v-for="(item,index) in reportType" :key="index">
+              <el-radio :label="item" name="type">{{item}}</el-radio>
+            </span>
+          </el-radio-group>
+          <span v-if="!isModifyMode" class="badge">{{report.type}}</span>
+        </el-form-item>
+        <el-form-item label="测试对象" prop="target">
+          <el-input autosize v-if="isModifyMode" type="textarea" v-model="report.target"></el-input>
+          <span v-if="!isModifyMode">{{report.target}}</span>
+        </el-form-item>
+        <el-form-item label="测试内容" prop="content">
+          <el-input autosize v-if="isModifyMode" type="textarea" v-model="report.content"></el-input>
+          <span v-if="!isModifyMode">{{report.content}}</span>
+        </el-form-item>
+        <el-form-item prop="file" label="报告文件">
+          <el-upload
+            style="width: 400px"
+            v-if="isModifyMode"
+            drag
+            class="upload-demo"
+            action=""
+            :on-remove="handleRemove"
+            :before-remove="beforeRemove"
+            multiple
+            :limit="1"
+            :on-exceed="handleExceed"
+            :before-upload="beforeFileUpload"
+            :file-list="report.file"
+            :http-request="uploadReportFile"
+          >
+            <i class="el-icon-upload"></i>
+            <div class="el-upload__text">
+              将文件拖到此处,或
+              <em>点击上传</em>
+            </div>
+            <div class="el-upload__tip" slot="tip">请上传报告文件</div>
+          </el-upload>
+          <div v-if="!isModifyMode">
+            <span v-if="report.fileUrl==null">暂无文件</span>
+            <a :href="report.fileUrl" v-if="report.fileUrl!=null">
+              <el-link :underline="false" type="primary"><i class="el-icon-document"></i>下载文档</el-link>
+            </a>
+          </div>
+        </el-form-item>
+
+        <el-form-item label="结论" prop="conclusion">
+          <el-input autosize v-if="isModifyMode" type="textarea" v-model="report.conclusion"></el-input>
+          <span v-if="!isModifyMode">{{report.conclusion}}</span>
+        </el-form-item>
+        <el-form-item v-if="!isModifyMode">
+          <div class="btn btn-medium btn-info" @click="modifyForm()">修改</div>
+          <div class="btn btn-medium" @click="back()">返回</div>
+        </el-form-item>
+        <el-form-item v-if="isModifyMode">
+          <div class="btn btn-medium btn-info" @click="submitForm('report')">确认修改</div>
+          <div class="btn btn-medium" @click="resetForm('report')">重置</div>
+          <div class="btn btn-medium" @click="cancelCreate('report')">取消</div>
+        </el-form-item>
+      </el-form>
+    </div>
+  </div>
+</template>
+
+<script>
+import Http from '@/js/http.js'
+import Apis from '@/js/api.js'
+import {notify} from '@/constants/index'
+import {getAllReportTypes, storageGet} from '@/js/index'
+
+export default {
+  name: 'TaskReport',
+  components: {},
+  data () {
+    return {
+      user: {},
+      loading: false,
+      reportId: 0,
+      projectId: '',
+      taskId: '',
+      isModifyMode: false,
+      reportType: [],
+      report: {
+        name: '',
+        type: '',
+        description: '',
+        target: '',
+        content: '',
+        file: [],
+        fileUrl: '',
+        conclusion: ''
+      },
+      rules: {
+        name: [
+          {required: true, message: '任务名称不可为空', trigger: 'blur'},
+          {min: 5, max: 50, message: '报告名称长度在 5 到 50 个字符', trigger: 'blur'}
+        ],
+        type: [
+          {required: true, message: '报告类型不可为空'},
+        ],
+        target: [
+          {required: true, message: '测试对象不可为空', trigger: 'blur'}
+        ],
+        content: [
+          {required: true, message: '测试内容不可为空', trigger: 'blur'}
+        ],
+        conclusion: [
+          {required: true, message: '结论不可为空', trigger: 'blur'}
+        ]
+      }
+    }
+  },
+  mounted () {
+    this.$nextTick(() => {
+      this.init()
+    })
+  },
+  methods: {
+    init () {
+      this.reportId = this.$route.params.reportId
+      this.projectId = this.$route.params.projectId
+      this.taskId = this.$route.params.taskId
+      this.setReportType()
+      this.setUserInfo()
+      this.loadData()
+    },
+    modifyForm () {
+      this.isModifyMode = true
+    },
+    submitForm (formName) {
+      this.$refs['report'].validate(valid => {
+        if (valid) {
+          this.isModifyMode = false
+          this.showLoading()
+          const newReport = {
+            name: this.report.name,
+            scope: this.taskId == null ? 0 : 1,
+            type: this.report.type,
+            dependencyCode: this.taskId == null ? this.projectId : this.taskId,
+            target: this.report.target,
+            content: this.report.content,
+            file: this.report.fileUrl,
+            conclusion: this.report.conclusion
+          }
+          console.log(newReport)
+          Http.put(Apis.REPORT.UPDATE_TASK_REPORT.replace('{projectId}', this.projectId).replace('{taskId}', this.taskId).replace('{reportId}', this.reportId), newReport).then((res) => {
+            console.log(res)
+            this.hideLoading()
+            this.isModifyMode = false
+          }).catch((error) => {
+            this.hideLoading()
+            notify('error', error.data)
+          })
+          //提交 report
+        } else {
+          notify('error', '表单填写有误')
+          return false
+        }
+      })
+    },
+    resetForm (formName) {
+      this.$refs[formName].resetFields()
+      this.report.name = ''
+      this.report.target = ''
+      this.report.content = ''
+      this.report.file = ''
+      this.report.type = ''
+      this.report.conclusion = ''
+    },
+    cancelCreate () {
+      this.isModifyMode = false
+      //请求 report
+    },
+    handleRemove (file, fileList) {
+      console.log(file, fileList)
+    },
+    handleExceed (files, fileList) {
+      this.$message.warning(
+        `当前限制选择 1 个文件,本次选择了 ${
+          files.length
+          } 个文件,共选择了 ${files.length + fileList.length} 个文件`
+      )
+    },
+    beforeRemove (file, fileList) {
+      //return this.$confirm(`确定移除 ${file.name}?`)
+    },
+    beforeFileUpload (file) {
+      console.log(file)
+      const isPDF = file.type === 'application/pdf'
+      const isDOC = file.type === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
+      const isEXCEL = file.type === 'application/vnd.ms-excel'
+      const isXLS = file.type === 'application/x-xls'
+      const isTXT = file.type === 'text/plain'
+      const isXLSX = file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
+      //console.log(file)
+      if (!(isDOC || isEXCEL || isPDF || isTXT || isXLS || isXLSX)) {
+        this.$message.error('上传文件只能是 PDF 、 DOC 、DOCX 、XLS、TXT、XLSX 格式!')
+      }
+      return isDOC || isEXCEL || isPDF || isTXT || isXLS || isXLSX
+    },
+    back () {
+      this.$router.push({
+        name: 'Task',
+        params: {
+          projectId: this.projectId,
+          taskId: this.taskId
+        }
+      })
+    },
+    loadData () {
+      //pro1564487183259
+      //pro1564487183259_task1564487274060
+      //pro1564487183259pro1564487183259_task1564487274060_rep1564488510500
+      this.showLoading()
+      Http.get(Apis.REPORT.GET_TASK_REPORT.replace('{projectId}', this.projectId).replace('{taskId}', this.taskId).replace('{reportId}', this.reportId)).then((res) => {
+        console.log(res)
+        this.report.name = res.crowdReportVO.name
+        this.report.crowdTestTaskId = res.crowdReportVO.crowdTestTaskId
+        this.report.scope = res.crowdReportVO.scope
+        this.report.type = res.crowdReportVO.type
+        this.report.description = res.crowdReportVO.description
+        this.report.content = res.crowdReportVO.content
+        this.report.fileUrl = res.crowdReportVO.file
+        this.report.conclusion = res.crowdReportVO.conclusion
+        this.report.target = res.crowdReportVO.target
+        this.hideLoading()
+      }).catch((error) => {
+        this.hideLoading()
+        notify('error', '打开报告失败:' + error.data)
+      })
+    },
+    uploadReportFile (param) {
+      this.showLoading()
+      const formData = new FormData()
+      let config = {
+        //添加请求头
+        headers: {'Content-Type': 'multipart/form-data'},
+      }
+      formData.append('file', param.file)
+      Http.upload(Apis.FILE.UPLOAD_REPORT_FILE.replace('{userId}', this.user.userVO.id), formData, config).then((res) => {
+        console.log('上传成功')
+        this.report.fileUrl = res.data
+        console.log(res)
+        this.hideLoading()
+      }).catch((error) => {
+        this.hideLoading()
+        notify('error', '文件上传失败:' + error.data)
+      })
+    },
+    setReportType () {
+      getAllReportTypes().then((res) => {
+        this.reportType = res
+      }).catch((error) => {
+        notify('error', '加载报告类型失败')
+      })
+    },
+    setUserInfo () {
+      this.user = storageGet('user')
+    },
+    updateReportSuccess () {
+
+    },
+    showLoading () {
+      this.loading = true
+    },
+    hideLoading () {
+      this.loading = false
+    }
+  },
+  watch: {
+    reportType (val) {
+      this.reportType = val
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+  .el-radio {
+    margin: 10px 20px 10px 0;
+  }
+
+  .el-form-item /deep/ .el-tabs__content {
+    max-height: 120px !important;
+    overflow: auto;
+  }
+
+  .el-row {
+    margin-bottom: 10px;
+  }
+</style>

+ 96 - 78
src/components/report/ReportCreate.vue → src/components/report/TaskReportCreate.vue

@@ -1,43 +1,27 @@
 <template>
-  <div class="create-container">
+  <div class="create-container" v-loading="loading">
     <div class="title h1">创建报告</div>
     <div class="create-body">
       <el-form :model="report" :rules="rules" ref="report" label-width="12%" class="demo-report">
         <el-form-item label="报告名称" prop="name">
-          <el-input v-model="report.name"></el-input>
+          <el-input size="small" v-model="report.name"></el-input>
         </el-form-item>
         <el-form-item label="报告类型" prop="type">
           <el-radio-group v-model="report.type">
-            <el-radio label="0" name="type">{{ reportType['0'] }}</el-radio>
-            <el-radio label="1" name="type">{{ reportType['1'] }}</el-radio>
-            <el-radio label="2" name="type">{{ reportType['2'] }}</el-radio>
-            <el-radio label="3" name="type">{{ reportType['3'] }}</el-radio>
-            <el-radio label="4" name="type">{{ reportType['4'] }}</el-radio>
-            <el-radio label="5" name="type">{{ reportType['5'] }}</el-radio>
+            <span v-for="(item,index) in reportType" :key="index">
+              <el-radio :label="item" name="type">{{item}}</el-radio>
+            </span>
           </el-radio-group>
         </el-form-item>
-        <el-form-item label="摘要" prop="abstract">
-          <div>
-            <el-row :gutter="2">
-              <el-col :span="2">
-                <span>测试对象</span>
-              </el-col>
-              <el-col :span="10">
-                <el-input type="textarea" v-model="report.target"></el-input>
-              </el-col>
-            </el-row>
-            <el-row :gutter="2">
-              <el-col :span="2">
-                <span>测试内容</span>
-              </el-col>
-              <el-col :span="10">
-                <el-input type="textarea" v-model="report.content"></el-input>
-              </el-col>
-            </el-row>
-          </div>
+        <el-form-item label="测试对象" prop="target">
+          <el-input autosize style="width: 400px" type="textarea" v-model="report.target"></el-input>
+        </el-form-item>
+        <el-form-item label="测试内容" prop="content">
+          <el-input autosize style="width: 400px" type="textarea" v-model="report.content"></el-input>
         </el-form-item>
         <el-form-item prop="file" label="报告文件">
           <el-upload
+            style="width: 400px"
             drag
             class="upload-demo"
             action="https://jsonplaceholder.typicode.com/posts/"
@@ -60,12 +44,12 @@
         </el-form-item>
 
         <el-form-item label="结论" prop="conclusion">
-          <el-input type="textarea" v-model="report.conclusion"></el-input>
+          <el-input autosize style="width: 400px" type="textarea" v-model="report.conclusion"></el-input>
         </el-form-item>
         <el-form-item>
-          <div class="btn btn-primary btn-info" @click="submitForm('report')">提交</div>
-          <div class="btn btn-primary" @click="resetForm('report')">重置</div>
-          <div class="btn btn-primary" @click="cancelCreate('report')">取消</div>
+          <div class="btn btn-medium btn-info" @click="submitForm('report')">提交</div>
+          <div class="btn btn-medium" @click="resetForm('report')">重置</div>
+          <div class="btn btn-medium" @click="cancelCreate('report')">取消</div>
         </el-form-item>
       </el-form>
     </div>
@@ -75,14 +59,17 @@
 <script>
 import Http from '@/js/http.js'
 import Apis from '@/js/api.js'
-import ReportType from '@/constants/enum/report-type.js'
 import {notify} from '@/constants/index'
+import {getAllReportTypes, storageGet} from '@/js/index'
+
 export default {
-  name: 'ReportCreate',
+  name: 'TaskReportCreate',
   components: {},
   data () {
     return {
-      reportType: ReportType,
+      user: {},
+      loading: false,
+      reportType: [],
       scope: 0,
       projectId: '',
       taskId: '',
@@ -98,24 +85,20 @@ export default {
       },
       rules: {
         name: [
-          {required: true, message: '请输入报告名称', trigger: 'blur'}
-          // { min: 3, max: 5, message: "长度在 3 到 5 个字符", trigger: "blur" }
-        ],
-        abstract: [
-          {
-            required: true,
-            message: '请输入摘要信息',
-            trigger: 'change'
-          }
+          {required: true, message: '任务名称不可为空', trigger: 'blur'},
+          {min: 5, max: 50, message: '报告名称长度在 5 到 50 个字符', trigger: 'blur'}
         ],
         type: [
-          {required: true, message: '请选择报告类型', trigger: 'change'}
+          {required: true, message: '报告类型不可为空'},
+        ],
+        target: [
+          {required: true, message: '测试对象不可为空', trigger: 'blur'}
         ],
-        file: [
-          {required: true, message: '请上传报告文件', trigger: 'change'}
+        content: [
+          {required: true, message: '测试内容不可为空', trigger: 'blur'}
         ],
         conclusion: [
-          {required: true, message: '请输入报告结论', trigger: 'blur'}
+          {required: true, message: '结论不可为空', trigger: 'blur'}
         ]
       }
     }
@@ -131,38 +114,36 @@ export default {
       this.dependencyCode = this.$route.params.dependencyCode
       this.projectId = this.$route.params.projectId
       this.taskId = this.$route.params.taskId
+      this.setUserInfo()
+      this.setReportType()
     },
     submitForm (formName) {
-      const newReport = {
-        name: this.report.name,
-        scope: this.scope,
-        type: this.report.type,
-        dependencyCode: this.dependencyCode,
-        target: this.report.target,
-        content: this.report.content,
-        file: this.report.fileUrl,
-        conclusion: this.report.conclusion
-      }
-      console.log(newReport)
-      if (this.taskId == null) {
-        Http.post(Apis.REPORT.CREATE_PROJECT_REPORT.replace('{projectId}', this.projectId), newReport).then((res) => {
-          console.log(res)
-        })
-      } else {
-        Http.post(Apis.REPORT.CREATE_TASK_REPORT.replace('{projectId}', this.projectId).replace('{taskId}', this.taskId), newReport).then((res) => {
-          console.log(res)
-        })
-      }
-
-      // this.$refs[formName].validate(valid => {
-      //   if (valid) {
-      //
-      //     //提交 report
-      //   } else {
-      //     console.log('error submit!!')
-      //     return false
-      //   }
-      // })
+      this.$refs['report'].validate(valid => {
+        if (valid) {
+          this.showLoading()
+          const newReport = {
+            name: this.report.name,
+            scope: this.scope,
+            type: this.report.type,
+            dependencyCode: this.dependencyCode,
+            target: this.report.target,
+            content: this.report.content,
+            file: this.report.fileUrl,
+            conclusion: this.report.conclusion
+          }
+          console.log(newReport)
+          Http.post(Apis.REPORT.CREATE_TASK_REPORT.replace('{projectId}', this.projectId).replace('{taskId}', this.taskId), newReport).then((res) => {
+            this.hideLoading()
+            this.createReportSuccess(res.crowdReportVO.code)
+          }).catch((error) => {
+            this.hideLoading()
+            notify('error', '报告创建失败:' + error.data)
+          })
+        } else {
+          notify('error', '表单填写有误')
+          return false
+        }
+      })
     },
     resetForm (formName) {
       this.$refs[formName].resetFields()
@@ -217,13 +198,46 @@ export default {
         headers: {'Content-Type': 'multipart/form-data'},
       }
       formData.append('file', param.file)
-      Http.upload(Apis.FILE.UPLOAD_REPORT_FILE.replace('{userId}', 3), formData, config).then((res) => {
+      Http.upload(Apis.FILE.UPLOAD_REPORT_FILE.replace('{userId}', this.user.userVO.id), formData, config).then((res) => {
         console.log('上传成功')
         this.report.fileUrl = res.data
         console.log(res)
       })
+    },
+    setReportType () {
+      this.reportType = getAllReportTypes().then((res) => {
+        this.reportType = res
+      }).catch((error) => {
+        notify('error', '获取报告类型列表失败')
+      })
+    },
+    setUserInfo () {
+      this.user = storageGet('user')
+    },
+    createReportSuccess (reportId) {
+      this.$alert('报告创建成功', '创建成功', {
+        confirmButtonText: '确定',
+        callback: action => {
+          this.$router.push({
+            name: 'TaskReport',
+            params: {reportId: reportId, projectId: this.projectId, taskId: this.taskId}
+          })
+        }
+      })
+    },
+    showLoading () {
+      this.loading = true
+    },
+    hideLoading () {
+      this.loading = false
+    }
+  },
+  watch: {
+    reportType (val) {
+      this.reportType = val
     }
   }
+
 }
 </script>
 
@@ -240,4 +254,8 @@ export default {
   .el-row {
     margin-bottom: 10px;
   }
+
+  .el-input {
+    width: 400px;
+  }
 </style>

+ 499 - 226
src/components/task/Task.vue

@@ -1,40 +1,40 @@
 <template>
-  <div class="create-container">
+  <div class="create-container" v-loading="loading">
     <div class="title h1" v-if="!isModifyMode">任务</div>
     <div class="create-body">
       <div class="title h2" v-if="!isModifyMode">基本信息</div>
       <el-form :model="task" :rules="rules" ref="task" label-width="12%" class="demo-task">
-        <el-form-item label="任务名称" prop="name">
-          <el-input v-if="isModifyMode" v-model="task.title"></el-input>
+        <el-form-item label="任务名称" prop="title">
+          <el-input size="small" v-if="isModifyMode" v-model="task.title"></el-input>
           <span v-if="!isModifyMode">{{task.title}}</span>
         </el-form-item>
         <el-form-item label="任务描述" prop="desc">
-          <el-input v-if="isModifyMode" type="textarea" v-model="task.description"></el-input>
+          <el-input autosize v-if="isModifyMode" type="textarea" v-model="task.description"></el-input>
           <span v-if="!isModifyMode">{{task.description}}</span>
         </el-form-item>
         <el-form-item label="任务报价" prop="quotePrice">
-          <el-input v-if="isModifyMode" v-model="task.quotePrice"></el-input>
-          <span v-if="!isModifyMode">{{task.quotePrice}}</span>
-        </el-form-item>
-        <el-form-item label="任务定价" prop="fixedPrice">
-          <el-input v-if="isModifyMode" v-model="task.fixedPrice"></el-input>
-          <span v-if="!isModifyMode">{{task.fixedPrice}}</span>
+          <el-input size="small" type="number" v-if="isModifyMode" v-model="task.quotePrice">
+            <template slot="append">¥</template>
+          </el-input>
+          <span v-if="!isModifyMode">{{task.quotePrice}}¥</span>
         </el-form-item>
+        <!--<el-form-item type="number" label="任务定价" prop="fixedPrice">-->
+        <!--<el-input v-if="isModifyMode" v-model="task.fixedPrice">-->
+        <!--<template slot="append">¥</template>-->
+        <!--</el-input>-->
+        <!--<span v-if="!isModifyMode">{{task.fixedPrice}}</span>-->
+        <!--</el-form-item>-->
         <el-form-item label="业务类型" prop="serviceType">
           <el-radio-group v-if="isModifyMode" v-model="task.serviceType">
-            <el-radio label="0" name="type">{{serviceType[0]}}</el-radio>
-            <el-radio label="1" name="type">{{serviceType[1]}}</el-radio>
-            <el-radio label="2" name="type">{{serviceType[2]}}</el-radio>
-            <el-radio label="3" name="type">{{serviceType[3]}}</el-radio>
-            <el-radio label="4" name="type">{{serviceType[4]}}</el-radio>
-            <el-radio label="5" name="type">{{serviceType[5]}}</el-radio>
-            <el-radio label="6" name="type">{{serviceType[6]}}</el-radio>
+            <span v-for="(item,index) in serviceType" :key="index">
+              <el-radio :label="item" name="type">{{item}}</el-radio>
+            </span>
           </el-radio-group>
-          <span class="badge" v-if="!isModifyMode">{{serviceType[task.serviceType]}}</span>
+          <span class="badge" v-if="!isModifyMode">{{task.serviceType}}</span>
         </el-form-item>
         <el-form-item label="任务可见性" prop="resource">
           <div v-if="!isModifyMode">
-            <div v-if="task.resource=='1'">{{updateLocation(task.location)}}</div>
+            <!--<div v-if="task.resource=='1'">{{updateLocation(task.location)}}</div>-->
             <div v-if="task.resource=='0'">{{task.institution}}</div>
             <div v-if="task.resource=='2'">{{resourceType[task.resource]}}</div>
           </div>
@@ -51,22 +51,24 @@
                   name="type"
                   v-for="item,index in institutionArray"
                   :key="index"
-                ></el-radio>
+                >{{item.name}}
+                </el-radio>
               </el-radio-group>
             </el-tab-pane>
-            <el-tab-pane :label="resourceType[1]" name="1">
-              <provincecity
-                ref="addFormProvince"
-                @selectChange="locationChange"
-                :provinceCode="task.location.provinceCode"
-                :cityCode="task.location.cityCode"
-              ></provincecity>
-            </el-tab-pane>
+            <!--<el-tab-pane :label="resourceType[1]" name="1">-->
+            <!--<provincecity-->
+            <!--ref="addFormProvince"-->
+            <!--@selectChange="locationChange"-->
+            <!--:provinceCode="task.location == null ||task.location.provinceCode==null?'3200':task.location.provinceCode"-->
+            <!--:cityCode="task.location == null ||task.location.cityCode==null?'3201':task.location.cityCode"-->
+            <!--&gt;</provincecity>-->
+            <!--</el-tab-pane>-->
             <el-tab-pane :label="resourceType[2]" name="2"></el-tab-pane>
           </el-tabs>
         </el-form-item>
         <el-form-item label="需求文档" prop="doc">
           <el-upload
+            style="width: 400px"
             v-if="isModifyMode"
             drag
             class="upload-demo"
@@ -75,7 +77,7 @@
             :before-remove="beforeRemove"
             :limit="1"
             :on-exceed="handleExceed"
-            :before-upload="beforeFileUpload"
+
             :http-request="uploadRequireDoc"
             :file-list="task.doc"
           >
@@ -84,20 +86,21 @@
               将文件拖到此处,或
               <em>点击上传</em>
             </div>
-            <div class="el-upload__tip" slot="tip">请上传需求文档</div>
           </el-upload>
           <span v-if="!isModifyMode">
-              <span v-if="task.requireDocUrl == null">
-                暂无文件
+              <span v-if="task.requireDocUrl == null || task.requireDocUrl == ''">
+                <i class="el-icon-document"></i>暂无文件
               </span>
-              <span v-if="task.requireDocUrl != null">
-                <a :href="task.requireDocUrl">{{task.requireDocUrl}}</a>
+              <span v-if="task.requireDocUrl != null && task.requireDocUrl != ''">
+                <a :href="task.requireDocUrl"><el-link :underline="false" type="primary"><i
+                  class="el-icon-document"></i>下载文档</el-link></a>
               </span>
             </span>
         </el-form-item>
         <el-form-item label="任务截止时间" prop="datetime">
           <div class="block" v-if="isModifyMode">
             <el-date-picker
+              size="small"
               v-model="task.datetime"
               type="datetime"
               placeholder="选择截止时间"
@@ -105,19 +108,77 @@
               :picker-options="pickerOptions"
             ></el-date-picker>
           </div>
-          <span v-if="!isModifyMode">{{task.datetime}}</span>
+          <span v-if="!isModifyMode">{{reformDate(new Date(task.datetime))}}</span>
         </el-form-item>
         <el-form-item v-if="isModifyMode">
-          <div class="btn btn-medium btn-info" @click="submitForm('task')">确认修改</div>
-          <div class="btn btn-medium" @click="resetForm('task')">重置</div>
-          <div class="btn btn-medium" @click="cancelMode('task')">取消</div>
+          <div class="btn btn-small btn-info" @click="updateTask()">确认修改</div>
+          <div class="btn btn-small" @click="resetForm()">重置</div>
+          <div class="btn btn-small" @click="cancelMode()">取消</div>
         </el-form-item>
         <el-form-item v-if="!isModifyMode">
-          <div class="btn btn-medium btn-info" @click="submitTaskRequest()">提交任务</div>
-          <div class="btn btn-medium btn-info" @click="applyTask()">接收任务</div>
-          <div class="btn btn-medium btn-info" @click="modifyForm()">修改</div>
-          <div class="btn btn-medium btn-info" @click="createReport()">上传报告</div>
-          <div class="btn btn-medium" @click="toProject()">前往项目</div>
+          <el-button size="mini" @click="toProject()">项目详情</el-button>
+          <el-popover
+            placement="top-start"
+            title="确认结束?"
+            width="200"
+            trigger="hover"
+            content="测评机构已提交结束申请,请确认是否结束该任务">
+            <el-button v-if="taskOperationControl.confirmFinish" type="success" size="mini" slot="reference"
+                       @click="endTask()">确认结束
+            </el-button>
+          </el-popover>
+
+          <el-popover
+            placement="top-start"
+            title="确认提交?"
+            width="200"
+            trigger="hover"
+            content="提交任务后不可更改,等待区域管理员验收">
+            <el-button v-if="taskOperationControl.finish" type="primary" size="mini" slot="reference"
+                       @click="submitTaskRequest()">提交任务
+            </el-button>
+          </el-popover>
+
+          <el-popover
+            placement="top-start"
+            title="确认拒绝?"
+            width="200"
+            trigger="hover"
+            content="拒绝后不可再接收此任务,且该任务对您不可见">
+            <el-button v-if="taskOperationControl.reject" type="danger" size="mini" slot="reference"
+                       @click="rejectTask()">拒绝任务
+            </el-button>
+          </el-popover>
+
+          <el-popover
+            placement="top-start"
+            title="确认接收?"
+            width="200"
+            trigger="hover"
+            content="接收任务后请认真完成!">
+            <el-button v-if="taskOperationControl.receive" type="primary" size="mini" slot="reference"
+                       @click="receiveTask()">接收任务
+            </el-button>
+          </el-popover>
+
+
+          <el-button v-if="taskOperationControl.update" type="primary" size="mini" @click="modifyForm()">修改任务
+          </el-button>
+          <el-button v-if="taskOperationControl.uploadReport" type="primary" size="mini" @click="toCreateReport()">
+            上传报告
+          </el-button>
+          <!--<div class="btn btn-small btn-info"-->
+          <!--v-if="taskOperationControl.confirmFinish"-->
+          <!--@click="endTask()">确认结束-->
+          <!--</div>-->
+          <!--<div class="btn btn-small btn-info" v-if="!taskOperationControl.finish" @click="submitTaskRequest()">提交任务-->
+          <!--</div>-->
+          <!--<div class="btn btn-small btn-info" v-if="!taskOperationControl.receive" @click="receiveTask()">接收任务</div>-->
+          <!--<div class="btn btn-small btn-danger" v-if="!taskOperationControl.reject" @click="rejectTask()">拒绝任务</div>-->
+          <!--<div class="btn btn-small btn-info" v-if="taskOperationControl.update" @click="modifyForm()">修改任务</div>-->
+          <!--<div class="btn btn-small btn-info" v-if="!taskOperationControl.uploadReport" @click="toCreateReport()">上传报告-->
+          <!--</div>-->
+
         </el-form-item>
       </el-form>
     </div>
@@ -129,15 +190,27 @@
 </template>
 
 <script>
-import Enum from '@/constants/enum/index'
 import ResourceType from '@/constants/enum/resource-type.js'
-import ServiceType from '@/constants/enum/service-type'
 import provincecity from '@/components/commons/ProvinceCity'
-import provinceCityJSON from '@/constants/provinceCity.json'
 import ReportList from '@/components/report/ReportList'
 import Http from '@/js/http.js'
 import Apis from '@/js/api.js'
 import {notify} from '@/constants/index'
+import {
+  ensureEndTask,
+  getAllAgencies,
+  getAllServiceTypes,
+  getFormalTimeFromDate,
+  getProvinceCodeByProvinceName,
+  getProvinceNameByProvinceCode,
+  getTask,
+  receiveTaskRequest,
+  rejectTask,
+  storageGet,
+  submitTaskRequest,
+  updateTask
+} from '@/js/index'
+
 export default {
   name: 'Task',
   components: {
@@ -146,20 +219,32 @@ export default {
   },
   data () {
     return {
+      user: {},
+      rolesPermissions: {},
+      loading: false,
       isModifyMode: false,
-      institutionArray: Enum.institution,
+      institutionArray: [],
       tabPosition: 'top',
       resourceType: ResourceType,
-      serviceType: ServiceType,
+      serviceType: [],
       taskId: '',
       projectId: '',
+      taskOperationControl: {
+        confirmFinish: false,
+        finish: false,
+        receive: false,
+        update: false,
+        uploadReport: false
+      },
       task: {
+        agencyId: '',
+        status: '',
         name: '',
         desc: '',
-        type: '',
+        serviceType: '',
         resource: '',
         location: {},
-        institution: '',
+        institution: {},
         datetime: '',
         quotePrice: '',
         fixedPrice: '',
@@ -194,46 +279,68 @@ export default {
         ]
       },
       rules: {
-        // name: [
-        //   {required: true, message: '请输入任务名称', trigger: 'blur'}
-        //   // { min: 3, max: 5, message: "长度在 3 到 5 个字符", trigger: "blur" }
-        // ],
-        // datetime: [
-        //   {
-        //     type: 'date',
-        //     required: true,
-        //     message: '请选择截止时间',
-        //     trigger: 'change'
-        //   }
-        // ],
-        // type: [
-        //   {required: true, message: '请选择业务类型', trigger: 'change'}
-        // ],
-        //desc: [{required: true, message: '请填写任务描述', trigger: 'blur'}],
-        // quotePrice: [{required: true, message: '请填写任务报价', trigger: 'blur'}],
-        //fixedPrice: [{required: true, message: '请填写任务定价', trigger: 'blur'}]
+        title: [
+          {required: true, message: '请输入任务名称', trigger: 'blur'},
+          {min: 5, max: 50, message: '任务名称长度在 5 到 50 个字符', trigger: 'blur'}
+        ],
+        type: [
+          {required: true, message: '业务类型不可为空'},
+        ],
+        desc: [{required: false, message: '请填写描述', trigger: 'blur'}],
+        //price: [{required: true, message: '请填写价格', trigger: 'blur'}],
+        quotePrice: [
+          {required: true, message: '预算不可为空', trigger: 'blur'},
+          {
+            validator: (rule, value, callback) => {
+              if (value <= 0) {
+                callback(new Error('请输入大于0的数'))
+              } else {
+                callback()
+              }
+            }, trigger: 'blur'
+          },
+        ],
+        resource: [
+          {required: true},
+          {
+            validator: (rule, value, callback) => {
+              if (value == 0 && this.task.institution.id == null) {
+                callback(new Error('定向发布至少要选择一个测评机构'))
+              } else {
+                callback()
+              }
+            }, trigger: 'change'
+          },
+        ],
+        datetime: [{required: true, message: '截止时间不可为空', trigger: 'blur'}],
       }
     }
   },
   watch: {
-    'task.institution' () {
-      if (this.task.institution) {
-        this.$refs.addFormProvince.resetProviceCity()
-        this.task.location = {provinceCode: '', cityCode: ''}
-      }
+    institutionArray (val) {
+      this.institutionArray = val
     },
-    'task.location' () {
-      if (this.task.location.provinceCode || this.task.location.cityCode) {
-        this.task.institution = ''
-      }
-    },
-    'task.resource' () {
-      if (this.task.resource == '广场') {
-        this.$refs.addFormProvince.resetProviceCity()
-        this.task.institution = ''
-        this.task.location = {provinceCode: '', cityCode: ''}
-      }
+    serviceType (val) {
+      this.serviceType = val
     },
+    // 'task.institution' () {
+    //   if (this.task.institution) {
+    //     //this.$refs.addFormProvince.resetProviceCity()
+    //     this.task.location = {provinceCode: '', cityCode: ''}
+    //   }
+    // },
+    // 'task.location' () {
+    //   if (this.task.location.provinceCode || this.task.location.cityCode) {
+    //     this.task.institution = ''
+    //   }
+    // },
+    // 'task.resource' () {
+    //   if (this.task.resource == '广场') {
+    //     this.$refs.addFormProvince.resetProviceCity()
+    //     this.task.institution = ''
+    //     this.task.location = {provinceCode: '', cityCode: ''}
+    //   }
+    // },
     deep: true
   },
   mounted () {
@@ -245,136 +352,191 @@ export default {
     init () {
       this.taskId = this.$route.params.taskId
       this.projectId = this.$route.params.projectId
-      this.loadData(this.projectId, this.taskId)
-    },
-    updateLocation (location) {
-      var provinceName = ''
-      var cityName = ''
-      for (var item of provinceCityJSON.provinces) {
-        if (item.code === location.provinceCode) {
-          provinceName = item.name
-          for (var city of item.cities) {
-            if (city.code === location.cityCode) {
-              cityName = city.name
-              break
-            }
-          }
-        }
-      }
-      return provinceName + ' / ' + cityName
+      this.setUserInfo()
+      this.setServiceType()
+      //this.loadData(this.projectId, this.taskId)
+      this.getTaskDetail()
+      this.setInstitutions()
+    },
+
+    //跳转至项目详情页面
+    toProject () {
+      this.$router.push({
+        name: 'Project',
+        params: {projectId: this.projectId}
+      })
+    },
+    //切换至可编辑页面
+    modifyForm () {
+      this.isModifyMode = true
     },
-    submitForm (formName) {
-      console.log(this.task)
-      this.$refs[formName].validate(valid => {
+    //切换至不可编辑页面
+    cancelMode () {
+      this.isModifyMode = false
+    },
+    //重置表单
+    resetForm () {
+      this.task.name = ''
+      this.task.desc = ''
+      this.task.quotePrice = ''
+      this.task.fixedPrice = ''
+      this.task.type = ''
+      this.task.resource = '2' //如果是广场不用管Location和institution ,定向看institution,区域看location
+      this.task.location = {provinceCode: '', cityCode: ''}
+      this.task.institution = ''
+      this.task.datetime = ''
+    },
+    //显示页面加载画面
+    showLoading () {
+      this.loading = true
+    },
+    //隐藏页面加载画面
+    hideLoading () {
+      this.loading = false
+    },
+    //加载用户信息
+    setUserInfo () {
+      this.user = storageGet('user')
+      this.rolesPermissions = storageGet('rolesPermissions')
+    },
+    //加载任务的服务类型
+    setServiceType () {
+      getAllServiceTypes().then((res) => {
+        this.serviceType = res
+      }).catch((error) => {
+        notify('error', '加载任务类型失败')
+      })
+    },
+    //加载所有的测评机构
+    setInstitutions () {
+      getAllAgencies().then((res) => {
+        this.institutionArray = res
+      }).catch((error) => {
+        notify('error', '获取机构列表失败')
+      })
+    },
+    //获取任务详情
+    getTaskDetail () {
+      this.showLoading()
+      getTask(this.projectId, this.taskId, this.getTaskDetailSuccess, this.getTaskDetailFail)
+    },
+    //获取任务详情成功时回调函数
+    getTaskDetailSuccess (res) {
+      this.hideLoading()
+      //console.log(res.crowdTaskVO)
+      this.taskId = res.crowdTaskVO.id
+      this.projectId = res.crowdTaskVO.projectId
+      this.task.title = res.crowdTaskVO.title
+      this.task.description = res.crowdTaskVO.description
+      this.task.serviceType = res.crowdTaskVO.serviceType
+      this.task.resource = res.crowdTaskVO.resource
+      this.task.location = getProvinceCodeByProvinceName(res.crowdTaskVO.location.provinceCode, res.crowdTaskVO.location.cityCode)
+      this.task.institution = res.crowdTaskVO.institution
+      this.task.datetime = new Date(res.crowdTaskVO.datetime)
+      this.task.quotePrice = res.crowdTaskVO.quotePrice
+      this.task.fixedPrice = res.crowdTaskVO.fixedPrice
+      this.task.doc = []
+      this.task.requireDocUrl = res.crowdTaskVO.requirementFile
+      this.task.agencyId = res.crowdTaskVO.agencyId
+      this.task.status = res.crowdTaskVO.status
+      this.taskOperationControl = res.taskOperationControl
+      this.reportList = res.crowdReportVOList
+    },
+    //获取任务详情失败时回调函数
+    getTaskDetailFail (error) {
+      this.hideLoading()
+      notify('error', '获取任务详情失败:' + error.data)
+    },
+    //更新任务信息
+    updateTask () {
+      this.$refs['task'].validate(valid => {
         if (valid) {
-          this.isModifyMode = false
+          this.showLoading()
           const newTask = {
             name: this.task.title,
             desc: this.task.description,
             type: this.task.serviceType,
             resource: this.task.resource,
-            location: this.task.location,
-            institution: this.task.institution,
+            location: this.task.location == null ? {} : getProvinceNameByProvinceCode(this.task.location.provinceCode, this.task.location.cityCode),
+            institution: this.task.institution.id,
             datetime: this.task.datetime,
             quotePrice: this.task.quotePrice,
             fixedPrice: this.task.fixedPrice,
-            requireDoc: this.task.requireDocUrl
+            requirementFile: this.task.requireDocUrl
           }
-          //修改TASK
-          Http.put(Apis.TASK.UPDATE_TASK.replace('{projectId}', this.projectId).replace('{taskId}', this.taskId), newTask).then((res) => {
-            console.log(res)
-          })
-          //提交 task
+          //console.log(newTask)
+          updateTask(this.projectId, this.taskId, newTask, this.updateTaskSuccess, this.updateTaskFail)
         } else {
-          console.log('error submit!!')
+          notify('error', '表单填写有误!')
           return false
         }
       })
     },
-    cancelMode (formName) {
-      this.isModifyMode = false
-    },
-    modifyForm () {
-      this.isModifyMode = true
-    },
-    resetForm (formName) {
-      this.$refs.addFormProvince.resetProviceCity()
-      this.$refs[formName].resetFields()
-      this.task.name = ''
-      this.task.desc = ''
-      this.task.quotePrice = ''
-      this.task.fixedPrice = ''
-      this.task.type = ''
-      this.task.resource = '2'; //如果是广场不用管Location和institution ,定向看institution,区域看location
-      (this.task.location = {provinceCode: '', cityCode: ''}),
-        (this.task.institution = '')
-      this.task.datetime = ''
+    //更新任务信息成功时回调函数
+    updateTaskSuccess (res) {
+      this.cancelMode()
+      this.taskId = res.crowdTaskVO.id
+      this.projectId = res.crowdTaskVO.projectId
+      this.task.title = res.crowdTaskVO.title
+      this.task.description = res.crowdTaskVO.description
+      this.task.serviceType = res.crowdTaskVO.serviceType
+      this.task.resource = res.crowdTaskVO.resource
+      this.task.location = res.crowdTaskVO.location == null ? {
+        provinceCode: 3200,
+        cityCode: 3201
+      } : getProvinceCodeByProvinceName(res.crowdTaskVO.location.provinceCode, res.crowdTaskVO.location.cityCode)
+      this.task.institution = res.crowdTaskVO.institution
+      this.task.datetime = new Date(res.crowdTaskVO.datetime)
+      this.task.quotePrice = res.crowdTaskVO.quotePrice
+      this.task.fixedPrice = res.crowdTaskVO.fixedPrice
+      this.task.doc = []
+      this.task.requireDocUrl = res.crowdTaskVO.requirementFile
+      this.reportList = res.crowdReportVOList
+      this.hideLoading()
+      notify('success', '修改成功')
     },
-    locationChange (provinceId, cityId) {
-      if (provinceId || cityId) {
-        this.task.location = {provinceCode: provinceId, cityCode: cityId}
-      }
+    //更新任务信息失败时回调函数
+    updateTaskFail (error) {
+      notify('error', '修改失败:' + error.data)
+      this.hideLoading()
     },
-    toProject () {
-      this.$router.push({
-        name: 'Project',
-        params: {projectId: this.projectId}
-      })
-    },
-    applyTask () {
-      const data = {
-        userId: 3,
-        projectId: this.projectId,
-        taskId: this.taskId
+    //上传任务需求文档
+    uploadRequireDoc (param) {
+      const formData = new FormData()
+      let config = {
+        //添加请求头
+        headers: {'Content-Type': 'multipart/form-data'},
       }
-      Http.post(Apis.USER.ACCEPT_TASK, data).then((res) => {
-        console.log(res)
+      formData.append('file', param.file)
+      Http.upload(Apis.FILE.REQUIREMENT_FILE.replace('{userId}', this.user.userVO.id), formData, config).then((res) => {
+        this.uploadRequireDocSuccess(res)
+      }).catch((error) => {
+        this.uploadRequireDocFail(error)
       })
     },
-    submitTaskRequest () {
-      const data = {
-        userId: 3,
-        projectId: this.projectId,
-        taskId: this.taskId
-      }
-      Http.post(Apis.USER.SUBMIT_TASK_REQUEST, data).then((res) => {
-        console.log(res)
-      })
+    //上传任务需求文档成功时回调函数
+    uploadRequireDocSuccess (res) {
+      this.hideLoading()
+      console.log('上传成功')
+      this.task.requireDocUrl = res.data
+      console.log(res.data)
     },
-    createReport () {
-      this.$router.push({
-        name: 'ReportCreate',
-        params: {
-          scope: 1,
-          dependencyCode: this.taskId,
-          projectId: this.projectId,
-          taskId: this.taskId,
-        }
-      })
+    //上传任务需求文档失败时回调函数
+    uploadRequireDocFail (error) {
+      this.hideLoading()
+      notify('error', '任务需求文档上传失败:' + error.data)
     },
-    loadData (projectId, taskId) {
-      //replace('{taskId}', this.taskId)
-      Http.get(Apis.TASK.GET_TASK.replace('{projectId}', projectId).replace('{taskId}', taskId)).then((res) => {
-        this.taskId = res.crowdTaskVO.id
-        this.projectId = res.crowdTaskVO.projectId
-        this.task.title = res.crowdTaskVO.title
-        this.task.description = res.crowdTaskVO.description
-        this.task.serviceType = res.crowdTaskVO.serviceType
-        this.task.resource = res.crowdTaskVO.resource
-        this.task.location = res.crowdTaskVO.location
-        this.task.institution = res.crowdTaskVO.institution
-        this.task.datetime = new Date(res.crowdTaskVO.datetime)
-        this.task.quotePrice = res.crowdTaskVO.quotePrice
-        this.task.fixedPrice = res.crowdTaskVO.fixedPrice
-        this.task.doc = []
-        this.task.requireDocUrl = res.crowdTaskVO.requireDocUrl
+    //文档上传前响应函数
 
-        this.reportList = res.crowdReportVOList
-      })
+    //移除文档前的响应函数
+    beforeRemove (file, fileList) {
+      //return this.$confirm(`确定移除 ${file.name}?`)
     },
+    //移除文档时的响应函数
     handleRemove (file, fileList) {
       console.log(file, fileList)
     },
+    //需求文档添加进来时的响应函数
     handleExceed (files, fileList) {
       this.$message.warning(
         `当前限制选择 1 个文件,本次选择了 ${
@@ -382,54 +544,165 @@ export default {
           } 个文件,共选择了 ${files.length + fileList.length} 个文件`
       )
     },
-    beforeRemove (file, fileList) {
-      //return this.$confirm(`确定移除 ${file.name}?`)
+    //接收任务
+    receiveTask () {
+      this.$confirm('确认接收任务?', '提示', {
+        confirmButtonText: '确认接收',
+        cancelButtonText: '取消',
+        type: 'success'
+      }).then(() => {
+        this.showLoading()
+        receiveTaskRequest(this.projectId, this.taskId, this.user.userVO.id, this.receiveTaskSuccess, this.receiveTaskFail)
+      }).catch(() => {
+      })
     },
-    beforeFileUpload (file) {
-      console.log(file)
-      const isPDF = file.type === 'application/pdf'
-      const isDOC = file.type === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
-      const isEXCEL = file.type === 'application/vnd.ms-excel'
-      const isXLS = file.type === 'application/x-xls'
-      const isTXT = file.type === 'text/plain'
-      const isXLSX = file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
-      //console.log(file)
-      if (!(isDOC || isEXCEL || isPDF || isTXT || isXLS || isXLSX)) {
-        this.$message.error('上传文件只能是 PDF 、 DOC 、DOCX 、XLS、TXT、XLSX 格式!')
-      }
-      return isDOC || isEXCEL || isPDF || isTXT || isXLS || isXLSX
+    //接收任务成功时的回调函数
+    receiveTaskSuccess (res) {
+      this.hideLoading()
+      notify('success', '接收任务成功')
+      console.log(res)
+      this.taskOperationControl = res.taskOperationControl
+      this.task.status = res.crowdTaskVO.status
+      this.task.institution = res.crowdTaskVO.institution
     },
-    uploadProjectCreateExcelFile (param) {
-      const formData = new FormData()
-      let config = {
-        //添加请求头
-        headers: {'Content-Type': 'multipart/form-data'},
-      }
-      formData.append('file', param.file)
-      Http.upload(Apis.PROJECT.ADD_PROJECT_BY_EXCEL, formData, config).then((res) => {
-        console.log('上传成功')
-        this.project.excelFileUrl = res.data
-        console.log(res.data)
+    //接收任务失败时的回调函数
+    receiveTaskFail (error) {
+      this.hideLoading()
+      notify('error', '接收任务失败:' + error.data)
+    },
+    //拒绝任务
+    rejectTask () {
+      this.$confirm('确认拒绝任务?拒绝后将不能再接收该任务', '提示', {
+        confirmButtonText: '确认拒绝',
+        cancelButtonText: '取消',
+        type: 'success'
+      }).then(() => {
+        this.showLoading()
+        rejectTask(this.projectId, this.taskId, this.rejectTaskSuccess, this.rejectTaskFail)
+      }).catch(() => {
+
       })
     },
-    uploadRequireDoc (param) {
-      const formData = new FormData()
-      let config = {
-        //添加请求头
-        headers: {'Content-Type': 'multipart/form-data'},
-      }
-      formData.append('file', param.file)
-      Http.upload(Apis.FILE.REQUIREMENT_FILE.replace('{userId}', 3), formData, config).then((res) => {
-        console.log('上传成功')
-        this.task.requireDocUrl = res.data
-        console.log(res.data)
+    //拒绝任务成功时的回调函数
+    rejectTaskSuccess (res) {
+      this.hideLoading()
+      this.$router.push({
+        name: 'Mine'
+      })
+      notify('success', '拒绝任务成功,已为您自动跳转到个人中心')
+    },
+    //拒绝任务失败时的回调函数
+    rejectTaskFail (error) {
+      this.hideLoading()
+      notify('error', '拒绝任务失败:' + error.data)
+    },
+    //提交结束任务申请
+    submitTaskRequest () {
+      this.$confirm('确认提交任务?提交后将不能再修改', '提示', {
+        confirmButtonText: '确认提交',
+        cancelButtonText: '取消',
+        type: 'success'
+      }).then(() => {
+        this.showLoading()
+        submitTaskRequest(this.projectId, this.taskId, this.submitTaskRequestSuccess, this.submitTaskRequestFail)
+      }).catch(() => {
+
       })
     },
+    //提交结束任务申请成功时的回调函数
+    submitTaskRequestSuccess (res) {
+      this.hideLoading()
+      console.log(res)
+      this.taskOperationControl = res.taskOperationControl
+      this.task.status = res.crowdTaskVO.status
+      this.task.institution = res.crowdTaskVO.institution
+      notify('success', '提交任务成功,等待区域管理员审核')
+    },
+    //提交结束任务申请失败时的回调函数
+    submitTaskRequestFail (error) {
+      this.hideLoading()
+      notify('error', '提交任务失败:' + error.data)
+    },
+    //结束任务
+    endTask () {
+      this.$confirm('确认结束任务?', '提示', {
+        confirmButtonText: '确认结束',
+        cancelButtonText: '取消',
+        type: 'success'
+      }).then(() => {
+        this.showLoading()
+        ensureEndTask(this.projectId, this.taskId, this.endTaskSuccess, this.endTaskFail)
+      }).catch(() => {
+
+      })
+    },
+    //结束任务成功时的回调函数
+    endTaskSuccess (res) {
+      this.hideLoading()
+      this.taskOperationControl = res.taskOperationControl
+      this.task.status = res.crowdTaskVO.status
+      this.task.institution = res.crowdTaskVO.institution
+      notify('success', '结束任务成功!')
+    },
+    //结束任务失败时的回调函数
+    endTaskFail (error) {
+      this.hideLoading()
+      notify('error', '结束任务失败:' + error.data)
+    },
+    //跳转到创建项目报告页面
+    toCreateReport () {
+      this.$router.push({
+        name: 'TaskReportCreate',
+        params: {
+          scope: 1,
+          dependencyCode: this.taskId,
+          projectId: this.projectId,
+          taskId: this.taskId,
+        }
+      })
+    },
+    reformDate (date) {
+      return getFormalTimeFromDate(date)
+    }
   },
-  // created () {
-  //   this.loadData()
-  // }
 }
+//回收站
+//
+// updateLocation (location) {
+//   console.log(location)
+//   const loactionName = getProvinceNameByProvinceCode(location.provinceCode, location.cityCode)
+//   // var provinceName = ''
+//   // var cityName = ''
+//   // for (var item of provinceCityJSON.provinces) {
+//   //   if (item.code === location.provinceCode) {
+//   //     provinceName = item.name
+//   //     for (var city of item.cities) {
+//   //       if (city.code === location.cityCode) {
+//   //         cityName = city.name
+//   //         break
+//   //       }
+//   //     }
+//   //   }
+//   // }
+//   return loactionName.provinceCode + ' / ' + loactionName.cityCode
+// },
+//
+// locationChange (provinceId, cityId) {
+//   if (provinceId || cityId) {
+//     this.task.location = {provinceCode: provinceId, cityCode: cityId}
+//   }
+// },
+// submitForm (formName) {
+// this.$refs[formName].validate(valid => {
+//   if (valid) {
+//     this.isModifyMode = false
+//
+//   } else {
+//     console.log('error submit!!')
+//     return false
+//   }
+// })
+// },
 </script>
 
 <style lang="less" scoped>

+ 164 - 124
src/components/task/TaskCreate.vue

@@ -1,33 +1,33 @@
 <template>
-  <div class="create-container">
+  <div class="create-container" v-loading="loading">
     <div class="title h1">创建任务</div>
     <div class="create-body">
       <el-form :model="task" :rules="rules" ref="task" label-width="12%" class="demo-task">
         <el-form-item label="任务名称" prop="name">
-          <el-input v-model="task.name"></el-input>
+          <el-input size="small" v-model="task.name"></el-input>
         </el-form-item>
         <el-form-item label="任务描述" prop="desc">
-          <el-input type="textarea" v-model="task.desc"></el-input>
+          <el-input autosize type="textarea" style="width: 400px" v-model="task.desc"></el-input>
         </el-form-item>
         <el-form-item label="任务报价" prop="quotePrice">
-          <el-input v-model="task.quotePrice"></el-input>
-        </el-form-item>
-        <el-form-item label="任务定价" prop="fixedPrice">
-          <el-input v-model="task.fixedPrice"></el-input>
+          <el-input size="small" type="number" v-model="task.quotePrice">
+            <template slot="append">¥</template>
+          </el-input>
         </el-form-item>
+        <!--<el-form-item type="number" label="任务定价" prop="fixedPrice">-->
+        <!--<el-input v-model="task.fixedPrice">-->
+        <!--<template slot="append">¥</template>-->
+        <!--</el-input>-->
+        <!--</el-form-item>-->
         <el-form-item label="业务类型" prop="type">
           <el-radio-group v-model="task.type">
-            <el-radio label="0" name="type">{{serviceType[0]}}</el-radio>
-            <el-radio label="1" name="type">{{serviceType[1]}}</el-radio>
-            <el-radio label="2" name="type">{{serviceType[2]}}</el-radio>
-            <el-radio label="3" name="type">{{serviceType[3]}}</el-radio>
-            <el-radio label="4" name="type">{{serviceType[4]}}</el-radio>
-            <el-radio label="5" name="type">{{serviceType[5]}}</el-radio>
-            <el-radio label="6" name="type">{{serviceType[6]}}</el-radio>
+            <span v-for="(item,index) in serviceType" :key="index">
+              <el-radio :label="item" name="type">{{item}}</el-radio>
+            </span>
           </el-radio-group>
         </el-form-item>
         <el-form-item label="任务可见性" prop="resource">
-          <el-tabs :tab-position="tabPosition" v-model="task.resource" style="max-height: 200px;">
+          <el-tabs :tab-position="tabPosition" v-model="task.resource" style="width: 800px">
             <el-tab-pane :label="resourceType[0]" name="0">
               <el-radio-group v-model="task.institution">
                 <el-radio
@@ -35,24 +35,25 @@
                   name="type"
                   v-for="item,index in institutionArray"
                   :key="index"
-                ></el-radio>
+                >{{item.name}}
+                </el-radio>
               </el-radio-group>
             </el-tab-pane>
-            <el-tab-pane :label="resourceType[1]" name="1">
-              <provincecity
-                ref="addFormProvince"
-                @selectChange="locationChange"
-                :provinceCode="task.location.provinceCode"
-                :cityCode="task.location.cityCode"
-              ></provincecity>
-            </el-tab-pane>
+            <!--<el-tab-pane :label="resourceType[1]" name="1">-->
+            <!--<provincecity-->
+            <!--ref="addFormProvince"-->
+            <!--@selectChange="locationChange"-->
+            <!--:provinceCode="task.location.provinceCode"-->
+            <!--:cityCode="task.location.cityCode"-->
+            <!--&gt;</provincecity>-->
+            <!--</el-tab-pane>-->
             <el-tab-pane :label="resourceType[2]" name="2"></el-tab-pane>
           </el-tabs>
         </el-form-item>
         <el-form-item label="需求文档" prop="doc">
           <el-upload
-            v-if="isModifyMode"
             drag
+            style="width: 400px"
             class="upload-demo"
             action=""
             :on-remove="handleRemove"
@@ -68,18 +69,9 @@
               将文件拖到此处,或
               <em>点击上传</em>
             </div>
-            <div class="el-upload__tip" slot="tip">请上传需求文档</div>
           </el-upload>
-          <span v-if="!isModifyMode">
-              <span v-if="task.requireDocUrl == null">
-                暂无文件
-              </span>
-              <span v-if="task.requireDocUrl != null">
-                <a :href="task.requireDocUrl">{{task.requireDocUrl}}</a>
-              </span>
-            </span>
         </el-form-item>
-        <el-form-item label="任务截止时间" prop="datetime">
+        <el-form-item size="small" label="任务截止时间" prop="datetime">
           <div class="block">
             <el-date-picker
               v-model="task.datetime"
@@ -91,9 +83,9 @@
           </div>
         </el-form-item>
         <el-form-item>
-          <div class="btn btn-primary btn-info" @click="submitForm('task')">立即创建</div>
-          <div class="btn btn-primary" @click="resetForm('task')">重置</div>
-          <div class="btn btn-primary" @click="cancelCreate('task')">取消</div>
+          <div class="btn btn-medium btn-info" @click="submitForm('task')">立即创建</div>
+          <div class="btn btn-medium" @click="resetForm('task')">重置</div>
+          <div class="btn btn-medium" @click="cancelCreate('task')">取消</div>
         </el-form-item>
       </el-form>
     </div>
@@ -101,14 +93,14 @@
 </template>
 
 <script>
-import Enum from '@/constants/enum/index'
 import provincecity from '@/components/commons/ProvinceCity'
 import provinceCityJSON from '@/constants/provinceCity.json'
 import Http from '@/js/http.js'
 import Apis from '@/js/api.js'
 import ResourceType from '@/constants/enum/resource-type.js'
-import ServiceType from '@/constants/enum/service-type'
 import {notify} from '@/constants/index'
+import {getAllAgencies, getAllServiceTypes, getProvinceNameByProvinceCode, storageGet} from '@/js/index'
+
 export default {
   name: 'Task',
   components: {
@@ -116,16 +108,18 @@ export default {
   },
   data () {
     return {
+      user: {},
       projectId: 0,
-      institutionArray: Enum.institution,
+      institutionArray: [],
       tabPosition: 'top',
       resourceType: ResourceType,
-      serviceType: ServiceType,
+      loading: false,
+      serviceType: [],
       task: {
         name: '',
         desc: '',
         type: '',
-        resource: '1', //如果是广场不用管Location和institution ,定向看institution,区域看location
+        resource: '0', //如果是广场不用管Location和institution ,定向看institution,区域看location
         location: {provinceCode: '3200', cityCode: '3201'},
         institution: '',
         datetime: '',
@@ -162,45 +156,67 @@ export default {
       },
       rules: {
         name: [
-          {required: true, message: '请输入任务名称', trigger: 'blur'}
-          // { min: 3, max: 5, message: "长度在 3 到 5 个字符", trigger: "blur" }
+          {required: true, message: '请输入任务名称', trigger: 'blur'},
+          {min: 5, max: 50, message: '任务名称长度在 5 到 50 个字符', trigger: 'blur'}
         ],
-        datetime: [
+        type: [
+          {required: true, message: '业务类型不可为空'},
+        ],
+        desc: [{required: false, message: '请填写描述', trigger: 'blur'}],
+        //price: [{required: true, message: '请填写价格', trigger: 'blur'}],
+        quotePrice: [
+          {required: true, message: '预算不可为空', trigger: 'blur'},
           {
-            type: 'date',
-            required: true,
-            message: '请选择截止时间',
-            trigger: 'change'
-          }
+            validator: (rule, value, callback) => {
+              if (parseInt(value) < 0) {
+                callback(new Error('请输入不小于0的数'))
+              } else {
+                callback()
+              }
+            }, trigger: 'blur'
+          },
         ],
-        type: [
-          {required: true, message: '请选择业务类型', trigger: 'change'}
+        resource: [
+          {required: true},
+          {
+            validator: (rule, value, callback) => {
+              if (value == 0 && this.task.institution.id == null) {
+                callback(new Error('定向发布至少要选择一个测评机构'))
+              } else {
+                callback()
+              }
+            }, trigger: 'change'
+          },
         ],
-        desc: [{required: true, message: '请填写任务描述', trigger: 'blur'}],
-        quotePrice: [{required: true, message: '请填写任务报价', trigger: 'blur'}],
-        fixedPrice: [{required: true, message: '请填写任务定价', trigger: 'blur'}]
+        datetime: [{required: true, message: '截止时间不可为空', trigger: 'blur'}],
       }
     }
   },
   watch: {
-    'task.institution' () {
-      if (this.task.institution) {
-        this.$refs.addFormProvince.resetProviceCity()
-        this.task.location = {provinceCode: '', cityCode: ''}
-      }
-    },
-    'task.location' () {
-      if (this.task.location.provinceCode || this.task.location.cityCode) {
-        this.task.institution = ''
-      }
+    serviceType (val) {
+      this.serviceType = val
     },
-    'task.resource' () {
-      if (this.task.resource == '广场') {
-        this.$refs.addFormProvince.resetProviceCity()
-        this.task.institution = ''
-        this.task.location = {provinceCode: '', cityCode: ''}
-      }
+    institution (val) {
+      this.institution = val
     },
+    // 'task.institution' () {
+    //   if (this.task.institution) {
+    //     this.$refs.addFormProvince.resetProviceCity()
+    //     this.task.location = {provinceCode: '', cityCode: ''}
+    //   }
+    // },
+    // 'task.location' () {
+    //   if (this.task.location.provinceCode || this.task.location.cityCode) {
+    //     this.task.institution = ''
+    //   }
+    // },
+    // 'task.resource' () {
+    //   if (this.task.resource == '广场') {
+    //     this.$refs.addFormProvince.resetProviceCity()
+    //     this.task.institution = ''
+    //     this.task.location = {provinceCode: '', cityCode: ''}
+    //   }
+    // },
     deep: true
   },
   mounted () {
@@ -211,6 +227,9 @@ export default {
   methods: {
     init () {
       this.projectId = this.$route.params.projectId
+      this.setServiceType()
+      this.setInstitutions()
+      this.setUserInfo()
     },
     updateLocation (location) {
       var provinceName = ''
@@ -229,44 +248,35 @@ export default {
       return provinceName + ' / ' + cityName
     },
     submitForm (formName) {
-      const newTask = {
-        name: this.task.name,
-        desc: this.task.desc,
-        type: this.task.type,
-        resource: this.task.resource,
-        location: this.task.location,
-        institution: this.task.institution,
-        datetime: this.task.datetime,
-        quotePrice: this.task.quotePrice,
-        fixedPrice: this.task.fixedPrice,
-        requireDocUrl: this.task.requireDocUrl
-      }
-      Http.post(Apis.TASK.CREATE_TASK.replace('{projectId}', this.projectId), newTask).then((res) => {
-        console.log(res)
-        this.cancelCreate()
+      this.$refs['task'].validate(valid => {
+        if (valid) {
+          this.showLoading()
+          const newTask = {
+            name: this.task.name,
+            desc: this.task.desc,
+            type: this.task.type,
+            resource: this.task.resource,
+            location: getProvinceNameByProvinceCode(this.task.location.provinceCode, this.task.location.cityCode),
+            institution: this.task.institution.id,
+            datetime: this.task.datetime,
+            quotePrice: this.task.quotePrice,
+            fixedPrice: this.task.fixedPrice,
+            requirementFile: this.task.requireDocUrl
+          }
+          Http.post(Apis.TASK.CREATE_TASK.replace('{projectId}', this.projectId), newTask).then((res) => {
+            console.log(res)
+            this.hideLoading()
+            this.createTaskSuccess(res.crowdTaskVO.id)
+          }).catch((error) => {
+            console.log(error)
+            this.hideLoading()
+            notify('error', error.data)
+          })
+        } else {
+          notify('error', '表单填写有误!')
+          return false
+        }
       })
-      // this.$refs[formName].validate(valid => {
-      //   if (valid) {
-      //     const newTask = {
-      //       name: this.task.title,
-      //       desc: this.task.description,
-      //       type: this.task.serviceType,
-      //       resource: this.task.resource,
-      //       location: this.task.location,
-      //       institution:this.task.institution,
-      //       datetime:this.task.datetime,
-      //       quotePrice: this.task.quotePrice,
-      //       fixedPrice: this.task.fixedPrice
-      //     }
-      //     Http.post(Apis.TASK.CREATE_TASK.replace('{projectId}', 'PROJECT_1'), this.task).then((res) => {
-      //       console.log(res)
-      //     })
-      //     //提交 task
-      //   } else {
-      //     console.log('error submit!!')
-      //     return false
-      //   }
-      // })
     },
     resetForm (formName) {
       this.$refs.addFormProvince.resetProviceCity()
@@ -319,32 +329,58 @@ export default {
       }
       return isDOC || isEXCEL || isPDF || isTXT || isXLS || isXLSX
     },
-    uploadProjectCreateExcelFile (param) {
-      const formData = new FormData()
-      let config = {
-        //添加请求头
-        headers: {'Content-Type': 'multipart/form-data'},
-      }
-      formData.append('file', param.file)
-      Http.upload(Apis.PROJECT.ADD_PROJECT_BY_EXCEL, formData, config).then((res) => {
-        console.log('上传成功')
-        this.project.excelFileUrl = res.data
-        console.log(res.data)
-      })
-    },
     uploadRequireDoc (param) {
+      this.showLoading()
       const formData = new FormData()
       let config = {
         //添加请求头
         headers: {'Content-Type': 'multipart/form-data'},
       }
       formData.append('file', param.file)
-      Http.upload(Apis.FILE.REQUIREMENT_FILE.replace('{userId}', 3), formData, config).then((res) => {
-        console.log('上传成功')
+      Http.upload(Apis.FILE.REQUIREMENT_FILE.replace('{userId}', this.user.userVO.id), formData, config).then((res) => {
+        this.hideLoading()
+        notify('success', '上传成功')
         this.task.requireDocUrl = res.data
         console.log(res.data)
+      }).catch((error) => {
+        this.hideLoading()
+        notify('error', '上传失败:' + error.data)
+      })
+    },
+    setServiceType () {
+      this.serviceType = getAllServiceTypes().then((res) => {
+        this.serviceType = res
+      }).catch((error) => {
+        notify('error', '加载服务类型列表失败')
       })
     },
+    setInstitutions () {
+      getAllAgencies().then((res) => {
+        this.institutionArray = res
+      }).catch((error) => {
+        notify('error', '测评机构加载失败')
+      })
+    },
+    setUserInfo () {
+      this.user = storageGet('user')
+    },
+    createTaskSuccess (taskId) {
+      this.$alert('任务创建成功', '创建成功', {
+        confirmButtonText: '确定',
+        callback: action => {
+          this.$router.push({
+            name: 'Task',
+            params: {projectId: this.projectId, taskId: taskId}
+          })
+        }
+      })
+    },
+    showLoading () {
+      this.loading = true
+    },
+    hideLoading () {
+      this.loading = false
+    }
   }
 }
 </script>
@@ -354,6 +390,10 @@ export default {
     margin: 10px 20px 10px 0;
   }
 
+  .el-input {
+    width: 400px;
+  }
+
   .el-form-item /deep/ .el-tabs__content {
     max-height: 120px !important;
     overflow: auto;

+ 37 - 9
src/js/api.js

@@ -5,13 +5,22 @@ export default {
     UPDATE_PROJECT: '/api/project/{projectId}/',
     DELETE_PROJECT: '/api/project/{projectId}/',
     ADD_PROJECT: '/api/greenChannel/project/',
+    ADD_PROJECT_BY_EXCEL_PRE: '/api/greenChannel/excel/{userId}/projects',
     ADD_PROJECT_BY_EXCEL: '/api/greenChannel/projects',
+    ACCEPT_PROJECT: '/api/project/{projectId}/regionManager/{userId}',
+    REJECT_PROJECT: '/api/project/{projectId}/status/rejected',
+    SUBMIT_PROJECT: '/api/project/{projectId}/status/committed',
+    END_PROJECT: '/api/project/{projectId}/status/finished'
   },
   TASK: {
     GET_TASK: '/api/project/{projectId}/task/{taskId}/',
     CREATE_TASK: '/api/project/{projectId}/task/',
     UPDATE_TASK: '/api/project/{projectId}/task/{taskId}/',
-    DELETE_TASK: '/api/project/{projectId}/task/{taskId}/'
+    DELETE_TASK: '/api/project/{projectId}/task/{taskId}/',
+    ACCEPT_TASK: '/api/project/{projectId}/task/{taskId}/agency/{userId}', // PUT
+    REJECT_TASK: '/api/project/{projectId}/task/{taskId}/status/reject',
+    SUBMIT_TASK: '/api/project/{projectId}/task/{taskId}/status/commit',
+    END_TASK: '/api/project/{projectId}/task/{taskId}/status/finished',
   },
   REPORT: {
     GET_TASK_REPORT: '/api/project/{projectId}/task/{taskId}/report/{reportId}/',
@@ -29,18 +38,32 @@ export default {
     UPLOAD_REPORT_FILE: '/api/files/report/{userId}/',
     UPLOAD_EXCEL: '',
     UPLOAD_IMAGE: '/api/files/image/{userId}/',
+    GET_TEMPLATE_EXCEL_FILE: ''
   },
   USER: {
-    ACCEPT_TASK: '',
-    ACCEPT_PROJECT: '',
-    SUBMIT_TASK_REQUEST: '',
-    SUBMIT_PROJECT_REQUEST: '',
-    END_TASK: '',
-    END_PROJECT: '',
-    AGENCY_AUTHENTICATION: '/api/user/{userId}/agency/',
     ADD_AGENCY: '/api/greenChannel/agency/',
-    GET_CURRENT_USER: '',
+    GET_CURRENT_USER: '/api/common/currentUser/',
     GET_USER_IDENTITY: '',
+    GET_AUTH_URLS: '',
+    LOGOUT: '/api/common/logout',
+    SUBMIT_INDIVIDUAL_AUTHENTICATION_INFO: '/api/user/{userId}/personalAuth/',
+    SUBMIT_ENTERPRISE_AUTHENTICATION_INFO: '/api/user/{userId}/enterpriseAuth',
+    SUBMIT_AGENCY_AUTHENTICATION_INFO: '/api/user/{userId}/agency/',
+    UPDATE_INDIVIDUAL_AUTHENTICATION_INFO: '/api/user/{userId}/personalAuth',
+    UPDATE_ENTERPRISE_AUTHENTICATION_INFO: '/api/user/{userId}/enterpriseAuth',
+    UPDATE_AGENCY_AUTHENTICATION_INFO: '/api/user/{userId}/agency/',
+    UPDATE_AGENCY_RESOURCE_AND_ABILITY:'/api/user/{userId}/agency/resource',
+    GET_INDIVIDUAL_AUTHENTICATION_INFO: '/api/user/{userId}/personalAuth',
+    GET_ENTERPRISE_AUTHENTICATION_INFO: '/api/user/{userId}/enterpriseAuth',
+    GET_AGENCY_AUTHENTICATION_INFO: '/api/user/{userId}/agency',
+    GET_ALL_HANDLING_AUTH_INFO: '/api/user/authentication/handling',
+    GET_ALL_HANDLED_AUTH_INFO: '/api/user/authentication/handled',
+    PASS_AGENCY_AUTH:'/api/user/{userId}/agency/status/accept',
+    PASS_ENTERPRISE_AUTH:'/api/user/{userId}/enterpriseAuth/status/accept',
+    PASS_INDIVIDUAL_AUTH:'/api/user/{userId}/personalAuth/status/accept',
+    REJECT_AGENCY_AUTH:'/api/user/{userId}/agency/status/reject',
+    REJECT_ENTERPRISE_AUTH:'/api/user/{userId}/enterpriseAuth/status/reject',
+    REJECT_INDIVIDUAL_AUTH:'/api/user/{userId}/personalAuth/status/reject',
   },
   PAGE: {
     HOME_PAGE: '/api/common/index/',
@@ -49,5 +72,10 @@ export default {
     TASK_DETAIL_PAGE: '/api/page/taskDetail/{taskId}/',
     PROJECT_DETAIL_PAGE: '/api/project/{projectId}/',
     REPORT_DETAIL_PAGE: '/api/page/reportDetail/{reportId}/',
+  },
+  GENERAL: {
+    GET_ALL_ABILITIES: '',
+    GET_ALL_INSTITUTIONS: '/api/regionalManager',
+    GET_ALL_AGENCIES: '/api/agency/list'
   }
 }

+ 44 - 0
src/js/fileService.js

@@ -0,0 +1,44 @@
+import Http from './http'
+import Apis from './api'
+//上传文档
+export const uploadFile = (url, file) => {
+  const formData = new FormData()
+  let config = {
+    //添加请求头
+    headers: {'Content-Type': 'multipart/form-data'},
+  }
+  formData.append('file', file)
+  return Http.upload(url, formData, config)
+}
+
+//上传图片
+export const uploadImage = (file, uploadImageSuccess, uploadImageFail) => {
+  const formData = new FormData()
+  let config = {
+    //添加请求头
+    headers: {'Content-Type': 'multipart/form-data'},
+  }
+  formData.append('file', file)
+  Http.upload(Apis.FILE.UPLOAD_IMAGE, formData, config).then((res) => {
+    uploadImageSuccess(res)
+  }).catch((error) => {
+    uploadImageFail(error)
+  })
+}
+
+//上传图片前检测
+export const beforeUploadImage = () => {
+
+}
+
+//上传文档前检测
+export const beforeUploadFile = () => {
+
+}
+export const checkFileType = (file, typeList, checkFileTypeError) => {
+  var fileType = file.name.split('.')[file.name.split('.').length - 1].toLowerCase()
+  if (!typeList.includes(fileType)) {
+    checkFileTypeError()
+  }
+  return typeList.includes(fileType)
+}

+ 167 - 0
src/js/generalService.js

@@ -0,0 +1,167 @@
+import Http from './http'
+import Apis from './api'
+import ProvinceJson from '../constants/provinceCity'
+//存session
+export const storageSave = (key, value) => {
+  sessionStorage.setItem(key, JSON.stringify(value))
+}
+
+//取session
+export const storageGet = (key) => {
+  // return new Promise((resolve) => {
+  //   resolve(JSON.parse(sessionStorage.getItem(key)))
+  // })
+  return JSON.parse(sessionStorage.getItem(key))
+}
+
+//获取用户id
+export const getUserIdentity = () => {
+  return Http.get(Apis.USER.GET_USER_IDENTITY)
+}
+
+//获取所有测评能力
+export const getAllAbilities = () => {
+  return ['接口测试', '安全漏洞扫描', '风险评估服务', '源代码安全审计服务', '功能测试服务', '性能测试', '功能和易用性测试']
+  //return Http.get(Apis.GENERAL.GET_ALL_ABILITIES)
+}
+
+//获取所有测评资源种类
+export const getAllAgencyResourceTypes = () => {
+  return ['人力资源', '服务器资源', '专用设备']
+  //return Http.get(Apis.GENERAL.GET_ALL_ABILITIES)
+}
+
+//获取所有服务类型
+export const getAllServiceTypes = () => {
+  const data = ['接口测试', '安全漏洞扫描', '风险评估服务', '源代码安全审计服务', '功能测试服务', '性能测试', '功能和易用性测试']
+  return new Promise((resolve) => {
+    resolve(data)
+  })
+  //return Http.get(Apis.GENERAL.GET_ALL_ABILITIES)
+}
+
+//获取所有报告类型
+export const getAllReportTypes = () => {
+  const data = ['可行性报告', '测试方案', '测试报告', '缺陷报告', '用例报告', '其他']
+  return new Promise((resolve) => {
+    resolve(data)
+  })
+  //return Http.get(Apis.GENERAL.GET_ALL_ABILITIES)
+}
+
+//获取所有平台类型
+export const getAllPlatformTypes = () => {
+  return ['ANDROID', 'IOS', 'WEB']
+  //return Http.get(Apis.GENERAL.GET_ALL_ABILITIES)
+}
+//获取所有定向发布的目标
+export const getAllInstitutions = () => {
+  return Http.get(Apis.GENERAL.GET_ALL_INSTITUTIONS)
+}
+
+//获取所有测评机构
+export const getAllAgencies = () => {
+  // const data = [{
+  //   id: 1,
+  //   name: '慕测'
+  // }, {
+  //   id: 2,
+  //   name: '南大'
+  // }]
+  //
+  // return new Promise((resolve) => {
+  //   resolve(data)
+  // })
+  return Http.get(Apis.GENERAL.GET_ALL_AGENCIES)
+}
+
+//通过代码获取省、市名称
+export const getProvinceNameByProvinceCode = (provinceCode, cityCode) => {
+  for (var i = 0; i < ProvinceJson.provinces.length; i++) {
+    if (ProvinceJson.provinces[i].code == provinceCode) {
+      for (var j = 0; j < ProvinceJson.provinces[i].cities.length; j++) {
+        if (ProvinceJson.provinces[i].cities[j].code == cityCode) {
+          return {
+            'provinceCode': ProvinceJson.provinces[i].name,
+            'cityCode': ProvinceJson.provinces[i].cities[j].name
+          }
+        }
+      }
+    }
+  }
+  return {
+    'provinceCode': '江苏省',
+    'cityCode': '南京市'
+  }
+}
+//通过名称获取省、市代码
+export const getProvinceCodeByProvinceName = (provinceName, cityName) => {
+  for (var i = 0; i < ProvinceJson.provinces.length; i++) {
+    if (ProvinceJson.provinces[i].name == provinceName) {
+      for (var j = 0; j < ProvinceJson.provinces[i].cities.length; j++) {
+        if (ProvinceJson.provinces[i].cities[j].name == cityName) {
+          return {
+            'provinceCode': ProvinceJson.provinces[i].code,
+            'cityCode': ProvinceJson.provinces[i].cities[j].code
+          }
+        }
+      }
+    }
+  }
+  return {
+    'provinceCode': '3200',
+    'cityCode': '3201'
+  }
+}
+
+//获取批量上传项目模板文件
+export const getGreenChannelAddProjectExcelTemplateFile = (getTemplateExcelSuccess, getTemplateExcelFail) => {
+  const data = {
+    fileUrl: 'http://mooctest-crowd-service.oss-cn-hangzhou.aliyuncs.com/Others/%E9%A1%B9%E7%9B%AE%E5%AF%BC%E5%85%A5%E6%A8%A1%E6%9D%BF.xlsx'
+  }
+  new Promise((resolve) => {
+    resolve(data)
+  }).then((res) => {
+    getTemplateExcelSuccess(res)
+  }).catch((error) => {
+    getTemplateExcelFail(error)
+  })
+  // Http.get(Apis.FILE.GET_TEMPLATE_EXCEL_FILE).then((res) => {
+  //   getTemplateExcelSuccess(res)
+  // }).catch((error) => {
+  //   getTemplateExcelFail(error)
+  // })
+}
+Date.prototype.Format = function (fmt) {
+  var o = {
+    'M+': this.getMonth() + 1, //月份
+    'd+': this.getDate(), //日
+    'h+': this.getHours(), //小时
+    'm+': this.getMinutes(), //分
+    's+': this.getSeconds(), //秒
+    'q+': Math.floor((this.getMonth() + 3) / 3), //季度
+    'S': this.getMilliseconds() //毫秒
+  }
+  if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + '').substr(4 - RegExp.$1.length))
+  for (var k in o) {
+    if (new RegExp('(' + k + ')').test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length)))
+  }
+  return fmt
+}
+export const getFormalTimeFromDate = (date) => {
+  return date.Format('yyyy-MM-dd hh:mm:ss')
+}
+
+//
+export const getIndexStatisticsInfo = () => {
+  const data = {
+    userNum: 100,
+    agencyNum: 200,
+    deviceNum: 345,
+    projectNum: 23,
+    taskNum: 123
+  }
+  return new Promise((resolve) => {
+    resolve(data)
+  })
+}

+ 10 - 23
src/js/http.js

@@ -1,21 +1,9 @@
 import axios from 'axios'
 
 const TIME_OUT_MS = 60 * 1000 // 默认请求超时时间
+const BASE_URL = process.env.API_ROOT
 axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'
 
-// // 请求拦截器
-// axios.interceptors.request.use(function (config) {
-//   return config
-// }, function (error) {
-//   return Promise.reject(error)
-// })
-// // 响应拦截器
-// axios.interceptors.response.use(function (response) {
-//   return response
-// }, function (error) {
-//   return Promise.reject(error)
-// })
-
 /*
  * @param response 返回数据列表
  */
@@ -48,8 +36,7 @@ function handleResults (response) {
 }
 
 function handleUrl (url) {
-  //url = 'http://crowd.mooctest.net' + url
-  return url
+  return BASE_URL + url
 }
 
 /*
@@ -63,9 +50,9 @@ function handleParams (data) {
 export default {
   post (url, data) {
     return new Promise((resolve, reject) => {
-      axios.post(url, handleParams(data)).then(
+      axios.post(handleUrl(url), handleParams(data)).then(
         (result) => {
-          resolve(result)
+          resolve(result.data)
         }
       ).catch(
         (error) => {
@@ -80,7 +67,7 @@ export default {
         .then(response => {
           resolve(response.data)
         }).catch(error => {
-        reject(error)
+        reject(error.response)
       })
 
     })
@@ -88,20 +75,20 @@ export default {
   },
   put (url, data) {
     return new Promise((resolve, reject) => {
-      axios.put(url, JSON.parse(JSON.stringify(data))).then(
+      axios.put(handleUrl(url), JSON.parse(JSON.stringify(data))).then(
         (result) => {
-          resolve(result)
+          resolve(result.data)
         }
       ).catch(
         (error) => {
-          reject(error)
+          reject(error.response)
         }
       )
     })
   },
   delete (url, data) {
     return new Promise((resolve, reject) => {
-      axios.delete(url, {data: handleParams(data)}).then(
+      axios.delete(handleUrl(url), {data: handleParams(data)}).then(
         (result) => {
           resolve(result)
         }
@@ -114,7 +101,7 @@ export default {
   },
   upload (url, data, config) {
     return new Promise((resolve, reject) => {
-      axios.post(url, data, config).then(
+      axios.post(handleUrl(url), data, config).then(
         (result) => {
           resolve(result)
         }

+ 775 - 112
src/js/index.js

@@ -1,121 +1,784 @@
-import Http from './http'
-import Apis from './api'
-
-//存session
-export const storageSave = (key, value) => {
-  sessionStorage.setItem(key, value)
+import {
+  checkPassAuth,
+  checkRejectAuth,
+  deleteAuthInfo,
+  getAllHandledAuthInfo,
+  getAllHandlingAuthInfo,
+  getAuthUrls,
+  getCurrentAgencyAuthInfo,
+  getCurrentAuthenInfo,
+  getCurrentEnterpriseAuthInfo,
+  getCurrentIndividualAuthenInfo,
+  getCurrentUser,
+  getRolesPermissions,
+  logout,
+  updateAgencyAuthInfo,
+  updateEnterpriseAuthInfo,
+  updateIndividualAuthInfo,
+  uploadAgencyAuthenticationInfo,
+  uploadEnterpriseAuthenticationInfo,
+  uploadIndividualAuthenticationInfo,
+  updateAgencyResourceAndAbility
+} from './userService'
+import {
+  createProject,
+  deleteProject,
+  ensureEndProject,
+  getProject,
+  receiveProjectRequest,
+  rejectProject,
+  submitProjectRequest,
+  updateProject
+} from './projectService'
+import {
+  createTask,
+  deleteTask,
+  ensureEndTask,
+  getTask,
+  receiveTaskRequest,
+  rejectTask,
+  submitTaskRequest,
+  updateTask
+} from './taskService'
+import {
+  createProjectReport,
+  createTaskReport,
+  deleteProjectReport,
+  deleteTaskReport,
+  getProjectReport,
+  getTaskReport,
+  updateProjectReport,
+  updateTaskReport,
+} from './reportService'
+import {beforeUploadFile, beforeUploadImage, checkFileType, uploadFile, uploadImage,} from './fileService'
+import {
+  getAllAbilities,
+  getAllAgencies,
+  getAllAgencyResourceTypes,
+  getAllInstitutions,
+  getAllPlatformTypes,
+  getAllReportTypes,
+  getAllServiceTypes,
+  getFormalTimeFromDate,
+  getGreenChannelAddProjectExcelTemplateFile,
+  getIndexStatisticsInfo,
+  getProvinceCodeByProvinceName,
+  getProvinceNameByProvinceCode,
+  getUserIdentity,
+  storageGet,
+  storageSave
+} from './generalService'
+
+export {
+  /*******************************************************************************/
+  /*******************************userService*************************************/
+  /*******************************************************************************/
+  //TODO 尚未使用 用户放弃认证,删除用户认证信息
+  deleteAuthInfo,
+  //获取所有未处理认证信息
+  getAllHandlingAuthInfo,
+  //获取所有已处理认证信息
+  getAllHandledAuthInfo,
+  //TODO 目前使用本地数据 需要修改 获取所有可以访问的url
+  getAuthUrls,
+  //TODO 目前使用本地数据 需要修改 获取当前用户的认证信息
+  getCurrentAuthenInfo,
+  //TODO 可以使用 需要重构 获取当前用户信息
+  getCurrentUser,
+  //TODO 基本无用 获取当前用户所有的角色权限
+  getRolesPermissions,
+  //TODO 可以使用 需要重构 用户登出
+  logout,
+  //TODO 尚未使用 代码未实现 更新机构认证信息
+  updateAgencyAuthInfo,
+  //TODO 尚未使用 代码未实现 更新企业认证信息
+  updateEnterpriseAuthInfo,
+  //TODO 尚未使用 代码未实现 更新个人认证信息
+  updateIndividualAuthInfo,
+  //TODO 尚未使用 代码未实现 上传机构认证信息
+  uploadAgencyAuthenticationInfo,
+  //TODO 尚未使用 代码未实现 上传企业认证信息
+  uploadEnterpriseAuthenticationInfo,
+  //TODO 尚未使用 代码未实现 上传个人认证信息
+  uploadIndividualAuthenticationInfo,
+  getCurrentIndividualAuthenInfo,
+  getCurrentEnterpriseAuthInfo,
+  getCurrentAgencyAuthInfo,
+  checkPassAuth,
+  checkRejectAuth,
+  updateAgencyResourceAndAbility
 }
-
-//取session
-export const storageGet = (key) => {
-  return sessionStorage.getItem(key)
+export {
+  /*******************************************************************************/
+  /*******************************projectService**********************************/
+  /*******************************************************************************/
+  //TODO 可以使用 需要重构 创建项目
+  createProject,
+  //TODO 可以使用 需要重构 删除项目
+  deleteProject,
+  //项目拥有者确认结束项目
+  ensureEndProject,
+  //TODO 可以使用 需要重构 获取项目信息
+  getProject,
+  //区域管理员接收项目
+  receiveProjectRequest,
+  //区域管理员拒绝项目
+  rejectProject,
+  //区域管理员提交项目
+  submitProjectRequest,
+  //TODO 可以使用 需要重构 项目拥有者修改项目
+  updateProject,
 }
-
-//获取用户id
-export const getUserIdentity = () => {
-  return Http.get(Apis.USER.GET_USER_IDENTITY)
+export {
+  /*******************************************************************************/
+  /*******************************taskService*************************************/
+  /*******************************************************************************/
+  //TODO 可以使用 需要重构 创建任务
+  createTask,
+  //TODO 可以使用 需要重构 删除任务
+  deleteTask,
+  //区域管理员确认结束项目
+  ensureEndTask,
+  //查看任务信息
+  getTask,
+  //测评机构接收任务
+  receiveTaskRequest,
+  //测评机构拒绝任务
+  rejectTask,
+  //测评机构提交任务
+  submitTaskRequest,
+  //区域管理员修改任务
+  updateTask,
 }
-
-//获取用户信息
-export const getCurrentUser = () => {
-  return Http.get(Apis.USER.GET_CURRENT_USER)
+export {
+  /*******************************************************************************/
+  /*******************************reportService***********************************/
+  /*******************************************************************************/
+  //TODO 尚未使用 代码未实现 创建项目报告
+  createProjectReport,
+  //TODO 尚未使用 代码未实现 创建任务报告
+  createTaskReport,
+  //TODO 尚未使用 代码未实现 删除项目报告
+  deleteProjectReport,
+  //TODO 尚未使用 代码未实现 删除任务报告
+  deleteTaskReport,
+  //TODO 尚未使用 代码未实现 获取项目报告详情
+  getProjectReport,
+  //TODO 尚未使用 代码未实现 获取任务报告详情
+  getTaskReport,
+  //TODO 尚未使用 代码未实现 修改项目报告
+  updateProjectReport,
+  //TODO 尚未使用 代码未实现 修改任务报告
+  updateTaskReport,
 }
-
-//上传文档
-export const uploadFile = () => {
+export {
+  /*******************************************************************************/
+  /*******************************fileService*************************************/
+  /*******************************************************************************/
+  //TODO 尚未使用 代码未实现 上传图片
+  uploadImage,
+  //TODO 尚未使用 代码未实现 上传文档
+  uploadFile,
+  //TODO 尚未使用 代码未实现 校验上传格式
+  checkFileType,
+  //TODO 尚未使用 代码未实现 上传需求文档
+  //TODO 尚未使用 代码未实现 上传安装包
+  //TODO 尚未使用 代码未实现 上传批量创建项目文件
+
+  beforeUploadImage,
+  beforeUploadFile,
 
 }
-
-//上传图片
-export const uploadImage = () => {
-
+export {
+  /*******************************************************************************/
+  /*******************************generalService**********************************/
+  /*******************************************************************************/
+  //TODO 目前使用本地数据 需要修改 获取所有测评能力
+  getAllAbilities,
+  //TODO 可以使用 需要重构 获取所有测评机构
+  getAllAgencies,
+  //TODO 目前使用本地数据 需要修改 获取所有测评能力 获取所有测评资源类型
+  getAllAgencyResourceTypes,
+  //TODO 可以使用 需要重构 获取所有区域管理员
+  getAllInstitutions,
+  //TODO 目前使用本地数据 需要修改 获取所有测试平台类型
+  getAllPlatformTypes,
+  //TODO 目前使用本地数据 需要修改 获取所有报告类型
+  getAllReportTypes,
+  //TODO 目前使用本地数据 需要修改 获取所有服务类型(与获取所有测评能力相同)
+  getAllServiceTypes,
+  //获取绿色通道创建项目时的模板文件
+  getGreenChannelAddProjectExcelTemplateFile,
+  //通过省和市名称获取省市代码
+  getProvinceCodeByProvinceName,
+  //通过省市代码获取省市名称
+  getProvinceNameByProvinceCode,
+  //TODO 尚未使用 代码未实现 获取用户id
+  getUserIdentity,
+  //读取本地数据
+  storageGet,
+  //保存数据到本地
+  storageSave,
+  getFormalTimeFromDate,
+  getIndexStatisticsInfo
 }
 
-//上传图片前检测
-export const beforeUploadImage = () => {
-
-}
-
-//上传文档前检测
-export const beforeUploadFile = () => {
-
-}
-
-//创建项目
-export const createProject = () => {
-
-}
-
-//修改项目
-export const updateProject = () => {
-
-}
-
-//查看项目
-export const getProject = () => {
-
-}
-
-//删除项目
-export const deleteProject = () => {
-
-}
-
-//区域管理员提出接收项目申请
-export const receiveProjectRequest = () => {
-
-}
-
-//区域管理员提出结束项目申请
-export const endProjectRequest = () => {
-
+export const defaultValue = {
+  name: '普通用户',
+  image: 'http://www.mooctest.net/assets/img/mooctest.png',
 }
-
-//用户确认结束项目
-export const ensureEndProject = () => {
-
-}
-
-//创建任务
-export const createTask = () => {
-
-}
-
-//修改任务
-export const updateTask = () => {
-
-}
-
-//查看任务
-export const getTask = () => {
-
-}
-
-//删除任务
-export const udeleteTask = () => {
-
-}
-
-//测评机构申请任务
-export const receiveTaskRequest = () => {
-
-}
-
-//测评机构提出结束任务申请
-export const endTaskRequest = () => {
-
-}
-
-//区域管理员确认结束任务
-
-//创建项目报告
-
-//创建任务报告
-
-//修改项目报告
-
-//修改任务报告
-
-//查看报告
-
-//删除报告
+//
+// //存session
+// export const storageSave = (key, value) => {
+//   sessionStorage.setItem(key, JSON.stringify(value))
+// }
+//
+// //取session
+// export const storageGet = (key) => {
+//   // return new Promise((resolve) => {
+//   //   resolve(JSON.parse(sessionStorage.getItem(key)))
+//   // })
+//   return JSON.parse(sessionStorage.getItem(key))
+// }
+//
+// //获取用户id
+// export const getUserIdentity = () => {
+//   return Http.get(Apis.USER.GET_USER_IDENTITY)
+// }
+//
+// //获取用户信息
+// export const getCurrentUser = () => {
+//   // const data = {
+//   //   userVO: {
+//   //     id: 3,
+//   //     photo: 'http://www.mooctest.net/assets/img/mooctest.png',
+//   //     name: '郭超',
+//   //     roleList: ['区域管理员', '个人用户', '企业用户', '测评机构', '系统管理员'],
+//   //     mobile: '110',
+//   //     email: '12345@qq.com',
+//   //   },
+//   //   agency: '',
+//   // }
+//   // return new Promise((resolve) => {
+//   //   resolve(data)
+//   // })
+//   return Http.get(Apis.USER.GET_CURRENT_USER)
+// }
+// //
+// export const getRolesPermissions = (roleList) => {
+//   const roles = {
+//     regionManager: 'RegionalManager',
+//     individualUser: 'generalUser',
+//     enterpriseUser: 'enterpriseUser',
+//     agency: 'evaluationAgency',
+//     systemAdministrator: 'SystemAdministrator'
+//   }
+//   const permissions = {
+//     isRegionManager: false,
+//     isIndividualUser: false,
+//     isEnterpriseUser: false,
+//     isAgency: false,
+//     isSystemAdministrator: false
+//   }
+//   if (roleList.includes(roles.regionManager)) {
+//     permissions.isRegionManager = true
+//     permissions.isEnterpriseUser = true
+//     permissions.isIndividualUser = true
+//   }
+//   if (roleList.includes(roles.agency)) {
+//     permissions.isAgency = true
+//     permissions.isEnterpriseUser = true
+//     permissions.isIndividualUser = true
+//   }
+//   if (roleList.includes(roles.enterpriseUser)) {
+//     permissions.isEnterpriseUser = true
+//   }
+//   if (roleList.includes(roles.individualUser)) {
+//     permissions.isIndividualUser = true
+//   }
+//   if (roleList.includes(roles.systemAdministrator)) {
+//     permissions.isSystemAdministrator = true
+//     permissions.isRegionManager = true
+//     permissions.isAgency = true
+//     permissions.isEnterpriseUser = true
+//     permissions.isIndividualUser = true
+//   }
+//   return permissions
+// }
+//
+// export const logout = () => {
+//   sessionStorage.removeItem('user')
+//   sessionStorage.removeItem('rolesPermissions')
+//   return Http.get(Apis.USER.LOGOUT)
+// }
+//
+// //上传文档
+// export const uploadFile = (url, file) => {
+//   const formData = new FormData()
+//   let config = {
+//     //添加请求头
+//     headers: {'Content-Type': 'multipart/form-data'},
+//   }
+//   formData.append('file', file)
+//   return Http.upload(url, formData, config)
+// }
+//
+// //上传图片
+// export const uploadImage = (file, uploadImageSuccess, uploadImageFail) => {
+//   const formData = new FormData()
+//   let config = {
+//     //添加请求头
+//     headers: {'Content-Type': 'multipart/form-data'},
+//   }
+//   formData.append('file', file)
+//   Http.upload(Apis.FILE.UPLOAD_IMAGE, formData, config).then((res) => {
+//     uploadImageSuccess(res)
+//   }).catch((error) => {
+//     uploadImageFail(error)
+//   })
+// }
+//
+// //上传图片前检测
+// export const beforeUploadImage = () => {
+//
+// }
+//
+// //上传文档前检测
+// export const beforeUploadFile = () => {
+//
+// }
+//
+// //创建项目
+// export const createProject = (project) => {
+//   return Http.post(Apis.PROJECT.CREATE_PROJECT, project)
+// }
+//
+// //修改项目
+// export const updateProject = (project, projectId) => {
+//   return Http.put(Apis.PROJECT.UPDATE_PROJECT.replace('{projectId}', projectId), project)
+// }
+//
+// //查看项目
+// export const getProject = (projectId) => {
+//   Http.get(Apis.PROJECT.GET_PROJECT.replace('{projectId}', projectId))
+// }
+//
+// //删除项目
+// export const deleteProject = (projectId, deleteProjectSuccess, deleteProjectFail) => {
+//   Http.put(Apis.PROJECT.DELETE_PROJECT.replace('{projectId}', projectId), {}).then((res) => {
+//     deleteProjectSuccess(res)
+//   }).catch((error) => {
+//     deleteProjectFail(error)
+//   })
+// }
+//
+// //区域管理员提出接收项目申请
+// export const receiveProjectRequest = (projectId, userId, receiveProjectSuccess, receiveProjectFail) => {
+//   console.log('调用')
+//   Http.put(Apis.PROJECT.ACCEPT_PROJECT.replace('{projectId}', projectId).replace('{userId}', userId), {}).then((res) => {
+//     console.log(res)
+//     receiveProjectSuccess(res)
+//
+//   }).catch((error) => {
+//     console.log(error)
+//     receiveProjectFail(error)
+//   })
+// }
+//
+// //区域管理员拒绝项目
+// export const rejectProject = (projectId, rejectProjectSuccess, rejectProjectFail) => {
+//   Http.put(Apis.PROJECT.REJECT_PROJECT.replace('{projectId}', projectId), {}).then((res) => {
+//     rejectProjectSuccess(res)
+//   }).catch((error) => {
+//     rejectProjectFail(error)
+//   })
+// }
+//
+// //区域管理员提出结束项目申请
+// export const submitProjectRequest = (projectId, submitProjectReuqestSuccess, submitProjectRequestFail) => {
+//   Http.put(Apis.PROJECT.SUBMIT_PROJECT.replace('{projectId}', projectId), {}).then((res) => {
+//     submitProjectReuqestSuccess(res)
+//   }).catch((error) => {
+//     submitProjectRequestFail(error)
+//   })
+// }
+//
+// //用户确认结束项目
+// export const ensureEndProject = (projectId, endProjectSuccess, endProjectFail) => {
+//   Http.put(Apis.PROJECT.END_PROJECT.replace('{projectId}', projectId), {}).then((res) => {
+//     endProjectSuccess(res)
+//   }).catch((error) => {
+//     endProjectFail(error)
+//   })
+// }
+//
+// //创建任务
+// export const createTask = (projectId, task) => {
+//   return Http.post(Apis.TASK.CREATE_TASK.replace('{projectId}', projectId), task)
+// }
+//
+// //修改任务
+// export const updateTask = (projectId, taskId, task, updateTaskSuccess, updateTaskFail) => {
+//   Http.put(Apis.TASK.UPDATE_TASK.replace('{projectId}', projectId).replace('{taskId}', taskId), task).then((res) => {
+//     updateTaskSuccess(res)
+//   }).catch((error) => {
+//     updateTaskFail(error)
+//   })
+// }
+//
+// //查看任务
+// export const getTask = (projectId, taskId, getTaskSuccess, getTaskFail) => {
+//   Http.get(Apis.TASK.GET_TASK.replace('{projectId}', projectId).replace('{taskId}', taskId), {}).then((res) => {
+//     getTaskSuccess(res)
+//   }).catch((error) => {
+//     getTaskFail(error)
+//   })
+// }
+//
+// //删除任务
+// export const deleteTask = (projectId, taskId, deleteTaskSuccess, deleteTaskFail) => {
+//   Http.put(Apis.TASK.DELETE_TASK.replace('{projectId}', projectId).replace('taskId', taskId), {}).then((res) => {
+//     deleteTaskSuccess(res)
+//   }).catch((error) => {
+//     deleteTaskFail(error)
+//   })
+// }
+//
+// //测评机构接受任务
+// export const receiveTaskRequest = (projectId, taskId, userId, receiveTaskRequestSuccess, receiveTaskRequestFail) => {
+//   Http.put(Apis.TASK.ACCEPT_TASK.replace('{projectId}', projectId).replace('{taskId}', taskId).replace('{userId}', userId), {}).then((res) => {
+//     receiveTaskRequestSuccess(res)
+//   }).catch((error) => {
+//     receiveTaskRequestFail(error)
+//   })
+//
+// }
+//
+// //测评机构提出结束任务申请
+// export const submitTaskRequest = (projectId, taskId, submitTaskSuccess, submitTaskFail) => {
+//   Http.put(Apis.TASK.SUBMIT_TASK.replace('{projectId}', projectId).replace('{taskId}', taskId), {}).then((res) => {
+//     submitTaskSuccess(res)
+//   }).catch((error) => {
+//     submitTaskFail(error)
+//   })
+// }
+//
+// export const rejectTask = (projectId, taskId, rejectTaskSuccess, rejectTaskFail) => {
+//   Http.put(Apis.TASK.REJECT_TASK.replace('{projectId}', projectId).replace('{taskId}', taskId), {}).then((res) => {
+//     rejectTaskSuccess(res)
+//   }).catch((error) => {
+//     rejectTaskFail(error)
+//   })
+// }
+//
+// //区域管理员确认结束任务
+// export const ensureEndTask = (projectId, taskId, endTaskSuccess, endTaskFail) => {
+//   Http.put(Apis.TASK.END_TASK.replace('{projectId}', projectId).replace('{taskId}', taskId), {}).then((res) => {
+//     endTaskSuccess(res)
+//   }).catch((error) => {
+//     endTaskFail(error)
+//   })
+// }
+//
+// //创建项目报告
+// export const createProjectReport = () => {
+//
+// }
+//
+// //创建任务报告
+// export const createTaskReport = () => {
+//
+// }
+//
+// //修改项目报告
+// export const updateProjectReport = () => {
+//
+// }
+//
+// //修改任务报告
+// export const updateTaskReport = () => {
+//
+// }
+//
+// //查看报告
+// export const getReport = () => {
+//
+// }
+//
+// //删除项目报告
+// export const deleteProjectReport = (projectId, reportId, deleteProjectReportSuccess, deleteProjectReportFail) => {
+//   Http.put(Apis.REPORT.DELETE_PROJECT_REPORT.replace('{projectId}', projectId).replace('{reportId}', reportId), {}).then((res) => {
+//     deleteProjectReportSuccess(res)
+//   }).catch((error) => {
+//     deleteProjectReportFail(error)
+//   })
+// }
+//
+// //删除任务报告
+// export const deleteTaskReport = (projectId, taskId, reportId, deleteTaskReportSuccess, deleteTaskReportFail) => {
+//   Http.put(Apis.REPORT.DELETE_TASK_REPORT.replace('{projectId}', projectId).replace('{taskId}', taskId).replace('{reportId}', reportId), {}).then((res) => {
+//     deleteTaskReportSuccess(res)
+//   }).catch((error) => {
+//     deleteTaskReportFail(error)
+//   })
+// }
+//
+// //获取所有测评能力
+// export const getAllAbilities = () => {
+//   return ['接口测试', '安全漏洞扫描', '风险评估服务', '源代码安全审计服务', '功能测试服务', '性能测试', '功能和易用性测试']
+//   //return Http.get(Apis.GENERAL.GET_ALL_ABILITIES)
+// }
+//
+// //获取所有测评资源种类
+// export const getAllAgencyResourceTypes = () => {
+//   return ['人力资源', '服务器资源', '专用设备']
+//   //return Http.get(Apis.GENERAL.GET_ALL_ABILITIES)
+// }
+//
+// //获取所有服务类型
+// export const getAllServiceTypes = () => {
+//   const data = ['接口测试', '安全漏洞扫描', '风险评估服务', '源代码安全审计服务', '功能测试服务', '性能测试', '功能和易用性测试']
+//   return new Promise((resolve) => {
+//     resolve(data)
+//   })
+//   //return Http.get(Apis.GENERAL.GET_ALL_ABILITIES)
+// }
+//
+// //获取所有报告类型
+// export const getAllReportTypes = () => {
+//   const data = ['项目可行性报告', '项目测试方案', '项目测试报告', '项目缺陷报告', '项目用例报告', '其他']
+//   return new Promise((resolve) => {
+//     resolve(data)
+//   })
+//   //return Http.get(Apis.GENERAL.GET_ALL_ABILITIES)
+// }
+//
+// //获取所有平台类型
+// export const getAllPlatformTypes = () => {
+//   return ['ANDROID', 'IOS', 'WEB']
+//   //return Http.get(Apis.GENERAL.GET_ALL_ABILITIES)
+// }
+//
+// //获取当前角色可访问的url
+// export const getAuthUrls = () => {
+//   return [
+//     '/', '/home', '/square', '/mine', '/project/create',
+//     '/project/:projectId', '/project/:projectId/task/create',
+//     '/project/:projectId/task/:taskId', '/project/:projectId/analyse',
+//     '/report/create', '/report/:reportId', '/greenChannel/addProject', '/greenChannel/addAgency',
+//     '/authentication/individual', '/authentication/enterprise',
+//     '/authentication/agency', '/authentication/index'
+//   ]
+//   //return Http.get(Apis.USER.GET_AUTH_URLS)
+// }
+//
+// //上传个人认证信息
+// export const uploadIndividualAuthenticationInfo = () => {
+//   Http.post(Apis)
+// }
+//
+// //上传企业认证信息
+// export const uploadEnterpriseAuthenticationInfo = () => {
+//
+// }
+//
+// //上传机构认证信息
+// export const uploadAgencyAuthenticationInfo = () => {
+//
+// }
+//
+// //获取所有定向发布的目标
+// export const getAllInstitutions = () => {
+//   return Http.get(Apis.GENERAL.GET_ALL_INSTITUTIONS)
+// }
+//
+// //获取所有测评机构
+// export const getAllAgencies = () => {
+//   // const data = [{
+//   //   id: 1,
+//   //   name: '慕测'
+//   // }, {
+//   //   id: 2,
+//   //   name: '南大'
+//   // }]
+//   //
+//   // return new Promise((resolve) => {
+//   //   resolve(data)
+//   // })
+//   return Http.get(Apis.GENERAL.GET_ALL_AGENCIES)
+// }
+//
+// //通过代码获取省、市名称
+// export const getProvinceNameByProvinceCode = (provinceCode, cityCode) => {
+//   for (var i = 0; i < ProvinceJson.provinces.length; i++) {
+//     if (ProvinceJson.provinces[i].code == provinceCode) {
+//       for (var j = 0; j < ProvinceJson.provinces[i].cities.length; j++) {
+//         if (ProvinceJson.provinces[i].cities[j].code == cityCode) {
+//           return {
+//             'provinceCode': ProvinceJson.provinces[i].name,
+//             'cityCode': ProvinceJson.provinces[i].cities[j].name
+//           }
+//         }
+//       }
+//     }
+//   }
+//   return {
+//     'provinceCode': '江苏省',
+//     'cityCode': '南京市'
+//   }
+// }
+// //通过名称获取省、市代码
+// export const getProvinceCodeByProvinceName = (provinceName, cityName) => {
+//   for (var i = 0; i < ProvinceJson.provinces.length; i++) {
+//     if (ProvinceJson.provinces[i].name == provinceName) {
+//       for (var j = 0; j < ProvinceJson.provinces[i].cities.length; j++) {
+//         if (ProvinceJson.provinces[i].cities[j].name == cityName) {
+//           return {
+//             'provinceCode': ProvinceJson.provinces[i].code,
+//             'cityCode': ProvinceJson.provinces[i].cities[j].code
+//           }
+//         }
+//       }
+//     }
+//   }
+//   return {
+//     'provinceCode': '3200',
+//     'cityCode': '3201'
+//   }
+// }
+//
+// //获取批量上传项目模板文件
+// export const getGreenChannelAddProjectExcelTemplateFile = (getTemplateExcelSuccess, getTemplateExcelFail) => {
+//   const data = {
+//     fileUrl: 'http://mooctest-crowd-service.oss-cn-hangzhou.aliyuncs.com/Others/%E9%A1%B9%E7%9B%AE%E5%AF%BC%E5%85%A5%E6%A8%A1%E6%9D%BF.xlsx'
+//   }
+//   new Promise((resolve) => {
+//     resolve(data)
+//   }).then((res) => {
+//     getTemplateExcelSuccess(res)
+//   }).catch((error) => {
+//     getTemplateExcelFail(error)
+//   })
+//   // Http.get(Apis.FILE.GET_TEMPLATE_EXCEL_FILE).then((res) => {
+//   //   getTemplateExcelSuccess(res)
+//   // }).catch((error) => {
+//   //   getTemplateExcelFail(error)
+//   // })
+// }
+//
+// //获取所有认证消息
+// export const getAllAuthentications = () => {
+//   return [{
+//     userVO: {},
+//     type: '',
+//     status: '',
+//     authenticationDetail: {}
+//   }]
+// }
+//
+// export const getCurrentAuthenInfo = () => {
+//   const individualData = {
+//     type: '个人',//企业、机构、个人
+//     //共有
+//     id: 1,
+//     userId: 3,
+//     bankAccount: '621000999000999000',
+//     address: '江苏科技大厦',
+//     status: '认证失败',
+//     rejectReason: '太强',
+//     createTime: '2019.13.12',
+//     //个人
+//     realName: '李白',
+//     IDCard: '32092111111111',
+//     IDCardPhoto: 'http://www.mooctest.net/assets/img/mooctest.png',
+//   }
+//   const enterpriseData = {
+//     type: '企业',//企业、机构、个人
+//     //共有
+//     id: 1,
+//     userId: 3,
+//     bankAccount: '621000999000999000',
+//     address: '江苏科技大厦1901',
+//     status: '',
+//     rejectReason: '',
+//     createTime: '',
+//     //企业
+//     companyName: '慕测呀',
+//     legalPersonName: '郭超啊',
+//     businessLicensePhoto: null,
+//     unifiedSocialCreditCode: '1900000000086',
+//
+//   }
+//   const agencyData = {
+//     type: '机构',//企业、机构、个人
+//     //共有
+//     id: 1,
+//     userId: 3,
+//     bankAccount: '100000000086',
+//     address: '江苏科技大厦1901',
+//     status: '',
+//     rejectReason: '123123123',
+//     createTime: '',
+//     //机构
+//     evaluationAgencyName: '慕测科技',
+//     evaluationAgencyAbilityList: ['接口测试', '安全漏洞扫描', '风险评估服务', '源代码安全审计服务', '功能测试服务', '性能测试', '功能和易用性测试'],
+//     evaluationAgencyResourceList: [
+//       {
+//         id: 0,
+//         type: '人力资源',
+//         name: '专家',
+//         totalNum: 100,
+//         availableNum: 3,
+//       },
+//       {
+//         id: 1,
+//         type: '人力资源',
+//         name: '程序员',
+//         totalNum: 100,
+//         availableNum: 3,
+//       }
+//     ],
+//     agencyPhoto: 'http://www.mooctest.net/assets/img/mooctest.png',
+//   }
+//   return new Promise((resolve) => {
+//     resolve(enterpriseData)
+//   })
+// }
+// //放弃认证
+// export const deleteAuthInfo = () => {
+//   const data = {}
+//   return new Promise((resolve) => {
+//     resolve(data)
+//   })
+//   //return Http.get(Apis.GENERAL.GET_ALL_ABILITIES)
+// }
+// //
+// export const updateIndividualAuthInfo = (userId, authInfo) => {
+//   // const data = {}
+//   // return new Promise((resolve) => {
+//   //   resolve(data)
+//   // })
+//   return Http.put(Apis.USER.UPDATE_INDIVIDUAL_AUTHENTICATION_INFO.replace('{userId}', userId), authInfo)
+// }
+// export const updateAgencyAuthInfo = (userId, authInfo) => {
+//   // const data = {}
+//   // return new Promise((resolve) => {
+//   //   resolve(data)
+//   // })
+//   return Http.put(Apis.USER.UPDATE_AGENCY_AUTHENTICATION_INFO.replace('{userId}', userId), authInfo)
+// }
+// export const updateEnterpriseAuthInfo = (userId, authInfo) => {
+//   // const data = {}
+//   // return new Promise((resolve) => {
+//   //   resolve(data)
+//   // })
+//   return Http.put(Apis.USER.UPDATE_ENTERPRISE_AUTHENTICATION_INFO.replace('{userId}', userId), authInfo)
+// }
+// //
+// export const checkFileType = (file, typeList, checkFileTypeError) => {
+//   var fileType = file.name.split('.')[file.name.split('.').length - 1].toLowerCase()
+//   if (!typeList.includes(fileType)) {
+//     checkFileTypeError()
+//   }
+//   return typeList.includes(fileType)
+// }

+ 65 - 0
src/js/projectService.js

@@ -0,0 +1,65 @@
+import Http from './http'
+import Apis from './api'
+//创建项目
+export const createProject = (project) => {
+  return Http.post(Apis.PROJECT.CREATE_PROJECT, project)
+}
+
+//修改项目
+export const updateProject = (project, projectId) => {
+  return Http.put(Apis.PROJECT.UPDATE_PROJECT.replace('{projectId}', projectId), project)
+}
+
+//查看项目
+export const getProject = (projectId) => {
+  Http.get(Apis.PROJECT.GET_PROJECT.replace('{projectId}', projectId))
+}
+
+//删除项目
+export const deleteProject = (projectId, deleteProjectSuccess, deleteProjectFail) => {
+  Http.put(Apis.PROJECT.DELETE_PROJECT.replace('{projectId}', projectId), {}).then((res) => {
+    deleteProjectSuccess(res)
+  }).catch((error) => {
+    deleteProjectFail(error)
+  })
+}
+
+//区域管理员提出接收项目申请
+export const receiveProjectRequest = (projectId, userId, receiveProjectSuccess, receiveProjectFail) => {
+  console.log('调用')
+  Http.put(Apis.PROJECT.ACCEPT_PROJECT.replace('{projectId}', projectId).replace('{userId}', userId), {}).then((res) => {
+    console.log(res)
+    receiveProjectSuccess(res)
+
+  }).catch((error) => {
+    console.log(error)
+    receiveProjectFail(error)
+  })
+}
+
+//区域管理员拒绝项目
+export const rejectProject = (projectId, rejectProjectSuccess, rejectProjectFail) => {
+  Http.put(Apis.PROJECT.REJECT_PROJECT.replace('{projectId}', projectId), {}).then((res) => {
+    rejectProjectSuccess(res)
+  }).catch((error) => {
+    rejectProjectFail(error)
+  })
+}
+
+//区域管理员提出结束项目申请
+export const submitProjectRequest = (projectId, submitProjectReuqestSuccess, submitProjectRequestFail) => {
+  Http.put(Apis.PROJECT.SUBMIT_PROJECT.replace('{projectId}', projectId), {}).then((res) => {
+    submitProjectReuqestSuccess(res)
+  }).catch((error) => {
+    submitProjectRequestFail(error)
+  })
+}
+
+//用户确认结束项目
+export const ensureEndProject = (projectId, endProjectSuccess, endProjectFail) => {
+  Http.put(Apis.PROJECT.END_PROJECT.replace('{projectId}', projectId), {}).then((res) => {
+    endProjectSuccess(res)
+  }).catch((error) => {
+    endProjectFail(error)
+  })
+}

+ 48 - 0
src/js/reportService.js

@@ -0,0 +1,48 @@
+import Http from './http'
+import Apis from './api'
+//创建项目报告
+export const createProjectReport = () => {
+
+}
+
+//创建任务报告
+export const createTaskReport = () => {
+
+}
+
+//修改项目报告
+export const updateProjectReport = () => {
+
+}
+
+//修改任务报告
+export const updateTaskReport = () => {
+
+}
+
+//查看项目报告
+export const getProjectReport = () => {
+
+}
+//查看任务报告
+export const getTaskReport = () => {
+
+}
+
+//删除项目报告
+export const deleteProjectReport = (projectId, reportId, deleteProjectReportSuccess, deleteProjectReportFail) => {
+  Http.put(Apis.REPORT.DELETE_PROJECT_REPORT.replace('{projectId}', projectId).replace('{reportId}', reportId), {}).then((res) => {
+    deleteProjectReportSuccess(res)
+  }).catch((error) => {
+    deleteProjectReportFail(error)
+  })
+}
+
+//删除任务报告
+export const deleteTaskReport = (projectId, taskId, reportId, deleteTaskReportSuccess, deleteTaskReportFail) => {
+  Http.put(Apis.REPORT.DELETE_TASK_REPORT.replace('{projectId}', projectId).replace('{taskId}', taskId).replace('{reportId}', reportId), {}).then((res) => {
+    deleteTaskReportSuccess(res)
+  }).catch((error) => {
+    deleteTaskReportFail(error)
+  })
+}

+ 69 - 0
src/js/taskService.js

@@ -0,0 +1,69 @@
+import Http from './http'
+import Apis from './api'
+//创建任务
+export const createTask = (projectId, task) => {
+  return Http.post(Apis.TASK.CREATE_TASK.replace('{projectId}', projectId), task)
+}
+
+//修改任务
+export const updateTask = (projectId, taskId, task, updateTaskSuccess, updateTaskFail) => {
+  Http.put(Apis.TASK.UPDATE_TASK.replace('{projectId}', projectId).replace('{taskId}', taskId), task).then((res) => {
+    updateTaskSuccess(res)
+  }).catch((error) => {
+    updateTaskFail(error)
+  })
+}
+
+//查看任务
+export const getTask = (projectId, taskId, getTaskSuccess, getTaskFail) => {
+  Http.get(Apis.TASK.GET_TASK.replace('{projectId}', projectId).replace('{taskId}', taskId), {}).then((res) => {
+    getTaskSuccess(res)
+  }).catch((error) => {
+    getTaskFail(error)
+  })
+}
+
+//删除任务
+export const deleteTask = (projectId, taskId, deleteTaskSuccess, deleteTaskFail) => {
+  Http.put(Apis.TASK.DELETE_TASK.replace('{projectId}', projectId).replace('taskId', taskId), {}).then((res) => {
+    deleteTaskSuccess(res)
+  }).catch((error) => {
+    deleteTaskFail(error)
+  })
+}
+
+//测评机构接受任务
+export const receiveTaskRequest = (projectId, taskId, userId, receiveTaskRequestSuccess, receiveTaskRequestFail) => {
+  Http.put(Apis.TASK.ACCEPT_TASK.replace('{projectId}', projectId).replace('{taskId}', taskId).replace('{userId}', userId), {}).then((res) => {
+    receiveTaskRequestSuccess(res)
+  }).catch((error) => {
+    receiveTaskRequestFail(error)
+  })
+
+}
+
+//测评机构提出结束任务申请
+export const submitTaskRequest = (projectId, taskId, submitTaskSuccess, submitTaskFail) => {
+  Http.put(Apis.TASK.SUBMIT_TASK.replace('{projectId}', projectId).replace('{taskId}', taskId), {}).then((res) => {
+    submitTaskSuccess(res)
+  }).catch((error) => {
+    submitTaskFail(error)
+  })
+}
+
+export const rejectTask = (projectId, taskId, rejectTaskSuccess, rejectTaskFail) => {
+  Http.put(Apis.TASK.REJECT_TASK.replace('{projectId}', projectId).replace('{taskId}', taskId), {}).then((res) => {
+    rejectTaskSuccess(res)
+  }).catch((error) => {
+    rejectTaskFail(error)
+  })
+}
+
+//区域管理员确认结束任务
+export const ensureEndTask = (projectId, taskId, endTaskSuccess, endTaskFail) => {
+  Http.put(Apis.TASK.END_TASK.replace('{projectId}', projectId).replace('{taskId}', taskId), {}).then((res) => {
+    endTaskSuccess(res)
+  }).catch((error) => {
+    endTaskFail(error)
+  })
+}

+ 0 - 0
src/js/test.js


+ 310 - 0
src/js/userService.js

@@ -0,0 +1,310 @@
+import Http from './http'
+import Apis from './api'
+//获取用户信息
+export const getCurrentUser = (getCurrentUserSuccess, getCurrentUserFail) => {
+  // const data = {
+  //   userVO: {
+  //     id: 3,
+  //     photo: 'http://www.mooctest.net/assets/img/mooctest.png',
+  //     name: '郭超',
+  //     roleList: ['区域管理员', '个人用户', '企业用户', '测评机构', '系统管理员'],
+  //     mobile: '110',
+  //     email: '12345@qq.com',
+  //   },
+  //   agency: '',
+  // }
+  // return new Promise((resolve) => {
+  //   resolve(data)
+  // })
+  return Http.get(Apis.USER.GET_CURRENT_USER)
+  // Http.get(Apis.USER.GET_CURRENT_USER).then((res) => {
+  //   getCurrentUserSuccess(res)
+  // }).catch((error) => {
+  //   getCurrentUserFail(error)
+  // })
+}
+//
+export const getRolesPermissions = (roleList) => {
+  const roles = {
+    regionManager: 'RegionalManager',
+    individualUser: 'generalUser',
+    enterpriseUser: 'enterpriseUser',
+    agency: 'evaluationAgency',
+    systemAdministrator: 'SystemAdministrator'
+  }
+  const permissions = {
+    isRegionManager: false,
+    isIndividualUser: false,
+    isEnterpriseUser: false,
+    isAgency: false,
+    isSystemAdministrator: false
+  }
+  if (roleList.includes(roles.regionManager)) {
+    permissions.isRegionManager = true
+    permissions.isEnterpriseUser = true
+    permissions.isIndividualUser = true
+  }
+  if (roleList.includes(roles.agency)) {
+    permissions.isAgency = true
+    permissions.isEnterpriseUser = true
+    permissions.isIndividualUser = true
+  }
+  if (roleList.includes(roles.enterpriseUser)) {
+    permissions.isEnterpriseUser = true
+  }
+  if (roleList.includes(roles.individualUser)) {
+    permissions.isIndividualUser = true
+  }
+  if (roleList.includes(roles.systemAdministrator)) {
+    permissions.isSystemAdministrator = true
+    permissions.isRegionManager = true
+    permissions.isAgency = true
+    permissions.isEnterpriseUser = true
+    permissions.isIndividualUser = true
+  }
+  return permissions
+}
+
+export const logout = () => {
+  sessionStorage.removeItem('user')
+  sessionStorage.removeItem('rolesPermissions')
+  return Http.get(Apis.USER.LOGOUT)
+}
+//获取当前角色可访问的url
+export const getAuthUrls = () => {
+  return [
+    '/', '/home', '/square', '/mine', '/project/create',
+    '/project/:projectId', '/project/:projectId/task/create',
+    '/project/:projectId/task/:taskId', '/project/:projectId/analyse',
+    '/report/create', '/report/:reportId', '/greenChannel/addProject', '/greenChannel/addAgency',
+    '/authentication/individual', '/authentication/enterprise',
+    '/authentication/agency', '/authentication/index'
+  ]
+  //return Http.get(Apis.USER.GET_AUTH_URLS)
+}
+
+//上传个人认证信息
+export const uploadIndividualAuthenticationInfo = (userId, userAuthInfo, uploadIndividualAuthenticationInfoSuccess, uploadIndividualAuthenticationInfoFail) => {
+  Http.post(Apis.USER.SUBMIT_INDIVIDUAL_AUTHENTICATION_INFO.replace('{userId}', userId), userAuthInfo).then((res) => {
+    uploadIndividualAuthenticationInfoSuccess(res)
+  }).catch(error => {
+    uploadIndividualAuthenticationInfoFail(error)
+  })
+}
+
+//上传企业认证信息
+export const uploadEnterpriseAuthenticationInfo = (userId, userAuthInfo, uploadEnterpriseAuthenticationInfoSuccess, uploadEnterpriseAuthenticationInfoFail) => {
+  Http.post(Apis.USER.SUBMIT_ENTERPRISE_AUTHENTICATION_INFO.replace('{userId}', userId), userAuthInfo).then((res) => {
+    uploadEnterpriseAuthenticationInfoSuccess(res)
+  }).catch(error => {
+    uploadEnterpriseAuthenticationInfoFail(error)
+  })
+}
+
+//上传机构认证信息
+export const uploadAgencyAuthenticationInfo = (userId, userAuthInfo, uploadAgencyAuthenticationInfoSuccess, uploadAgencyAuthenticationInfoFail) => {
+  Http.post(Apis.USER.SUBMIT_AGENCY_AUTHENTICATION_INFO.replace('{userId}', userId), userAuthInfo).then((res) => {
+    uploadAgencyAuthenticationInfoSuccess(res)
+  }).catch(error => {
+    uploadAgencyAuthenticationInfoFail(error)
+  })
+}
+
+//获取所有未处理认证消息
+export const getAllHandlingAuthInfo = (getAllHandlingAuthInfoSuccess, getAllHandlingAuthInfoFail) => {
+  Http.get(Apis.USER.GET_ALL_HANDLING_AUTH_INFO).then((res) => {
+    getAllHandlingAuthInfoSuccess(res)
+  }).catch((error) => {
+    getAllHandlingAuthInfoFail(error)
+  })
+}
+//获取所有已处理认证消息
+export const getAllHandledAuthInfo = (getAllHandledAuthInfoSuccess, getAllHandledAuthInfoFail) => {
+  Http.get(Apis.USER.GET_ALL_HANDLED_AUTH_INFO).then((res) => {
+    getAllHandledAuthInfoSuccess(res)
+  }).catch((error) => {
+    getAllHandledAuthInfoFail(error)
+  })
+}
+export const getCurrentIndividualAuthenInfo = (userId, getCurrentIndividualAuthenInfoSuccess, getCurrentIndividualAuthenInfoFail) => {
+  Http.get(Apis.USER.GET_INDIVIDUAL_AUTHENTICATION_INFO.replace('{userId}', userId)).then((res) => {
+    getCurrentIndividualAuthenInfoSuccess(res)
+  }).catch((error) => {
+    getCurrentIndividualAuthenInfoFail(error)
+  })
+}
+
+export const getCurrentEnterpriseAuthInfo = (userId, getCurrentEnterpriseAuthInfoSuccess, getCurrentEnterpriseAuthInfoFail) => {
+  Http.get(Apis.USER.GET_ENTERPRISE_AUTHENTICATION_INFO.replace('{userId}', userId)).then((res) => {
+    getCurrentEnterpriseAuthInfoSuccess(res)
+  }).catch((error) => {
+    getCurrentEnterpriseAuthInfoFail(error)
+  })
+}
+export const getCurrentAgencyAuthInfo = (userId, getCurrentEnterpriseAuthInfoSuccess, getCurrentEnterpriseAuthInfoFail) => {
+  Http.get(Apis.USER.GET_AGENCY_AUTHENTICATION_INFO.replace('{userId}', userId)).then((res) => {
+    getCurrentEnterpriseAuthInfoSuccess(res)
+  }).catch((error) => {
+    getCurrentEnterpriseAuthInfoFail(error)
+  })
+}
+export const getCurrentAuthenInfo = () => {
+  const individualData = {
+    type: '个人',//企业、机构、个人
+    //共有
+    id: 1,
+    userId: 3,
+    bankAccount: '621000999000999000',
+    address: '江苏科技大厦',
+    status: '认证失败',
+    rejectReason: '太强',
+    createTime: '2019.13.12',
+    //个人
+    realName: '李白',
+    IDCard: '32092111111111',
+    IDCardPhoto: 'http://www.mooctest.net/assets/img/mooctest.png',
+  }
+  const enterpriseData = {
+    type: '企业',//企业、机构、个人
+    //共有
+    id: 1,
+    userId: 3,
+    bankAccount: '621000999000999000',
+    address: '江苏科技大厦1901',
+    status: '',
+    rejectReason: '',
+    createTime: '',
+    //企业
+    companyName: '慕测呀',
+    legalPersonName: '郭超啊',
+    businessLicensePhoto: null,
+    unifiedSocialCreditCode: '1900000000086',
+
+  }
+  const agencyData = {
+    type: '机构',//企业、机构、个人
+    //共有
+    id: 1,
+    userId: 3,
+    bankAccount: '100000000086',
+    address: '江苏科技大厦1901',
+    status: '',
+    rejectReason: '123123123',
+    createTime: '',
+    //机构
+    evaluationAgencyName: '慕测科技',
+    evaluationAgencyAbilityList: ['接口测试', '安全漏洞扫描', '风险评估服务', '源代码安全审计服务', '功能测试服务', '性能测试', '功能和易用性测试'],
+    evaluationAgencyResourceList: [
+      {
+        id: 0,
+        type: '人力资源',
+        name: '专家',
+        totalNum: 100,
+        availableNum: 3,
+      },
+      {
+        id: 1,
+        type: '人力资源',
+        name: '程序员',
+        totalNum: 100,
+        availableNum: 3,
+      }
+    ],
+    agencyPhoto: 'http://www.mooctest.net/assets/img/mooctest.png',
+  }
+  return new Promise((resolve) => {
+    resolve(enterpriseData)
+  })
+}
+//放弃认证
+export const deleteAuthInfo = () => {
+  const data = {}
+  return new Promise((resolve) => {
+    resolve(data)
+  })
+  //return Http.get(Apis.GENERAL.GET_ALL_ABILITIES)
+}
+//
+export const updateIndividualAuthInfo = (userId, authInfo, updateIndividualAuthInfoSuccess, updateIndividualAuthInfoFail) => {
+  // const data = {}
+  // return new Promise((resolve) => {
+  //   resolve(data)
+  // })
+  Http.put(Apis.USER.UPDATE_INDIVIDUAL_AUTHENTICATION_INFO.replace('{userId}', userId), authInfo).then((res) => {
+    updateIndividualAuthInfoSuccess(res)
+  }).catch((error) => {
+    updateIndividualAuthInfoFail(error)
+  })
+}
+export const updateAgencyAuthInfo = (userId, authInfo, updateAgencyAuthInfoSuccess, updateAgencyAuthInfoFail) => {
+  Http.put(Apis.USER.UPDATE_AGENCY_AUTHENTICATION_INFO.replace('{userId}', userId), authInfo).then((res) => {
+    updateAgencyAuthInfoSuccess(res)
+  }).catch((error) => {
+    updateAgencyAuthInfoFail(error)
+  })
+}
+export const updateAgencyResourceAndAbility = (userId, authInfo, updateAgencyResourceAndAbilitySuccess, updateAgencyResourceAndAbilityFail) => {
+  Http.post(Apis.USER.UPDATE_AGENCY_RESOURCE_AND_ABILITY.replace('{userId}', userId), authInfo).then((res) => {
+    updateAgencyResourceAndAbilitySuccess(res)
+  }).catch((error) => {
+    updateAgencyResourceAndAbilityFail(error)
+  })
+}
+export const updateEnterpriseAuthInfo = (userId, authInfo, updateEnterpriseAuthInfoSuccess, updateEnterpriseAuthInfoFail) => {
+  // const data = {}
+  // return new Promise((resolve) => {
+  //   resolve(data)
+  // })
+  Http.put(Apis.USER.UPDATE_ENTERPRISE_AUTHENTICATION_INFO.replace('{userId}', userId), authInfo).then((res) => {
+    updateEnterpriseAuthInfoSuccess(res)
+  }).catch((error) => {
+    updateEnterpriseAuthInfoFail(error)
+  })
+}
+
+export const checkPassAuth = (type, userId, checkPassAuthSuccess, checkPassAuthFail) => {
+  if (type == 'agency') {
+    Http.put(Apis.USER.PASS_AGENCY_AUTH.replace('{userId}', userId), {}).then((res) => {
+      checkPassAuthSuccess(res)
+    }).catch((error) => {
+      checkPassAuthFail(error)
+    })
+  }
+  if (type == 'personal') {
+    Http.put(Apis.USER.PASS_INDIVIDUAL_AUTH.replace('{userId}', userId), {}).then((res) => {
+      checkPassAuthSuccess(res)
+    }).catch((error) => {
+      checkPassAuthFail(error)
+    })
+  }
+  if (type == 'enterprise') {
+    Http.put(Apis.USER.PASS_ENTERPRISE_AUTH.replace('{userId}', userId), {}).then((res) => {
+      checkPassAuthSuccess(res)
+    }).catch((error) => {
+      checkPassAuthFail(error)
+    })
+  }
+}
+export const checkRejectAuth = (type, userId, data, checkRejectAuthSuccess, checkRejectAuthFail) => {
+  if (type == 'agency') {
+    Http.put(Apis.USER.REJECT_AGENCY_AUTH.replace('{userId}', userId), data).then((res) => {
+      checkRejectAuthSuccess(res)
+    }).catch((error) => {
+      checkRejectAuthFail(error)
+    })
+  }
+  if (type == 'personal') {
+    Http.put(Apis.USER.REJECT_INDIVIDUAL_AUTH.replace('{userId}', userId), data).then((res) => {
+      checkRejectAuthSuccess(res)
+    }).catch((error) => {
+      checkRejectAuthFail(error)
+    })
+  }
+  if (type == 'enterprise') {
+    Http.put(Apis.USER.REJECT_ENTERPRISE_AUTH.replace('{userId}', userId), data).then((res) => {
+      checkRejectAuthSuccess(res)
+    }).catch((error) => {
+      checkRejectAuthFail(error)
+    })
+  }
+}

+ 176 - 43
src/main.js

@@ -4,59 +4,189 @@ import Vue from 'vue'
 import App from './App'
 import router from './router'
 import 'font-awesome/css/font-awesome.css'
-import './style/main.scss';
-
-
+import './style/main.scss'
+import {getAuthUrls, getCurrentUser, getRolesPermissions, storageGet, storageSave} from '@/js/index'
+import {notify} from '@/constants/index'
 import {
-  Carousel,Tag, Card, CarouselItem,Dialog, Row, Col, Table, TableColumn, Form, FormItem, Button, ButtonGroup,
-  Menu, Submenu, MenuItem, MenuItemGroup, Input, InputNumber, Radio, RadioGroup, RadioButton,
-  Checkbox, CheckboxButton, CheckboxGroup, DatePicker, TimeSelect, TimePicker, Switch, Select,
-  Option, Upload, Tabs, TabPane, Collapse, CollapseItem, MessageBox, Message, Notification,
+  Avatar,
+  Badge,
+  Button,
+  ButtonGroup,
+  Card,
+  Carousel,
+  CarouselItem,
+  Checkbox,
+  CheckboxButton,
+  CheckboxGroup,
+  Col,
+  Collapse,
+  CollapseItem,
+  DatePicker,
+  Dialog,
+  Dropdown,
+  DropdownItem,
+  DropdownMenu,
+  Form,
+  FormItem,
+  Image,
+  Input,
+  InputNumber,
+  Link,
+  Loading,
+  Menu,
+  MenuItem,
+  MenuItemGroup,
+  Message,
+  MessageBox,
+  Notification,
+  Option,
+  Pagination,
+  Popover,
+  Radio,
+  RadioButton,
+  RadioGroup,
+  Row,
+  Select,
+  Submenu,
+  Switch,
+  Table,
+  TableColumn,
+  TabPane,
+  Tabs,
+  Tag,
+  TimePicker,
+  TimeSelect,
+  Tooltip,
+  Upload,
 } from 'element-ui'
+function getCurrentUserSuccess(res){
+
+}
+// var _hmt = _hmt || [];
+// (function() {
+//   var hm = document.createElement("script");
+//   hm.src = "https://hm.baidu.com/hm.js?0e3bd98236bd62558926fc433751d60c";
+//   var s = document.getElementsByTagName("script")[0];
+//   s.parentNode.insertBefore(hm, s);
+// })();
+router.beforeEach((to, from, next) => {
+  // if (_hmt) {
+  //   if (to.path) {
+  //     _hmt.push(['_trackPageview', '/#' + to.fullPath]);
+  //   }
+  // }
+  const urls = getAuthUrls()
+  if (storageGet('user') == null) {
+    getCurrentUser().then((res) => {
+      storageSave('user', res)
+      storageSave('rolesPermissions', getRolesPermissions(res.roleList))
+      if (to.matched.some(record => record.meta.requireAuth)) { // 判断该路由是否需要登录权限
+        if (sessionStorage.userName === '2' && urls.includes(to.matched[0].path)) { // 判断缓存里面是否有 userName  //在登录的时候设置它的值
+          next()
+        } else {
+          next({
+            path: '/',
+            query: {
+              redirect: to.fullPath
+            } // 将跳转的路由path作为参数,登录成功后跳转到该路由
+          })
+        }
+      } else {
+        next()
+      }
+    }).catch((error) => {
+      notify('warning', '请登录')
+      if (to.matched.some(record => record.meta.requireAuth)) { // 判断该路由是否需要登录权限
+        if (sessionStorage.userName === '2' && urls.includes(to.matched[0].path)) { // 判断缓存里面是否有 userName  //在登录的时候设置它的值
+          next()
+        } else {
+          next({
+            path: '/',
+            query: {
+              redirect: to.fullPath
+            } // 将跳转的路由path作为参数,登录成功后跳转到该路由
+          })
+        }
+      } else {
+        next()
+      }
+    })
+  } else {
+    if (to.matched.some(record => record.meta.requireAuth)) { // 判断该路由是否需要登录权限
+      if (sessionStorage.userName === '2' && urls.includes(to.matched[0].path)) { // 判断缓存里面是否有 userName  //在登录的时候设置它的值
+        next()
+      } else {
+        next({
+          path: '/',
+          query: {
+            redirect: to.fullPath
+          } // 将跳转的路由path作为参数,登录成功后跳转到该路由
+        })
+      }
+    } else {
+      next()
+    }
+  }
+  //console.log(to.matched[0].path)
+  //console.log(urls.includes(to.matched[0].path))
+
+})
+
 // require('./mock.js')
 Vue.use(Carousel)
 Vue.use(CarouselItem)
 Vue.use(Row)
 Vue.use(Col)
-Vue.use(Table);
-Vue.use(TableColumn);
-Vue.use(Form);
-Vue.use(FormItem);
-Vue.use(Button);
-Vue.use(ButtonGroup);
-Vue.use(Menu);
-Vue.use(Submenu);
-Vue.use(MenuItem);
-Vue.use(MenuItemGroup);
-Vue.use(Input);
-Vue.use(InputNumber);
-Vue.use(Radio);
-Vue.use(RadioGroup);
-Vue.use(RadioButton);
-Vue.use(Checkbox);
-Vue.use(CheckboxButton);
-Vue.use(CheckboxGroup);
-Vue.use(DatePicker);
-Vue.use(TimeSelect);
-Vue.use(TimePicker);
-Vue.use(Switch);
-Vue.use(Select);
-Vue.use(Option);
-Vue.use(Upload);
-Vue.use(Tabs);
-Vue.use(TabPane);
-Vue.use(Collapse);
-Vue.use(CollapseItem);
+Vue.use(Table)
+Vue.use(TableColumn)
+Vue.use(Form)
+Vue.use(FormItem)
+Vue.use(Button)
+Vue.use(ButtonGroup)
+Vue.use(Menu)
+Vue.use(Submenu)
+Vue.use(MenuItem)
+Vue.use(MenuItemGroup)
+Vue.use(Input)
+Vue.use(InputNumber)
+Vue.use(Radio)
+Vue.use(RadioGroup)
+Vue.use(RadioButton)
+Vue.use(Checkbox)
+Vue.use(CheckboxButton)
+Vue.use(CheckboxGroup)
+Vue.use(DatePicker)
+Vue.use(TimeSelect)
+Vue.use(TimePicker)
+Vue.use(Switch)
+Vue.use(Select)
+Vue.use(Option)
+Vue.use(Upload)
+Vue.use(Tabs)
+Vue.use(TabPane)
+Vue.use(Collapse)
+Vue.use(CollapseItem)
 Vue.use(Dialog)
 Vue.use(Card)
 Vue.use(Tag)
+Vue.use(Avatar)
+Vue.use(Pagination)
+Vue.use(Link)
+Vue.use(Loading)
+Vue.use(Tooltip)
+Vue.use(Dropdown)
+Vue.use(DropdownItem)
+Vue.use(DropdownMenu)
+Vue.use(Image)
+Vue.use(Badge)
+Vue.use(Popover)
 
-Vue.prototype.$msgbox = MessageBox;
-Vue.prototype.$alert = MessageBox.alert;
-Vue.prototype.$confirm = MessageBox.confirm;
-Vue.prototype.$prompt = MessageBox.prompt;
-Vue.prototype.$notify = Notification;
-Vue.prototype.$message = Message;
+Vue.prototype.$msgbox = MessageBox
+Vue.prototype.$alert = MessageBox.alert
+Vue.prototype.$confirm = MessageBox.confirm
+Vue.prototype.$prompt = MessageBox.prompt
+Vue.prototype.$notify = Notification
+Vue.prototype.$message = Message
 
 Vue.config.productionTip = false
 
@@ -64,6 +194,9 @@ Vue.config.productionTip = false
 new Vue({
   el: '#app',
   router,
-  components: { App },
+  data:{
+    Bus:new Vue()
+  },
+  components: {App},
   template: '<App/>'
 })

+ 158 - 15
src/router/index.js

@@ -11,11 +11,8 @@ import Project from '@/components/project/Project'
 import ProjectCreate from '@/components/project/ProjectCreate'
 import AnalyseDemand from '@/components/project/AnalyseDemand'
 
-import Report from '@/components/report/Report'
-import ReportCreate from '@/components/report/ReportCreate'
 import ProjectAdd from '@/components/cheat/ProjectAdd'
 import AgencyAdd from '@/components/cheat/AgencyAdd'
-import Authentication from '@/components/authen/Authentication'
 
 Vue.use(Router)
 
@@ -24,72 +21,218 @@ export default new Router({
     {
       path: '/',
       name: 'Index',
-      component: Home
+      component: Home,
+      meta: {
+        title: '',
+        requireAuth: false,  // false表示不需要登录,true表示需要登录
+      },
     },
     {
       path: '/home',
       name: 'Home',
       component: resolve => require(['@/components/Home.vue'], resolve),
+      meta: {
+        title: '',
+        requireAuth: false,
+      },
     },
     {
       path: '/square',
       name: 'Square',
       component: resolve => require(['@/components/Square.vue'], resolve),
+      meta: {
+        title: '',
+        requireAuth: false,
+      },
     },
     {
       path: '/mine',
       name: 'Mine',
       component: resolve => require(['@/components/Mine.vue'], resolve),
+      meta: {
+        title: '',
+        requireAuth: false,
+      },
     },
     {
       path: '/project/create',
       name: 'ProjectCreate',
       component: resolve => require(['@/components/project/ProjectCreate.vue'], resolve),
+      meta: {
+        title: '',
+        requireAuth: false,
+      },
     },
     {
       path: '/project/:projectId',
       name: 'Project',
       component: resolve => require(['@/components/project/Project.vue'], resolve),
+      meta: {
+        title: '',
+        requireAuth: false,
+      },
     },
     {
       path: '/project/:projectId/task/create',
       name: 'TaskCreate',
       component: resolve => require(['@/components/task/TaskCreate.vue'], resolve),
+      meta: {
+        title: '',
+        requireAuth: false,
+      },
     },
     {
       path: '/project/:projectId/task/:taskId',
       name: 'Task',
       component: resolve => require(['@/components/task/Task.vue'], resolve),
+      meta: {
+        title: '',
+        requireAuth: false,
+      },
     },
     {
       path: '/project/:projectId/analyse',
       name: 'AnalyseDemand',
       component: resolve => require(['@/components/project/AnalyseDemand.vue'], resolve),
+      meta: {
+        title: '',
+        requireAuth: false,
+      },
     },
     {
-      path: '/report/create',
-      name: 'ReportCreate',
-      component: resolve => require(['@/components/report/ReportCreate.vue'], resolve),
+      path: '/project/:projectId/report/create',
+      name: 'ProjectReportCreate',
+      component: resolve => require(['@/components/report/ProjectReportCreate.vue'], resolve),
+      meta: {
+        title: '',
+        requireAuth: false,
+      },
     },
     {
-      path: '/report/:reportId',
-      name: 'Report',
-      component: resolve => require(['@/components/report/Report.vue'], resolve),
+      path: '/project/:projectId/task/:taskId/report/create',
+      name: 'TaskReportCreate',
+      component: resolve => require(['@/components/report/TaskReportCreate.vue'], resolve),
+      meta: {
+        title: '',
+        requireAuth: false,
+      },
     },
     {
-      path: '/addProject',
+      path: '/project/:projectId/task/:taskId/report/:reportId',
+      name: 'TaskReport',
+      component: resolve => require(['@/components/report/TaskReport.vue'], resolve),
+      meta: {
+        title: '',
+        requireAuth: false,
+      },
+    },
+    {
+      path: '/project/:projectId/report/:reportId',
+      name: 'ProjectReport',
+      component: resolve => require(['@/components/report/ProjectReport.vue'], resolve),
+      meta: {
+        title: '',
+        requireAuth: false,
+      },
+    },
+    {
+      path: '/greenChannel/addProject',
       name: 'ProjectAdd',
       component: resolve => require(['@/components/cheat/ProjectAdd.vue'], resolve),
+      meta: {
+        title: '',
+        requireAuth: false,
+      },
     },
     {
-      path: '/addAgency',
+      path: '/greenChannel/addAgency',
       name: 'AgencyAdd',
       component: resolve => require(['@/components/cheat/AgencyAdd.vue'], resolve),
+      meta: {
+        title: '',
+        requireAuth: false,
+      },
+    },
+    {
+      path: '/authentication/individual/create',
+      name: 'IndividualAuthenticationCreate',
+      component: resolve => require(['@/components/authen/IndividualAuthenticationCreate.vue'], resolve),
+      meta: {
+        title: '',
+        requireAuth: false,
+      },
+    },
+    {
+      path: '/authentication/enterprise/create',
+      name: 'EnterpriseAuthenticationCreate',
+      component: resolve => require(['@/components/authen/EnterpriseAuthenticationCreate.vue'], resolve),
+      meta: {
+        title: '',
+        requireAuth: false,
+      },
+    },
+    {
+      path: '/authentication/agency/create',
+      name: 'AgencyAuthenticationCreate',
+      component: resolve => require(['@/components/authen/AgencyAuthenticationCreate.vue'], resolve),
+      meta: {
+        title: '',
+        requireAuth: false,
+      },
+    },
+    {
+      path: '/authentication/individual/:userId',
+      name: 'IndividualAuthentication',
+      component: resolve => require(['@/components/authen/IndividualAuthentication.vue'], resolve),
+      meta: {
+        title: '',
+        requireAuth: false,
+      },
+    },
+    {
+      path: '/authentication/enterprise/:userId',
+      name: 'EnterpriseAuthentication',
+      component: resolve => require(['@/components/authen/EnterpriseAuthentication.vue'], resolve),
+      meta: {
+        title: '',
+        requireAuth: false,
+      },
+    },
+    {
+      path: '/authentication/agency/:userId',
+      name: 'AgencyAuthentication',
+      component: resolve => require(['@/components/authen/AgencyAuthentication.vue'], resolve),
+      meta: {
+        title: '',
+        requireAuth: false,
+      },
+    },
+    {
+      path: '/authentication/index',
+      name: 'AuthenticationIndex',
+      component: resolve => require(['@/components/authen/AuthenticationIndex.vue'], resolve),
+      meta: {
+        title: '',
+        requireAuth: false,
+      },
+    },
+    {
+      path: '/authentication/manage',
+      name: 'AuthenticationManage',
+      component: resolve => require(['@/components/authen/AuthenticationManage.vue'], resolve),
+      meta: {
+        title: '',
+        requireAuth: false,
+      },
     },
     {
-      path: '/authentication',
-      name: 'Authentication',
-      component: resolve => require(['@/components/authen/Authentication.vue'], resolve),
+      path: '/agency/:userId',
+      name: 'Agency',
+      component: resolve => require(['@/components/cheat/AgencyDetail.vue'], resolve),
+      meta: {
+        title: '',
+        requireAuth: false,
+      },
     },
   ]
 })

+ 11 - 0
tool4deploy/Dockerfile

@@ -0,0 +1,11 @@
+FROM nginx
+
+RUN rm -rf /usr/share/nginx/html/*
+
+COPY ./crowd-web /usr/share/nginx/html/
+
+RUN chmod -R 777 /usr/share/nginx/html
+
+EXPOSE 80
+
+CMD ["nginx", "-g", "daemon off;"]

+ 28 - 0
tool4deploy/conf.d/nginx.conf

@@ -0,0 +1,28 @@
+server {
+        listen       80;
+        server_name  crowd.test.mooctest.net;
+        root /usr/share/nginx/html;
+        #charset koi8-r;
+
+        #access_log  logs/host.access.log  main;
+
+        location / {
+            root /usr/share/nginx/html;
+        }
+
+        location /api {
+            proxy_set_header Host                          $host;
+            proxy_set_header X-Real-IP                  $remote_addr;
+            proxy_set_header X-Forwarded-For      $proxy_add_x_forwarded_for;
+            proxy_pass http://backend:8080;
+        }
+
+        #error_page  404              /404.html;
+
+        # redirect server error pages to the static page /50x.html
+        #
+        error_page   500 502 503 504  /50x.html;
+        location = /50x.html {
+            root   html;
+        }
+ }

+ 0 - 132
tool4deploy/nginx.conf

@@ -1,132 +0,0 @@
-#user  nobody;
-worker_processes  1;
-
-#error_log  logs/error.log;
-#error_log  logs/error.log  notice;
-#error_log  logs/error.log  info;
-
-#pid        logs/nginx.pid;
-
-
-events {
-    worker_connections  1024;
-}
-
-
-http {
-    include       mime.types;
-    default_type  application/octet-stream;
-
-    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
-    #                  '$status $body_bytes_sent "$http_referer" '
-    #                  '"$http_user_agent" "$http_x_forwarded_for"';
-
-    #access_log  logs/access.log  main;
-    server_names_hash_bucket_size 64;
-    sendfile        on;
-    #tcp_nopush     on;
-
-    #keepalive_timeout  0;
-    keepalive_timeout  65;
-    
-    #gzip  on;
-	
-	server {
-		
-		listen		80;
-		server_name crowd.test.mooctest.net;
-		
-		location / {
-			proxy_pass http://localhost:5757;
-		}
-
-		location /api {
-			proxy_pass http://localhost:8080;
-		}
-	}
-
-
-
-    server {
-        listen       80;
-        server_name  localhost;
-
-        #charset koi8-r;
-
-        #access_log  logs/host.access.log  main;
-
-        location / {
-            root   html;
-            index  index.html index.htm;
-        }
-
-        #error_page  404              /404.html;
-
-        # redirect server error pages to the static page /50x.html
-        #
-        error_page   500 502 503 504  /50x.html;
-        location = /50x.html {
-            root   html;
-        }
-
-        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
-        #
-        #location ~ \.php$ {
-        #    proxy_pass   http://127.0.0.1;
-        #}
-
-        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
-        #
-        #location ~ \.php$ {
-        #    root           html;
-        #    fastcgi_pass   127.0.0.1:9000;
-        #    fastcgi_index  index.php;
-        #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
-        #    include        fastcgi_params;
-        #}
-
-        # deny access to .htaccess files, if Apache's document root
-        # concurs with nginx's one
-        #
-        #location ~ /\.ht {
-        #    deny  all;
-        #}
-    }
-
-
-    # another virtual host using mix of IP-, name-, and port-based configuration
-    #
-    #server {
-    #    listen       8000;
-    #    listen       somename:8080;
-    #    server_name  somename  alias  another.alias;
-
-    #    location / {
-    #        root   html;
-    #        index  index.html index.htm;
-    #    }
-    #}
-
-
-    # HTTPS server
-    #
-    #server {
-    #    listen       443 ssl;
-    #    server_name  localhost;
-
-    #    ssl_certificate      cert.pem;
-    #    ssl_certificate_key  cert.key;
-
-    #    ssl_session_cache    shared:SSL:1m;
-    #    ssl_session_timeout  5m;
-
-    #    ssl_ciphers  HIGH:!aNULL:!MD5;
-    #    ssl_prefer_server_ciphers  on;
-
-    #    location / {
-    #        root   html;
-    #        index  index.html index.htm;
-    #    }
-    #}
-
-}

Some files were not shown because too many files changed in this diff