Explorar o código

Merge branch 'Dev' into 'Test'

Dev

See merge request crowd-2019/crowd-test-service-front!2
薛晓波 %!s(int64=6) %!d(string=hai) anos
pai
achega
a7b9698e7f
Modificáronse 51 ficheiros con 4257 adicións e 1914 borrados
  1. 2 1
      build/webpack.dev.conf.js
  2. 11 3
      config/index.js
  3. 47 4
      package-lock.json
  4. 4 1
      package.json
  5. 88 98
      src/components/Home.vue
  6. 24 34
      src/components/InstitutionRank.vue
  7. 85 167
      src/components/Mine.vue
  8. 7 27
      src/components/PersonRank.vue
  9. 18 250
      src/components/Square.vue
  10. 198 0
      src/components/authen/Authentication.vue
  11. 315 0
      src/components/cheat/AgencyAdd.vue
  12. 469 0
      src/components/cheat/ProjectAdd.vue
  13. 244 230
      src/components/commons/Header.vue
  14. 41 44
      src/components/commons/ProjectItem.vue
  15. 9 3
      src/components/commons/ProvinceCity.vue
  16. 5 0
      src/components/commons/TaskCard.vue
  17. 58 47
      src/components/commons/TaskItem.vue
  18. 6 0
      src/components/project/AnalyseDemand.vue
  19. 390 343
      src/components/project/Project.vue
  20. 290 130
      src/components/project/ProjectCreate.vue
  21. 190 114
      src/components/report/Report.vue
  22. 136 66
      src/components/report/ReportCreate.vue
  23. 61 55
      src/components/report/ReportList.vue
  24. 306 152
      src/components/task/Task.vue
  25. 234 102
      src/components/task/TaskCreate.vue
  26. 2 2
      src/constants/enum/index.js
  27. 10 0
      src/constants/enum/report-type.js
  28. 7 0
      src/constants/enum/resource-type.js
  29. 52 24
      src/constants/index.js
  30. 53 0
      src/js/api.js
  31. 129 0
      src/js/http.js
  32. 121 0
      src/js/index.js
  33. 5 1
      src/main.js
  34. 32 0
      src/mock.js
  35. 6 0
      src/mock/createAnalyseDemandMock.js
  36. 6 0
      src/mock/createProjectMock.js
  37. 6 0
      src/mock/createReportMock.js
  38. 6 0
      src/mock/createTaskMock.js
  39. 96 0
      src/mock/getHomePageMock.js
  40. 139 0
      src/mock/getMyCrowdTestMock.js
  41. 57 0
      src/mock/getProjectDetailMock.js
  42. 27 0
      src/mock/getReportDetailMock.js
  43. 100 0
      src/mock/getSquarePageMock.js
  44. 84 0
      src/mock/getTaskDetailMock.js
  45. 10 0
      src/mock/test.js
  46. 6 0
      src/mock/updateProjectMock.js
  47. 6 0
      src/mock/updateReportMock.js
  48. 6 0
      src/mock/updateTaskMock.js
  49. 29 13
      src/router/index.js
  50. 21 0
      src/store/index.js
  51. 3 3
      src/style/main.scss

+ 2 - 1
build/webpack.dev.conf.js

@@ -42,7 +42,8 @@ const devWebpackConfig = merge(baseWebpackConfig, {
     quiet: true, // necessary for FriendlyErrorsPlugin
     watchOptions: {
       poll: config.dev.poll,
-    }
+    },
+    disableHostCheck: true, //  开发环境使用true方便开发,生产环境使用false
   },
   plugins: [
     new webpack.DefinePlugin({

+ 11 - 3
config/index.js

@@ -10,11 +10,19 @@ module.exports = {
     // Paths
     assetsSubDirectory: 'static',
     assetsPublicPath: '/',
-    proxyTable: {},
+    proxyTable: {// config/index.js  文件
+      '/api': {
+        target: 'http://localhost:8080/', // 设置你调用的接口域名和端口号
+        changeOrigin: true,     // 跨域
+        pathRewrite: {
+          '^/api': '/'
+        }
+      },
+    },
 
     // Various Dev Server settings
     host: 'localhost', // can be overwritten by process.env.HOST
-    port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
+    port: 5757, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
     autoOpenBrowser: false,
     errorOverlay: true,
     notifyOnErrors: true,
@@ -56,7 +64,7 @@ module.exports = {
      * Source Maps
      */
 
-    productionSourceMap: true,
+    productionSourceMap: false,
     // https://webpack.js.org/configuration/devtool/#production
     devtool: '#source-map',
 

+ 47 - 4
package-lock.json

@@ -536,6 +536,38 @@
       "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==",
       "dev": true
     },
+    "axios": {
+      "version": "0.19.0",
+      "resolved": "https://registry.npm.taobao.org/axios/download/axios-0.19.0.tgz",
+      "integrity": "sha1-jgm/89kSLhM/e4EByPvdAO09Krg=",
+      "requires": {
+        "follow-redirects": "1.5.10",
+        "is-buffer": "^2.0.2"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "3.1.0",
+          "resolved": "http://registry.npm.taobao.org/debug/download/debug-3.1.0.tgz",
+          "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=",
+          "requires": {
+            "ms": "2.0.0"
+          }
+        },
+        "follow-redirects": {
+          "version": "1.5.10",
+          "resolved": "http://registry.npm.taobao.org/follow-redirects/download/follow-redirects-1.5.10.tgz",
+          "integrity": "sha1-e3qfmuov3/NnhqlP9kPtB/T/Xio=",
+          "requires": {
+            "debug": "=3.1.0"
+          }
+        },
+        "is-buffer": {
+          "version": "2.0.3",
+          "resolved": "http://registry.npm.taobao.org/is-buffer/download/is-buffer-2.0.3.tgz",
+          "integrity": "sha1-Ts8/z3ScvR5HJonhCaxmJhol5yU="
+        }
+      }
+    },
     "babel-code-frame": {
       "version": "6.26.0",
       "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
@@ -2173,8 +2205,7 @@
     "commander": {
       "version": "2.17.1",
       "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz",
-      "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==",
-      "dev": true
+      "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg=="
     },
     "commondir": {
       "version": "1.0.1",
@@ -6558,6 +6589,14 @@
         "minimist": "0.0.8"
       }
     },
+    "mockjs": {
+      "version": "1.0.1-beta3",
+      "resolved": "https://registry.npm.taobao.org/mockjs/download/mockjs-1.0.1-beta3.tgz",
+      "integrity": "sha1-0jTzwnJWOXVk8slVFC6JGQlTcgk=",
+      "requires": {
+        "commander": "*"
+      }
+    },
     "move-concurrently": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
@@ -6575,8 +6614,7 @@
     "ms": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-      "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
-      "dev": true
+      "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
     },
     "multicast-dns": {
       "version": "6.2.3",
@@ -11799,6 +11837,11 @@
       "integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==",
       "dev": true
     },
+    "vuex": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npm.taobao.org/vuex/download/vuex-3.1.1.tgz",
+      "integrity": "sha1-DCZL/jDNvM+Wq52zF30hGCilkQ4="
+    },
     "watchpack": {
       "version": "1.6.0",
       "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz",

+ 4 - 1
package.json

@@ -11,10 +11,13 @@
     "build": "node build/build.js"
   },
   "dependencies": {
+    "axios": "latest",
     "element-ui": "^2.8.2",
     "font-awesome": "^4.7.0",
+    "mockjs": "^1.0.1-beta3",
     "vue": "^2.5.2",
-    "vue-router": "^3.0.1"
+    "vue-router": "^3.0.1",
+    "vuex": "^3.1.1"
   },
   "devDependencies": {
     "autoprefixer": "^7.1.2",

+ 88 - 98
src/components/Home.vue

@@ -2,12 +2,11 @@
   <div class="home-container">
     <div class="home-banner-wrap">
       <el-carousel height="400px" :interval="10000" arrow="always">
-        <el-carousel-item>
-          <img class="banner_back banner_back_1" src="@/assets/img/home_ban1.jpg">
-          <router-link :to="{ name: 'ProjectCreate'}"><div class="btn btn-medium btn-home-apply">申请项目</div></router-link>
-        </el-carousel-item>
-        <el-carousel-item>
-          <img class="banner_back banner_back_2" src="@/assets/img/home_ban2.png">
+        <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>
         </el-carousel-item>
       </el-carousel>
     </div>
@@ -20,21 +19,21 @@
           </span>
         </div>
         <el-row :gutter="20">
-          <el-col :span="6" v-for="item,index in taskList" :key="index">
+          <el-col :span="6" v-for="item,index in hotTaskList" :key="index">
             <task-card :item="item"/>
           </el-col>
         </el-row>
       </div>
 
-      <div  class="home-block">
+      <div class="home-block">
         <el-row :gutter="20">
-          <el-col  :xs="20" :sm="20" :md="20" :lg="12" :xl="12">
+          <el-col :xs="20" :sm="20" :md="20" :lg="12" :xl="12">
             <div class="title">机构排名</div>
-            <institution-rank />
+            <institution-rank :item="institutionRank"/>
           </el-col>
-          <el-col  :xs="20" :sm="20" :md="20" :lg="12" :xl="12">
-              <div class="title">用户排名</div>
-              <person-rank />
+          <el-col :xs="20" :sm="20" :md="20" :lg="12" :xl="12">
+            <div class="title">用户排名</div>
+            <person-rank :item="personRank"/>
           </el-col>
         </el-row>
 
@@ -44,103 +43,94 @@
 </template>
 
 <script>
-import TaskCard from "@/components/commons/TaskCard";
-import InstitutionRank from "@/components/InstitutionRank";
-import PersonRank from "@/components/PersonRank";
+import TaskCard from '@/components/commons/TaskCard'
+import InstitutionRank from '@/components/InstitutionRank'
+import PersonRank from '@/components/PersonRank'
+import Http from '@/js/http.js'
+import Apis from '@/js/api.js'
+import {notify} from '@/constants/index'
+
 export default {
-  name: "Home",
-  components: { TaskCard, InstitutionRank, PersonRank },
-  data() {
+  name: 'Home',
+  components: {TaskCard, InstitutionRank, PersonRank},
+  data () {
     return {
-      taskList: [
-        {
-          id: 0,
-          title: "发送群文件测试",
-          description: "任务描述文字xxxx",
-          price: "30",
-          serviceType: 1,
-          status: 0,
-          projectId:123
-        },
-        {
-          id: 1,
-          title: "多人聊天发送文件测试",
-          description: "任务描述文字xxxx",
-          price: "10",
-          serviceType: 0,
-          status: 1,
-          projectId:234
-        },
-        {
-          id: 2,
-          title: "浏览器波洞星球",
-          description: "任务描述文字xxxx",
-          price: "10",
-          serviceType: 2,
-          status: 0,
-          projectId:345
-        },
-        {
-          id: 3,
-          title: "举报支持选择聊天记录(安全)",
-          description: "任务描述文字xxxx",
-          price: "0",
-          serviceType: 1,
-          status: 1,
-          projectId:456
-        }
-      ]
-    };
+      hotTaskList: [],
+      institutionRank: [],
+      personRank: [],
+      imgList: [],
+
+    }
+  },
+  methods: {
+    //加载数据
+    loadData: function () {
+      console.log('loadData')
+      Http.get(Apis.PAGE.HOME_PAGE).then((res) => {
+        console.log(res)
+        this.hotTaskList = res.hotTaskList
+        this.institutionRank = res.agencyRank
+        this.personRank = res.userRank
+        this.imgList = res.imgList
+      })
+    },
   },
-  methods:{
+  created: function () {
+    //notify('info', 'info')
+    //notify('success', 'success')
+    //notify('error', 'error')
+    //notify('warning', 'warning')
+    this.loadData()
   }
-};
+}
 </script>
 
 <style lang="less" scoped>
-.home-banner-wrap {
-  background: linear-gradient(#4a90e2, rgb(74, 109, 226));
-  background: -webkit-linear-gradient(#4a90e2, rgb(74, 109, 226));
-  background: -o-linear-gradient(#4a90e2, rgb(74, 109, 226));
-  .banner_back {
-    height: 100%;
+  .home-banner-wrap {
+    background: linear-gradient(#4a90e2, rgb(74, 109, 226));
+    background: -webkit-linear-gradient(#4a90e2, rgb(74, 109, 226));
+    background: -o-linear-gradient(#4a90e2, rgb(74, 109, 226));
+    .banner_back {
+      height: 100%;
+    }
+    .banner_back_1 {
+      float: right;
+    }
   }
-  .banner_back_1 {
-    float: right;
+
+  .el-carousel__item h3 {
+    color: #475669;
+    font-size: 14px;
+    opacity: 0.75;
+    line-height: 150px;
+    margin: 0;
   }
-}
 
-.el-carousel__item h3 {
-  color: #475669;
-  font-size: 14px;
-  opacity: 0.75;
-  line-height: 150px;
-  margin: 0;
-}
+  .el-carousel__item:nth-child(2n) {
+    background-color: #bed2c0;
+  }
 
-.el-carousel__item:nth-child(2n) {
-  background-color: #bed2c0;
-}
+  .el-carousel__item:nth-child(2n + 1) {
+    background-color: #eeeef2;
+  }
 
-.el-carousel__item:nth-child(2n + 1) {
-  background-color: #eeeef2;
-}
+  .home-body-wrap {
+    padding: 40px 80px;
+  }
 
-.home-body-wrap {
-  padding: 40px 80px;
-}
-.more-info {
-  float: right;
-  cursor: pointer;
-  font-size: 1.4rem;
-}
-.btn-home-apply {
-  position: absolute;
-  bottom: 10%;
-  left: 20%;
-}
+  .more-info {
+    float: right;
+    cursor: pointer;
+    font-size: 1.4rem;
+  }
 
-.home-block{
-  margin:10px 0;
-}
+  .btn-home-apply {
+    position: absolute;
+    bottom: 10%;
+    left: 20%;
+  }
+
+  .home-block {
+    margin: 10px 0;
+  }
 </style>

+ 24 - 34
src/components/InstitutionRank.vue

@@ -1,55 +1,45 @@
 <template>
   <div>
-    <el-table :data="tableData"  :showHeader="false" border style="width: 100%">
+    <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"/>
+          <img class="logo-img" :src="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>
+      <el-table-column prop="name">
+        <template slot-scope="scope"><span class="institution-name">{{scope.row.name}}</span></template>
+      </el-table-column>
     </el-table>
   </div>
 </template>
 
 <script>
 export default {
-  name: "InstitutionRank",
-  data() {
+  name: 'InstitutionRank',
+  props: {item: {}},
+  data () {
     return {
-      tableData: [
-        {
-          logo: "http://www.mooctest.net/assets/img/mooctest.png",
-          name: "慕测科技"
-        },
-        {
-          logo: "https://docs.alibabagroup.com/assets2/images/cn/global/logo_header.png",
-          name: "上海软件"
-        },
-        {
-          logo: "http://www.mooctest.net/assets/img/mooctest.png",
-          name: "QQ众测"
-        },
-        {
-          logo: "https://docs.alibabagroup.com/assets2/images/cn/global/logo_header.png",
-          name: "阿里巴巴"
-        },
-        {
-          logo: "https://docs.alibabagroup.com/assets2/images/cn/global/logo_header.png",
-          name: "阿里巴巴"
-        }
-      ]
-    };
+      tableData: this.item
+    }
+  },
+  watch:{
+    item(){
+      this.tableData = this.item
+    }
   }
-};
+}
 </script>
 
 <style lang="less" scoped>
-.logo-img{
-    width:100px
-}
-.institution-name{
+  .logo-img {
+    height: 50px;
+    width: 100px;
+    object-fit: contain;
+  }
+
+  .institution-name {
     font-size: 16px;
     font-weight: 600;
-}
+  }
 </style>

+ 85 - 167
src/components/Mine.vue

@@ -1,4 +1,3 @@
-
 <template>
   <div class="mine-container">
     <div class="mine-top-wrapper">
@@ -20,25 +19,25 @@
             </p>
             <div class="username_box">
               <div class="username_icon username_"></div>
-              <span class="username">小明</span>
+              <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"
-              >注册</a>
-            </p>
+            <!--<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">--</em>
+                <em class="num1">{{user.score}}</em>
               </a>
               <span class="line">|</span>
               <a href="/rule/merit" target="_blank">
                 威望
-                <em class="num2">--</em>
+                <em class="num2">{{user.prestige}}</em>
               </a>
             </p>
             <p>
@@ -53,180 +52,99 @@
     <div class="mine-body">
       <el-tabs tabPosition="top" type="card">
         <el-tab-pane label="未完成任务">
-          <task-item v-for="(item,index) in taskList1" :key="index" :taskId="item.id"/>
+          <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"/>
         </el-tab-pane>
         <el-tab-pane label="已完成任务">
-          <task-item v-for="(item,index) in taskList2" :key="index" :taskId="item.id"/>
+          <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"/>
         </el-tab-pane>
         <el-tab-pane label="已申请项目">
-          <project-item v-for="(item,index) in projectList1" :key="index" :projectId="item.id"/>
+          <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>
       </el-tabs>
     </div>
   </div>
 </template>
-      
+
 <script>
-import TaskItem from "@/components/commons/TaskItem";
-import ProjectItem from "@/components/commons/ProjectItem";
+import TaskItem from '@/components/commons/TaskItem'
+import ProjectItem from '@/components/commons/ProjectItem'
+import Http from '@/js/http.js'
+import Apis from '@/js/api.js'
+import {notify} from '@/constants/index'
 export default {
-  name: "Mine",
-  components: { TaskItem, ProjectItem },
-  data() {
+  name: 'Mine',
+  components: {TaskItem, ProjectItem},
+  data () {
     return {
-      taskList1: [
-        {
-          id: 0,
-          title: "发送群文件测试",
-          description: "任务描述文字xxxx",
-          price: "30",
-          serviceType: 1,
-          status: 0
-        },
-        {
-          id: 1,
-          title: "多人聊天发送文件测试",
-          description: "任务描述文字xxxx",
-          price: "10",
-          serviceType: 0,
-          status: 1
-        },
-        {
-          id: 2,
-          title: "浏览器波洞星球",
-          description: "任务描述文字xxxx",
-          price: "10",
-          serviceType: 2,
-          status: 0
-        },
-        {
-          id: 3,
-          title: "举报支持选择聊天记录(安全)",
-          description: "任务描述文字xxxx",
-          price: "0",
-          serviceType: 1,
-          status: 1
-        },
-        {
-          id: 4,
-          title: "发送群文件测试",
-          description: "任务描述文字xxxx",
-          price: "30",
-          serviceType: 1,
-          status: 0
+      unFinishedTaskList: [],
+      finishedTaskList: [],
+      appliedProjectList: [],
+      user: {}
+    }
+  },
+  methods: {
+    loadData () {
+      Http.get(Apis.PAGE.MY_CROWD_TEST_PAGE.replace('{userId}', 3), {}).then((res) => {
+        if (res.unfinishedTasks != null && res.unfinishedTasks.length > 0) {
+          this.unFinishedTaskList = res.unfinishedTasks
         }
-      ],
-      taskList2: [
-        {
-          id: 6,
-          title: "浏览器波洞星球",
-          description: "任务描述文字xxxx",
-          price: "10",
-          serviceType: 2,
-          status: 0
-        },
-        {
-          id: 7,
-          title: "举报支持选择聊天记录(安全)",
-          description: "任务描述文字xxxx",
-          price: "0",
-          serviceType: 1,
-          status: 1
-        },
-        {
-          id: 8,
-          title: "发送群文件测试",
-          description: "任务描述文字xxxx",
-          price: "30",
-          serviceType: 1,
-          status: 0
-        },
-        {
-          id: 9,
-          title: "多人聊天发送文件测试",
-          description: "任务描述文字xxxx",
-          price: "10",
-          serviceType: 0,
-          status: 1
-        },
-        {
-          id: 10,
-          title: "浏览器波洞星球",
-          description: "任务描述文字xxxx",
-          price: "10",
-          serviceType: 2,
-          status: 0
-        },
-        {
-          id: 11,
-          title: "举报支持选择聊天记录(安全)",
-          description: "任务描述文字xxxx",
-          price: "0",
-          serviceType: 1,
-          status: 2
+        if (res.finishedTasks != null && res.finishedTasks.length > 0) {
+          this.finishedTaskList = res.finishedTasks
         }
-      ],
-      projectList1: [
-        {
-          id: 1,
-          code: "27382hdsjkfdskfK",
-          name: "多人聊天发送文件测试",
-          platform: [0],
-          description: "任务描述文字xxxx",
-          price: "10"
-        },
-        {
-          id: 2,
-          code: "jzlk9dfsndfsmd ",
-          name: "多人聊天发送文件测试",
-          platform: [0, 1],
-          description: "任务描述文字xxxx",
-          price: "90"
-        },
-        {
-          id: 3,
-          code: "437849sdbsjbsf",
-          name: "多人聊天发送文件测试",
-          platform: [1, 2],
-          description: "任务描述文字xxxx",
-          price: "50"
+        if (res.crowdProjectVOList != null && res.crowdProjectVOList.length > 0) {
+          this.appliedProjectList = res.crowdProjectVOList
         }
-      ]
-    };
+        if (res.userVO != null && res.userVO.length > 0) {
+          this.user = res.userVO
+        }
+      })
+    }
+  },
+  created: function () {
+    this.loadData()
   }
-};
+}
 </script>
-      
+
 <style lang="less" scoped>
-.mine-container {
-  padding: 0 80px 40px 80px;
-}
-.mine-top-wrapper {
-  height: 350px;
-  background-color: #fff;
-}
-[class*="el-col-"] {
-  height: 100%;
-}
+  .mine-container {
+    padding: 0 80px 40px 80px;
+  }
 
-.advertise-imgs {
-  height: 100%;
-}
+  .mine-top-wrapper {
+    height: 350px;
+    background-color: #fff;
+  }
 
-.advertise-imgs img {
-  width: 100%;
-  height: 100%;
-}
-.user-banner {
-  text-align: center;
-  display: inline-table;
-  height: 100%;
-  width: 100%;
-  margin-top: 40px;
-}
-.mine-body {
-  margin-top: 30px;
-}
+  [class*="el-col-"] {
+    height: 100%;
+  }
+
+  .advertise-imgs {
+    height: 100%;
+  }
+
+  .advertise-imgs img {
+    width: 100%;
+    height: 100%;
+  }
+
+  .user-banner {
+    text-align: center;
+    display: inline-table;
+    height: 100%;
+    width: 100%;
+    margin-top: 40px;
+  }
+
+  .mine-body {
+    margin-top: 30px;
+  }
 </style>
 
-      

+ 7 - 27
src/components/PersonRank.vue

@@ -16,35 +16,15 @@
 <script>
 export default {
   name: "PersonRank",
+  props: {item: {}},
   data() {
     return {
-      tableData: [
-        {
-          logo: "http://www.mooctest.net/assets/img/mooctest.png",
-          name: "小王",
-          number: "200",
-        },
-        {
-          logo: "https://docs.alibabagroup.com/assets2/images/cn/global/logo_header.png",
-          name: "小黄",
-          number: "190",
-        },
-        {
-          logo: "http://www.mooctest.net/assets/img/mooctest.png",
-          name: "小莉",
-          number: "120",
-        },
-        {
-          logo: "https://docs.alibabagroup.com/assets2/images/cn/global/logo_header.png",
-          name: "小张",
-          number: "80",
-        },
-        {
-          logo: "https://docs.alibabagroup.com/assets2/images/cn/global/logo_header.png",
-          name: "小张",
-          number: "70",
-        }
-      ]
+      tableData: this.item
+    }
+  },
+  watch:{
+    item(){
+      this.tableData = this.item
     }
   }
 };

+ 18 - 250
src/components/Square.vue

@@ -3,7 +3,7 @@
     <div class="title">全部任务</div>
 
     <div class="square-list-container">
-      <task-item v-for="(item,index) in list" :key="index" :taskId="item.id" />
+      <task-item v-for="(item,index) in list" :key="index" :task="item" />
       <div v-if="loading" class="loading">
         <span></span>
         <span></span>
@@ -20,263 +20,25 @@
 
 <script>
 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() {
     return {
-      loading: false,
+      loading: true,
       nomore:false,
-      list: [
-        {
-          id: 0,
-          title: "发送群文件测试",
-          platform: [0, 1],
-          description: "任务描述文字xxxx",
-          price: "30",
-          业务类型: 1,
-          participantNum: 30,
-          status: 0
-        },
-        {
-          id: 1,
-          title: "多人聊天发送文件测试",
-          platform: [0],
-          description: "任务描述文字xxxx",
-          price: "10",
-          业务类型: 0,
-          participantNum: 0,
-          status: 1
-        },
-        {
-          id: 2,
-          title: "浏览器波洞星球",
-          platform: [1],
-          description: "任务描述文字xxxx",
-          price: "10",
-          业务类型: 2,
-          participantNum: 21,
-          status: 0
-        },
-        {
-          id: 3,
-          title: "举报支持选择聊天记录(安全)",
-          platform: [0, 1, 2],
-          description: "任务描述文字xxxx",
-          price: "0",
-          业务类型: 1,
-          participantNum: 1,
-          status: 1
-        },
-        {
-          id: 4,
-          title: "发送群文件测试",
-          platform: [0, 1],
-          description: "任务描述文字xxxx",
-          price: "30",
-          业务类型: 1,
-          participantNum: 30,
-          status: 0
-        },
-        {
-          id: 5,
-          title: "多人聊天发送文件测试",
-          platform: [0],
-          description: "任务描述文字xxxx",
-          price: "10",
-          业务类型: 0,
-          participantNum: 0,
-          status: 1
-        },
-        {
-          id: 6,
-          title: "浏览器波洞星球",
-          platform: [1],
-          description: "任务描述文字xxxx",
-          price: "10",
-          业务类型: 2,
-          participantNum: 21,
-          status: 0
-        },
-        {
-          id: 7,
-          title: "举报支持选择聊天记录(安全)",
-          platform: [0, 1, 2],
-          description: "任务描述文字xxxx",
-          price: "0",
-          业务类型: 1,
-          participantNum: 1,
-          status: 1
-        },
-        {
-          id: 8,
-          title: "发送群文件测试",
-          platform: [0, 1],
-          description: "任务描述文字xxxx",
-          price: "30",
-          业务类型: 1,
-          participantNum: 30,
-          status: 0
-        },
-        {
-          id: 9,
-          title: "多人聊天发送文件测试",
-          platform: [0],
-          description: "任务描述文字xxxx",
-          price: "10",
-          业务类型: 0,
-          participantNum: 0,
-          status: 1
-        },
-        {
-          id: 10,
-          title: "浏览器波洞星球",
-          platform: [1],
-          description: "任务描述文字xxxx",
-          price: "10",
-          业务类型: 2,
-          participantNum: 21,
-          status: 0
-        },
-        {
-          id: 11,
-          title: "举报支持选择聊天记录(安全)",
-          platform: [0, 1, 2],
-          description: "任务描述文字xxxx",
-          price: "0",
-          业务类型: 1,
-          participantNum: 1,
-          status: 1
-        }
-      ],
-      list1: [
-        {
-          id: 0,
-          title: "1发送群文件测试",
-          platform: [0, 1],
-          description: "任务描述文字xxxx",
-          price: "30",
-          serviceType: 1,
-          participantNum: 30,
-          status: 0
-        },
-        {
-          id: 1,
-          title: "多人聊天发送文件测试",
-          platform: [0],
-          description: "任务描述文字xxxx",
-          price: "10",
-          serviceType: 0,
-          participantNum: 0,
-          status: 1
-        },
-        {
-          id: 2,
-          title: "浏览器波洞星球",
-          platform: [1],
-          description: "任务描述文字xxxx",
-          price: "10",
-          serviceType: 2,
-          participantNum: 21,
-          status: 0
-        },
-        {
-          id: 3,
-          title: "举报支持选择聊天记录(安全)",
-          platform: [0, 1, 2],
-          description: "任务描述文字xxxx",
-          price: "0",
-          serviceType: 1,
-          participantNum: 1,
-          status: 1
-        },
-        {
-          id: 4,
-          title: "发送群文件测试",
-          platform: [0, 1],
-          description: "任务描述文字xxxx",
-          price: "30",
-          serviceType: 1,
-          participantNum: 30,
-          status: 0
-        },
-        {
-          id: 5,
-          title: "多人聊天发送文件测试",
-          platform: [0],
-          description: "任务描述文字xxxx",
-          price: "10",
-          serviceType: 0,
-          participantNum: 0,
-          status: 1
-        },
-        {
-          id: 6,
-          title: "浏览器波洞星球",
-          platform: [1],
-          description: "任务描述文字xxxx",
-          price: "10",
-          serviceType: 2,
-          participantNum: 21,
-          status: 0
-        },
-        {
-          id: 7,
-          title: "举报支持选择聊天记录(安全)",
-          platform: [0, 1, 2],
-          description: "任务描述文字xxxx",
-          price: "0",
-          serviceType: 1,
-          participantNum: 1,
-          status: 1
-        },
-        {
-          id: 8,
-          title: "发送群文件测试",
-          platform: [0, 1],
-          description: "任务描述文字xxxx",
-          price: "30",
-          serviceType: 1,
-          participantNum: 30,
-          status: 0
-        },
-        {
-          id: 9,
-          title: "多人聊天发送文件测试",
-          platform: [0],
-          description: "任务描述文字xxxx",
-          price: "10",
-          serviceType: 0,
-          participantNum: 0,
-          status: 1
-        },
-        {
-          id: 10,
-          title: "浏览器波洞星球",
-          platform: [1],
-          description: "任务描述文字xxxx",
-          price: "10",
-          serviceType: 2,
-          participantNum: 21,
-          status: 0
-        },
-        {
-          id: 11,
-          title: "举报支持选择聊天记录(安全)",
-          platform: [0, 1, 2],
-          description: "任务描述文字xxxx",
-          price: "0",
-          serviceType: 1,
-          participantNum: 1,
-          status: 1
-        }
-      ]
+      list: [],
     };
   },
   mounted() {
     window.addEventListener("scroll", this.throttle(this.setpage, 1000), false);
   },
+  created() {
+    this.loadData()
+  },
   methods: {
     throttle(func, wait, options) {
       let context, args, result;
@@ -322,15 +84,21 @@ export default {
       if (scrollTop + windowHeight + 5 >= scrollHeight) {
         console.log("加载更多数据");
         // this.loading=true;
-        //获取数据请求 请求结束后 
-        //成功设置 this.list =[...this.list,...this.list1];  this.loading=false; 
+        //获取数据请求 请求结束后
+        //成功设置 this.list =[...this.list,...this.list1];  this.loading=false;
         //失败设置 没有更多  this.nomore = true; this.loading = false;
         // window.setTimeout(()=>{this.loading=false;
         // console.log(this.list);},5000)
-        
+
       }
       else{this.loading=false;}
       window.clearTimeout();
+    },
+    loadData() {
+      console.log("loadData")
+      Http.get(Apis.PAGE.SQUARE_PAGE).then((res) => {
+        this.list = res.crowdTaskVOList
+      })
     }
   }
 };

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

@@ -0,0 +1,198 @@
+<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>

+ 315 - 0
src/components/cheat/AgencyAdd.vue

@@ -0,0 +1,315 @@
+<template>
+  <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-item label="机构名称" prop="name">
+          <el-input 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-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-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-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-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>
+          <!--<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>
+        <el-form-item prop="file" label="头像">
+          <el-upload
+            v-if="isModifyMode"
+            class="avatar-uploader"
+            :show-file-list="false"
+            action="https://jsonplaceholder.typicode.com/posts/"
+            :before-upload="beforeFileUpload"
+            :http-request="uploadFile"
+            :file-list="agency.photo"
+          >
+            <img v-if="agency.photoUrl" :src="agency.photoUrl" class="avatar">
+            <i v-else class="el-icon-plus avatar-uploader-icon"></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="agency.photo==null">暂无文件</span>-->
+          <!--<a :href="agency.photo" v-if="agency.photo!=null"><i class="fa fa-file-text-o"></i>-->
+          <!--{{agency.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>
+      <el-dialog
+        title="测评机构添加成功"
+        :visible.sync="dialogVisible"
+        width="30%"
+        :before-close="handleDialogClose"
+        center>
+        <span>
+          <el-card class="box-card" shadow="always">
+            <div slot="header" class="clearfix">
+              <span>您添加的机构信息</span>
+            </div>
+            <div class="text item">
+              <ul style="list-style-type:none">
+                <li>机构名称:{{ agency.name }}</li>
+                <li>机构电话:{{ agency.mobile }}</li>
+                <li>银行卡账户:{{ agency.bankAccount }}</li>
+                <li>地址:{{ agency.address }}</li>
+                <li>邮箱:{{ agency.email }}</li>
+              </ul>
+            </div>
+          </el-card>
+          <br/>
+          <el-card class="box-card" shadow="always">
+            <div class="text item">
+              您可以使用以下的账号密码登录系统:
+              <ul style="list-style-type:none">
+                <li>账号:{{ agency.email }}</li>
+                <li>密码:{{ agency.mobile }}</li>
+              </ul>
+              也可以使用手机号{{ agency.mobile }}验证码登录
+            </div>
+          </el-card>
+        </span>
+        <span slot="footer" class="dialog-footer">
+    <el-button @click="handleDialogClose">返 回</el-button>
+    <el-button type="primary" @click="toLogin">去登录</el-button>
+  </span>
+      </el-dialog>
+    </div>
+  </div>
+</template>
+
+<script>
+import Http from '@/js/http'
+import Apis from '@/js/api'
+import {notify} from '@/constants/index'
+
+export default {
+  name: 'AgencyAdd',
+  data () {
+    return {
+      userId: 0,
+      isModifyMode: true,
+      dialogVisible: false,
+      agency: {
+        mobile: '',
+        email: '',
+        name: '',
+        bankAccount: '',
+        address: '',
+        ability: '',
+        resource: '',
+        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'}
+        // ]
+      }
+    }
+  },
+  methods: {
+    //加载数据
+    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)
+      })
+    },
+    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) => {
+        this.agency.photoUrl = res.data
+        console.log(res.data)
+        notify('success', '上传成功')
+        sessionStorage.setItem('file', 'qweqewqweqweqweqew')
+        sessionStorage.getItem('file')
+      }).catch(error => {
+        notify('error', error.data.msg)
+      })
+    },
+    handleDialogClose (done) {
+      this.$confirm('确认退出?退出前请记录下登录账号和密码,否则无法找回!!!')
+        .then(_ => {
+          //done()
+          this.hideDialog()
+        })
+        .catch(_ => {
+        })
+    },
+    showDialog () {
+      this.dialogVisible = true
+    },
+    hideDialog () {
+      this.dialogVisible = false
+      this.resetForm()
+    },
+    toLogin () {
+      this.hideDialog()
+      this.$router.push({
+        name: 'Home',
+        // params: {projectId: projectId, taskId: taskId}
+      })
+    },
+    resetForm () {
+      this.agency = {
+        mobile: '',
+        email: '',
+        name: '',
+        bankAccount: '',
+        address: '',
+        ability: '',
+        resource: '',
+        photo: [],
+        photoUrl: '',
+        password: '',
+        username: '',
+      }
+    }
+  },
+  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;
+  }
+</style>

+ 469 - 0
src/components/cheat/ProjectAdd.vue

@@ -0,0 +1,469 @@
+<template>
+  <div class="create-container">
+    <div class="create-body">
+      <div class="title">创建项目</div>
+      <el-tabs tabPosition="top" type="card">
+        <el-tab-pane label="单个创建项目">
+          <el-form :model="project" :rules="rules" ref="project" label-width="12%" class="demo-report">
+            <el-form-item label="项目名称" prop="name">
+              <el-input v-if="isModifyMode" v-model="project.name"></el-input>
+              <!--<span v-if="!isModifyMode">{{project.name}}</span>-->
+            </el-form-item>
+            <el-form-item label="项目描述" prop="name">
+              <el-input v-if="isModifyMode" v-model="project.description"></el-input>
+              <!--<span v-if="!isModifyMode">{{project.description}}</span>-->
+            </el-form-item>
+            <el-form-item label="联系人姓名" prop="name">
+              <el-input v-if="isModifyMode" v-model="project.contactName"></el-input>
+              <!--<span v-if="!isModifyMode">{{project.contactName}}</span>-->
+            </el-form-item>
+            <el-form-item label="联系人电话" prop="name">
+              <el-input v-if="isModifyMode" v-model="project.contactPhone"></el-input>
+              <!--<span v-if="!isModifyMode">{{project.contactPhone}}</span>-->
+            </el-form-item>
+            <el-form-item label="项目定价" prop="name">
+              <el-input v-if="isModifyMode" v-model="project.price"></el-input>
+              <!--<span v-if="!isModifyMode">{{project.price}}</span>-->
+            </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>
+              </el-checkbox-group>
+              <!--<span-->
+              <!--v-if="!isModifyMode"-->
+              <!--class="badge"-->
+              <!--v-for="item in project.platform"-->
+              <!--&gt;{{platformType[item]}}</span>-->
+            </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>
+              </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
+                class="upload-demo"
+                action=""
+                :on-remove="handleRemove"
+                :before-remove="beforeRemove"
+                multiple
+                :limit="1"
+                :on-exceed="handleExceed"
+                :before-upload="beforeFileUpload"
+                :http-request="uploadRequireDoc"
+                :file-list="project.requireDoc"
+              >
+                <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="project.file==null || project.file.length === 0">暂无文件</span>-->
+              <!--<a :href="project.file[0]" v-if="project.file!=null && project.file.length > 0"><i-->
+              <!--class="fa fa-file-text-o"></i>-->
+              <!--{{project.file[0]}}</a>-->
+              <!--</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"
+                :http-request="uploadApkFile"
+                :before-upload="beforeFileUpload"
+                :file-list="project.file"
+              >
+                <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="project.file==null || project.file.length === 0">暂无文件</span>-->
+              <!--<a :href="project.file[0]" v-if="project.file!=null && project.file.length > 0"><i-->
+              <!--class="fa fa-file-text-o"></i>-->
+              <!--{{project.file[0]}}</a>-->
+              <!--</div>-->
+            </el-form-item>
+            <el-form-item label="项目截止时间" prop="datetime">
+              <div class="block" v-if="isModifyMode">
+                <el-date-picker
+                  v-model="project.datetime"
+                  type="datetime"
+                  placeholder="选择截止时间"
+                  align="right"
+                  :picker-options="pickerOptions"
+                ></el-date-picker>
+              </div>
+              <span v-if="!isModifyMode">{{new Date(project.datetime)}}</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>
+            </el-form-item>
+          </el-form>
+        </el-tab-pane>
+        <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>
+            </el-form-item>
+            <el-form-item type="file" prop="file" label="Excel文件">
+              <el-upload
+                v-if="isModifyMode"
+                drag
+                class="upload-demo"
+                action=""
+                :on-remove="handleRemove"
+                :before-remove="beforeRemove"
+                :limit="1"
+                :on-exceed="handleExceed"
+                :before-upload="beforeFileUpload"
+                :http-request="uploadProjectCreateExcelFile"
+                :file-list="project.excelFile"
+              >
+                <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="project.file==null">暂无文件</span>-->
+              <!--<a :href="project.file" v-if="project.file!=null"><i class="fa fa-file-text-o"></i>-->
+              <!--{{project.file}}</a>-->
+              <!--</div>-->
+            </el-form-item>
+            <el-form-item v-if="isModifyMode">
+              <div class="btn btn-primary btn-info" @click="submitByFile()">确认提交</div>
+            </el-form-item>
+          </el-form>
+          <el-dialog
+            title="您添加的项目"
+            :visible.sync="dialogVisible"
+            width="80%"
+            :before-close="handleDialogClose"
+            center>
+        <span>
+          <el-table
+            :data="tableData"
+            style="width: auto">
+      <el-table-column
+        prop="date"
+        label="项目名称">
+      </el-table-column>
+      <el-table-column
+        prop="name"
+        label="项目测试平台">
+      </el-table-column>
+      <el-table-column
+        prop="address"
+        label="项目联系人">
+      </el-table-column>
+            <el-table-column
+              prop="address"
+              label="联系方式">
+      </el-table-column>
+            <el-table-column
+              prop="address"
+              label="项目测试类型">
+      </el-table-column>
+            <el-table-column
+              prop="address"
+              label="项目需求描述">
+      </el-table-column>
+            <el-table-column
+              prop="address"
+              label="测试报告内容">
+      </el-table-column>
+            <el-table-column
+              prop="address"
+              label="测试报告结论">
+      </el-table-column>
+    </el-table>
+        </span>
+            <span slot="footer" class="dialog-footer">
+    <el-button @click="handleDialogClose">取消</el-button>
+    <el-button type="primary" @click="ensureSubmitExcel">确认</el-button>
+  </span>
+          </el-dialog>
+        </el-tab-pane>
+
+      </el-tabs>
+
+    </div>
+  </div>
+</template>
+
+<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'
+
+export default {
+  name: 'ProjectAdd',
+  data () {
+    return {
+      userId: 0,
+      dialogVisible: false,
+      isModifyMode: true,
+      serviceType: ServiceType,
+      platform: PlatformType,
+      isFormSubmit: true,
+      downloadFile: '123.xls',
+      project: {
+        name: '',
+        description: '',
+        contactName: '',
+        contactPhone: '',
+        platform: [],
+        type: [],
+        requireDoc: [],
+        requireDocUrl: '',
+        file: [],
+        fileUrl: '',
+        excelFile: [],
+        excelFileUrl: '',
+        price: '',
+        datetime: ''
+      },
+      projectList: [],
+      excelFile: {},
+      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'}
+        // ]
+      },
+      pickerOptions: {
+        shortcuts: [
+          {
+            text: '今天',
+            onClick (picker) {
+              picker.$emit('pick', new Date())
+            }
+          },
+          {
+            text: '昨天',
+            onClick (picker) {
+              const date = new Date()
+              date.setTime(date.getTime() - 3600 * 1000 * 24)
+              picker.$emit('pick', date)
+            }
+          },
+          {
+            text: '一周前',
+            onClick (picker) {
+              const date = new Date()
+              date.setTime(date.getTime() - 3600 * 1000 * 24 * 7)
+              picker.$emit('pick', date)
+            }
+          }
+        ]
+      },
+      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 弄'
+      }]
+    }
+  },
+  methods: {
+    //加载数据
+    loadData: function () {
+    },
+    modifyInfo () {
+      this.isModifyMode = true
+    },
+    submitInfo () {
+      //this.isModifyMode = false
+      const newProject = {
+        userId: 3,
+        name: this.project.name,
+        description: this.project.description,
+        contactName: this.project.contactName,
+        contactPhone: this.project.contactPhone,
+        platform: this.project.platform,
+        type: this.project.type,
+        doc: this.project.requireDocUrl,
+        file: this.project.fileUrl,
+        price: this.project.price,
+        datetime: this.project.datetime
+      }
+      Http.post(Apis.PROJECT.ADD_PROJECT, newProject).then((res) => {
+        notify('success', '项目添加成功')
+        console.log(res)
+      }).catch(error => {
+        notify('error', error.data.msg)
+      })
+    },
+    submitByFile () {
+      const formData = new FormData()
+      let config = {
+        //添加请求头
+        headers: {'Content-Type': 'multipart/form-data'},
+      }
+      formData.append('file', this.excelFile)
+      this.showDialog()
+      // Http.upload(Apis.PROJECT.ADD_PROJECT_BY_EXCEL, formData, config).then((res) => {
+      //   console.log(res)
+      //   this.projectList = res.data
+      //   notify('success', '项目添加成功')
+      // }).catch(error => {
+      //   notify('error', error)
+      // })
+    },
+    // 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 () {
+
+    },
+    uploadProjectCreateExcelFile (param) {
+      this.excelFile = param.file
+    },
+    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.project.requireDocUrl = res.data
+        console.log(res.data)
+        notify('success', '上传成功')
+      }).catch(error => {
+        notify('error', error.data.msg)
+      })
+    },
+    uploadApkFile (param) {
+      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('上传成功')
+        this.project.fileUrl = res.data
+        console.log(res)
+        notify('success', '上传成功')
+      }).catch(error => {
+        notify('error', error.data.msg)
+      })
+    },
+    handleDialogClose (done) {
+      this.$confirm('确认退出?退出前请记录下登录账号和密码,否则无法找回!!!')
+        .then(_ => {
+          //done()
+          this.hideDialog()
+        })
+        .catch(_ => {
+        })
+    },
+    ensureSubmitExcel () {
+
+    },
+    showDialog () {
+      this.dialogVisible = true
+    },
+    hideDialog () {
+      this.dialogVisible = false
+      this.resetForm()
+    },
+  },
+  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>

+ 244 - 230
src/components/commons/Header.vue

@@ -9,18 +9,18 @@
           aria-expanded="false"
           aria-label="Toggle navigation"
           @click="openNavBarFunc"
-           v-bind:class="['navbar-toggler',{ 'open-fixed': openNavBar}]"
+          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>
       </div>
-      <div class="collapse navbar-collapse"  v-bind:style="{right:openNavBar?'230px':'0'}">
-        <ul class="navbar-nav ml-auto"  >
+      <div class="collapse navbar-collapse" v-bind:style="{right:openNavBar?'230px':'0'}">
+        <ul class="navbar-nav ml-auto">
           <li class="dropdown nav-item">
             <router-link to="/home">
-              <a  class="dropdown-toggle nav-link" data-toggle="dropdown">
+              <a class="dropdown-toggle nav-link" data-toggle="dropdown">
                 <img class="icon" src="@/assets/img/home_icon.svg">
                 <span>首页</span>
               </a>
@@ -28,7 +28,7 @@
           </li>
           <li class="dropdown nav-item">
             <router-link to="/square">
-              <a  class="dropdown-toggle nav-link" data-toggle="dropdown">
+              <a class="dropdown-toggle nav-link" data-toggle="dropdown">
                 <img class="icon" src="@/assets/img/square_icon.svg">
                 <span>任务广场</span>
               </a>
@@ -36,7 +36,7 @@
           </li>
           <li class="dropdown nav-item">
             <router-link to="/mine">
-              <a  class="dropdown-toggle nav-link" data-toggle="dropdown">
+              <a class="dropdown-toggle nav-link" data-toggle="dropdown">
                 <img class="icon" src="@/assets/img/mine_icon.svg">
                 <span>我的众测</span>
               </a>
@@ -57,280 +57,294 @@
 </template>
 
 <script>
+
 export default {
-  name: "header-container",
-  data(){
-    return{
-      openNavBar:false
+  name: 'header-container',
+  data () {
+    return {
+      openNavBar: false,
+      userIdentity: '',
     }
   },
-  methods:{
-    openNavBarFunc(){
-      this.openNavBar = !this.openNavBar;
+  methods: {
+    openNavBarFunc () {
+      this.openNavBar = !this.openNavBar
+    },
+    getCurrentUser () {
+      // Http.get(Apis.USER.GET_CURRENT_USER).then((res) => {
+      //   sessionStorage.setItem('user', JSON.stringify(res))
+      // })
+    },
+    getUserIdentity () {
+
     }
-  }
-};
+  },
+  mounted () {
+    this.$nextTick(() => {
+      this.getCurrentUser()
+    })
+  },
+}
 </script>
 
 <style lang="less" scoped>
 
-.open-fixed{
-  position:fixed;
-  right:5px;
-  z-index: 1033;
-}
-
-.navbar {
-  background-color: #fff !important;
-  box-shadow: none;
-  padding-top: 10px;
-  padding-bottom: 10px;
-  color: #000;
-  transition: all 0.15s ease 0s;
-  display: flex;
-  flex-wrap: wrap;
-  align-items: center;
-  justify-content: space-between;
-}
-
-@media (max-width: 991px) {
-  [class*="navbar-expand-"] > .container {
-    padding-left: 15px;
-    padding-right: 15px;
+  .open-fixed {
+    position: fixed;
+    right: 5px;
+    z-index: 1033;
   }
-}
 
-.navbar > .container {
-  display: flex;
-  flex-wrap: wrap;
-  align-items: center;
-  justify-content: space-between;
-  flex: 1;
-}
+  .navbar {
+    background-color: #fff !important;
+    box-shadow: none;
+    padding-top: 10px;
+    padding-bottom: 10px;
+    color: #000;
+    transition: all 0.15s ease 0s;
+    display: flex;
+    flex-wrap: wrap;
+    align-items: center;
+    justify-content: space-between;
+  }
 
-.navbar .navbar-brand {
-  position: relative;
-  color: inherit;
-  font-size: 1.8rem;
-  line-height: 30px;
-  padding: 10px 0;
-  margin-right: 1rem;
-  display: inline-block;
-  white-space: nowrap;
-}
+  @media (max-width: 991px) {
+    [class*="navbar-expand-"] > .container {
+      padding-left: 15px;
+      padding-right: 15px;
+    }
+  }
 
-@media (max-width: 991px) {
-  .navbar .navbar-translate {
-    width: 100%;
-    position: relative;
+  .navbar > .container {
     display: flex;
-    -ms-flex-pack: justify !important;
-    justify-content: space-between !important;
-    -ms-flex-align: center;
+    flex-wrap: wrap;
     align-items: center;
-    transition: transform 0.5s cubic-bezier(0.685, 0.0473, 0.346, 1);
+    justify-content: space-between;
+    flex: 1;
   }
-}
 
-.navbar-collapse {
-  flex-basis: 100%;
-  flex-grow: 1;
-  align-items: center;
-}
+  .navbar .navbar-brand {
+    position: relative;
+    color: inherit;
+    font-size: 1.8rem;
+    line-height: 30px;
+    padding: 10px 0;
+    margin-right: 1rem;
+    display: inline-block;
+    white-space: nowrap;
+  }
 
-@media (max-width: 991px) {
-  .navbar-collapse {
-    position: fixed;
-    display: block;
-    top: 0;
-    height:100vh;
-    width: 230px;
-    right: 0;
-    margin-right: 0 !important;
-    z-index: 1032;
-    visibility: visible;
-    background-color: #fff;
-    overflow-y: visible;
-    border-top: none;
-    text-align: left;
-    padding-right: 0;
-    padding-left: 0;
-    max-height: none !important;
-    -webkit-transform: translate3d(230px, 0, 0);
-    transform: translate3d(230px, 0, 0);
-    transition: all 0.5s cubic-bezier(0.685, 0.0473, 0.346, 1);
+  @media (max-width: 991px) {
+    .navbar .navbar-translate {
+      width: 100%;
+      position: relative;
+      display: flex;
+      -ms-flex-pack: justify !important;
+      justify-content: space-between !important;
+      -ms-flex-align: center;
+      align-items: center;
+      transition: transform 0.5s cubic-bezier(0.685, 0.0473, 0.346, 1);
+    }
   }
-}
 
-@media (min-width: 992px) {
   .navbar-collapse {
-    display: flex !important;
-    flex-basis: auto;
+    flex-basis: 100%;
+    flex-grow: 1;
+    align-items: center;
   }
-}
-
-[type="reset"],
-[type="submit"],
-button,
-html [type="button"] {
-  -webkit-appearance: button;
-}
-
-.navbar-toggler {
-  padding: 0.25rem 0.75rem;
-  font-size: 1.25rem;
-  line-height: 1;
-  background-color: transparent;
-  border: 1px solid transparent;
-  border-radius: 0.25rem;
-  outline: none;
-}
 
+  @media (max-width: 991px) {
+    .navbar-collapse {
+      position: fixed;
+      display: block;
+      top: 0;
+      height: 100vh;
+      width: 230px;
+      right: 0;
+      margin-right: 0 !important;
+      z-index: 1032;
+      visibility: visible;
+      background-color: #fff;
+      overflow-y: visible;
+      border-top: none;
+      text-align: left;
+      padding-right: 0;
+      padding-left: 0;
+      max-height: none !important;
+      -webkit-transform: translate3d(230px, 0, 0);
+      transform: translate3d(230px, 0, 0);
+      transition: all 0.5s cubic-bezier(0.685, 0.0473, 0.346, 1);
+    }
+  }
 
+  @media (min-width: 992px) {
+    .navbar-collapse {
+      display: flex !important;
+      flex-basis: auto;
+    }
+  }
 
-.navbar-toggler:not(:disabled):not(.disabled) {
-  cursor: pointer;
-}
+  [type="reset"],
+  [type="submit"],
+  button,
+  html [type="button"] {
+    -webkit-appearance: button;
+  }
 
-@media (min-width: 992px) {
   .navbar-toggler {
-    display: none;
+    padding: 0.25rem 0.75rem;
+    font-size: 1.25rem;
+    line-height: 1;
+    background-color: transparent;
+    border: 1px solid transparent;
+    border-radius: 0.25rem;
+    outline: none;
   }
-}
-@media (max-width: 991px) {
-  .navbar.navbar-transparent .navbar-toggler .navbar-toggler-icon {
-    background-color: #fff;
+
+  .navbar-toggler:not(:disabled):not(.disabled) {
+    cursor: pointer;
   }
-}
 
-.navbar .navbar-toggler .navbar-toggler-icon + .navbar-toggler-icon {
-  margin-top: 4px;
-}
+  @media (min-width: 992px) {
+    .navbar-toggler {
+      display: none;
+    }
+  }
 
-.navbar .navbar-toggler .navbar-toggler-icon {
-  width: 22px;
-  height: 2px;
-  vertical-align: middle;
-  outline: 0;
-  display: block;
-  border-radius: 1px;
-}
+  @media (max-width: 991px) {
+    .navbar.navbar-transparent .navbar-toggler .navbar-toggler-icon {
+      background-color: #fff;
+    }
+  }
 
-.navbar .navbar-toggler .navbar-toggler-icon {
-  background-color: #555;
-}
+  .navbar .navbar-toggler .navbar-toggler-icon + .navbar-toggler-icon {
+    margin-top: 4px;
+  }
 
-.navbar-toggler-icon {
-  display: inline-block;
-  width: 1.5em;
-  height: 1.5em;
-  vertical-align: middle;
-  content: "";
-  background: no-repeat 50%;
-  background-size: 100% 100%;
-}
+  .navbar .navbar-toggler .navbar-toggler-icon {
+    width: 22px;
+    height: 2px;
+    vertical-align: middle;
+    outline: 0;
+    display: block;
+    border-radius: 1px;
+  }
 
-.navbar-nav {
-  display: flex;
-  flex-direction: column;
-  padding-left: 0;
-  margin-bottom: 0;
-  list-style: none;
-  text-align: center;
-}
+  .navbar .navbar-toggler .navbar-toggler-icon {
+    background-color: #555;
+  }
 
-@media (min-width: 991px) {
-  .navbar .navbar-nav {
-    align-items: center;
+  .navbar-toggler-icon {
+    display: inline-block;
+    width: 1.5em;
+    height: 1.5em;
+    vertical-align: middle;
+    content: "";
+    background: no-repeat 50%;
+    background-size: 100% 100%;
   }
-}
 
-@media (min-width: 992px) {
   .navbar-nav {
-    flex-direction: row;
+    display: flex;
+    flex-direction: column;
+    padding-left: 0;
+    margin-bottom: 0;
+    list-style: none;
+    text-align: center;
   }
-}
 
-@media (max-width: 991px) {
-  .navbar-nav {
-    margin-top:70px;
-    text-align: right;
+  @media (min-width: 991px) {
+    .navbar .navbar-nav {
+      align-items: center;
+    }
   }
-}
 
-.ml-auto,
-.mx-auto {
-  margin-left: auto !important;
-}
+  @media (min-width: 992px) {
+    .navbar-nav {
+      flex-direction: row;
+    }
+  }
 
-.collapsing,
-.dropdown,
-.dropup {
-  position: relative;
-}
+  @media (max-width: 991px) {
+    .navbar-nav {
+      margin-top: 70px;
+      text-align: right;
+    }
+  }
 
-.dropdown-menu {
-  position: absolute;
-  top: 100%;
-  left: 0;
-  z-index: 1000;
-  float: left;
-  min-width: 10rem;
-  padding: 0.5rem 0;
-  margin: 0.125rem 0 0;
-  font-size: 1rem;
-  color: #212529;
-  text-align: left;
-  list-style: none;
-  background-color: #fff;
-  background-clip: padding-box;
-  border: 1px solid rgba(0, 0, 0, 0.15);
-  border-radius: 0.25rem;
-  box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2),
+  .ml-auto,
+  .mx-auto {
+    margin-left: auto !important;
+  }
+
+  .collapsing,
+  .dropdown,
+  .dropup {
+    position: relative;
+  }
+
+  .dropdown-menu {
+    position: absolute;
+    top: 100%;
+    left: 0;
+    z-index: 1000;
+    float: left;
+    min-width: 10rem;
+    padding: 0.5rem 0;
+    margin: 0.125rem 0 0;
+    font-size: 1rem;
+    color: #212529;
+    text-align: left;
+    list-style: none;
+    background-color: #fff;
+    background-clip: padding-box;
+    border: 1px solid rgba(0, 0, 0, 0.15);
+    border-radius: 0.25rem;
+    box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2),
     0 1px 5px 0 rgba(0, 0, 0, 0.12);
-  display: none;
-  padding: 0.3125rem 0;
-  border: 0;
-  opacity: 0;
-  transform: scale(0);
-  transform-origin: 0 0;
-  will-change: transform, opacity;
-  transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1),
+    display: none;
+    padding: 0.3125rem 0;
+    border: 0;
+    opacity: 0;
+    transform: scale(0);
+    transform-origin: 0 0;
+    will-change: transform, opacity;
+    transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1),
     opacity 0.2s cubic-bezier(0.4, 0, 0.2, 1);
-  box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.26);
-}
-
-.navbar-nav .dropdown-menu {
-  float: none;
-}
+    box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.26);
+  }
 
-@media (min-width: 992px) {
   .navbar-nav .dropdown-menu {
-    position: absolute;
+    float: none;
   }
-}
 
-@media (min-width: 992px) {
-  .navbar-nav .nav-link {
-    padding-right: 0.5rem;
-    padding-left: 0.5rem;
+  @media (min-width: 992px) {
+    .navbar-nav .dropdown-menu {
+      position: absolute;
+    }
   }
-}
 
-.navbar .navbar-nav .nav-item .nav-link {
-  padding: 15px;
-  // text-align: center;
-  height: 20px;
-  vertical-align: middle;
-  color: inherit;
-  display: block;
-}
+  @media (min-width: 992px) {
+    .navbar-nav .nav-link {
+      padding-right: 0.5rem;
+      padding-left: 0.5rem;
+    }
+  }
 
-.nav-link > span {
-  /* font-size: 1.2rem; */
-  height: 100%;
-  vertical-align: middle;
-  display: inline-block;
-  line-height: 20px;
-}
+  .navbar .navbar-nav .nav-item .nav-link {
+    padding: 15px;
+    // text-align: center;
+    height: 20px;
+    vertical-align: middle;
+    color: inherit;
+    display: block;
+  }
+
+  .nav-link > span {
+    /* font-size: 1.2rem; */
+    height: 100%;
+    vertical-align: middle;
+    display: inline-block;
+    line-height: 20px;
+  }
 </style>

+ 41 - 44
src/components/commons/ProjectItem.vue

@@ -4,11 +4,11 @@
       <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.code}}</span>
-    <span class="col-md-1 col-sm-5">
+    <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.toLowerCase()=='ios','android-platform': item.toLowerCase()=='android','web-platform': item.toLowerCase()=='web'}]"
-        v-for="item in platformType"
+        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>
@@ -19,57 +19,54 @@
 </template>
 
 <script>
-import PlatformType from "@/constants/enum/platform-type";
+import PlatformType from '@/constants/enum/platform-type'
+
 export default {
-  name: "Project-Item",
+  name: 'Project-Item',
   props: {
-    projectId: Number
+    projectItem: {}
   },
-  data() {
+  data () {
     return {
-      project: {
-        id: 1,
-        code: "27382hdsjkfdskfK",
-        name: "多人聊天发送文件测试",
-        platform: [0],
-        description: "任务描述文字xxxx",
-        price: "10"
-      },
-      platformType: []
-    };
+      project: this.projectItem,
+      platformType: PlatformType
+    }
   },
-  mounted() {
-    this.project.platform.map(item => {
-      this.platformType.push(PlatformType[item]);
-    });
+  mounted () {
+    // this.project.platform.map(item => {
+    //   this.platformType.push(PlatformType[item]);
+    // });
   },
   methods: {
-    goToProjectDetail(id) {
-      console.log(id);
-      this.$router.push({ name: "Project", params: { projectId: id } });
+    goToProjectDetail (id) {
+      console.log(id)
+      this.$router.push({name: 'Project', params: {projectId: id}})
     }
   }
-};
+}
 </script>
 
 <style lang="less" scoped>
-.project-item-container {
-  padding: 20px;
-  border: 1px solid #eee;
-  margin: 15px 5px;
-  span {
-    display: inline-block;
+  .project-item-container {
+    padding: 20px;
+    border: 1px solid #eee;
+    margin: 15px 5px;
+    span {
+      display: inline-block;
+    }
+  }
+
+  .project-cover {
+    width: 200px;
+    height: 130px;
+    vertical-align: middle;
+  }
+
+  .project-title {
+    font-weight: 700;
+  }
+
+  .project-td {
+    padding: 15px;
   }
-}
-.project-cover {
-  width: 200px;
-  height: 130px;
-  vertical-align: middle;
-}
-.project-title {
-  font-weight: 700;
-}
-.project-td {
-  padding: 15px;
-}
 </style>

+ 9 - 3
src/components/commons/ProvinceCity.vue

@@ -27,7 +27,7 @@
     </el-form-item>
   </div>
 </template>
- 
+
 <script type="text/javascript">
 import provinceCity from "@/constants/provinceCity.json";
 export default {
@@ -93,12 +93,18 @@ export default {
         this.city = "";
       }
     }
+  },
+  watch:{
+    data(){
+      this.province = this.provinceCode
+      this.city = this.cityCode
+    }
   }
 };
 </script>
- 
+
 <style lang="less" scoped>
 .page-form-item {
   display: inline-block;
 }
-</style>
+</style>

+ 5 - 0
src/components/commons/TaskCard.vue

@@ -35,6 +35,11 @@ export default {
     //   this.platformType.push(PlatformType[item])
     // })
   },
+  watch:{
+    item() {
+
+    }
+  },
   methods:{
     goToTaskDetail(projectId,id){
       this.$router.push({name: "Task", params: {projectId:projectId,taskId: id}})

+ 58 - 47
src/components/commons/TaskItem.vue

@@ -1,14 +1,15 @@
 <template>
-  <div class="task-item-container" >
+  <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">{{task.title}}</span>
-      <span class="col-md-1 col-sm-5 ">{{serviceType}}</span>
-      <span class="col-md-1 col-sm-5 ">¥{{task.price}}</span>
-      <span class="col-md-1 col-sm-5 ">{{taskStatus}}</span>
-      <span class="task-td">
-       <span class="btn btn-medium btn-info" @click="goToTaskDetail(task.projectId,taskId)">查看详情</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>
 
   </div>
@@ -17,57 +18,67 @@
 <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",
+  name: 'Task-Item',
   props: {
-    taskId: Number
+    task: {}
   },
-  data() {
+  data () {
     return {
-      task: {
-        id: 1,
-        cover: "@/assets/img/home_ban2.png",
-        title: "多人聊天发送文件测试",
-        description: "任务描述文字xxxx",
-        price: "10",
-        serviceType: 0,
-        status: 1,
-        projectId:1123 
-      },
-      taskStatus:"进行中",
-      serviceType:""
+      taskTable: this.task,
+      taskStatus: TaskStatus,//TaskStatus[this.task.status],
+      serviceType: ServiceType,//[this.task.serviceType],
+      platformType: []
     }
   },
-  mounted(){
-    this.taskStatus = TaskStatus[this.task.status];
-    this.serviceType = ServiceType[this.task.serviceType]
+  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)
+  }
+  ,
+  methods: {
+    goToTaskDetail (projectId, id) {
+      this.$router.push({name: 'Task', params: {projectId: projectId, taskId: id}})
+    }
   },
-  methods:{
-     goToTaskDetail(projectId,id){
-      this.$router.push({name: "Task", params: {projectId:projectId,taskId: id}})
+  watch: {
+    task () {
+      this.taskTable = this.task
     }
   }
-};
+}
+
 </script>
 
 <style lang="less" scoped>
-.task-item-container {
-  padding: 20px;
-  border: 1px solid #eee;
-  margin: 15px 5px;
-  span{
-    display: inline-block;
+  .task-item-container {
+    padding: 20px;
+    border: 1px solid #eee;
+    margin: 15px 5px;
+    span {
+      display: inline-block;
+    }
+  }
+
+  .task-cover {
+    width: 200px;
+    height: 130px;
+    vertical-align: middle;
+  }
+
+  .task-title {
+    font-weight: 700;
+  }
+
+  .task-td {
+    padding: 15px;
   }
-}
-.task-cover {
-  width: 200px;
-  height:130px;
-  vertical-align: middle;
-}
-.task-title{
-  font-weight: 700;
-}
-.task-td{
-    padding:15px;
-}
 </style>

+ 6 - 0
src/components/project/AnalyseDemand.vue

@@ -50,6 +50,8 @@
 </template>
 
 <script>
+import Http from '@/js/http.js'
+import Apis from '@/js/api.js'
 export default {
   name: "AnalyseDemand",
   data() {
@@ -73,6 +75,10 @@ export default {
       this.$refs[formName].validate(valid => {
         if (valid) {
           console.log(this.analyseDemand);
+          Http.get(Apis.PROJECT.CREATE_ANALYSE_DEMAND_SUBMIT,this.analyseDemand).then((res)=>{
+            console.log(res)
+            console.log(this.analyseDemand)
+          })
           //提交 project
         } else {
           console.log("error submit!!");

+ 390 - 343
src/components/project/Project.vue

@@ -6,7 +6,7 @@
       <div v-if="!isModifyMode" class="el-form-item">
         <label class="el-form-item__label" style="width: 12%;">编号</label>
         <div class="el-form-item__content" style="margin-left: 12%;">
-          <div>{{project.code}}</div>
+          <div>{{projectId}}</div>
         </div>
       </div>
       <el-form :model="project" :rules="rules" ref="project" label-width="12%" class="demo-project">
@@ -21,8 +21,8 @@
                 <span>联系人</span>
               </el-col>
               <el-col :span="10">
-                <el-input v-if="isModifyMode" v-model="project.contact.name" placeholder="请输入联系人姓名"></el-input>
-                <div v-if="!isModifyMode">{{project.contact.name}}</div>
+                <el-input v-if="isModifyMode" v-model="project.contactName" placeholder="请输入联系人姓名"></el-input>
+                <div v-if="!isModifyMode">{{project.contactName}}</div>
               </el-col>
             </el-row>
             <el-row :gutter="2">
@@ -32,27 +32,27 @@
               <el-col :span="10">
                 <el-input
                   v-if="isModifyMode"
-                  v-model="project.contact.phone"
+                  v-model="project.contactPhone"
                   placeholder="请输入联系人电话"
                 ></el-input>
-                <div v-if="!isModifyMode">{{project.contact.phone}}</div>
+                <div v-if="!isModifyMode">{{project.contactPhone}}</div>
               </el-col>
             </el-row>
           </div>
         </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>
+            <el-checkbox label="IOS">IOS</el-checkbox>
+            <el-checkbox label="ANDROID">ANDROID</el-checkbox>
+            <el-checkbox label="WEB">WEB</el-checkbox>
           </el-checkbox-group>
           <span
             v-if="!isModifyMode"
-            v-bind:class="['badge',{ 'ios-platform': item.toLowerCase()=='ios','android-platform': item.toLowerCase()=='android','web-platform': item.toLowerCase()=='web'}]"
-            v-for="item in platformType"
+            class="badge"
+            v-for="item in project.platform"
           >{{item}}</span>
         </el-form-item>
-        <el-form-item label="需求描述" prop="desc">
+        <el-form-item label="需求描述">
           <el-input v-if="isModifyMode" type="textarea" v-model="project.desc"></el-input>
           <span v-if="!isModifyMode">{{project.desc}}</span>
         </el-form-item>
@@ -65,31 +65,33 @@
 
         <el-form-item label="服务类型" prop="type">
           <el-checkbox-group v-if="isModifyMode" v-model="project.type">
-            <el-checkbox label="接口测试" name="type"></el-checkbox>
-            <el-checkbox label="安全漏洞扫描" name="type"></el-checkbox>
-            <el-checkbox label="风险评估服务" name="type"></el-checkbox>
-            <el-checkbox label="源代码安全审计服务" name="type"></el-checkbox>
-            <el-checkbox label="功能测试服务" name="type"></el-checkbox>
-            <el-checkbox label="性能测试" name="type"></el-checkbox>
-            <el-checkbox label="功能和易用性测试" name="type"></el-checkbox>
+            <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>
           </el-checkbox-group>
-          <span v-if="!isModifyMode" class="badge" v-for="item in project.type">{{item}}</span>
+          <span v-if="!isModifyMode" class="badge" v-for="item in project.type">{{serviceType[item]}}</span>
         </el-form-item>
-        <el-form-item label="用途" prop="useage">
-          <el-input v-if="isModifyMode" v-model="project.useage"></el-input>
-          <span v-if="!isModifyMode">{{project.useage}}</span>
+        <el-form-item label="用途" prop="usage">
+          <el-input v-if="isModifyMode" v-model="project.usage"></el-input>
+          <span v-if="!isModifyMode">{{project.usage}}</span>
         </el-form-item>
 
         <el-form-item label="预算" prop="budget">
           <el-input v-if="isModifyMode" type="number" v-model="project.budget">
-            <template slot="append">¥</template>
+            ¥
+            <template slot="append"></template>
           </el-input>
           <span v-if="!isModifyMode">{{project.budget}}¥</span>
         </el-form-item>
         <el-form-item label="项目可见性" prop="resource">
           <div v-if="!isModifyMode">
-            <div v-if="project.resource=='定向'">{{project.institution}}</div>
-            <div v-if="project.resource=='非定向'">{{project.resource}}</div>
+            <div v-if="project.resource=='1'">{{updateLocation(project.location)}}</div>
+            <div v-if="project.resource=='0'">{{project.institution}}</div>
+            <div v-if="project.resource=='2'">{{resourceType[project.resource]}}</div>
           </div>
           <el-tabs
             :tab-position="tabPosition"
@@ -97,27 +99,41 @@
             style="max-height: 200px;"
             v-if="isModifyMode"
           >
-            <el-tab-pane label="定向" name="定向">
+            <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"
+                  v-for="(item,index) in institutionArray"
                   :key="index"
                 ></el-radio>
               </el-radio-group>
             </el-tab-pane>
-            <el-tab-pane label="非定向" name="非定向"></el-tab-pane>
+            <el-tab-pane :label="resourceType[1]" name="1">
+              <provincecity
+                ref="addFormProvince"
+                @selectChange="locationChange"
+                :provinceCode="project.location.provinceCode"
+                :cityCode="project.location.cityCode"
+              ></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"
-            class="upload-demo"
             drag
-            action="https://jsonplaceholder.typicode.com/posts/"
-            multiple
+            class="upload-demo"
+            action=""
+            :on-remove="handleRemove"
+            :before-remove="beforeRemove"
+            :limit="1"
+            :on-exceed="handleExceed"
+            :before-upload="beforeFileUpload"
+            :http-request="uploadRequireDoc"
+            :file-list="project.doc"
           >
             <i class="el-icon-upload"></i>
             <div class="el-upload__text">
@@ -126,16 +142,21 @@
             </div>
             <div class="el-upload__tip" slot="tip">请上传需求文档</div>
           </el-upload>
-          <span v-if="!isModifyMode">{{project.doc}}</span>
+          <span v-if="!isModifyMode"><a :href="project.requireDocUrl">{{project.requireDocUrl.split('/')[project.requireDocUrl.split('/').length-1]}}</a></span>
         </el-form-item>
         <el-form-item label="安装包" prop="file">
           <el-upload
             v-if="isModifyMode"
-            class="upload-demo"
             drag
-            action="https://jsonplaceholder.typicode.com/posts/"
-            multiple
-            :before-upload="beforeFileUpload"
+            class="upload-demo"
+            action=""
+            :on-remove="handleRemove"
+            :before-remove="beforeRemove"
+            :limit="1"
+            :on-exceed="handleExceed"
+            :before-upload="beforeApkUpload"
+            :http-request="uploadApkFile"
+            :file-list="project.file"
           >
             <i class="el-icon-upload"></i>
             <div class="el-upload__text">
@@ -144,7 +165,7 @@
             </div>
             <div class="el-upload__tip" slot="tip">只能上传Android或IOS安装包文件</div>
           </el-upload>
-          <span v-if="!isModifyMode">{{project.file}}</span>
+          <span v-if="!isModifyMode"><a :href="project.fileUrl">{{project.fileUrl.split('/')[project.fileUrl.split('/').length-1]}}</a></span>
         </el-form-item>
         <el-form-item label="项目截止时间" prop="datetime">
           <div class="block" v-if="isModifyMode">
@@ -164,6 +185,8 @@
           <div class="btn btn-medium" @click="cancelMode('project')">取消</div>
         </el-form-item>
         <el-form-item v-if="!isModifyMode">
+          <div class="btn btn-medium btn-info" @click="submitProjectRequest()">提交项目</div>
+          <div class="btn btn-medium btn-info" @click="applyProject()">接受项目</div>
           <div class="btn btn-medium btn-info" @click="modifyForm()">修改</div>
           <div class="btn btn-medium btn-info" @click="analyseDemand()">分析需求</div>
           <div class="btn btn-medium btn-info" @click="createTask()">新建任务</div>
@@ -209,11 +232,13 @@
               <div
                 class="btn btn-small btn-info"
                 @click="handleAccept(scope.$index, scope.row.id)"
-              >接受</div>
+              >接受
+              </div>
               <div
                 class="btn btn-small btn-danger"
                 @click="handleReject(scope.$index, scope.row.id)"
-              >拒绝</div>
+              >拒绝
+              </div>
             </template>
           </el-table-column>
         </el-table>
@@ -223,19 +248,19 @@
     <div class="create-body" v-if="!isModifyMode">
       <div class="title h2">任务列表</div>
       <div class="task-list">
-        <el-table :showHeader="false" :data="project.task" style="width: 100%" max-height="400">
-          <el-table-column prop="name" label="任务名称" title="任务名称"></el-table-column>
+        <el-table :showHeader="true" :stripe="true" :data="task" style="width: 100%">
+          <el-table-column prop="title" label="任务名称" title="任务名称"></el-table-column>
           <el-table-column prop="datetime" sortable label="任务截止时间"></el-table-column>
           <el-table-column prop="resource" label="任务可见性">
             <template slot-scope="scope">
-              <div v-if="scope.row.resource=='区域'">{{updateLocation(scope.row.location)}}</div>
-              <div v-if="scope.row.resource=='定向'">{{scope.row.institution}}</div>
-              <div v-if="scope.row.resource=='广场'">{{scope.row.resource}}</div>
+              <div v-if="scope.row.resource=='1'">{{updateLocation(scope.row.location)}}</div>
+              <div v-if="scope.row.resource=='0'">{{scope.row.institution}}</div>
+              <div v-if="scope.row.resource=='2'">{{resourceType[scope.row.resource]}}</div>
             </template>
           </el-table-column>
           <el-table-column prop="type" label="业务类型">
             <template slot-scope="scope">
-              <div class="badge">{{scope.row.type}}</div>
+              <div class="badge">{{serviceType[scope.row.serviceType]}}</div>
             </template>
           </el-table-column>
 
@@ -244,11 +269,13 @@
               <div
                 class="btn btn-small btn-info"
                 @click="goToTaskDetail(projectId, scope.row.id)"
-              >查看详情</div>
+              >查看详情
+              </div>
               <div
                 class="btn btn-small btn-danger"
                 @click="handleDelete(scope.$index, scope.row.id)"
-              >删除</div>
+              >删除
+              </div>
             </template>
           </el-table-column>
         </el-table>
@@ -257,389 +284,409 @@
 
     <div class="create-body" v-if="!isModifyMode">
       <div class="title h2">报告列表</div>
-      <report-list/>
+      <report-list v-bind:reports="project.reportList" v-bind:taskId=null v-bind:projectId="projectId"/>
     </div>
   </div>
 </template>
 
 <script>
-import Enum from "@/constants/enum/index";
-import PlatformType from "@/constants/enum/platform-type";
-import provinceCity from "@/constants/provinceCity.json";
-import ReportList from "@/components/report/ReportList";
+import Enum from '@/constants/enum/index'
+import PlatformType from '@/constants/enum/platform-type'
+import ReportList from '@/components/report/ReportList'
+import Http from '@/js/http.js'
+import Apis from '@/js/api.js'
+import ResourceType from '@/constants/enum/resource-type'
+import provincecity from '@/components/commons/ProvinceCity'
+import provinceCityJSON from '@/constants/provinceCity.json'
+import ServiceType from '@/constants/enum/service-type'
+import {notify} from '@/constants/index'
+
 export default {
-  name: "Project",
-  components: { ReportList },
-  data() {
+  name: 'Project',
+  components: {
+    provincecity,
+    ReportList
+  },
+  data () {
     var validatePass = (rule, value, callback) => {
-      var reg = /^(0|86|17951)?(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$/;
-      if (value.phone) {
-        if (!reg.test(value.phone)) {
-          callback(new Error("请检查手机号码"));
+      var reg = /^(0|86|17951)?(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$/
+      if (this.project.contactPhone) {
+        if (!reg.test(this.project.contactPhone)) {
+          callback(new Error('请检查手机号码'))
         } else {
-          callback();
+          callback()
         }
       }
-    };
+    }
     return {
       projectId: 0,
-      tabPosition: "top",
+      tabPosition: 'top',
       institutionArray: Enum.institution,
       isModifyMode: false,
-      platformType: [],
+      platformType: PlatformType,
+      resourceType: ResourceType,
+      serviceType: ServiceType,
       project: {
-        name: "项目名",
-        code: "27382hdsjkfdskfK",
-        contact: {
-          name: "小王",
-          phone: "12426177281"
-        },
-        type: ["安全漏洞扫描"],
-        platform: ["0", "1"],
-        desc: "需求描述文字",
-        doc: "",
-        file: "http://a.apk",
-        resource: "非定向",
-        institution: "",
-        datetime: new Date("2018-11-11 23:11:11"),
-        price: "400",
-        useage: "练习",
-        budget: "100",
-        task: [
-          {
-            id: "1",
-            name: "任务1",
-            desc: "任务描述文字",
-            type: "安全漏洞扫描",
-            resource: "广场",
-            location: "",
-            institution: "",
-            datetime: "2018-11-12 11:11:01",
-            worker: ""
-          },
-          {
-            id: "2",
-            name: "任务2",
-            desc: "任务描述文字",
-            type: "接口测试",
-            resource: "定向",
-            location: "",
-            institution: "上软",
-            datetime: "2018-11-11 10:11:01",
-            worker: ""
-          },
-          {
-            id: "3",
-            name: "任务3",
-            desc: "任务描述文字",
-            type: "功能测试服务",
-            resource: "区域",
-            location: { provinceCode: "3200", cityCode: "3201" },
-            institution: "",
-            datetime: "2018-11-11 11:11:01",
-            worker: ""
-          }
-        ]
+        userId: 0,
+        name: '',
+        type: '',
+        platform: '',
+        desc: '',
+        resource: '',
+        location: '',
+        institution: '',
+        contactName: '',
+        contactPhone: '',
+        doc: [],
+        requireDocUrl: '',
+        file: [],
+        fileUrl: '',
+        budget: '',
+        price: '',
+        datetime: '',
+        usage: '',
       },
-      analyseDemandList: [
-        {
-          id: "1",
-          institution: "上软",
-          feasibilityReport: {
-            name: "可行性分析报告",
-            url: "feasibilityReport.docx"
-          },
-          priceAuditReport: { name: "价格审核告", url: "priceAuditReport.docx" }
-        }
-      ],
+      task: [],
+      analyseDemandList: [],
       pickerOptions: {
         shortcuts: [
           {
-            text: "今天",
-            onClick(picker) {
-              picker.$emit("pick", new Date());
+            text: '今天',
+            onClick (picker) {
+              picker.$emit('pick', new Date())
             }
           },
           {
-            text: "昨天",
-            onClick(picker) {
-              const date = new Date();
-              date.setTime(date.getTime() - 3600 * 1000 * 24);
-              picker.$emit("pick", date);
+            text: '昨天',
+            onClick (picker) {
+              const date = new Date()
+              date.setTime(date.getTime() - 3600 * 1000 * 24)
+              picker.$emit('pick', date)
             }
           },
           {
-            text: "一周前",
-            onClick(picker) {
-              const date = new Date();
-              date.setTime(date.getTime() - 3600 * 1000 * 24 * 7);
-              picker.$emit("pick", date);
+            text: '一周前',
+            onClick (picker) {
+              const date = new Date()
+              date.setTime(date.getTime() - 3600 * 1000 * 24 * 7)
+              picker.$emit('pick', date)
             }
           }
         ]
       },
       rules: {
         name: [
-          { required: true, message: "请输入项目名称", trigger: "blur" }
+          {required: true, message: '请输入项目名称', trigger: 'blur'}
           // { min: 3, max: 5, message: "长度在 3 到 5 个字符", trigger: "blur" }
         ],
         type: [
           {
-            type: "array",
+            type: 'array',
             required: true,
-            message: "请至少选择一种服务类型",
-            trigger: "change"
+            message: '请至少选择一种服务类型',
+            trigger: 'change'
           }
         ],
         platform: [
           {
-            type: "array",
+            type: 'array',
             required: true,
-            message: "请至少选择一个平台",
-            trigger: "change"
+            message: '请至少选择一个平台',
+            trigger: 'change'
           }
         ],
-        desc: [{ required: true, message: "请填写活动形式", trigger: "blur" }],
-        contact: [{ validator: validatePass, trigger: "blur" }],
+        desc: [{required: true, message: '请填写活动形式', trigger: 'blur'}],
+        contact: [{validator: validatePass, trigger: 'blur'}],
         resource: [
           {
             required: true,
-            message: "请选择项目可见性",
-            trigger: "change"
+            message: '请选择项目可见性',
+            trigger: 'change'
           }
         ]
       }
-    };
+    }
   },
-  mounted() {
+  mounted () {
     this.$nextTick(() => {
-      this.init();
-    });
+      this.init()
+    })
   },
   watch: {
-    "project.resource"() {
-      if (this.project.resource == "非定向") {
-        this.project.institution = "";
+    '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: {
-    updateLocation(location) {
-      var provinceName = "";
-      var cityName = "";
-      for (var item of provinceCity.provinces) {
+    updateLocation (location) {
+      var provinceName = ''
+      var cityName = ''
+      for (var item of provinceCityJSON.provinces) {
         if (item.code === location.provinceCode) {
-          provinceName = item.name;
+          provinceName = item.name
           for (var city of item.cities) {
             if (city.code === location.cityCode) {
-              cityName = city.name;
-              break;
+              cityName = city.name
+              break
             }
           }
         }
       }
-      return provinceName + " / " + cityName;
+      return provinceName + ' / ' + cityName
     },
-    init() {
-      this.projectId = +this.$route.params.projectId;
-      this.project.platform.map(item => {
-        this.platformType.push(PlatformType[item]);
-      });
+    init () {
+      this.projectId = this.$route.params.projectId
+      this.loadData()
+      // this.project.platform.map(item => {
+      //   this.platformType.push(PlatformType[item])
+      // })
     },
-    submitForm(formName) {
-      this.$refs[formName].validate(valid => {
-        if (valid) {
-          this.isModifyMode = false;
-          console.log(this.project);
-          //提交 project
-        } else {
-          console.log("error submit!!");
-          return false;
-        }
-      });
+    //提交修改
+    submitForm (formName) {
+      //PROJ--2019073114009
+      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,
+        price: this.project.price,
+        datetime: this.project.datetime,
+        usage: this.project.usage,
+      }
+      console.log(newProject)
+      Http.put(Apis.PROJECT.UPDATE_PROJECT.replace('{projectId}', this.projectId), newProject).then((res) => {
+        console.log(res)
+        this.isModifyMode = false
+        notify('success', '项目修改成功')
+      }).catch(error => {
+        notify('error', error.data.msg)
+      })
+      // this.$refs[formName].validate(valid => {
+      //   if (valid) {
+      //
+      //     //提交 project
+      //   } else {
+      //     console.log('error submit!!')
+      //     return false
+      //   }
+      // })
     },
-    resetForm(formName) {
-      this.$refs[formName].resetFields();
-      this.project.name = "";
-      this.project.type = [];
-      this.project.platform = [];
-      this.project.desc = "";
-      this.project.doc = "";
-      this.project.file = "";
-      this.project.contact = {
-        name: "",
-        phone: ""
-      };
-      this.project.resource = "非定向";
-      this.project.institution = "";
-      this.project.datetime = "";
-      this.project.price = "";
-      this.project.useage = "";
-      this.project.budget = "";
+    //重置表单
+    resetForm (formName) {
+      this.$refs[formName].resetFields()
+      this.project.name = ''
+      this.project.type = []
+      this.project.platform = []
+      this.project.desc = ''
+      this.project.doc = ''
+      this.project.file = ''
+      this.project.contactName = ''
+      this.project.contactPhone = ''
+      this.project.resource = '2'
+      this.project.institution = ''
+      this.project.datetime = ''
+      this.project.price = ''
+      this.project.usage = ''
+      this.project.budget = ''
     },
-    modifyForm() {
-      this.isModifyMode = true;
+    //进入修改项目页面
+    modifyForm () {
+      this.isModifyMode = true
+      this.project.type = []
+      this.project.platform = []
       //获得update 信息
-      this.project = {
-        name: "项目名",
-        code: "27382hdsjkfdskfK",
-        contact: {
-          name: "小王",
-          phone: "13818022817"
-        },
-        type: ["安全漏洞扫描"],
-        platform: ["0", "1"],
-        desc: "需求描述文字",
-        doc: "",
-        file: "http://a.apk",
-        resource: "非定向",
-        institution: "",
-        datetime: new Date("2018-11-11 23:11:11"),
-        price: "400",
-        useage: "练习",
-        budget: "100",
-        task: [
-          {
-            id: "1",
-            name: "任务1",
-            desc: "任务描述文字",
-            type: "安全漏洞扫描",
-            resource: "广场",
-            location: { provinceCode: "", cityCode: "" },
-            institution: "",
-            datetime: "2018-11-12 11:11:01",
-            worker: ""
-          },
-          {
-            id: "2",
-            name: "任务2",
-            desc: "任务描述文字",
-            type: "接口测试",
-            resource: "定向",
-            location: { provinceCode: "", cityCode: "" },
-            institution: "上软",
-            datetime: "2018-11-11 10:11:01",
-            worker: ""
-          },
-          {
-            id: "3",
-            name: "任务3",
-            desc: "任务描述文字",
-            type: "功能测试服务",
-            resource: "区域",
-            location: { provinceCode: "3200", cityCode: "3201" },
-            institution: "",
-            datetime: "2018-11-11 11:11:01",
-            worker: ""
-          }
-        ]
-      };
+      //this.loadData()
     },
-    cancelMode(formName) {
-      this.isModifyMode = false;
-      //获得update 信息
-      this.project = {
-        name: "项目名",
-        code: "27382hdsjkfdskfK",
-        contact: {
-          name: "小王",
-          phone: "13818022817"
-        },
-        type: ["安全漏洞扫描"],
-        platform: ["0", "1"],
-        desc: "需求描述文字",
-        doc: "",
-        file: "http://a.apk",
-        resource: "非定向",
-        institution: "",
-        datetime: new Date("2018-11-11 23:11:11"),
-        price: "400",
-        useage: "练习",
-        budget: "100",
-        task: [
-          {
-            id: "1",
-            name: "任务1",
-            desc: "任务描述文字",
-            type: "安全漏洞扫描",
-            resource: "广场",
-            location: "",
-            institution: "",
-            datetime: "2018-11-12 11:11:01",
-            worker: ""
-          },
-          {
-            id: "2",
-            name: "任务2",
-            desc: "任务描述文字",
-            type: "接口测试",
-            resource: "定向",
-            location: "",
-            institution: "上软",
-            datetime: "2018-11-11 10:11:01",
-            worker: ""
-          },
-          {
-            id: "3",
-            name: "任务3",
-            desc: "任务描述文字",
-            type: "功能测试服务",
-            resource: "区域",
-            location: { provinceCode: "3200", cityCode: "3201" },
-            institution: "",
-            datetime: "2018-11-11 11:11:01",
-            worker: ""
-          }
-        ]
-      };
+    //接收项目
+    submitProjectRequest () {
+      const data = {
+        userId: 3,
+        projectId: this.projectId
+      }
+      Http.post(Apis.USER.SUBMIT_PROJECT_REQUEST, data).then((res) => {
+        console.log(res)
+      })
+    },
+    //申请项目
+    applyProject () {
+      const data = {
+        userId: 3,
+        projectId: this.projectId
+      }
+      Http.post(Apis.USER.ACCEPT_PROJECT, data).then((res) => {
+        console.log(res)
+      })
+    },
+    cancelMode (formName) {
+      this.isModifyMode = false
+      this.loadData()
+
     },
-    goToTaskDetail(id) {
+    goToTaskDetail (projectId, taskId) {
       this.$router.push({
-        name: "Task",
-        params: { projectId: this.projectId, taskId: id }
-      });
+        name: 'Task',
+        params: {projectId: projectId, taskId: taskId}
+      })
     },
-    createTask() {
-      this.$router.push({ name: "TaskCreate" });
+    createTask () {
+      this.$router.push({name: 'TaskCreate'})
     },
-    createReport() {
-      this.$router.push({ name: "ReportCreate" });
+    createReport () {
+      this.$router.push({
+        name: 'ReportCreate',
+        params: {
+          scope: 0,
+          dependencyCode: this.projectId,
+          projectId: this.projectId,
+          taskId: null,
+        }
+      })
     },
-    handleDelete(index, id) {
-      this.project.task.splice(index, 1);
+    handleDelete (index, id) {
+      this.task.splice(index, 1)
     },
-    beforeFileUpload(file) {
-      const isAPK = file.type === "application/vnd.android.package-archive";
-      const isDMG = file.type === "application/octet-stream";
+    beforeApkUpload (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 格式!");
+        this.$message.error('上传安装包只能是 APK 或 DMG 格式!')
+      }
+      return isAPK || isDMG
+    },
+    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
+    },
+    analyseDemand () {
+      this.$router.push({name: 'AnalyseDemand'})
+    },
+    handleAccept (index, id) {
+      console.log('接受')
+    },
+    handleReject (index, id) {
+      console.log('拒绝')
+    },
+    loadData () {//PROJ--2019073114009
+      Http.get(Apis.PROJECT.GET_PROJECT.replace('{projectId}', this.projectId)).then((res) => {
+        //console.log(res)
+        this.projectId = res.projectDetails.id
+        this.project.name = res.projectDetails.name
+        this.project.contactName = res.projectDetails.contactName
+        this.project.contactPhone = res.projectDetails.contactPhone
+        this.project.type = res.projectDetails.type
+        this.project.platform = res.projectDetails.platform
+        this.project.desc = res.projectDetails.desc
+        this.project.doc = []
+        this.project.file = []
+        this.project.resource = res.projectDetails.resource
+        this.project.location = res.projectDetails.location
+        this.project.institution = res.projectDetails.institution
+        this.project.datetime = new Date(res.projectDetails.datetime)
+        this.project.price = res.projectDetails.price
+        this.project.budget = res.projectDetails.budget
+        this.project.usage = res.projectDetails.usage
+        this.project.fileUrl = res.projectDetails.file
+        this.project.requireDocUrl = res.projectDetails.doc
+
+        this.task = res.taskList
+        this.analyseDemandList = res.reportList
+      })
+    },
+    locationChange (provinceId, cityId) {
+      if (provinceId || cityId) {
+        this.project.location = {provinceCode: provinceId, cityCode: cityId}
       }
-      return isAPK && isDMG;
     },
-    analyseDemand() {
-      this.$router.push({ name: "AnalyseDemand" });
+    handleRemove (file, fileList) {
+      console.log(file, fileList)
     },
-    handleAccept(index, id) {
-      console.log("接受");
+    handleExceed (files, fileList) {
+      this.$message.warning(
+        `当前限制选择 1 个文件,本次选择了 ${
+          files.length
+          } 个文件,共选择了 ${files.length + fileList.length} 个文件`
+      )
     },
-    handleReject(index, id) {
-      console.log("拒绝");
+    beforeRemove (file, fileList) {
+      //return this.$confirm(`确定移除 ${file.name}?`)
+    },
+    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.project.requireDocUrl = res.data
+        console.log(res.data)
+      })
+    },
+    uploadApkFile (param) {
+      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('上传成功')
+        this.project.fileUrl = res.data
+        console.log(res)
+      })
     }
   }
-};
+}
 </script>
 
 <style lang="less" scoped>
-.task-list {
-  margin: 0 30px;
-}
-.el-col {
-  padding: 0 !important;
-}
-.el-row {
-  margin-bottom: 10px;
-}
+  .task-list {
+    margin: 0 30px;
+  }
+
+  .el-col {
+    padding: 0 !important;
+  }
+
+  .el-row {
+    margin-bottom: 10px;
+  }
 </style>
 

+ 290 - 130
src/components/project/ProjectCreate.vue

@@ -13,7 +13,7 @@
                 <span>联系人</span>
               </el-col>
               <el-col :span="10">
-                <el-input v-model="project.contact.name" placeholder="请输入联系人姓名"></el-input>
+                <el-input v-model="project.contactName" placeholder="请输入联系人姓名"></el-input>
               </el-col>
             </el-row>
             <el-row :gutter="2">
@@ -21,16 +21,16 @@
                 <span>联系人电话</span>
               </el-col>
               <el-col :span="10">
-                <el-input v-model="project.contact.phone" placeholder="请输入联系人电话"></el-input>
+                <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="0">IOS</el-checkbox>
-            <el-checkbox label="1">ANDROID</el-checkbox>
-            <el-checkbox label="2">WEB</el-checkbox>
+            <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>
         <el-form-item label="需求描述" prop="desc">
@@ -43,17 +43,17 @@
         </el-form-item>
         <el-form-item label="服务类型" prop="type">
           <el-checkbox-group v-model="project.type">
-            <el-checkbox label="接口测试" name="type"></el-checkbox>
-            <el-checkbox label="安全漏洞扫描" name="type"></el-checkbox>
-            <el-checkbox label="风险评估服务" name="type"></el-checkbox>
-            <el-checkbox label="源代码安全审计服务" name="type"></el-checkbox>
-            <el-checkbox label="功能测试服务" name="type"></el-checkbox>
-            <el-checkbox label="性能测试" name="type"></el-checkbox>
-            <el-checkbox label="功能和易用性测试" name="type"></el-checkbox>
+            <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>
           </el-checkbox-group>
         </el-form-item>
-        <el-form-item label="用途" prop="useage">
-          <el-input v-model="project.useage"></el-input>
+        <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">
@@ -66,7 +66,7 @@
             v-model="project.resource"
             style="max-height: 200px;"
           >
-            <el-tab-pane label="定向" name="定向">
+            <el-tab-pane :label="resourceType[0]" name="0">
               <el-radio-group v-model="project.institution">
                 <el-radio
                   :label="item"
@@ -76,15 +76,29 @@
                 ></el-radio>
               </el-radio-group>
             </el-tab-pane>
-            <el-tab-pane label="非定向" name="非定向"></el-tab-pane>
+            <el-tab-pane :label="resourceType[1]" name="1">
+              <provincecity
+                ref="addFormProvince"
+                @selectChange="locationChange"
+                :provinceCode="project.location.provinceCode"
+                :cityCode="project.location.cityCode"
+              ></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
-            class="upload-demo"
             drag
-            action="https://jsonplaceholder.typicode.com/posts/"
-            multiple
+            class="upload-demo"
+            action=""
+            :on-remove="handleRemove"
+            :before-remove="beforeRemove"
+            :limit="1"
+            :on-exceed="handleExceed"
+            :before-upload="beforeFileUpload"
+            :http-request="uploadRequireDoc"
+            :file-list="project.doc"
           >
             <i class="el-icon-upload"></i>
             <div class="el-upload__text">
@@ -96,11 +110,15 @@
         </el-form-item>
         <el-form-item label="安装包" prop="file">
           <el-upload
-            class="upload-demo"
             drag
-            action="https://jsonplaceholder.typicode.com/posts/"
-            multiple
-            :before-upload="beforeFileUpload"
+            class="upload-demo"
+            action=""
+            :on-remove="handleRemove"
+            :limit="1"
+            :on-exceed="handleExceed"
+            :before-upload="beforeApkUpload"
+            :http-request="uploadApkFile"
+            :file-list="project.file"
           >
             <i class="el-icon-upload"></i>
             <div class="el-upload__text">
@@ -122,7 +140,7 @@
           </div>
         </el-form-item>
         <el-form-item>
-          <div class="btn btn-medium btn-info" @click="submitForm('project')">立即申请</div>
+          <div class="btn btn-medium btn-info" v-on:click="submitForm('project')">立即申请</div>
           <div class="btn btn-medium" @click="resetForm('project')">重置</div>
         </el-form-item>
       </el-form>
@@ -131,179 +149,321 @@
 </template>
 
 <script>
-import Enum from "@/constants/enum/index";
-import PlatformType from "@/constants/enum/platform-type";
-import provinceCity from "@/constants/provinceCity.json";
+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'
+
 export default {
-  name: "ProjectCreate",
-  data() {
+  name: 'ProjectCreate',
+  components: {
+    provincecity
+  },
+  data () {
     var validatePass = (rule, value, callback) => {
-      var reg = /^(0|86|17951)?(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$/;
-      if (value.phone) {
-        if (!reg.test(value.phone)) {
-          callback(new Error("请检查手机号码"));
+      var reg = /^(0|86|17951)?(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$/
+      if (this.contactPhone) {
+        if (!reg.test(this.contactPhone)) {
+          callback(new Error('请检查手机号码'))
         } else {
-          callback();
+          callback()
         }
       }
-    };
+    }
     return {
-      tabPosition: "top",
+      tabPosition: 'top',
       institutionArray: Enum.institution,
       platformType: [],
+      serviceType: ServiceType,
+      resourceType: ResourceType,
       project: {
-        name: "",
-        contact: {
-          name: "",
-          phone: ""
-        },
+        userId: 3,
+        name: '',
+        contactName: '',
+        contactPhone: '',
         type: [],
         platform: [],
-        desc: "",
-        doc: "",
-        file: "",
-        resource: "非定向",
-        institution: "",
-        datetime: "",
-        price: "",
-        useage: "",
-        budget: ""
+        desc: '',
+        doc: [],
+        file: [],
+        requireDocUrl: '',
+        fileUrl: '',
+        resource: '0',
+        location: {provinceCode: '3200', cityCode: '3201'},
+        institution: '',
+        datetime: '',
+        price: '',
+        usage: '',
+        budget: ''
       },
       pickerOptions: {
         shortcuts: [
           {
-            text: "今天",
-            onClick(picker) {
-              picker.$emit("pick", new Date());
+            text: '今天',
+            onClick (picker) {
+              picker.$emit('pick', new Date())
             }
           },
           {
-            text: "昨天",
-            onClick(picker) {
-              const date = new Date();
-              date.setTime(date.getTime() - 3600 * 1000 * 24);
-              picker.$emit("pick", date);
+            text: '昨天',
+            onClick (picker) {
+              const date = new Date()
+              date.setTime(date.getTime() - 3600 * 1000 * 24)
+              picker.$emit('pick', date)
             }
           },
           {
-            text: "一周前",
-            onClick(picker) {
-              const date = new Date();
-              date.setTime(date.getTime() - 3600 * 1000 * 24 * 7);
-              picker.$emit("pick", date);
+            text: '一周前',
+            onClick (picker) {
+              const date = new Date()
+              date.setTime(date.getTime() - 3600 * 1000 * 24 * 7)
+              picker.$emit('pick', date)
             }
           }
         ]
       },
       rules: {
         name: [
-          { required: true, message: "请输入项目名称", trigger: "blur" }
+          {required: true, message: '请输入项目名称', trigger: 'blur'}
           // { min: 3, max: 5, message: "长度在 3 到 5 个字符", trigger: "blur" }
         ],
         type: [
           {
-            type: "array",
+            type: 'array',
             required: true,
-            message: "请至少选择一种服务类型",
-            trigger: "change"
+            message: '请至少选择一种服务类型',
+            trigger: 'change'
           }
         ],
         platform: [
           {
-            type: "array",
+            type: 'array',
             required: true,
-            message: "请至少选择一个平台",
-            trigger: "change"
+            message: '请至少选择一个平台',
+            trigger: 'change'
           }
         ],
-        desc: [{ required: true, message: "请填写活动形式", trigger: "blur" }],
-        contact: [{ validator: validatePass, trigger: "blur" }],
+        desc: [{required: true, message: '请填写活动形式', trigger: 'blur'}],
+        contact: [{validator: validatePass, trigger: 'blur'}],
         resource: [
           {
             required: true,
-            message: "请选择项目可见性",
-            trigger: "change"
+            message: '请选择项目可见性',
+            trigger: 'change'
           }
         ]
       }
-    };
+    }
   },
-  mounted() {
+  mounted () {
     this.$nextTick(() => {
-      this.init();
-    });
+      this.init()
+    })
   },
   watch: {
-    "project.resource"() {
-      if (this.project.resource == "非定向") {
-        this.project.institution = "";
+    '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: {
-    init() {
-      this.project.platform.map(item => {
-        this.platformType.push(PlatformType[item]);
-      });
+    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
+    },
+    locationChange (provinceId, cityId) {
+      if (provinceId || cityId) {
+        this.project.location = {provinceCode: provinceId, cityCode: cityId}
+      }
     },
-    submitForm(formName) {
-      this.$refs[formName].validate(valid => {
-        if (valid) {
-          console.log(this.project);
-          //提交 project
+    init () {
+      // 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
         } else {
-          console.log("error submit!!");
-          return false;
+          this.$router.go(-1)
         }
-      });
+      }).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();
-      this.project.name = "";
-      this.project.type = [];
-      this.project.platform = [];
-      this.project.desc = "";
-      this.project.file = "";
-      this.project.doc = "";
-      this.project.contact = {
-        name: "",
-        phone: ""
-      };
+    resetForm (formName) {
+      this.$refs[formName].resetFields()
+      this.project.name = ''
+      this.project.type = []
+      this.project.platform = []
+      this.project.desc = ''
+      this.project.file = ''
+      this.project.doc = ''
+      this.project.contactName = ''
+      this.project.contactPhone = ''
 
-      this.project.resource = "非定向";
-      this.project.institution = "";
-      this.project.datetime = "";
-      this.project.price = "";
-      this.project.useage = "";
-      this.project.budget = "";
+      this.project.resource = '非定向'
+      this.project.institution = ''
+      this.project.datetime = ''
+      this.project.price = ''
+      this.project.usage = ''
+      this.project.budget = ''
     },
-    beforeFileUpload(file) {
-      const isAPK = file.type === "application/vnd.android.package-archive";
-      const isDMG = file.type === "application/octet-stream";
+    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 格式!");
+        this.$message.error('上传安装包只能是 APK 或 DMG 格式!')
       }
-      return isAPK && isDMG;
+      return isAPK || isDMG
+    },
+    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
+    },
+    loadData () {
+      Http.get(Apis.PAGE.PROJECT_DETAIL_PAGE).then((res) => {
+        this.project = res.project
+      })
+    },
+    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}?`)
+    },
+    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.project.requireDocUrl = res.data
+        console.log(this.project.doc)
+        //console.log(res.data)
+      })
+
+    },
+    uploadApkFile (param) {
+      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('上传成功')
+        this.project.fileUrl = res.data
+        console.log(res)
+      })
     }
   }
-};
+}
 </script>
 
 <style lang="less" scoped>
-.el-col {
-  padding: 0 !important;
-}
-.el-row {
-  margin-bottom: 10px;
-}
-.el-radio {
-  margin: 10px 20px 10px 0;
-}
-.el-form-item /deep/.el-tabs__content {
-  max-height: 120px !important;
-  overflow: auto;
-}
+  .el-col {
+    padding: 0 !important;
+  }
+
+  .el-row {
+    margin-bottom: 10px;
+  }
+
+  .el-radio {
+    margin: 10px 20px 10px 0;
+  }
+
+  .el-form-item /deep/ .el-tabs__content {
+    max-height: 120px !important;
+    overflow: auto;
+  }
 </style>
 

+ 190 - 114
src/components/report/Report.vue

@@ -8,14 +8,14 @@
         </el-form-item>
         <el-form-item label="报告类型" prop="type">
           <el-radio-group v-if="isModifyMode" v-model="report.type">
-            <el-radio label="项目可行性报告" name="type"></el-radio>
-            <el-radio label="项目测试方案" name="type"></el-radio>
-            <el-radio label="项目测试报告" name="type"></el-radio>
-            <el-radio label="项目缺陷报告" name="type"></el-radio>
-            <el-radio label="项目用例报告" name="type"></el-radio>
-            <el-radio label="其他" name="type"></el-radio>
+            <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">{{report.type}}</span>
+          <span v-if="!isModifyMode" class="badge">{{serviceType[report.type]}}</span>
         </el-form-item>
         <el-form-item label="摘要" prop="abstract">
           <div>
@@ -24,8 +24,8 @@
                 <span>测试对象</span>
               </el-col>
               <el-col :span="10">
-                <el-input v-if="isModifyMode" type="textarea" v-model="report.abstract.target"></el-input>
-                <span v-if="!isModifyMode">{{report.abstract.target}}</span>
+                <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">
@@ -33,8 +33,8 @@
                 <span>测试内容</span>
               </el-col>
               <el-col :span="10">
-                <el-input v-if="isModifyMode" type="textarea" v-model="report.abstract.content"></el-input>
-                <span v-if="!isModifyMode">{{report.abstract.content}}</span>
+                <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>
@@ -44,7 +44,7 @@
             v-if="isModifyMode"
             drag
             class="upload-demo"
-            action="https://jsonplaceholder.typicode.com/posts/"
+            action=""
             :on-remove="handleRemove"
             :before-remove="beforeRemove"
             multiple
@@ -52,6 +52,7 @@
             :on-exceed="handleExceed"
             :before-upload="beforeFileUpload"
             :file-list="report.file"
+            :http-request="uploadReportFile"
           >
             <i class="el-icon-upload"></i>
             <div class="el-upload__text">
@@ -61,8 +62,9 @@
             <div class="el-upload__tip" slot="tip">请上传报告文件</div>
           </el-upload>
           <div v-if="!isModifyMode">
-            <span v-if="report.file.length==0">暂无文件</span>
-            <a :href="report.file[0].url" v-if="report.file.length>0"><i class="fa fa-file-text-o"></i> {{report.file[0].name}}</a>
+            <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>
 
@@ -85,137 +87,211 @@
 </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",
+  name: 'Report-Create',
   components: {},
-  data() {
+  data () {
     return {
       reportId: 0,
+      projectId: '',
+      taskId: '',
       isModifyMode: false,
+      serviceType: ServiceType,
       report: {
-        name: "测试报告1",
-        abstract: {
-          target: "测试对象xxxx",
-          content: "测试内容xxxxx"
-        },
-        file: [{ name: "report5", url: "report5.excel" }],
-        type: "项目测试方案",
-        conclusion: "app挺好"
+        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" }
-        ]
+        // 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() {
+  mounted () {
     this.$nextTick(() => {
-      this.init();
-    });
+      this.init()
+    })
   },
   methods: {
-    init() {
-      this.reportId = +this.$route.params.reportId;
+    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;
-      //请求 report
-      this.report = {
-        name: "测试报告1",
-        abstract: {
-          target: "测试对象xxxx",
-          content: "测试内容xxxxx"
-        },
-        file: [{ name: "report5", url: "report5.excel" }],
-        type: "项目测试方案",
-        conclusion: "app挺好"
-      };
+    modifyForm () {
+      this.isModifyMode = true
     },
-    submitForm(formName) {
-      this.$refs[formName].validate(valid => {
-        if (valid) {
-          this.isModifyMode = false;
-          console.log(this.report);
-          //提交 report
-        } else {
-          console.log("error submit!!");
-          return false;
-        }
-      });
+    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.abstract.target = "";
-      this.report.abstract.content = "";
-      this.report.file = [];
-      this.report.type = "";
-      this.report.conclusion = "";
+    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;
+    cancelCreate () {
+      this.isModifyMode = false
       //请求 report
-      this.report = {
-        name: "测试报告1",
-        abstract: {
-          target: "测试对象xxxx",
-          content: "测试内容xxxxx"
-        },
-        file: [{ name: "report5", url: "report5.excel" }],
-        type: "项目测试方案",
-        conclusion: "app挺好"
-      };
     },
-    handleRemove(file, fileList) {
-      console.log(file, fileList);
+    handleRemove (file, fileList) {
+      console.log(file, fileList)
     },
-    handleExceed(files, fileList) {
+    handleExceed (files, fileList) {
       this.$message.warning(
         `当前限制选择 1 个文件,本次选择了 ${
           files.length
-        } 个文件,共选择了 ${files.length + fileList.length} 个文件`
-      );
+          } 个文件,共选择了 ${files.length + fileList.length} 个文件`
+      )
     },
-    beforeRemove(file, fileList) {
-      return this.$confirm(`确定移除 ${file.name}?`);
+    beforeRemove (file, fileList) {
+      //return this.$confirm(`确定移除 ${file.name}?`)
     },
-    beforeFileUpload() {},
-    back(){
+    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;
+        this.$router.push({path: '/'})
+        return false
       } else {
-        this.$router.go(-1);
+        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;
-}
+  .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>

+ 136 - 66
src/components/report/ReportCreate.vue

@@ -8,12 +8,12 @@
         </el-form-item>
         <el-form-item label="报告类型" prop="type">
           <el-radio-group v-model="report.type">
-            <el-radio label="项目可行性报告" name="type"></el-radio>
-            <el-radio label="项目测试方案" name="type"></el-radio>
-            <el-radio label="项目测试报告" name="type"></el-radio>
-            <el-radio label="项目缺陷报告" name="type"></el-radio>
-            <el-radio label="项目用例报告" name="type"></el-radio>
-            <el-radio label="其他" name="type"></el-radio>
+            <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>
           </el-radio-group>
         </el-form-item>
         <el-form-item label="摘要" prop="abstract">
@@ -23,7 +23,7 @@
                 <span>测试对象</span>
               </el-col>
               <el-col :span="10">
-                <el-input type="textarea" v-model="report.abstract.target"></el-input>
+                <el-input type="textarea" v-model="report.target"></el-input>
               </el-col>
             </el-row>
             <el-row :gutter="2">
@@ -31,7 +31,7 @@
                 <span>测试内容</span>
               </el-col>
               <el-col :span="10">
-                <el-input type="textarea" v-model="report.abstract.content"></el-input>
+                <el-input type="textarea" v-model="report.content"></el-input>
               </el-col>
             </el-row>
           </div>
@@ -48,6 +48,7 @@
             :on-exceed="handleExceed"
             :before-upload="beforeFileUpload"
             :file-list="report.file"
+            :http-request="uploadReportFile"
           >
             <i class="el-icon-upload"></i>
             <div class="el-upload__text">
@@ -72,102 +73,171 @@
 </template>
 
 <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'
 export default {
-  name: "ReportCreate",
+  name: 'ReportCreate',
   components: {},
-  data() {
+  data () {
     return {
+      reportType: ReportType,
+      scope: 0,
+      projectId: '',
+      taskId: '',
+      dependencyCode: '',
       report: {
-        name: "",
-        abstract: {
-          target: "",
-          content: ""
-        },
+        name: '',
+        target: '',
+        content: '',
         file: [],
-        type: "",
-        conclusion: ""
+        fileUrl: '',
+        type: '',
+        conclusion: ''
       },
       rules: {
         name: [
-          { required: true, message: "请输入报告名称", trigger: "blur" }
+          {required: true, message: '请输入报告名称', trigger: 'blur'}
           // { min: 3, max: 5, message: "长度在 3 到 5 个字符", trigger: "blur" }
         ],
         abstract: [
           {
             required: true,
-            message: "请输入摘要信息",
-            trigger: "change"
+            message: '请输入摘要信息',
+            trigger: 'change'
           }
         ],
         type: [
-          { required: true, message: "请选择报告类型", trigger: "change" }
+          {required: true, message: '请选择报告类型', trigger: 'change'}
         ],
         file: [
-          { required: true, message: "请上传报告文件", trigger: "change" }
+          {required: true, message: '请上传报告文件', trigger: 'change'}
         ],
         conclusion: [
-          { required: true, message: "请输入报告结论", trigger: "blur" }
+          {required: true, message: '请输入报告结论', trigger: 'blur'}
         ]
       }
-    };
+    }
+  },
+  mounted () {
+    this.$nextTick(() => {
+      this.init()
+    })
   },
-  mounted() {},
   methods: {
-    submitForm(formName) {
-      this.$refs[formName].validate(valid => {
-        if (valid) {
-          console.log(this.report);
-          //提交 report
-        } else {
-          console.log("error submit!!");
-          return false;
-        }
-      });
+    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
+    },
+    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
+      //   }
+      // })
     },
-    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 = "";
+    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() {
+    cancelCreate () {
       if (window.history.length <= 1) {
-        this.$router.push({ path: "/" });
-        return false;
+        this.$router.push({path: '/'})
+        return false
       } else {
-        this.$router.go(-1);
+        this.$router.go(-1)
       }
     },
-    handleRemove(file, fileList) {
-      console.log(file, fileList);
+    handleRemove (file, fileList) {
+      console.log(file, fileList)
     },
-    handleExceed(files, fileList) {
+    handleExceed (files, fileList) {
       this.$message.warning(
         `当前限制选择 1 个文件,本次选择了 ${
           files.length
-        } 个文件,共选择了 ${files.length + fileList.length} 个文件`
-      );
+          } 个文件,共选择了 ${files.length + fileList.length} 个文件`
+      )
+    },
+    beforeRemove (file, fileList) {
+      //return this.$confirm(`确定移除 ${file.name}?`)
     },
-    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
     },
-    beforeFileUpload() {}
+    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}', 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;
-}
+  .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>

+ 61 - 55
src/components/report/ReportList.vue

@@ -9,16 +9,17 @@
       </el-col>
     </el-row>-->
 
-    <el-table :showHeader="false" :data="reportList" style="width: 100%">
+    <el-table :showHeader="true" :data="reportList" style="width: 100%">
       <el-table-column prop="type" label="报告类型" title="报告类型">
         <template slot-scope="scope">
-          <span class="badge">{{scope.row.type}}</span>
+          <span class="badge">{{serviceType[scope.row.type]}}</span>
         </template>
       </el-table-column>
       <el-table-column prop="file" sortable label="报告文件">
         <template slot-scope="scope">
-          <span v-if="scope.row.file.length==0">暂无文件</span>
-          <a :href="scope.row.file[0].url" v-if="scope.row.file.length>0" target="_blank"><i class="fa fa-file-text-o"></i> {{scope.row.file[0].name}}</a>
+          <span v-if="scope.row.content==null">暂无文件</span>
+          <a :href="scope.row.content" v-if="scope.row.content!=0" target="_blank"><i
+            class="fa fa-file-text-o"></i> {{scope.row.content}}</a>
         </template>
       </el-table-column>
       <el-table-column align="right" label="操作">
@@ -31,75 +32,80 @@
   </div>
 </template>
 <script>
+
+import ServiceType from '../../constants/enum/service-type'
+
 export default {
-  name: "report-list",
-  data() {
+  name: 'report-list',
+  props: {
+    reports: {},
+    projectId: '',
+    taskId: ''
+  },
+  data () {
     return {
       editIndex: -1,
-      reportList: [
-        {
-          id:1,
-          type: "项目可行性报告",
-          file: []
-        },
-        {
-          id:2,
-          type: "项目测试方案(汇总)",
-          file: [{ name: "report2", url: "report2.excel" }]
-        },
-        {
-          id:3,
-          type: "项目测试报告(汇总)",
-          file: [{ name: "report3", url: "report3.excel" }]
-        },
-        {
-          id:4,
-          type: "项目缺陷报告(汇总)",
-          file: [{ name: "report4", url: "report4.excel" }]
-        },
-        {
-          id:5,
-          type: "项目用例报告(汇总)",
-          file: [{ name: "report5", url: "report5.excel" }]
-        }
-      ]
-    };
+      serviceType: ServiceType,
+      reportList: this.reports,
+      pid: this.projectId,
+      tid: this.taskId,
+    }
   },
   methods: {
-    handleEdit(index, row) {
-      this.$router.push({ name: "Report" ,params:{reportId:row.id}});
+    handleEdit (index, row) {
+      this.$router.push({
+        name: 'Report',
+        params: {
+          reportId: row.code,
+          projectId: this.pid,
+          taskId: this.tid
+        }
+      })
       // this.editIndex = index;
     },
-    handleDelete(index, row) {
-      this.reportList.splice(index, 1);
+    handleDelete (index, row) {
+      this.reportList.splice(index, 1)
     },
-    cancelEdit(index, row) {
-      this.editIndex = -1;
+    cancelEdit (index, row) {
+      this.editIndex = -1
     },
-    handleRemove(file, fileList) {
-      console.log(file, fileList);
+    handleRemove (file, fileList) {
+      console.log(file, fileList)
     },
-    handleExceed(files, fileList) {
+    handleExceed (files, fileList) {
       this.$message.warning(
         `当前限制选择 1 个文件,本次选择了 ${
           files.length
-        } 个文件,共选择了 ${files.length + fileList.length} 个文件`
-      );
+          } 个文件,共选择了 ${files.length + fileList.length} 个文件`
+      )
+    },
+    beforeRemove (file, fileList) {
+      return this.$confirm(`确定移除 ${file.name}?`)
+    },
+    beforeFileUpload () {
+    }
+  },
+  watch: {
+    reports () {
+      this.reportList = this.reports
     },
-    beforeRemove(file, fileList) {
-      return this.$confirm(`确定移除 ${file.name}?`);
+    projectId () {
+      this.pid = this.projectId
     },
-    beforeFileUpload() {}
+    taskId () {
+      this.tid = this.taskId
+    }
   }
-};
+}
 </script>
 
 
 <style lang="less" scoped>
-.report-container {
-  margin: 0 30px;
-}
-.el-row {
-  margin-bottom: 20px;
-}
+  .report-container {
+    margin: 0 30px;
+  }
+
+  .el-row {
+    margin-bottom: 20px;
+  }
 </style>

+ 306 - 152
src/components/task/Task.vue

@@ -5,30 +5,38 @@
       <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.name"></el-input>
-          <span v-if="!isModifyMode">{{task.name}}</span>
+          <el-input 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.desc"></el-input>
-          <span v-if="!isModifyMode">{{task.desc}}</span>
+          <el-input 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="type">
-          <el-radio-group v-if="isModifyMode" v-model="task.type">
-            <el-radio label="接口测试" name="type"></el-radio>
-            <el-radio label="安全漏洞扫描" name="type"></el-radio>
-            <el-radio label="风险评估服务" name="type"></el-radio>
-            <el-radio label="源代码安全审计服务" name="type"></el-radio>
-            <el-radio label="功能测试服务" name="type"></el-radio>
-            <el-radio label="性能测试" name="type"></el-radio>
-            <el-radio label="功能和易用性测试" name="type"></el-radio>
+        <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-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>
           </el-radio-group>
-          <span class="badge" v-if="!isModifyMode">{{task.type}}</span>
+          <span class="badge" v-if="!isModifyMode">{{serviceType[task.serviceType]}}</span>
         </el-form-item>
         <el-form-item label="任务可见性" prop="resource">
           <div v-if="!isModifyMode">
-            <div v-if="task.resource=='区域'">{{updateLocation(task.location)}}</div>
-            <div v-if="task.resource=='定向'">{{task.institution}}</div>
-            <div v-if="task.resource=='广场'">{{task.resource}}</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>
           <el-tabs
             :tab-position="tabPosition"
@@ -36,7 +44,7 @@
             style="max-height: 200px;"
             v-if="isModifyMode"
           >
-            <el-tab-pane label="定向" name="定向">
+            <el-tab-pane :label="resourceType[0]" name="0">
               <el-radio-group v-model="task.institution">
                 <el-radio
                   :label="item"
@@ -46,7 +54,7 @@
                 ></el-radio>
               </el-radio-group>
             </el-tab-pane>
-            <el-tab-pane label="区域" name="区域">
+            <el-tab-pane :label="resourceType[1]" name="1">
               <provincecity
                 ref="addFormProvince"
                 @selectChange="locationChange"
@@ -54,10 +62,39 @@
                 :cityCode="task.location.cityCode"
               ></provincecity>
             </el-tab-pane>
-            <el-tab-pane label="广场" name="广场"></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
+            class="upload-demo"
+            action=""
+            :on-remove="handleRemove"
+            :before-remove="beforeRemove"
+            :limit="1"
+            :on-exceed="handleExceed"
+            :before-upload="beforeFileUpload"
+            :http-request="uploadRequireDoc"
+            :file-list="task.doc"
+          >
+            <i class="el-icon-upload"></i>
+            <div class="el-upload__text">
+              将文件拖到此处,或
+              <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">
           <div class="block" v-if="isModifyMode">
             <el-date-picker
@@ -68,7 +105,7 @@
               :picker-options="pickerOptions"
             ></el-date-picker>
           </div>
-          <span v-if="!isModifyMode">{{new Date(task.datetime)}}</span>
+          <span v-if="!isModifyMode">{{task.datetime}}</span>
         </el-form-item>
         <el-form-item v-if="isModifyMode">
           <div class="btn btn-medium btn-info" @click="submitForm('task')">确认修改</div>
@@ -76,6 +113,7 @@
           <div class="btn btn-medium" @click="cancelMode('task')">取消</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>
@@ -85,206 +123,322 @@
     </div>
     <div class="create-body" v-if="!isModifyMode">
       <div class="title h2">报告列表</div>
-      <report-list/>
+      <report-list v-bind:reports="reportList" v-bind:taskId="taskId" v-bind:projectId="projectId"/>
     </div>
   </div>
 </template>
 
 <script>
-import Enum from "@/constants/enum/index";
-import provincecity from "@/components/commons/ProvinceCity";
-import provinceCityJSON from "@/constants/provinceCity.json";
-import ReportList from "@/components/report/ReportList";
+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'
 export default {
-  name: "Task",
+  name: 'Task',
   components: {
     provincecity,
     ReportList
   },
-  data() {
+  data () {
     return {
-      projectId: 0,
-      taskId: 0,
       isModifyMode: false,
       institutionArray: Enum.institution,
-      tabPosition: "top",
+      tabPosition: 'top',
+      resourceType: ResourceType,
+      serviceType: ServiceType,
+      taskId: '',
+      projectId: '',
       task: {
-        name: "任务名称xxxxs",
-        desc: "任务描述文字",
-        type: "安全漏洞扫描",
-        resource: "区域", //如果是广场不用管Location和institution ,定向看institution,区域看location
-        location: { provinceCode: "3200", cityCode: "3201" },
-        institution: "",
-        datetime: new Date("2018-11-11 23:11:11")
+        name: '',
+        desc: '',
+        type: '',
+        resource: '',
+        location: {},
+        institution: '',
+        datetime: '',
+        quotePrice: '',
+        fixedPrice: '',
+        doc: [],
+        requireDocUrl: '123.doc'
       },
+      reportList: [],
       pickerOptions: {
         shortcuts: [
           {
-            text: "今天",
-            onClick(picker) {
-              picker.$emit("pick", new Date());
+            text: '今天',
+            onClick (picker) {
+              picker.$emit('pick', new Date())
             }
           },
           {
-            text: "昨天",
-            onClick(picker) {
-              const date = new Date();
-              date.setTime(date.getTime() - 3600 * 1000 * 24);
-              picker.$emit("pick", date);
+            text: '昨天',
+            onClick (picker) {
+              const date = new Date()
+              date.setTime(date.getTime() - 3600 * 1000 * 24)
+              picker.$emit('pick', date)
             }
           },
           {
-            text: "一周前",
-            onClick(picker) {
-              const date = new Date();
-              date.setTime(date.getTime() - 3600 * 1000 * 24 * 7);
-              picker.$emit("pick", date);
+            text: '一周前',
+            onClick (picker) {
+              const date = new Date()
+              date.setTime(date.getTime() - 3600 * 1000 * 24 * 7)
+              picker.$emit('pick', date)
             }
           }
         ]
       },
       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" }]
+        // 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'}]
       }
-    };
+    }
   },
   watch: {
-    "task.institution"() {
+    'task.institution' () {
       if (this.task.institution) {
-        this.$refs.addFormProvince.resetProviceCity();
-        this.task.location = { provinceCode: "", cityCode: "" };
+        this.$refs.addFormProvince.resetProviceCity()
+        this.task.location = {provinceCode: '', cityCode: ''}
       }
     },
-    "task.location"() {
+    'task.location' () {
       if (this.task.location.provinceCode || this.task.location.cityCode) {
-        this.task.institution = "";
+        this.task.institution = ''
       }
     },
-    "task.resource"() {
-      if (this.task.resource == "广场") {
-        this.$refs.addFormProvince.resetProviceCity();
-        this.task.institution = "";
-        this.task.location = { provinceCode: "", cityCode: "" };
+    'task.resource' () {
+      if (this.task.resource == '广场') {
+        this.$refs.addFormProvince.resetProviceCity()
+        this.task.institution = ''
+        this.task.location = {provinceCode: '', cityCode: ''}
       }
     },
     deep: true
   },
-  mounted() {
+  mounted () {
     this.$nextTick(() => {
-      this.init();
-    });
+      this.init()
+    })
   },
   methods: {
-    init() {
-      this.taskId = +this.$route.params.taskId;
-      this.projectId = +this.$route.params.projectId;
+    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 = "";
+    updateLocation (location) {
+      var provinceName = ''
+      var cityName = ''
       for (var item of provinceCityJSON.provinces) {
         if (item.code === location.provinceCode) {
-          provinceName = item.name;
+          provinceName = item.name
           for (var city of item.cities) {
             if (city.code === location.cityCode) {
-              cityName = city.name;
-              break;
+              cityName = city.name
+              break
             }
           }
         }
       }
-      return provinceName + " / " + cityName;
+      return provinceName + ' / ' + cityName
     },
-    submitForm(formName) {
+    submitForm (formName) {
+      console.log(this.task)
       this.$refs[formName].validate(valid => {
         if (valid) {
-          this.isModifyMode = false;
-          console.log(this.task);
+          this.isModifyMode = false
+          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,
+            requireDoc: 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
         } else {
-          console.log("error submit!!");
-          return false;
+          console.log('error submit!!')
+          return false
         }
-      });
+      })
     },
-    cancelMode(formName) {
-      this.isModifyMode = false;
-      //获得task 信息
-      this.task = {
-        name: "任务名称xxxxs",
-        desc: "任务描述文字",
-        type: "安全漏洞扫描",
-        resource: "区域", //如果是广场不用管Location和institution ,定向看institution,区域看location
-        location: { provinceCode: "3200", cityCode: "3201" },
-        institution: "",
-        datetime: new Date("2018-11-11 23:11:11")
-      };
+    cancelMode (formName) {
+      this.isModifyMode = false
     },
-    modifyForm() {
-      this.isModifyMode = true;
-      //获得task 信息
-      this.task = {
-        name: "任务名称xxxxs",
-        desc: "任务描述文字",
-        type: "安全漏洞扫描",
-        resource: "区域", //如果是广场不用管Location和institution ,定向看institution,区域看location
-        location: { provinceCode: "3200", cityCode: "3201" },
-        institution: "",
-        datetime: new Date("2018-11-11 23:11:11")
-      };
+    modifyForm () {
+      this.isModifyMode = true
     },
-    resetForm(formName) {
-      this.$refs.addFormProvince.resetProviceCity();
-      this.$refs[formName].resetFields();
-      this.task.name = "";
-      this.task.desc = "";
-      this.task.type = "";
-      this.task.resource = "广场"; //如果是广场不用管Location和institution ,定向看institution,区域看location
-      (this.task.location = { provinceCode: "", cityCode: "" }),
-        (this.task.institution = "");
-      this.task.datetime = "";
+    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 = ''
     },
-    locationChange(provinceId, cityId) {
-      if (provinceId || cityId)
-        this.task.location = { provinceCode: provinceId, cityCode: cityId };
+    locationChange (provinceId, cityId) {
+      if (provinceId || cityId) {
+        this.task.location = {provinceCode: provinceId, cityCode: cityId}
+      }
     },
-    toProject() {
+    toProject () {
       this.$router.push({
-        name: "Project",
-        params: { projectId: this.projectId }
-      });
+        name: 'Project',
+        params: {projectId: this.projectId}
+      })
     },
-    applyTask() {
-      console.log("申请项目");
+    applyTask () {
+      const data = {
+        userId: 3,
+        projectId: this.projectId,
+        taskId: this.taskId
+      }
+      Http.post(Apis.USER.ACCEPT_TASK, data).then((res) => {
+        console.log(res)
+      })
     },
-    createReport() {
-      this.$router.push({ name: "ReportCreate" });
+    submitTaskRequest () {
+      const data = {
+        userId: 3,
+        projectId: this.projectId,
+        taskId: this.taskId
+      }
+      Http.post(Apis.USER.SUBMIT_TASK_REQUEST, data).then((res) => {
+        console.log(res)
+      })
     },
-  }
-};
+    createReport () {
+      this.$router.push({
+        name: 'ReportCreate',
+        params: {
+          scope: 1,
+          dependencyCode: this.taskId,
+          projectId: this.projectId,
+          taskId: this.taskId,
+        }
+      })
+    },
+    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
+      })
+    },
+    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
+    },
+    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) {
+      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)
+      })
+    },
+  },
+  // created () {
+  //   this.loadData()
+  // }
+}
 </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-radio {
+    margin: 10px 20px 10px 0;
+  }
+
+  .el-form-item /deep/ .el-tabs__content {
+    max-height: 120px !important;
+    overflow: auto;
+  }
 </style>

+ 234 - 102
src/components/task/TaskCreate.vue

@@ -9,20 +9,26 @@
         <el-form-item label="任务描述" prop="desc">
           <el-input type="textarea" 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-form-item>
         <el-form-item label="业务类型" prop="type">
           <el-radio-group v-model="task.type">
-            <el-radio label="接口测试" name="type"></el-radio>
-            <el-radio label="安全漏洞扫描" name="type"></el-radio>
-            <el-radio label="风险评估服务" name="type"></el-radio>
-            <el-radio label="源代码安全审计服务" name="type"></el-radio>
-            <el-radio label="功能测试服务" name="type"></el-radio>
-            <el-radio label="性能测试" name="type"></el-radio>
-            <el-radio label="功能和易用性测试" name="type"></el-radio>
+            <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>
           </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-tab-pane label="定向" name="定向">
+            <el-tab-pane :label="resourceType[0]" name="0">
               <el-radio-group v-model="task.institution">
                 <el-radio
                   :label="item"
@@ -32,7 +38,7 @@
                 ></el-radio>
               </el-radio-group>
             </el-tab-pane>
-            <el-tab-pane label="区域" name="区域">
+            <el-tab-pane :label="resourceType[1]" name="1">
               <provincecity
                 ref="addFormProvince"
                 @selectChange="locationChange"
@@ -40,10 +46,39 @@
                 :cityCode="task.location.cityCode"
               ></provincecity>
             </el-tab-pane>
-            <el-tab-pane label="广场" name="广场"></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
+            class="upload-demo"
+            action=""
+            :on-remove="handleRemove"
+            :before-remove="beforeRemove"
+            :limit="1"
+            :on-exceed="handleExceed"
+            :before-upload="beforeFileUpload"
+            :http-request="uploadRequireDoc"
+            :file-list="task.doc"
+          >
+            <i class="el-icon-upload"></i>
+            <div class="el-upload__text">
+              将文件拖到此处,或
+              <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">
           <div class="block">
             <el-date-picker
@@ -66,164 +101,261 @@
 </template>
 
 <script>
-import Enum from "@/constants/enum/index";
-import provincecity from "@/components/commons/ProvinceCity";
-import provinceCityJSON from "@/constants/provinceCity.json";
+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'
 export default {
-  name: "Task",
+  name: 'Task',
   components: {
     provincecity
   },
-  data() {
+  data () {
     return {
       projectId: 0,
       institutionArray: Enum.institution,
-      tabPosition: "top",
+      tabPosition: 'top',
+      resourceType: ResourceType,
+      serviceType: ServiceType,
       task: {
-        name: "",
-        desc: "",
-        type: "",
-        resource: "广场", //如果是广场不用管Location和institution ,定向看institution,区域看location
-        location: { provinceCode: "", cityCode: "" },
-        institution: "",
-        datetime: ""
+        name: '',
+        desc: '',
+        type: '',
+        resource: '1', //如果是广场不用管Location和institution ,定向看institution,区域看location
+        location: {provinceCode: '3200', cityCode: '3201'},
+        institution: '',
+        datetime: '',
+        quotePrice: '',
+        fixedPrice: '',
+        doc: [],
+        requireDocUrl: '123.doc'
       },
       pickerOptions: {
         shortcuts: [
           {
-            text: "今天",
-            onClick(picker) {
-              picker.$emit("pick", new Date());
+            text: '今天',
+            onClick (picker) {
+              picker.$emit('pick', new Date())
             }
           },
           {
-            text: "昨天",
-            onClick(picker) {
-              const date = new Date();
-              date.setTime(date.getTime() - 3600 * 1000 * 24);
-              picker.$emit("pick", date);
+            text: '昨天',
+            onClick (picker) {
+              const date = new Date()
+              date.setTime(date.getTime() - 3600 * 1000 * 24)
+              picker.$emit('pick', date)
             }
           },
           {
-            text: "一周前",
-            onClick(picker) {
-              const date = new Date();
-              date.setTime(date.getTime() - 3600 * 1000 * 24 * 7);
-              picker.$emit("pick", date);
+            text: '一周前',
+            onClick (picker) {
+              const date = new Date()
+              date.setTime(date.getTime() - 3600 * 1000 * 24 * 7)
+              picker.$emit('pick', date)
             }
           }
         ]
       },
       rules: {
         name: [
-          { required: true, message: "请输入任务名称", trigger: "blur" }
+          {required: true, message: '请输入任务名称', trigger: 'blur'}
           // { min: 3, max: 5, message: "长度在 3 到 5 个字符", trigger: "blur" }
         ],
         datetime: [
           {
-            type: "date",
+            type: 'date',
             required: true,
-            message: "请选择截止时间",
-            trigger: "change"
+            message: '请选择截止时间',
+            trigger: 'change'
           }
         ],
         type: [
-          { required: true, message: "请选择业务类型", trigger: "change" }
+          {required: true, message: '请选择业务类型', trigger: 'change'}
         ],
-        desc: [{ required: true, message: "请填写任务描述", trigger: "blur" }]
+        desc: [{required: true, message: '请填写任务描述', trigger: 'blur'}],
+        quotePrice: [{required: true, message: '请填写任务报价', trigger: 'blur'}],
+        fixedPrice: [{required: true, message: '请填写任务定价', trigger: 'blur'}]
       }
-    };
+    }
   },
   watch: {
-    "task.institution"() {
+    'task.institution' () {
       if (this.task.institution) {
-        this.$refs.addFormProvince.resetProviceCity();
-        this.task.location = { provinceCode: "", cityCode: "" };
+        this.$refs.addFormProvince.resetProviceCity()
+        this.task.location = {provinceCode: '', cityCode: ''}
       }
     },
-    "task.location"() {
+    'task.location' () {
       if (this.task.location.provinceCode || this.task.location.cityCode) {
-        this.task.institution = "";
+        this.task.institution = ''
       }
     },
-    "task.resource"() {
-      if (this.task.resource == "广场") {
-        this.$refs.addFormProvince.resetProviceCity();
-        this.task.institution = "";
-        this.task.location = { provinceCode: "", cityCode: "" };
+    'task.resource' () {
+      if (this.task.resource == '广场') {
+        this.$refs.addFormProvince.resetProviceCity()
+        this.task.institution = ''
+        this.task.location = {provinceCode: '', cityCode: ''}
       }
     },
     deep: true
   },
-  mounted() {
+  mounted () {
     this.$nextTick(() => {
-      this.init();
-    });
+      this.init()
+    })
   },
   methods: {
-    init() {
-      this.projectId = +this.$route.params.projectId;
+    init () {
+      this.projectId = this.$route.params.projectId
     },
-    updateLocation(location) {
-      var provinceName = "";
-      var cityName = "";
+    updateLocation (location) {
+      var provinceName = ''
+      var cityName = ''
       for (var item of provinceCityJSON.provinces) {
         if (item.code === location.provinceCode) {
-          provinceName = item.name;
+          provinceName = item.name
           for (var city of item.cities) {
             if (city.code === location.cityCode) {
-              cityName = city.name;
-              break;
+              cityName = city.name
+              break
             }
           }
         }
       }
-      return provinceName + " / " + cityName;
+      return provinceName + ' / ' + cityName
     },
-    submitForm(formName) {
-      this.$refs[formName].validate(valid => {
-        if (valid) {
-          console.log(this.task);
-          //提交 task
-        } else {
-          console.log("error submit!!");
-          return false;
-        }
-      });
+    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[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();
-      this.$refs[formName].resetFields();
-      this.task.name = "";
-      this.task.desc = "";
-      this.task.type = "";
-      this.task.resource = "广场"; //如果是广场不用管Location和institution ,定向看institution,区域看location
-      (this.task.location = { provinceCode: "", cityCode: "" }),
-        (this.task.institution = "");
-      this.task.datetime = "";
+    resetForm (formName) {
+      this.$refs.addFormProvince.resetProviceCity()
+      this.$refs[formName].resetFields()
+      this.task.name = ''
+      this.task.desc = ''
+      this.task.type = ''
+      this.task.resource = '广场'; //如果是广场不用管Location和institution ,定向看institution,区域看location
+      (this.task.location = {provinceCode: '', cityCode: ''}),
+        (this.task.institution = '')
+      this.task.datetime = ''
     },
-    locationChange(provinceId, cityId) {
-      if (provinceId || cityId)
-        this.task.location = { provinceCode: provinceId, cityCode: cityId };
+    locationChange (provinceId, cityId) {
+      if (provinceId || cityId) {
+        this.task.location = {provinceCode: provinceId, cityCode: cityId}
+      }
     },
-    cancelCreate() {
+    cancelCreate () {
       if (window.history.length <= 1) {
-        this.$router.push({ path: "/" });
-        return false;
+        this.$router.push({path: '/'})
+        return false
       } else {
-        this.$router.go(-1);
+        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
+    },
+    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) {
+      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)
+      })
+    },
   }
-};
+}
 </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-radio {
+    margin: 10px 20px 10px 0;
+  }
+
+  .el-form-item /deep/ .el-tabs__content {
+    max-height: 120px !important;
+    overflow: auto;
+  }
 </style>

+ 2 - 2
src/constants/enum/index.js

@@ -3,11 +3,11 @@ export default {
         "华东","华北","华中","华南","西南","西北","东北"
     ],
     institution:[
-        "慕测","上软","拓思","4","5","6","7","8","9","10",
+        "1","2","3","4","5","6","7","8","9","10",
         "11","12","13","14","15","16","17","18","19","20",
         "21","22","23","24","25","26","27","28","29","30",
         "31","32","33","34","35","36","37","38","39","40",
         "41","42","43","44","45","46","47","48","49","50",
         "51","52","53","54","55","56","57","58","59","60"
     ]
-}
+}

+ 10 - 0
src/constants/enum/report-type.js

@@ -0,0 +1,10 @@
+let ReportType = {
+  0: "项目可行性报告", //项目可行性报告
+  1: "项目测试方案",    //项目测试方案
+  2: "项目测试报告",   //项目测试报告
+  3: "项目缺陷报告",   //项目缺陷报告
+  4: "项目用例报告",   //项目用例报告
+  5: "其他",   //其他
+}
+
+export default ReportType

+ 7 - 0
src/constants/enum/resource-type.js

@@ -0,0 +1,7 @@
+let ResourceType = {
+  0: "定向",
+  1: "区域",
+  2: "广场",
+}
+
+export default ResourceType

+ 52 - 24
src/constants/index.js

@@ -1,26 +1,54 @@
+import {Notification} from 'element-ui'
+
 export const timeChange = (dateString, formdate) => {
-    if (dateString == null || dateString == '') {
-        return '';
-    }
-    // new Date('');传入毫秒数,也可以得到普通的时间,再对date处理
-    var date = new Date(parseInt(dateString));
-    //获取年份,月份,天数,小时数,分钟数,小于10的显示01-09
-    var year = date.getFullYear();
-    var month = date.getMonth() + 1 < 10 ? "0" + (date.getMonth() + 1) : date.getMonth() + 1;
-    var currentDate = date.getDate() < 10 ? "0" + date.getDate() : date.getDate();
-    var hours = date.getHours() < 10 ? "0" + date.getHours() : date.getHours();
-    var minutes = date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes();
-    if (formdate == null || formdate == "yyyy-mm-dd HH:mm") {
-        return year + "-" + month + "-" + currentDate + " " + hours + ":" + minutes;
-    } else if (formdate == "yyyy-mm-dd") {
-        return year + "-" + month + "-" + currentDate;
-    } else if (formdate == "yyyy-mm") {
-        return year + month;
-    } else if (formdate == "mm-dd") {
-        return month + "-" + currentDate;
-    } else if (formdate == "HH:mm") {
-        return hours + ":" + minutes;
-    } else {
-        return "";
-    }
+  if (dateString == null || dateString == '') {
+    return ''
+  }
+  // new Date('');传入毫秒数,也可以得到普通的时间,再对date处理
+  var date = new Date(parseInt(dateString))
+  //获取年份,月份,天数,小时数,分钟数,小于10的显示01-09
+  var year = date.getFullYear()
+  var month = date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1
+  var currentDate = date.getDate() < 10 ? '0' + date.getDate() : date.getDate()
+  var hours = date.getHours() < 10 ? '0' + date.getHours() : date.getHours()
+  var minutes = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes()
+  if (formdate == null || formdate == 'yyyy-mm-dd HH:mm') {
+    return year + '-' + month + '-' + currentDate + ' ' + hours + ':' + minutes
+  } else if (formdate == 'yyyy-mm-dd') {
+    return year + '-' + month + '-' + currentDate
+  } else if (formdate == 'yyyy-mm') {
+    return year + month
+  } else if (formdate == 'mm-dd') {
+    return month + '-' + currentDate
+  } else if (formdate == 'HH:mm') {
+    return hours + ':' + minutes
+  } else {
+    return ''
+  }
+}
+export const notify = (type, msg, title) => {
+  var title = '消息'
+  switch (type) {
+    case 'success':
+      title = '成功'
+      break
+    case 'warning':
+      title = '提醒'
+      break
+    case 'info':
+      title = '消息'
+      break
+    case 'error':
+      title = '错误'
+      break
+    default:
+      title = '消息'
+      break
+  }
+  return Notification({
+    title: title,
+    message: msg,
+    type: type,
+    duration: 3000
+  })
 }

+ 53 - 0
src/js/api.js

@@ -0,0 +1,53 @@
+export default {
+  PROJECT: {
+    GET_PROJECT: '/api/project/{projectId}/',
+    CREATE_PROJECT: '/api/project/',
+    UPDATE_PROJECT: '/api/project/{projectId}/',
+    DELETE_PROJECT: '/api/project/{projectId}/',
+    ADD_PROJECT: '/api/greenChannel/project/',
+    ADD_PROJECT_BY_EXCEL: '/api/greenChannel/projects',
+  },
+  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}/'
+  },
+  REPORT: {
+    GET_TASK_REPORT: '/api/project/{projectId}/task/{taskId}/report/{reportId}/',
+    GET_PROJECT_REPORT: '/api/project/{projectId}/report/{reportId}/',
+    CREATE_TASK_REPORT: '/api/project/{projectId}/task/{taskId}/report/',
+    CREATE_PROJECT_REPORT: '/api/project/{projectId}/report/',
+    UPDATE_TASK_REPORT: '/api/project/{projectId}/task/{taskId}/report/{reportId}/',
+    UPDATE_PROJECT_REPORT: '/api/project/{projectId}/report/{reportId}/',
+    DELETE_TASK_REPORT: '/api/project/{projectId}/task/{taskId}/report/{reportId}/',
+    DELETE_PROJECT_REPORT: ''
+  },
+  FILE: {
+    REQUIREMENT_FILE: '/api/files/requirementfile/{userId}/',
+    APK: '/api/files/apk/{userId}/',
+    UPLOAD_REPORT_FILE: '/api/files/report/{userId}/',
+    UPLOAD_EXCEL: '',
+    UPLOAD_IMAGE: '/api/files/image/{userId}/',
+  },
+  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_USER_IDENTITY: '',
+  },
+  PAGE: {
+    HOME_PAGE: '/api/common/index/',
+    SQUARE_PAGE: '/api/task/',
+    MY_CROWD_TEST_PAGE: '/api/common/mycrowd/{userId}',
+    TASK_DETAIL_PAGE: '/api/page/taskDetail/{taskId}/',
+    PROJECT_DETAIL_PAGE: '/api/project/{projectId}/',
+    REPORT_DETAIL_PAGE: '/api/page/reportDetail/{reportId}/',
+  }
+}

+ 129 - 0
src/js/http.js

@@ -0,0 +1,129 @@
+import axios from 'axios'
+
+const TIME_OUT_MS = 60 * 1000 // 默认请求超时时间
+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 返回数据列表
+ */
+function handleResults (response) {
+  let remoteResponse = response.data
+  var result = {
+    success: false,
+    message: '',
+    status: [],
+    errorCode: '',
+    data: {
+      total: 0,
+      results: []
+    }
+  }
+  if (remoteResponse.success) {
+    result.data.results = remoteResponse.data
+    result.data.total = remoteResponse.total
+    result.success = true
+  }
+  if (!remoteResponse.success) {
+    let code = remoteResponse.errorCode
+    if (code === 400) {
+      console.log('传参错误')
+    }
+    result.errorCode = remoteResponse.errorCode
+    result.message = remoteResponse.message
+  }
+  return result
+}
+
+function handleUrl (url) {
+  //url = 'http://crowd.mooctest.net' + url
+  return url
+}
+
+/*
+ * @param data 参数列表
+ * @return
+ */
+function handleParams (data) {
+  return JSON.parse(JSON.stringify(data))
+}
+
+export default {
+  post (url, data) {
+    return new Promise((resolve, reject) => {
+      axios.post(url, handleParams(data)).then(
+        (result) => {
+          resolve(result)
+        }
+      ).catch(
+        (error) => {
+          reject(error.response)
+        }
+      )
+    })
+  },
+  get (url) {
+    return new Promise((resolve, reject) => {
+      axios.get(handleUrl(url))
+        .then(response => {
+          resolve(response.data)
+        }).catch(error => {
+        reject(error)
+      })
+
+    })
+
+  },
+  put (url, data) {
+    return new Promise((resolve, reject) => {
+      axios.put(url, JSON.parse(JSON.stringify(data))).then(
+        (result) => {
+          resolve(result)
+        }
+      ).catch(
+        (error) => {
+          reject(error)
+        }
+      )
+    })
+  },
+  delete (url, data) {
+    return new Promise((resolve, reject) => {
+      axios.delete(url, {data: handleParams(data)}).then(
+        (result) => {
+          resolve(result)
+        }
+      ).catch(
+        (error) => {
+          reject(error)
+        }
+      )
+    })
+  },
+  upload (url, data, config) {
+    return new Promise((resolve, reject) => {
+      axios.post(url, data, config).then(
+        (result) => {
+          resolve(result)
+        }
+      ).catch(
+        (error) => {
+          reject(error)
+        }
+      )
+    })
+  },
+}
+

+ 121 - 0
src/js/index.js

@@ -0,0 +1,121 @@
+import Http from './http'
+import Apis from './api'
+
+//存session
+export const storageSave = (key, value) => {
+  sessionStorage.setItem(key, value)
+}
+
+//取session
+export const storageGet = (key) => {
+  return sessionStorage.getItem(key)
+}
+
+//获取用户id
+export const getUserIdentity = () => {
+  return Http.get(Apis.USER.GET_USER_IDENTITY)
+}
+
+//获取用户信息
+export const getCurrentUser = () => {
+  return Http.get(Apis.USER.GET_CURRENT_USER)
+}
+
+//上传文档
+export const uploadFile = () => {
+
+}
+
+//上传图片
+export const uploadImage = () => {
+
+}
+
+//上传图片前检测
+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 ensureEndProject = () => {
+
+}
+
+//创建任务
+export const createTask = () => {
+
+}
+
+//修改任务
+export const updateTask = () => {
+
+}
+
+//查看任务
+export const getTask = () => {
+
+}
+
+//删除任务
+export const udeleteTask = () => {
+
+}
+
+//测评机构申请任务
+export const receiveTaskRequest = () => {
+
+}
+
+//测评机构提出结束任务申请
+export const endTaskRequest = () => {
+
+}
+
+//区域管理员确认结束任务
+
+//创建项目报告
+
+//创建任务报告
+
+//修改项目报告
+
+//修改任务报告
+
+//查看报告
+
+//删除报告

+ 5 - 1
src/main.js

@@ -8,11 +8,12 @@ import './style/main.scss';
 
 
 import {
-  Carousel, CarouselItem, Row, Col, Table, TableColumn, Form, FormItem, Button, ButtonGroup,
+  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,
 } from 'element-ui'
+// require('./mock.js')
 Vue.use(Carousel)
 Vue.use(CarouselItem)
 Vue.use(Row)
@@ -46,6 +47,9 @@ Vue.use(Tabs);
 Vue.use(TabPane);
 Vue.use(Collapse);
 Vue.use(CollapseItem);
+Vue.use(Dialog)
+Vue.use(Card)
+Vue.use(Tag)
 
 Vue.prototype.$msgbox = MessageBox;
 Vue.prototype.$alert = MessageBox.alert;

+ 32 - 0
src/mock.js

@@ -0,0 +1,32 @@
+// 引入mockjs
+const Mock = require('mockjs')
+import Apis from './js/api.js'
+//const Apis = require('./js/api')
+const createAnalyseDemandMock = require('./mock/createAnalyseDemandMock')
+const createProjectMock = require('./mock/createProjectMock')
+const createReportMock = require('./mock/createReportMock')
+const createTaskMock = require('./mock/createTaskMock')
+const getMyCrowdTestMock = require('./mock/getMyCrowdTestMock')
+const getProjectDetailMock = require('./mock/getProjectDetailMock')
+const getReportDetailMock = require('./mock/getReportDetailMock')
+const getTaskDetailMock = require('./mock/getTaskDetailMock')
+const getHomePageMock = require('./mock/getHomePageMock')
+const getSquarePageMock = require('./mock/getSquarePageMock')
+const updateProjectMock = require('./mock/updateProjectMock')
+const updateTaskMock = require('./mock/updateTaskMock')
+const updateReportMock = require('./mock/updateReportMock')
+
+//Mock.mock( url, post/get , 返回的数据);
+Mock.mock(Apis.PROJECT.CREATE_ANALYSE_DEMAND_SUBMIT, 'post', createAnalyseDemandMock.data)
+Mock.mock(Apis.PROJECT.CREATE_PROJECT_SUBMIT, 'post', createProjectMock.data)
+Mock.mock(Apis.REPORT.CREATE_REPORT_SUBMIT, 'post', createReportMock.data)
+Mock.mock(Apis.TASK.CREATE_TASK, 'post', createTaskMock.data)
+Mock.mock(Apis.PAGE.HOME_PAGE, 'get', getHomePageMock.data)
+Mock.mock(Apis.PAGE.SQUARE_PAGE, 'get', getSquarePageMock.data)
+Mock.mock(Apis.PAGE.PROJECT_DETAIL_PAGE, 'get', getProjectDetailMock.data)
+Mock.mock(Apis.PAGE.REPORT_DETAIL_PAGE, 'get', getReportDetailMock.data)
+Mock.mock('/api/project/pro1564487183259/task/pro1564487183259_task1564487274060/', 'get', getTaskDetailMock.data)
+Mock.mock(Apis.PAGE.MY_CROWD_TEST_PAGE, 'get', getMyCrowdTestMock.data)
+Mock.mock(Apis.PROJECT.UPDATE_PROJECT_SUBMIT, 'put', updateProjectMock.data)
+Mock.mock(Apis.REPORT.UPDATE_REPORT_SUBMIT, 'put', updateReportMock.data)
+Mock.mock(Apis.TASK.UPDATE_TASK_SUBMIT, 'put', updateTaskMock.data)

+ 6 - 0
src/mock/createAnalyseDemandMock.js

@@ -0,0 +1,6 @@
+var Mock = require('mockjs')
+var data = Mock.mock(null)
+
+export {
+  data
+}

+ 6 - 0
src/mock/createProjectMock.js

@@ -0,0 +1,6 @@
+var Mock = require('mockjs')
+var data = Mock.mock(null)
+
+export {
+  data
+}

+ 6 - 0
src/mock/createReportMock.js

@@ -0,0 +1,6 @@
+var Mock = require('mockjs')
+var data = Mock.mock(null)
+
+export {
+  data
+}

+ 6 - 0
src/mock/createTaskMock.js

@@ -0,0 +1,6 @@
+var Mock = require('mockjs')
+var data = Mock.mock(null)
+
+export {
+  data
+}

+ 96 - 0
src/mock/getHomePageMock.js

@@ -0,0 +1,96 @@
+var Mock = require('mockjs')
+var data = Mock.mock({
+  hotTaskList: [
+    {
+      id: 0,
+      title: '发送群文件测试',
+      description: '任务描述文字xxxx',
+      price: '30',
+      serviceType: 1,
+      status: 0,
+      projectId: 123
+    },
+    {
+      id: 1,
+      title: '多人聊天发送文件测试',
+      description: '任务描述文字xxxx',
+      price: '10',
+      serviceType: 0,
+      status: 1,
+      projectId: 234
+    },
+    {
+      id: 2,
+      title: '浏览器波洞星球',
+      description: '任务描述文字xxxx',
+      price: '10',
+      serviceType: 2,
+      status: 0,
+      projectId: 345
+    },
+    {
+      id: 3,
+      title: '举报支持选择聊天记录(安全)',
+      description: '任务描述文字xxxx',
+      price: '0',
+      serviceType: 1,
+      status: 1,
+      projectId: 456
+    }
+  ],
+  institutionRank: [
+    {
+      logo: 'http://www.mooctest.net/assets/img/mooctest.png',
+      name: '慕测科技'
+    },
+    {
+      logo: 'https://docs.alibabagroup.com/assets2/images/cn/global/logo_header.png',
+      name: '上海软件'
+    },
+    {
+      logo: 'http://www.mooctest.net/assets/img/mooctest.png',
+      name: 'QQ众测'
+    },
+    {
+      logo: 'https://docs.alibabagroup.com/assets2/images/cn/global/logo_header.png',
+      name: '阿里巴巴'
+    },
+    {
+      logo: 'https://docs.alibabagroup.com/assets2/images/cn/global/logo_header.png',
+      name: '阿里巴巴'
+    }
+  ],
+  personRank: [
+    {
+      logo: 'http://www.mooctest.net/assets/img/mooctest.png',
+      name: '小王',
+      number: '200',
+    },
+    {
+      logo: 'https://docs.alibabagroup.com/assets2/images/cn/global/logo_header.png',
+      name: '小黄',
+      number: '190',
+    },
+    {
+      logo: 'http://www.mooctest.net/assets/img/mooctest.png',
+      name: '小莉',
+      number: '120',
+    },
+    {
+      logo: 'https://docs.alibabagroup.com/assets2/images/cn/global/logo_header.png',
+      name: '小张',
+      number: '80',
+    },
+    {
+      logo: 'https://docs.alibabagroup.com/assets2/images/cn/global/logo_header.png',
+      name: '小张',
+      number: '70',
+    }
+  ],
+  imgList: ['../assets/img/home_ban1.jpg', '../assets/img/home_ban2.jpg'],
+
+})
+
+export {
+  data
+}

+ 139 - 0
src/mock/getMyCrowdTestMock.js

@@ -0,0 +1,139 @@
+var Mock = require('mockjs')
+var data = Mock.mock({
+  unFinishedTaskList: [
+    {
+      id: 0,
+      coverImgUrl: 'http://www.mooctest.net/assets/img/mooctest.png',
+      projectId: 1123,
+      title: '发送群文件测试',
+      platform: [0, 1],
+      description: '任务描述文字xxxx',
+      price: '30',
+      serviceType: 1,
+      participantNum: 30,
+      status: 0
+    },
+    {
+      id: 1,
+      coverImgUrl: 'http://www.mooctest.net/assets/img/mooctest.png',
+      projectId: 1123,
+      title: '多人聊天发送文件测试',
+      platform: [0],
+      description: '任务描述文字xxxx',
+      price: '10',
+      serviceType: 0,
+      participantNum: 0,
+      status: 1
+    },
+    {
+      id: 2,
+      coverImgUrl: 'http://www.mooctest.net/assets/img/mooctest.png',
+      projectId: 1123,
+      title: '浏览器波洞星球',
+      platform: [1],
+      description: '任务描述文字xxxx',
+      price: '10',
+      serviceType: 2,
+      participantNum: 21,
+      status: 0
+    },
+    {
+      id: 3,
+      coverImgUrl: 'http://www.mooctest.net/assets/img/mooctest.png',
+      projectId: 1123,
+      title: '举报支持选择聊天记录(安全)',
+      platform: [0, 1, 2],
+      description: '任务描述文字xxxx',
+      price: '0',
+      serviceType: 1,
+      participantNum: 1,
+      status: 1
+    },
+  ],
+  finishedTaskList: [
+    {
+      id: 0,
+      coverImgUrl: 'http://www.mooctest.net/assets/img/mooctest.png',
+      projectId: 1123,
+      title: '发送群文件测试',
+      platform: [0, 1],
+      description: '任务描述文字xxxx',
+      price: '30',
+      serviceType: 1,
+      participantNum: 30,
+      status: 0
+    },
+    {
+      id: 1,
+      coverImgUrl: 'http://www.mooctest.net/assets/img/mooctest.png',
+      projectId: 1123,
+      title: '多人聊天发送文件测试',
+      platform: [0],
+      description: '任务描述文字xxxx',
+      price: '10',
+      serviceType: 0,
+      participantNum: 0,
+      status: 1
+    },
+    {
+      id: 2,
+      coverImgUrl: 'http://www.mooctest.net/assets/img/mooctest.png',
+      projectId: 1123,
+      title: '浏览器波洞星球',
+      platform: [1],
+      description: '任务描述文字xxxx',
+      price: '10',
+      serviceType: 2,
+      participantNum: 21,
+      status: 0
+    },
+    {
+      id: 3,
+      coverImgUrl: 'http://www.mooctest.net/assets/img/mooctest.png',
+      projectId: 1123,
+      title: '举报支持选择聊天记录(安全)',
+      platform: [0, 1, 2],
+      description: '任务描述文字xxxx',
+      price: '0',
+      serviceType: 1,
+      participantNum: 1,
+      status: 1
+    },
+  ],
+  appliedProjectList: [
+    {
+      id: 1,
+      code: '27382hdsjkfdskfK',
+      name: '多人聊天发送文件测试',
+      platform: [0],
+      description: '任务描述文字xxxx',
+      price: '10'
+    },
+    {
+      id: 2,
+      code: 'jzlk9dfsndfsmd ',
+      name: '多人聊天发送文件测试',
+      platform: [0, 1],
+      description: '任务描述文字xxxx',
+      price: '90'
+    },
+    {
+      id: 3,
+      code: '437849sdbsjbsf',
+      name: '多人聊天发送文件测试',
+      platform: [1, 2],
+      description: '任务描述文字xxxx',
+      price: '50'
+    }
+  ],
+  user: {
+    id: 123,
+    name: '李三',
+    score: 100,
+    prestige: 100,
+  }
+})
+
+export {
+  data
+}

+ 57 - 0
src/mock/getProjectDetailMock.js

@@ -0,0 +1,57 @@
+var Mock = require('mockjs')
+var data = Mock.mock({
+  'projectDetails': {
+    'id': 'PROJECT_1',
+    'name': '慕测平台',
+    'contactName': '郭超超',
+    'contactPhone': '18032653383',
+    'type': '1',
+    'platform': 'ceshi',
+    'desc': 'ceshi',
+    'doc': 'ceshi',
+    'file': 'cehsi',
+    'resource': 1,
+    'location': {
+      'provinceCode': '100',
+      'cityCode': '2333'
+    },
+    'institution': 6,
+    'datetime': '2019-07-29T20:54:23.000+0000',
+    'price': 20.0,
+    'budget': 20.0,
+    'usage': null
+  },
+  'taskList': [
+    {
+      'id': 1,
+      'name': '慕测平台-任务一',
+      'crowdTestProjectId': null,
+      'evaluationAgencyId': 1,
+      'type': '0',
+      'description': null,
+      'requirementFile': null,
+      'quotedPrice': 10.0,
+      'fixedPrice': null,
+      'status': 'HAS_CREATED',
+      'createTime': '2019-07-29T21:08:54.000+0000'
+    },
+    {
+      'id': 2,
+      'name': '慕测平台-任务二',
+      'crowdTestProjectId': null,
+      'evaluationAgencyId': 2,
+      'type': '0',
+      'description': null,
+      'requirementFile': null,
+      'quotedPrice': 10.0,
+      'fixedPrice': null,
+      'status': 'HAS_CREATED',
+      'createTime': '2019-07-29T21:08:56.000+0000'
+    }
+  ],
+  'reportList': null
+})
+
+export {
+  data
+}

+ 27 - 0
src/mock/getReportDetailMock.js

@@ -0,0 +1,27 @@
+var Mock = require('mockjs')
+var data = Mock.mock({
+  'report': {
+    'name': '测试报告1',
+    //报告摘要
+    'abstract': {
+      //测试对象
+      'target': 'aaaaaaaaaa',
+      //测试内容
+      'content': 'aaaaaaaaaaa'
+    },
+    'file': [{'name': 'report5', 'url': 'report5.excel'}],
+    // 0: "接口测试",
+    // 1: "安全漏洞扫描",
+    // 2: "风险评估服务",
+    // 3: "源代码安全审计服务",
+    // 4: "功能测试服务",
+    // 5: "性能测试",
+    // 6: "功能和易用性测试",
+    'type': '0',
+    'conclusion': 'app挺好'
+  }
+})
+
+export {
+  data
+}

+ 100 - 0
src/mock/getSquarePageMock.js

@@ -0,0 +1,100 @@
+var Mock = require('mockjs')
+var data = Mock.mock({
+  'taskList': [
+    {
+      //任务id
+      'id': 0,
+      //任务封面图
+      'coverImgUrl': '',
+      //所属项目id
+      'projectId': 1234,
+      //任务标题
+      'title': '发送群文件测试',
+      //任务平台;0:Andriod;1:IOS;2:Web
+      'platform': [0, 1],
+      //任务描述
+      'description': '任务描述文字xxxx',
+      //任务标价
+      'price': '30',
+      //任务服务类型
+      // 0: "接口测试",
+      // 1: "安全漏洞扫描",
+      // 2: "风险评估服务",
+      // 3: "源代码安全审计服务",
+      // 4: "功能测试服务",
+      // 5: "性能测试",
+      // 6: "功能和易用性测试",
+      'serviceType': 1,
+      //任务参与者
+      'participantNum': 30,
+      // 0: "已结束", //已结束
+      // 1: "进行中" //进行中
+      //任务状态
+      'status': 0
+    },
+    {
+      'id': 1,
+      'coverImgUrl': '',
+      'projectId': 1234,
+      'title': '多人聊天发送文件测试',
+      'platform': [0],
+      'description': '任务描述文字xxxx',
+      'price': '10',
+      'serviceType': 0,
+      'participantNum': 0,
+      'status': 1
+    },
+    {
+      'id': 1,
+      'coverImgUrl': '',
+      'projectId': 1234,
+      'title': '多人聊天发送文件测试',
+      'platform': [0],
+      'description': '任务描述文字xxxx',
+      'price': '10',
+      'serviceType': 0,
+      'participantNum': 0,
+      'status': 1
+    },
+    {
+      'id': 1,
+      'coverImgUrl': '',
+      'projectId': 1234,
+      'title': '多人聊天发送文件测试',
+      'platform': [0],
+      'description': '任务描述文字xxxx',
+      'price': '10',
+      'serviceType': 0,
+      'participantNum': 0,
+      'status': 1
+    },
+    {
+      'id': 1,
+      'coverImgUrl': '',
+      'projectId': 1234,
+      'title': '多人聊天发送文件测试',
+      'platform': [0],
+      'description': '任务描述文字xxxx',
+      'price': '10',
+      'serviceType': 0,
+      'participantNum': 0,
+      'status': 1
+    },
+    {
+      'id': 1,
+      'coverImgUrl': '',
+      'projectId': 1234,
+      'title': '多人聊天发送文件测试',
+      'platform': [0],
+      'description': '任务描述文字xxxx',
+      'price': '10',
+      'serviceType': 0,
+      'participantNum': 0,
+      'status': 1
+    }
+  ]
+})
+
+export {
+  data
+}

+ 84 - 0
src/mock/getTaskDetailMock.js

@@ -0,0 +1,84 @@
+var Mock = require('mockjs')
+var data = Mock.mock({
+  //任务信息
+  'crowdTaskVO': {
+    //任务id
+    'id': 1,
+    //任务所属项目id
+    'projectId': 234,
+    //任务标题
+    'title': '多人聊天发送文件测试',
+    //任务描述
+    'description': '任务描述文字xxxx',
+    'budget':0,
+    //任务定价
+    'price': 10,
+    //项目发布类型:定向或非定向
+    // 0: "定向",
+    // 1: "区域",
+    // 2: "广场",
+    'resource': '1',
+    //当任务发布类型为0或2时,location字段无效;发布类型为1时,location字段表示接收任务的区域
+    'location': {'provinceCode': '3200', 'cityCode': '3201'},
+    //当任务发布类型为1或2时,institution字段无效;发布类型为0时,institution字段表示接收任务的区域
+    'institution': '',
+    //任务服务类型
+    // 0: "接口测试",
+    // 1: "安全漏洞扫描",
+    // 2: "风险评估服务",
+    // 3: "源代码安全审计服务",
+    // 4: "功能测试服务",
+    // 5: "性能测试",
+    // 6: "功能和易用性测试",
+    'serviceType': 0,
+    /*任务状态
+              0: "已结束",
+              1: "进行中"
+              */
+    'status': 1,
+    //任务截止时间Date()类型
+    //new Date("2018-11-11 23:11:11")
+    'datetime': 'Sun Nov 11 2018 23:11:11 GMT+0800 (中国标准时间)'
+  },
+  // 任务报告列表
+  'crowdReportVOList': [
+    {
+      //报告id
+      'id': 2,
+      //报告类型
+      // 0: "接口测试",
+      // 1: "安全漏洞扫描",
+      // 2: "风险评估服务",
+      // 3: "源代码安全审计服务",
+      // 4: "功能测试服务",
+      // 5: "性能测试",
+      // 6: "功能和易用性测试",
+      'type': 1,
+      'file': [{
+        //报告文件名
+        'name': 'report2',
+        //报告文件url
+        'url': 'report2.excel'
+      }]
+    },
+    {
+      'id': 3,
+      // 0: "接口测试",
+      // 1: "安全漏洞扫描",
+      // 2: "风险评估服务",
+      // 3: "源代码安全审计服务",
+      // 4: "功能测试服务",
+      // 5: "性能测试",
+      // 6: "功能和易用性测试",
+      'type': 2,
+      'file': [{
+        'name': 'report3',
+        'url': 'report3.excel'
+      }]
+    }
+  ]
+})
+
+export {
+  data
+}

+ 10 - 0
src/mock/test.js

@@ -0,0 +1,10 @@
+var Mock = require('mockjs')
+var data = Mock.mock({
+  'list|1-10': [{
+    'id|+1': 1
+  }]
+})
+
+export {
+  data
+};

+ 6 - 0
src/mock/updateProjectMock.js

@@ -0,0 +1,6 @@
+var Mock = require('mockjs')
+var data = Mock.mock(null)
+
+export {
+  data
+}

+ 6 - 0
src/mock/updateReportMock.js

@@ -0,0 +1,6 @@
+var Mock = require('mockjs')
+var data = Mock.mock(null)
+
+export {
+  data
+}

+ 6 - 0
src/mock/updateTaskMock.js

@@ -0,0 +1,6 @@
+var Mock = require('mockjs')
+var data = Mock.mock(null)
+
+export {
+  data
+}

+ 29 - 13
src/router/index.js

@@ -13,8 +13,9 @@ 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)
 
@@ -28,52 +29,67 @@ export default new Router({
     {
       path: '/home',
       name: 'Home',
-      component: Home
+      component: resolve => require(['@/components/Home.vue'], resolve),
     },
     {
       path: '/square',
       name: 'Square',
-      component: Square
+      component: resolve => require(['@/components/Square.vue'], resolve),
     },
     {
       path: '/mine',
       name: 'Mine',
-      component: Mine
+      component: resolve => require(['@/components/Mine.vue'], resolve),
     },
     {
       path: '/project/create',
       name: 'ProjectCreate',
-      component: ProjectCreate
+      component: resolve => require(['@/components/project/ProjectCreate.vue'], resolve),
     },
     {
       path: '/project/:projectId',
       name: 'Project',
-      component: Project
+      component: resolve => require(['@/components/project/Project.vue'], resolve),
     },
     {
       path: '/project/:projectId/task/create',
       name: 'TaskCreate',
-      component: TaskCreate
+      component: resolve => require(['@/components/task/TaskCreate.vue'], resolve),
     },
     {
       path: '/project/:projectId/task/:taskId',
       name: 'Task',
-      component: Task
+      component: resolve => require(['@/components/task/Task.vue'], resolve),
     },
     {
       path: '/project/:projectId/analyse',
       name: 'AnalyseDemand',
-      component: AnalyseDemand
+      component: resolve => require(['@/components/project/AnalyseDemand.vue'], resolve),
     },
     {
       path: '/report/create',
       name: 'ReportCreate',
-      component: ReportCreate
+      component: resolve => require(['@/components/report/ReportCreate.vue'], resolve),
     },
     {
       path: '/report/:reportId',
       name: 'Report',
-      component: Report
-    }
+      component: resolve => require(['@/components/report/Report.vue'], resolve),
+    },
+    {
+      path: '/addProject',
+      name: 'ProjectAdd',
+      component: resolve => require(['@/components/cheat/ProjectAdd.vue'], resolve),
+    },
+    {
+      path: '/addAgency',
+      name: 'AgencyAdd',
+      component: resolve => require(['@/components/cheat/AgencyAdd.vue'], resolve),
+    },
+    {
+      path: '/authentication',
+      name: 'Authentication',
+      component: resolve => require(['@/components/authen/Authentication.vue'], resolve),
+    },
   ]
 })

+ 21 - 0
src/store/index.js

@@ -0,0 +1,21 @@
+import Vue from 'vue'
+import Vuex from 'vuex'
+
+Vue.use(Vuex)
+
+const store = new Vuex.Store({
+  state: {
+    isLogin:false
+  },
+  mutations:{
+
+  },
+  actions:{
+
+  },
+  modules:{
+
+  }
+})
+
+export default store

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 3 - 3
src/style/main.scss


Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio