Task.vue 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068
  1. <template>
  2. <div class="create-container" v-loading="loading">
  3. <div class="title h1" v-if="!isModifyMode">任务</div>
  4. <div class="create-body">
  5. <div class="title h2" v-if="!isModifyMode">基本信息</div>
  6. <el-row :gutter="20">
  7. <el-col :span="15">
  8. <el-form :model="task" :rules="rules" ref="task" label-width="120px" class="demo-task"
  9. style="margin:0 0 0 80px;">
  10. <el-form-item label="任务名称" prop="title" style="width: 700px;">
  11. <el-input size="small" v-if="isModifyMode" v-model="task.title"></el-input>
  12. <span v-if="!isModifyMode">{{ task.title }}</span>
  13. <el-tag v-if="!isModifyMode" :type="task.statusVO&&task.statusVO.style">{{
  14. task.statusVO ?
  15. task.statusVO.text : ''
  16. }}
  17. </el-tag>
  18. </el-form-item>
  19. <el-form-item label="任务描述" prop="description" style="width: 700px;">
  20. <el-input autosize v-if="isModifyMode" type="textarea" v-model="task.description"></el-input>
  21. <span v-if="!isModifyMode">{{ task.description ? task.description : '暂无' }}</span>
  22. </el-form-item>
  23. <el-form-item label="任务报价" prop="quotePrice" style="width: 700px;">
  24. <el-input size="small" type="number" v-if="isModifyMode" v-model="task.quotePrice">
  25. <template slot="append">¥</template>
  26. </el-input>
  27. <span v-if="!isModifyMode">¥{{ task.quotePrice }}</span>
  28. </el-form-item>
  29. <!--<el-form-item type="number" label="任务定价" prop="fixedPrice">-->
  30. <!--<el-input v-if="isModifyMode" v-model="task.fixedPrice">-->
  31. <!--<template slot="append">¥</template>-->
  32. <!--</el-input>-->
  33. <!--<span v-if="!isModifyMode">{{task.fixedPrice}}</span>-->
  34. <!--</el-form-item>-->
  35. <el-form-item label="测试类型" prop="serviceType">
  36. <el-radio-group v-if="isModifyMode" v-model="task.serviceType" @change="handleTestTypeChange">
  37. <span v-for="(item,index) in serviceType" :key="index">
  38. <el-radio :label="item.name" name="serviceType">{{ item.name }}</el-radio>
  39. </span>
  40. </el-radio-group>
  41. <span class="badge" v-if="!isModifyMode">{{ task.serviceType }}</span>
  42. </el-form-item>
  43. <el-form-item label="服务序列号" prop="endPoint" style="width: 700px;"
  44. v-if="showBD&&task.endPoint&&currType.type===1"
  45. >
  46. <el-input v-if="isModifyMode" v-model="task.endPoint.serverCode" label="examId"></el-input>
  47. <span v-if="!isModifyMode&&showBD">{{ task.endPoint.serverCode }}</span>
  48. </el-form-item>
  49. <el-form-item label="任务可见性" prop="resource" style="width: 700px;">
  50. <div v-if="!isModifyMode">
  51. <!--<div v-if="task.resource=='1'">{{updateLocation(task.location)}}</div>-->
  52. <div v-if="task.resource==0">定向</div>
  53. <div v-if="task.resource==2">{{ resourceType[task.resource] }}</div>
  54. </div>
  55. <el-tabs
  56. :tab-position="tabPosition"
  57. v-model="task.resource"
  58. style="max-height: 200px;"
  59. v-if="isModifyMode"
  60. >
  61. <el-tab-pane :label="resourceType[0]" name="0">
  62. <el-radio-group v-model="task.institution" @change="handleTestTypeChange">
  63. <el-radio v-for="(item,index) in institutionArray" :label="item.userId" name="type" :key="index">
  64. {{item.name}}
  65. </el-radio>
  66. </el-radio-group>
  67. </el-tab-pane>
  68. <!--<el-tab-pane :label="resourceType[1]" name="1">-->
  69. <!--<provincecity-->
  70. <!--ref="addFormProvince"-->
  71. <!--@selectChange="locationChange"-->
  72. <!--:provinceCode="task.location == null ||task.location.provinceCode==null?'3200':task.location.provinceCode"-->
  73. <!--:cityCode="task.location == null ||task.location.cityCode==null?'3201':task.location.cityCode"-->
  74. <!--&gt;</provincecity>-->
  75. <!--</el-tab-pane>-->
  76. <el-tab-pane :label="resourceType[2]" name="2"></el-tab-pane>
  77. </el-tabs>
  78. </el-form-item>
  79. <el-form-item v-if="!isModifyMode && task.resource==0 && showBD" label="接包人员/机构" prop="agencyName" style="width: 700px;">
  80. <span>{{task.agencyName}}</span>
  81. </el-form-item>
  82. <el-form-item label="领取人数" prop="contactPhone" v-if="isModifyMode&&task.resource !== '0' && currType.type===0">
  83. <el-input-number v-model="task.participantCount" :min="1" :max="1000" label="领取人数"></el-input-number>
  84. </el-form-item>
  85. <el-form-item label="领取人数" prop="contactPhone"
  86. v-if="isModifyMode&&task.resource !== '0' && currType.type===1">
  87. <el-input-number v-model="task.participantCount" :min="2" :max="1000" label="领取人数"></el-input-number>
  88. </el-form-item>
  89. <el-form-item label="领取人数" prop="quotePrice" v-if="!isModifyMode">
  90. {{ task.acceptedCount }}/{{ task.participantCount }}
  91. </el-form-item>
  92. <el-form-item label="需求文档" prop="doc">
  93. <el-upload
  94. style="width: 400px"
  95. v-if="isModifyMode"
  96. drag
  97. class="upload-demo"
  98. action=""
  99. :on-remove="handleRemove"
  100. :before-remove="beforeRemove"
  101. :limit="1"
  102. :on-exceed="handleExceed"
  103. :http-request="uploadRequireDoc"
  104. :file-list="task.doc"
  105. >
  106. <i class="el-icon-upload"></i>
  107. <div class="el-upload__text">
  108. 将文件拖到此处,或
  109. <em>点击上传</em>
  110. </div>
  111. </el-upload>
  112. <span>
  113. <span v-if="task.requireDocUrl == null || task.requireDocUrl == ''">
  114. <i class="el-icon-document"></i>暂无文件
  115. </span>
  116. <span v-if="task.requireDocUrl != null && task.requireDocUrl != ''">
  117. <a :href="task.requireDocUrl"><el-link :underline="false" type="primary"><i
  118. class="el-icon-document"></i>下载文档</el-link></a>
  119. </span>
  120. </span>
  121. </el-form-item>
  122. <el-form-item v-if="!isModifyMode && task.resource==0 && needAcceptedPWD && showBD" label="任务接收码" prop="agencyName" style="width: 700px;">
  123. <span>{{task.acceptedPassword}}</span>
  124. </el-form-item>
  125. <el-form-item label="任务截止时间" prop="datetime">
  126. <div class="block" v-if="isModifyMode">
  127. <el-date-picker
  128. size="small"
  129. v-model="task.datetime"
  130. type="datetime"
  131. placeholder="选择截止时间"
  132. align="right"
  133. :picker-options="pickerOptions"
  134. ></el-date-picker>
  135. </div>
  136. <span v-if="!isModifyMode">{{ dateFormat(new Date(task.datetime), 'yyyy-MM-dd HH:mm:ss') }}</span>
  137. </el-form-item>
  138. <el-form-item v-if="isModifyMode">
  139. <div class="btn btn-small btn-info" @click="updateTask()">确认修改</div>
  140. <!--<div class="btn btn-small" @click="resetForm()">重置</div>-->
  141. <div class="btn btn-small" @click="cancelMode()">取消</div>
  142. </el-form-item>
  143. <el-form-item v-if="editShortLink && task.endPoint.serverCode && taskOperationControl.confirmFinish"
  144. label="任务面板链接" props="shortLink">
  145. <el-input v-model="shortLink" placeholder="请输入短链接生成任务报告" style="width: 800px">
  146. <template slot="append">
  147. <el-button @click="getTaskDataBoard()">确定</el-button>
  148. </template>
  149. </el-input>
  150. </el-form-item>
  151. <el-form-item v-if="shortLink && !editShortLink" label="任务面板链接" props="shortLink">
  152. {{ shortLink }}
  153. <i class="el-icon-edit" @click="editShortLink = true" v-if="taskOperationControl.confirmFinish"/>
  154. </el-form-item>
  155. <el-form-item v-if="!isModifyMode">
  156. <el-button size="mini" @click="toProject()">项目详情</el-button>
  157. <el-popover
  158. placement="top-start"
  159. title="确认拒绝?"
  160. width="200"
  161. trigger="hover"
  162. content="拒绝后不可再接收此任务,且该任务对您不可见">
  163. <el-button v-if="taskOperationControl.reject" type="danger" size="mini" slot="reference"
  164. @click="rejectTask()">拒绝任务
  165. </el-button>
  166. </el-popover>
  167. <el-popover
  168. placement="top-start"
  169. title="确认接收?"
  170. width="200"
  171. trigger="hover"
  172. content="接收任务后请认真完成!">
  173. <el-button v-if="taskOperationControl.receive" type="primary" size="mini" slot="reference"
  174. @click="showTaskCodeModal = !showTaskCodeModal">接收任务
  175. </el-button>
  176. </el-popover>
  177. <el-button v-if="taskOperationControl.writeReport" type="primary" size="mini" @click="gotoWriteReport()">
  178. 填写报告
  179. </el-button>
  180. <el-button v-if="taskOperationControl.update" type="primary" size="mini" @click="modifyForm()">修改任务
  181. </el-button>
  182. <el-button v-if="featureTaskRecommend && taskOperationControl.taskRecommend" type="primary" size="mini"
  183. @click="recommendTask()">任务推荐
  184. </el-button>
  185. <el-button v-if="taskOperationControl.exportTask" type="primary" size="mini" @click="toExportTask()">导出任务</el-button>
  186. <el-button v-if="taskOperationControl.uploadReport" type="primary" size="mini" @click="toCreateReport()">
  187. 上传报告
  188. </el-button>
  189. <el-button v-if="taskOperationControl.taskDemonstrate" type="success" size="mini"
  190. @click="gotoDataboard()">
  191. 任务面板
  192. </el-button>
  193. <el-button v-if="taskOperationControl.forkTask" type="primary" size="mini"
  194. @click="showTaskForkModal = !showTaskForkModal">
  195. fork任务
  196. </el-button>
  197. <el-popover
  198. placement="top-start"
  199. title="确认提交?"
  200. width="200"
  201. trigger="hover"
  202. content="提交任务后不可更改,等待区域管理员验收">
  203. <el-button v-if="taskOperationControl.finish" type="primary" size="mini" slot="reference"
  204. @click="submitTaskRequest()">提交任务
  205. </el-button>
  206. </el-popover>
  207. <el-popover
  208. placement="top-start"
  209. title="确认结束?"
  210. width="200"
  211. trigger="hover"
  212. content="测评机构已提交结束申请,请确认是否结束该任务">
  213. <el-button v-if="taskOperationControl.confirmFinish" type="success" size="mini" slot="reference"
  214. @click="endTask()">确认结束
  215. </el-button>
  216. </el-popover>
  217. </el-form-item>
  218. </el-form>
  219. </el-col>
  220. <el-col :span="9">
  221. <TaskCloud :info="wordCloud" v-if="wordCloud.length"></TaskCloud>
  222. </el-col>
  223. </el-row>
  224. </div>
  225. <div class="create-body" v-if="!isModifyMode">
  226. <div class="title h2">用户报告列表</div>
  227. <el-collapse accordion style="margin: 0 30px">
  228. <el-collapse-item v-for="(item,index) in acceptedUserList" :key="item.id">
  229. <template slot="title">
  230. <el-row style="width: 100%;font-size: 16px">
  231. <el-col :span="6">{{ item.userVO.userName }}</el-col>
  232. <el-col :span="6">{{ item.userVO.email }}</el-col>
  233. <el-col :span="6">
  234. <el-tag type="success" v-if="item.crowdReportVOS">已提交报告</el-tag>
  235. <el-tag type="info" v-if="!item.crowdReportVOS">未提交报告</el-tag>
  236. </el-col>
  237. <el-col :span="6">
  238. <el-tag type="success" v-if="item.isCommitted">已提交任务</el-tag>
  239. <el-tag type="info" v-if="!item.isCommitted">未提交任务</el-tag>
  240. </el-col>
  241. </el-row>
  242. </template>
  243. <report-list v-bind:reports="item.crowdReportVOS" v-bind:taskId="taskId" v-bind:projectId="projectId"/>
  244. </el-collapse-item>
  245. </el-collapse>
  246. <!-- <report-list v-if="isAgency" v-bind:reports="reportList" v-bind:taskId="taskId" v-bind:projectId="projectId"/>-->
  247. <!-- <report-list v-bind:reports="reportList" v-bind:taskId="taskId" v-bind:projectId="projectId"/>-->
  248. </div>
  249. <el-dialog title="请输入任务接收码" :visible.sync="showTaskCodeModal">
  250. <el-input v-model="taskValidCode" autocomplete="off" placeholder="请输入任务接收码"></el-input>
  251. <div slot="footer" class="dialog-footer">
  252. <el-button @click="showTaskCodeModal = false;taskValidCode = ''">取 消</el-button>
  253. <el-button type="primary" @click="handleTaskCodeValid()">确 定</el-button>
  254. </div>
  255. </el-dialog>
  256. <el-dialog title="Fork任务?" :visible.sync="showTaskForkModal">
  257. <div>确定基于该任务Fork新任务?</div>
  258. <div slot="footer" class="dialog-footer">
  259. <el-button @click="showTaskForkModal = false;">取 消</el-button>
  260. <el-button type="primary" @click="handleForkTask()">确 定</el-button>
  261. </div>
  262. </el-dialog>
  263. </div>
  264. </template>
  265. <script>
  266. import ResourceType from '@/constants/enum/resource-type.js'
  267. import provincecity from '@/components/commons/ProvinceCity'
  268. import ReportList from '@/components/report/ReportList'
  269. import TaskCloud from '@/components/task/TaskCloud'
  270. import Http from '@/js/http.js'
  271. import Apis from '@/js/api.js'
  272. import {CONFIG} from "../../config";
  273. import {notify} from '@/constants/index'
  274. import {
  275. ensureEndTask,
  276. exportTask,
  277. getAllAgencies,
  278. getAllAgencyAndTestUser,
  279. getAllServiceTypes,
  280. getFormalTimeFromDate,
  281. getProvinceCodeByProvinceName,
  282. getProvinceNameByProvinceCode,
  283. getTask,
  284. receiveTaskRequest,
  285. rejectTask,
  286. storageGet,
  287. submitTaskRequest,
  288. updateTask,
  289. getTaskWordCloud,
  290. getTaskWordCloudByDescription
  291. } from '@/js/index'
  292. import {AxiosInstance as axios} from "axios";
  293. export default {
  294. name: 'Task',
  295. components: {
  296. provincecity,
  297. ReportList,
  298. TaskCloud
  299. },
  300. data() {
  301. return {
  302. showTaskCodeModal: false,
  303. showTaskForkModal: false,
  304. taskValidCode:'',
  305. featureTaskRecommend: CONFIG.feature_task_recommend,
  306. taskRecommendUrl: CONFIG.task_recommend_url,
  307. needAcceptedPWD: CONFIG.feature_task_acceptedPWD,
  308. currType: {},
  309. user: {},
  310. serviceName: '',
  311. showBD: true,
  312. rolesPermissions: {},
  313. loading: false,
  314. isModifyMode: false,
  315. institutionArray: [],
  316. tabPosition: 'top',
  317. resourceType: ResourceType,
  318. serviceType: [],
  319. taskId: '',
  320. projectId: '',
  321. taskOperationControl: {
  322. confirmFinish: false,
  323. finish: false,
  324. receive: false,
  325. update: false,
  326. uploadReport: false,
  327. writeReport: false,
  328. taskDemonstrate: false,
  329. taskRecommend: false,
  330. exportTask: false,
  331. forkTask: false,
  332. },
  333. crowdReportUrl: '',
  334. exportTaskUrl: '',
  335. wordCloud: [],
  336. task: {
  337. agencyId: '',
  338. agencyName: '',
  339. acceptedPassword: '',
  340. status: '',
  341. name: '',
  342. desc: '',
  343. serviceType: '',
  344. resource: '',
  345. location: {},
  346. institution: 0,
  347. datetime: '',
  348. quotePrice: '',
  349. fixedPrice: '',
  350. doc: [],
  351. requireDocUrl: '',
  352. participantCount: 1,
  353. exportUrl: '',
  354. title: '',
  355. description: '',
  356. endPoint: {
  357. serverCode: '',
  358. token: ''
  359. }
  360. },
  361. reportList: [],
  362. pickerOptions: {
  363. shortcuts: [
  364. {
  365. text: '今天',
  366. onClick(picker) {
  367. picker.$emit('pick', new Date())
  368. }
  369. },
  370. {
  371. text: '昨天',
  372. onClick(picker) {
  373. const date = new Date()
  374. date.setTime(date.getTime() - 3600 * 1000 * 24)
  375. picker.$emit('pick', date)
  376. }
  377. },
  378. {
  379. text: '一周前',
  380. onClick(picker) {
  381. const date = new Date()
  382. date.setTime(date.getTime() - 3600 * 1000 * 24 * 7)
  383. picker.$emit('pick', date)
  384. }
  385. }
  386. ]
  387. },
  388. rules: {
  389. title: [
  390. {required: true, message: '请输入任务名称', trigger: 'blur'},
  391. {min: 5, max: 50, message: '任务名称长度在 5 到 50 个字符', trigger: 'blur'}
  392. ],
  393. serviceType: [
  394. {required: true, message: '测试类型不可为空', trigger: 'change'},
  395. ],
  396. description: [{required: true, message: '请填写描述', trigger: 'blur'}],
  397. //price: [{required: true, message: '请填写价格', trigger: 'blur'}],
  398. quotePrice: [
  399. {required: true, message: '预算不可为空', trigger: 'blur'},
  400. {
  401. validator: (rule, value, callback) => {
  402. if (value < 0) {
  403. callback(new Error('请输入不小于0的数'))
  404. } else {
  405. callback()
  406. }
  407. }, trigger: 'blur'
  408. },
  409. ],
  410. resource: [
  411. {required: true},
  412. {
  413. validator: (rule, value, callback) => {
  414. if (value == 0 && this.task.institution == 0) {
  415. callback(new Error('定向发布至少要选择一个测评机构'))
  416. } else {
  417. callback()
  418. }
  419. }, trigger: 'change'
  420. },
  421. ],
  422. endPoint: [
  423. {
  424. validator: (rule, value, callback) => {
  425. if (this.currType.type === 1 && this.task.endPoint.serverCode === '') {
  426. callback(new Error('请填写对应得服务序列号'))
  427. } else {
  428. callback()
  429. }
  430. }, trigger: ['change', 'blur']
  431. },
  432. ],
  433. datetime: [{required: true, message: '截止时间不可为空', trigger: 'blur'}],
  434. },
  435. acceptedUserList: [],
  436. shortLink: '',
  437. editShortLink: false,
  438. }
  439. },
  440. watch: {
  441. institutionArray(val) {
  442. this.institutionArray = val
  443. },
  444. serviceType(val) {
  445. this.serviceType = val
  446. },
  447. deep: true
  448. },
  449. mounted() {
  450. this.$nextTick(() => {
  451. this.init()
  452. })
  453. },
  454. methods: {
  455. handleTaskCodeValid(){
  456. let str1 = this.projectId;
  457. let str2 = this.task.code;
  458. let str = str1.substring(str1.length-2) + str2.substring(str2.length-2);
  459. if(str === this.taskValidCode){
  460. //接收码正确,可以正确接收任务
  461. this.receiveTask();
  462. this.showTaskCodeModal = false;
  463. }else{
  464. // 提示接收码错误
  465. notify('error', '接收码错误')
  466. }
  467. },
  468. handleForkTask(){
  469. //跳转到taskFork
  470. this.$router.push({
  471. name: 'TaskCreate',
  472. params: this.task
  473. })
  474. this.showTaskForkModal = false;
  475. },
  476. //跳转到任务对应的数据面板
  477. gotoDataboard() {
  478. window.open(this.task.endPoint.token)
  479. },
  480. //根据短链接获取生成databoard
  481. getTaskDataBoard() {
  482. this.showLoading()
  483. Http.put(`/api/project/${this.projectId}/task/${this.taskId}/addToken`, {"token": this.shortLink}).then((res) => {
  484. this.taskOperationControl = res.taskOperationControl;
  485. this.task.endPoint = res.crowdTaskVO.endPointVO;
  486. this.shortLink = res.crowdTaskVO.endPointVO.token;
  487. if (this.shortLink != '') {
  488. this.editShortLink = false;
  489. }
  490. this.hideLoading()
  491. })
  492. },
  493. getServiceByCode(code) {
  494. let serviceName = this.serviceType.filter((item) => {
  495. return item.code === code;
  496. });
  497. return serviceName && serviceName[0] && serviceName[0]['name']
  498. },
  499. handleTestTypeChange(val) {
  500. let type = this.serviceType.filter((item) => {
  501. return item.code === val;
  502. });
  503. this.currType = type[0] ? type[0] : {};
  504. if (this.currType.type === 0) {
  505. this.$refs.task.clearValidate('endPoint');
  506. }
  507. },
  508. init() {
  509. console.log(CONFIG)
  510. this.taskId = this.$route.params.taskId
  511. this.projectId = this.$route.params.projectId
  512. this.setUserInfo()
  513. // this.setServiceType()
  514. //this.loadData(this.projectId, this.taskId)
  515. this.getTaskDetail()
  516. this.getWordCloud()
  517. // this.setInstitutions()
  518. },
  519. //北斗测试报告填写跳转
  520. gotoWriteReport() {
  521. window.open(this.crowdReportUrl, '_blank');
  522. },
  523. //跳转至项目详情页面
  524. toProject() {
  525. this.$router.push({
  526. name: 'Project',
  527. params: {projectId: this.projectId}
  528. })
  529. },
  530. //切换至可编辑页面
  531. modifyForm() {
  532. // this.task.serviceType = '
  533. this.setServiceType()
  534. this.setInstitutions();
  535. this.isModifyMode = true
  536. },
  537. //切换至不可编辑页面
  538. cancelMode() {
  539. this.isModifyMode = false
  540. },
  541. //重置表单
  542. resetForm() {
  543. this.task.name = ''
  544. this.task.desc = ''
  545. this.task.quotePrice = ''
  546. this.task.fixedPrice = ''
  547. this.task.type = ''
  548. this.task.resource = '2' //如果是广场不用管Location和institution ,定向看institution,区域看location
  549. this.task.location = {provinceCode: '', cityCode: ''}
  550. this.task.institution = 0
  551. this.task.datetime = ''
  552. this.task.participantCount = 1
  553. // this.task.endPointVO.caseId = ''
  554. // this.task.endPointVO.examId = ''
  555. },
  556. //显示页面加载画面
  557. showLoading() {
  558. this.loading = true
  559. },
  560. //隐藏页面加载画面
  561. hideLoading() {
  562. this.loading = false
  563. },
  564. //加载用户信息
  565. setUserInfo() {
  566. this.user = storageGet('user')
  567. this.rolesPermissions = storageGet('rolesPermissions')
  568. if (storageGet('rolesPermissions').isRegionManager || storageGet('rolesPermissions').isSystemAdministrator) {
  569. this.showBD = true;
  570. } else {
  571. this.showBD = false;
  572. }
  573. },
  574. //加载任务的测试类型
  575. setServiceType() {
  576. getAllServiceTypes().then((res) => {
  577. this.serviceType = res
  578. }).catch((error) => {
  579. notify('error', '加载测试类型失败')
  580. })
  581. },
  582. //加载所有的测评机构
  583. setInstitutions() {
  584. getAllAgencyAndTestUser().then((res) => {
  585. this.institutionArray = res
  586. }).catch((error) => {
  587. notify('error', '获取机构列表失败')
  588. })
  589. },
  590. //获取任务详情
  591. getTaskDetail() {
  592. this.showLoading()
  593. getTask(this.projectId, this.taskId, this.getTaskDetailSuccess, this.getTaskDetailFail)
  594. },
  595. //获取词云
  596. getWordCloud() {
  597. getTaskWordCloud(this.projectId, this.taskId, this.getTaskCloudSuccess, this.getTaskCloudFail)
  598. },
  599. //获取词云
  600. getWordCloudByDescription() {
  601. getTaskWordCloudByDescription(this.projectId, this.taskId, this.task.description, this.getTaskCloudSuccess, this.getTaskCloudFail)
  602. },
  603. getTaskCloudSuccess(words) {
  604. this.wordCloud = words.data;
  605. },
  606. getTaskCloudFail(err) {
  607. notify('error', err)
  608. },
  609. //获取任务详情成功时回调函数
  610. getTaskDetailSuccess(res) {
  611. this.hideLoading()
  612. // console.log(res)
  613. this.task = res.crowdTaskVO
  614. this.taskId = res.crowdTaskVO.id
  615. this.projectId = res.crowdTaskVO.projectId
  616. this.task.code = res.crowdTaskVO.code
  617. this.task.title = res.crowdTaskVO.title
  618. this.task.description = res.crowdTaskVO.description
  619. this.task.serviceType = res.crowdTaskVO.serviceType
  620. this.task.resource = res.crowdTaskVO.resource.toString()
  621. this.task.location = getProvinceCodeByProvinceName(res.crowdTaskVO.location.provinceCode, res.crowdTaskVO.location.cityCode)
  622. this.task.institution = res.crowdTaskVO.institution
  623. this.task.datetime = new Date(res.crowdTaskVO.datetime)
  624. this.task.quotePrice = res.crowdTaskVO.quotePrice
  625. this.task.agencyName = res.crowdTaskVO.agencyName
  626. this.task.acceptedPassword = res.crowdTaskVO.acceptedPassword
  627. this.task.acceptedCount = res.crowdTaskVO.acceptedCount
  628. this.task.participantCount = res.crowdTaskVO.participantCount
  629. this.task.fixedPrice = res.crowdTaskVO.fixedPrice
  630. this.task.doc = []
  631. this.task.requireDocUrl = res.crowdTaskVO.requirementFile
  632. this.task.agencyId = res.crowdTaskVO.agencyId
  633. this.task.exportUrl = res.crowdTaskVO.exportUrl
  634. this.task.status = res.crowdTaskVO.status
  635. this.task.statusVO = res.crowdTaskVO.statusVO
  636. this.task.endPoint = res.crowdTaskVO.endPointVO ? res.crowdTaskVO.endPointVO : {
  637. serverCode: '',
  638. }
  639. this.taskOperationControl = res.taskOperationControl;
  640. this.acceptedUserList = res.acceptedUserList;
  641. this.crowdReportUrl = res.crowdTaskVO.writeReportUrl;
  642. this.handleFormatReport(this.acceptedUserList);
  643. this.handleTestTypeChange(res.crowdTaskVO.serviceType);
  644. // this.serviceName = this.getServiceByCode(res.crowdTaskVO.serviceType);
  645. if (res.crowdTaskVO.endPointVO) {
  646. if (res.crowdTaskVO.endPointVO.token) {
  647. this.shortLink = res.crowdTaskVO.endPointVO.token;
  648. this.editShortLink = false
  649. } else {
  650. this.editShortLink = true
  651. }
  652. }
  653. // this.wordCloud = res.wordCloudList;
  654. // console.log(res.crowdTaskVO.endPointVO.token)
  655. // console.log(this.editShortLink)
  656. // console.log(this.isModifyMode)
  657. },
  658. //获取任务详情失败时回调函数
  659. getTaskDetailFail(error) {
  660. this.hideLoading()
  661. // notify('error', '获取任务详情失败:' + error.data)
  662. },
  663. //处理显示报告
  664. handleFormatReport(acceptedUserList) {
  665. acceptedUserList.map((user) => {
  666. user.crowdReportVOS && user.crowdReportVOS.map((report) => {
  667. report.userName = user.userVO.userName;
  668. this.reportList.push(report);
  669. })
  670. })
  671. },
  672. dateFormat(date, format) {
  673. date = new Date(date)
  674. let o = {
  675. 'M+': date.getMonth() + 1, //month
  676. 'd+': date.getDate(), //day
  677. 'H+': date.getHours(), //hour+8小时
  678. 'm+': date.getMinutes(), //minute
  679. 's+': date.getSeconds(), //second
  680. 'q+': Math.floor((date.getMonth() + 3) / 3), //quarter
  681. 'S': date.getMilliseconds() //millisecond
  682. }
  683. if (/(y+)/.test(format)) {
  684. format = format.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length));
  685. }
  686. for (let k in o)
  687. if (new RegExp('(' + k + ')').test(format))
  688. format = format.replace(RegExp.$1, RegExp.$1.length == 1 ? o[k] : ('00' + o[k]).substr(('' + o[k]).length));
  689. return format;
  690. },
  691. //更新任务信息
  692. updateTask() {
  693. this.$refs['task'].validate(valid => {
  694. if (valid) {
  695. this.showLoading()
  696. const newTask = {
  697. name: this.task.title,
  698. desc: this.task.description,
  699. type: this.serviceType.filter(type => type.name === this.task.serviceType)[0].code,
  700. resource: this.task.resource,
  701. location: this.task.location == null ? {} : getProvinceNameByProvinceCode(this.task.location.provinceCode, this.task.location.cityCode),
  702. institution: this.task.institution ? this.task.institution : null,
  703. datetime: this.task.datetime,
  704. quotePrice: this.task.quotePrice,
  705. fixedPrice: this.task.fixedPrice,
  706. requirementFile: this.task.requireDocUrl,
  707. participantCount: this.task.participantCount,
  708. endPoint: this.task.endPoint
  709. }
  710. //console.log(newTask)
  711. updateTask(this.projectId, this.taskId, newTask, this.updateTaskSuccess, this.updateTaskFail)
  712. } else {
  713. notify('error', '表单填写有误!')
  714. return false
  715. }
  716. })
  717. },
  718. //更新任务信息成功时回调函数
  719. updateTaskSuccess(res) {
  720. this.cancelMode()
  721. this.task = res.crowdTaskVO
  722. this.taskOperationControl = res.taskOperationControl
  723. this.taskId = res.crowdTaskVO.id
  724. this.projectId = res.crowdTaskVO.projectId
  725. this.task.projectId = res.crowdTaskVO.projectId
  726. this.task.title = res.crowdTaskVO.title
  727. this.task.description = res.crowdTaskVO.description
  728. this.task.serviceType = res.crowdTaskVO.serviceType
  729. this.task.resource = res.crowdTaskVO.resource.toString()
  730. this.task.location = res.crowdTaskVO.location == null ? {
  731. provinceCode: 3200,
  732. cityCode: 3201
  733. } : getProvinceCodeByProvinceName(res.crowdTaskVO.location.provinceCode, res.crowdTaskVO.location.cityCode)
  734. this.task.institution = res.crowdTaskVO.institution
  735. this.task.datetime = new Date(res.crowdTaskVO.datetime)
  736. this.task.quotePrice = res.crowdTaskVO.quotePrice
  737. this.task.fixedPrice = res.crowdTaskVO.fixedPrice
  738. // this.task.endPointVO = res.crowdTaskVO.endPointVO
  739. this.task.doc = []
  740. this.task.requireDocUrl = res.crowdTaskVO.requirementFile
  741. this.task.participantCount = res.crowdTaskVO.participantCount
  742. this.task.endPoint = res.crowdTaskVO.endPointVO ? res.crowdTaskVO.endPointVO : {
  743. serverCode: '',
  744. }
  745. this.task.createTime = res.crowdTaskVO.createTime,
  746. this.reportList = res.crowdReportVOList
  747. this.crowdReportUrl = res.crowdTaskVO.writeReportUrl;
  748. this.acceptedUserList = res.acceptedUserList
  749. this.handleTestTypeChange(res.crowdTaskVO.serviceType);
  750. this.serviceName = this.getServiceByCode(res.crowdTaskVO.serviceType)
  751. this.getWordCloudByDescription()
  752. this.hideLoading()
  753. notify('success', '修改成功')
  754. },
  755. //更新任务信息失败时回调函数
  756. updateTaskFail(error) {
  757. notify('error', '修改失败:' + error.data)
  758. this.hideLoading()
  759. },
  760. //上传任务需求文档
  761. uploadRequireDoc(param) {
  762. const formData = new FormData()
  763. let config = {
  764. //添加请求头
  765. headers: {'Content-Type': 'multipart/form-data'},
  766. }
  767. formData.append('file', param.file)
  768. Http.upload(Apis.FILE.REQUIREMENT_FILE.replace('{userId}', this.user.userVO.id), formData, config).then((res) => {
  769. notify('success', '上传成功')
  770. this.uploadRequireDocSuccess(res)
  771. }).catch((error) => {
  772. notify('error', '上传失败:' + error.data)
  773. this.uploadRequireDocFail(error)
  774. })
  775. },
  776. //上传任务需求文档成功时回调函数
  777. uploadRequireDocSuccess(res) {
  778. this.hideLoading()
  779. console.log('上传成功')
  780. this.task.requireDocUrl = res.data
  781. console.log(res.data)
  782. },
  783. //上传任务需求文档失败时回调函数
  784. uploadRequireDocFail(error) {
  785. this.hideLoading()
  786. notify('error', '任务需求文档上传失败:' + error.data)
  787. },
  788. //文档上传前响应函数
  789. //移除文档前的响应函数
  790. beforeRemove(file, fileList) {
  791. //return this.$confirm(`确定移除 ${file.name}?`)
  792. },
  793. //移除文档时的响应函数
  794. handleRemove(file, fileList) {
  795. console.log(file, fileList)
  796. },
  797. //需求文档添加进来时的响应函数
  798. handleExceed(files, fileList) {
  799. this.$message.warning(
  800. `当前限制选择 1 个文件,本次选择了 ${
  801. files.length
  802. } 个文件,共选择了 ${files.length + fileList.length} 个文件`
  803. )
  804. },
  805. //接收任务
  806. receiveTask() {
  807. this.$confirm('确认接收任务?', '提示', {
  808. confirmButtonText: '确认接收',
  809. cancelButtonText: '取消',
  810. type: 'success'
  811. }).then(() => {
  812. this.showLoading()
  813. receiveTaskRequest(this.projectId, this.taskId, this.user.userVO.id, this.receiveTaskSuccess, this.receiveTaskFail)
  814. }).catch(() => {
  815. })
  816. },
  817. //接收任务成功时的回调函数
  818. receiveTaskSuccess(res) {
  819. this.hideLoading()
  820. // this.getTaskDetail();
  821. notify('success', '接收任务成功')
  822. this.getTaskDetailSuccess(res);
  823. // console.log(res)
  824. // this.taskOperationControl = res.taskOperationControl
  825. // this.task.status = res.crowdTaskVO.status
  826. // this.task.institution = res.crowdTaskVO.institution
  827. // this.task = res.crowdTaskVO
  828. },
  829. //接收任务失败时的回调函数
  830. receiveTaskFail(error) {
  831. this.hideLoading()
  832. notify('error', '接收任务失败:' + error.data)
  833. },
  834. // 任务推荐
  835. recommendTask() {
  836. let task = {
  837. "title": this.task.title,
  838. "description": this.task.description,
  839. "participantCount": this.task.participantCount,
  840. "quotePrice": this.task.quotePrice,
  841. "requirementFile": this.task.requireDocUrl,
  842. "serviceType": this.task.serviceType,
  843. "createTime": this.task.createTime,
  844. "datetime": this.task.datetime
  845. };
  846. Http.post('/recommendationtest/query', task).then((res) => {
  847. window.open(this.taskRecommendUrl, "_blank");
  848. })
  849. },
  850. //拒绝任务
  851. rejectTask() {
  852. this.$confirm('确认拒绝任务?拒绝后将不能再接收该任务', '提示', {
  853. confirmButtonText: '确认拒绝',
  854. cancelButtonText: '取消',
  855. type: 'success'
  856. }).then(() => {
  857. this.showLoading()
  858. rejectTask(this.projectId, this.taskId, this.rejectTaskSuccess, this.rejectTaskFail)
  859. }).catch(() => {
  860. })
  861. },
  862. //拒绝任务成功时的回调函数
  863. rejectTaskSuccess(res) {
  864. this.hideLoading()
  865. this.$router.push({
  866. name: 'Mine'
  867. })
  868. notify('success', '拒绝任务成功,已为您自动跳转到个人中心')
  869. },
  870. //拒绝任务失败时的回调函数
  871. rejectTaskFail(error) {
  872. this.hideLoading()
  873. notify('error', '拒绝任务失败:' + error.data)
  874. },
  875. //提交结束任务申请
  876. submitTaskRequest() {
  877. this.$confirm('确认提交任务?提交后将不能再修改', '提示', {
  878. confirmButtonText: '确认提交',
  879. cancelButtonText: '取消',
  880. type: 'success'
  881. }).then(() => {
  882. this.showLoading()
  883. submitTaskRequest(this.projectId, this.taskId, this.submitTaskRequestSuccess, this.submitTaskRequestFail)
  884. }).catch(() => {
  885. })
  886. },
  887. //提交结束任务申请成功时的回调函数
  888. submitTaskRequestSuccess(res) {
  889. this.hideLoading()
  890. // this.task = res.crowdTaskVO
  891. // this.taskOperationControl = res.taskOperationControl
  892. // this.task.status = res.crowdTaskVO.status
  893. // this.task.institution = res.crowdTaskVO.institution
  894. notify('success', '提交任务成功,等待区域管理员审核')
  895. this.getTaskDetailSuccess(res);
  896. // this.getTaskDetail();
  897. },
  898. //提交结束任务申请失败时的回调函数
  899. submitTaskRequestFail(error) {
  900. this.hideLoading()
  901. notify('error', '提交任务失败:' + error.data)
  902. },
  903. //结束任务
  904. endTask() {
  905. this.$confirm('确认结束任务?', '提示', {
  906. confirmButtonText: '确认结束',
  907. cancelButtonText: '取消',
  908. type: 'success'
  909. }).then(() => {
  910. // this.getTaskDetail()
  911. this.showLoading()
  912. ensureEndTask(this.projectId, this.taskId, this.endTaskSuccess, this.endTaskFail)
  913. }).catch(() => {
  914. })
  915. },
  916. //结束任务成功时的回调函数
  917. endTaskSuccess(res) {
  918. // this.taskOperationControl = res.taskOperationControl
  919. // this.task.status = res.crowdTaskVO.status
  920. // this.task.institution = res.crowdTaskVO.institution
  921. notify('success', '结束任务成功!')
  922. this.getTaskDetailSuccess(res);
  923. this.hideLoading()
  924. // this.getTaskDetail();
  925. },
  926. //结束任务失败时的回调函数
  927. endTaskFail(error) {
  928. this.hideLoading()
  929. notify('error', '结束任务失败:' + error.data)
  930. },
  931. // 导出任务
  932. toExportTask() {
  933. exportTask(this.projectId, this.taskId, this.exportTaskSuccess, this.exportTaskFail);
  934. },
  935. // 导出任务成功时的回调函数
  936. exportTaskSuccess(res) {
  937. this.hideLoading()
  938. console.log(res.data)
  939. this.exportTaskUrl = res.data;
  940. window.open(this.exportTaskUrl, "_self");
  941. notify('success', '任务导出成功!')
  942. },
  943. // 导出任务失败时的回调函数
  944. exportTaskFail(error) {
  945. this.hideLoading()
  946. notify('error', '导出任务失败:' + error.data)
  947. },
  948. //跳转到创建项目报告页面
  949. toCreateReport() {
  950. this.$router.push({
  951. name: 'TaskReportCreate',
  952. params: {
  953. scope: 1,
  954. dependencyCode: this.taskId,
  955. projectId: this.projectId,
  956. taskId: this.taskId,
  957. }
  958. })
  959. },
  960. reformDate(date) {
  961. return getFormalTimeFromDate(date)
  962. }
  963. },
  964. }
  965. //回收站
  966. //
  967. // updateLocation (location) {
  968. // console.log(location)
  969. // const loactionName = getProvinceNameByProvinceCode(location.provinceCode, location.cityCode)
  970. // // var provinceName = ''
  971. // // var cityName = ''
  972. // // for (var item of provinceCityJSON.provinces) {
  973. // // if (item.code === location.provinceCode) {
  974. // // provinceName = item.name
  975. // // for (var city of item.cities) {
  976. // // if (city.code === location.cityCode) {
  977. // // cityName = city.name
  978. // // break
  979. // // }
  980. // // }
  981. // // }
  982. // // }
  983. // return loactionName.provinceCode + ' / ' + loactionName.cityCode
  984. // },
  985. //
  986. // locationChange (provinceId, cityId) {
  987. // if (provinceId || cityId) {
  988. // this.task.location = {provinceCode: provinceId, cityCode: cityId}
  989. // }
  990. // },
  991. // submitForm (formName) {
  992. // this.$refs[formName].validate(valid => {
  993. // if (valid) {
  994. // this.isModifyMode = false
  995. //
  996. // } else {
  997. // console.log('error submit!!')
  998. // return false
  999. // }
  1000. // })
  1001. // },
  1002. </script>
  1003. <style lang="less" scoped>
  1004. .el-radio {
  1005. margin: 10px 20px 10px 0;
  1006. }
  1007. .el-form-item /deep/ .el-tabs__content {
  1008. /*max-height: 120px !important;*/
  1009. overflow: auto;
  1010. }
  1011. .el-collapse-item__content {
  1012. padding-bottom: 0 !important;
  1013. }
  1014. </style>