index.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510
  1. <template>
  2. <div class="editPublishTask">
  3. <section class="main-section pubconfig">
  4. <div v-if="showEmpty">
  5. <header>
  6. <headTitle title="checklist" />
  7. </header>
  8. <div class="empty">
  9. 未设置 <span class="createBtn" @click="addAction">点击添加</span>
  10. </div>
  11. </div>
  12. <div v-else>
  13. <header>
  14. <headTitle title="checklist" :open-edit="openEdit" @editHandle="editHandle" />
  15. </header>
  16. <div class="wrap">
  17. <redTipword title="关联任务" :isedit="edit" />
  18. <multipleSelect placeholder="🔍 请输入任务名称或ID" :isedit="edit" :data="data.tasks" :task-id="taskId" @change="changeTask" />
  19. <div v-if="edit" style="margin-top: 30px">
  20. <redTipword title="选择checklist列表" :isedit="edit" />
  21. <checkboxList :selected-list="data.selectedBizTemplateIds" :data="temList" @change="updateSelectedTemHandle" />
  22. </div>
  23. </div>
  24. <div class="moduleList wrap">
  25. <redTipword v-if="!edit" title="检查项" :isedit="edit" />
  26. <div v-for="(item, index) in data.templates" :key="item.parentTemplateId" class="item">
  27. <div v-if="item.type === 1" style="width: 690px">
  28. <p :id="`s${item.parentTemplateId}`" class="title">
  29. <el-checkbox v-if="!edit" v-model="item.isCheck" :label="item.name" @change="updateCheckItemHandle(item)">{{ item.name }}</el-checkbox>
  30. <span v-else>{{ item.name }}</span>
  31. </p>
  32. <onlineCheckList
  33. :module-id="item.parentTemplateId"
  34. :isedit="edit"
  35. :data="item.onlineModule"
  36. :task-id="taskId"
  37. @changeSelectedHandle="changeOnlineSelectedHandle"
  38. @changeRow="changeOnlineModuleRow"
  39. @onChangeModuleName="(val, subIdx) => onChangeModuleName(val, subIdx, index)"
  40. />
  41. </div>
  42. <div v-else style="width: 690px">
  43. <p :id="`s${item.parentTemplateId}`" class="title">
  44. <el-checkbox v-if="!edit" v-model="item.isCheck" :label="item.name" @change="updateCheckItemHandle(item)">{{ item.name }}</el-checkbox>
  45. <span v-else>{{ item.name }}</span>
  46. </p>
  47. <normal-area
  48. v-if="edit"
  49. :id="'tem'+item.parentTemplateId"
  50. :value.sync="item.content"
  51. :empty-text="'点击'"
  52. :input-button="'修改模板'"
  53. :styles="{ padding: '0 0px 20px 0px', width: '690px' }"
  54. />
  55. <div v-else v-html="item.content" />
  56. </div>
  57. </div>
  58. </div>
  59. <div v-if="edit" class="control">
  60. <el-button size="small" @click="cancel()">取消</el-button>
  61. <el-button type="primary" size="small" @click="saveHandle()">
  62. 保存
  63. </el-button>
  64. </div>
  65. </div>
  66. </section>
  67. <div v-if="!edit">
  68. <section class="main-section">
  69. <div>
  70. <headTitle title="动态" />
  71. </div>
  72. <actionDynamic :comments="commentlist" :change-record="changeRecordList" @addComment="createCommentHandle" />
  73. </section>
  74. <div v-if="!showEmpty" class="step">
  75. <step :data="data.templates" :type-list="data.templates" @goto="scrollToHandle" />
  76. </div>
  77. </div>
  78. </div>
  79. </template>
  80. <script>
  81. const _ = require('lodash')
  82. import redTipword from '@/components/redTipTitle'
  83. import headTitle from '@/components/headTitle'
  84. import multipleSelect from './components/multipleSelect'
  85. import checkboxList from './components/checkboxList'
  86. import onlineCheckList from './components/onlineCheckList'
  87. import actionDynamic from '@/components/actionDynamic'
  88. import step from './components/step'
  89. // 富文本
  90. // import textArea from '@/components/input/textArea'
  91. import normalArea from '@/components/input/normalArea' // 富文本
  92. import 'tinymce/plugins/table'// 插入表格插件
  93. import store from '@/store'
  94. import {
  95. getCheckListBytask,
  96. getBizBindTemList,
  97. updateChecklist,
  98. createChecklist,
  99. updateTemplateCheckStatus,
  100. getCommentList,
  101. createComment,
  102. getRecordList
  103. } from '@/api/publishTask'
  104. export default {
  105. components: {
  106. redTipword,
  107. multipleSelect,
  108. checkboxList,
  109. onlineCheckList,
  110. normalArea,
  111. headTitle,
  112. actionDynamic,
  113. step
  114. },
  115. props: {
  116. taskId: {
  117. type: Number,
  118. required: true,
  119. default: -1
  120. },
  121. taskName: {
  122. type: String,
  123. required: true,
  124. default: ''
  125. },
  126. userNames: {
  127. type: String,
  128. required: true,
  129. default: ''
  130. },
  131. userInformation: {
  132. type: String,
  133. required: true,
  134. default: ''
  135. }
  136. },
  137. data() {
  138. return {
  139. description: '<p style="color:red;">123</p>',
  140. edit: false, // 是否是编辑状态
  141. showEmpty: true,
  142. openEdit: true,
  143. data: {},
  144. temList: [],
  145. commentlist: [], // 评价列表
  146. changeRecordList: [], // 变更记录列表
  147. checkListId: -1
  148. }
  149. },
  150. mounted() {
  151. // 获取模板列表
  152. this.getBizBindTemList()
  153. // 获取checklist详情
  154. this.getList()
  155. // 获取评论列表
  156. this.getCommentList()
  157. },
  158. methods: {
  159. // 获取checklist详情
  160. async getList() {
  161. if (this.taskId) {
  162. const res = await getCheckListBytask({ taskId: this.taskId })
  163. // res.data = null
  164. if (res.data) {
  165. // 如果绑定过
  166. this.showEmpty = false
  167. this.data = res.data
  168. this.checkListId = res.data.id
  169. // 获取变更记录
  170. this.getRecordList()
  171. } else {
  172. this.showEmpty = true
  173. }
  174. }
  175. },
  176. // 获取业务线下绑定的可以选checklist列表
  177. async getBizBindTemList() {
  178. const { bizId = null } = store.state.global || {}
  179. const res = await getBizBindTemList({ name: '', bizId })
  180. this.temList = res.data
  181. },
  182. async getCommentList() {
  183. const res = await getCommentList({ type: 5, joinId: this.taskId })
  184. if (res.code === 200) {
  185. this.commentlist = res.data
  186. }
  187. },
  188. // 获取变更记录
  189. async getRecordList() {
  190. const res = await getRecordList({ checkListId: this.checkListId })
  191. if (res.code === 200) {
  192. this.changeRecordList = res.data
  193. }
  194. },
  195. // 添加评论
  196. async createCommentHandle(content, callback) {
  197. const commentInfo = {
  198. joinId: this.taskId,
  199. content,
  200. type: 5,
  201. fatherId: 0,
  202. name: this.userNames,
  203. email: this.userInformation
  204. }
  205. const user = { name: this.userNames, ename: this.userInformation, id: '' }
  206. const res = await createComment({ commentInfo, user })
  207. if (res.code === 200) {
  208. this.$message({ message: '评论成功', type: 'success', duration: 1000, offset: 150 })
  209. this.getCommentList()
  210. callback()
  211. } else {
  212. this.$message.warning(res.msg)
  213. }
  214. },
  215. // 添加或者删除线上模板的模版名
  216. changeOnlineSelectedHandle(id, subIdx, value, type) {
  217. /**
  218. * id: 模块id
  219. * name: 线上模块中哪个模块下的模块名称
  220. * value: 模块名
  221. * type: 是添加还是删除
  222. **/
  223. // const tem = this.data.templates
  224. this.data.templates.map(t => {
  225. if (t.parentTemplateId === id) {
  226. if (type === 'del') {
  227. t.onlineModule.onlineOrder = t.onlineModule.onlineOrder.filter(g => g !== value)
  228. t.onlineModule.tableContent.map((t, i) => {
  229. if (i === subIdx) {
  230. t.moduleNames = t.moduleNames.filter(g => g !== value)
  231. }
  232. })
  233. } else if (!t.onlineModule.onlineOrder.includes(value)) {
  234. t.onlineModule.onlineOrder.push(value)
  235. t.onlineModule.tableContent.map((t, i) => {
  236. if (i === subIdx) {
  237. t.moduleNames.push(value)
  238. }
  239. })
  240. } else {
  241. this.$message({
  242. message: '已经添加过该模块名称',
  243. type: 'error'
  244. })
  245. }
  246. }
  247. })
  248. },
  249. changeOnlineModuleRow(type, mId, index) {
  250. this.data.templates.map(t => {
  251. if (t.parentTemplateId === mId) {
  252. if (type === 'del') {
  253. const delModuleNames = t.onlineModule.tableContent[index].moduleNames
  254. t.onlineModule.onlineOrder = t.onlineModule.onlineOrder.filter(t => !delModuleNames.includes(t))
  255. t.onlineModule.tableContent.splice(index, 1)
  256. } else {
  257. t.onlineModule.tableContent.splice(index + 1, 0, {
  258. module: `模块${index + 1}`,
  259. moduleNames: []
  260. })
  261. }
  262. }
  263. })
  264. },
  265. // 保存
  266. async saveHandle() {
  267. if (this.data.tasks.length < 1) {
  268. this.$message({
  269. message: '请关联一个任务',
  270. type: 'error'
  271. })
  272. return
  273. }
  274. let res = null
  275. if (this.data.id) {
  276. res = await updateChecklist(this.data)
  277. } else {
  278. res = await createChecklist(this.data)
  279. }
  280. if (res.code === 200) {
  281. this.edit = false
  282. this.openEdit = true
  283. // 保存更新变更记录
  284. this.getRecordList()
  285. this.getList()
  286. this.$message({
  287. message: '保存成功',
  288. type: 'success'
  289. })
  290. }
  291. },
  292. // 取消
  293. cancel() {
  294. this.edit = false
  295. this.openEdit = true
  296. this.data = this.copyData
  297. if (!this.data || JSON.stringify(this.data) === '{}') {
  298. this.showEmpty = true
  299. }
  300. },
  301. // 点击添加
  302. addAction() {
  303. // 校验是否绑定过checklist模板
  304. if (!this.RegHasCheckListTem()) {
  305. return
  306. }
  307. // 复制一份数据,以便取消时复原
  308. this.copyData = this.data
  309. // 编辑按钮隐藏
  310. this.openEdit = false
  311. // 编辑状态打开
  312. this.edit = true
  313. // 是否显示空状态
  314. this.showEmpty = false
  315. this.data = {
  316. selectedBizTemplateIds: [],
  317. templates: [],
  318. tasks: [{
  319. id: this.taskId,
  320. name: this.taskName
  321. }]
  322. }
  323. this.checkAllTem()
  324. },
  325. // 编辑
  326. editHandle() {
  327. // 校验是否绑定过checklist模板
  328. if (!this.RegHasCheckListTem()) {
  329. return
  330. }
  331. // 复制一份数据,以便取消时复原
  332. this.copyData = this.data
  333. // 编辑状态打开
  334. this.edit = true
  335. // 编辑按钮隐藏
  336. this.openEdit = false
  337. this.checkAllTem()
  338. },
  339. // 添加和编辑checklist时 如果没有选择模版默认全选。
  340. checkAllTem() {
  341. const { selectedBizTemplateIds } = this.data
  342. if (!selectedBizTemplateIds || selectedBizTemplateIds.length < 1) {
  343. this.temList.map(t => {
  344. this.data.selectedBizTemplateIds.push(t.id)
  345. const { content, isCheck, name, onlineModule, type, id: parentTemplateId } = t
  346. this.data.templates.push({
  347. content,
  348. isCheck,
  349. name,
  350. onlineModule,
  351. type,
  352. parentTemplateId,
  353. belongType: 2 // checklist的模板
  354. })
  355. })
  356. }
  357. },
  358. // 校验是否该业务线有绑定checklist模板
  359. RegHasCheckListTem() {
  360. if (!this.temList || this.temList.length < 1) {
  361. this.$message({
  362. message: '该业务线暂无绑定checklist模板,请先绑定checklist模板',
  363. type: 'error'
  364. })
  365. return false
  366. } else {
  367. return true
  368. }
  369. },
  370. // 修改checklist绑定模版列表
  371. updateSelectedTemHandle(checkedIds) {
  372. const selectedBizTemplateIds = []
  373. const tems = []
  374. const { templates } = this.data
  375. // 循环都有哪些tem被选择了
  376. checkedIds.map(checkedId => {
  377. // 先循环是否有存过模板数据
  378. this.temList.map(g => {
  379. if (g.id === checkedId) {
  380. selectedBizTemplateIds.push(g.id)
  381. const { content, isCheck, name, onlineModule, type, id: parentTemplateId } = g
  382. tems.push({
  383. content,
  384. isCheck,
  385. name,
  386. onlineModule,
  387. type,
  388. parentTemplateId,
  389. belongType: 2 // checklist的模板
  390. })
  391. }
  392. })
  393. })
  394. tems.map((h, index) => templates.map(j => {
  395. if (h.parentTemplateId === j.parentTemplateId) {
  396. tems[index] = { ...j }
  397. }
  398. }))
  399. this.data = { ...this.data, templates: tems, selectedBizTemplateIds }
  400. },
  401. // 锚点
  402. scrollToHandle(targe) {
  403. const anchorH = document.getElementById(targe).offsetTop
  404. const container = document.getElementsByClassName('main-wrapper')[0]
  405. container.scrollTop = anchorH - 20
  406. },
  407. // 解绑删除任务
  408. changeTask(task, type) {
  409. let hasTask = false
  410. let tasks = []
  411. this.data.tasks.map(g => {
  412. if (g.id === task.id) {
  413. hasTask = true
  414. }
  415. })
  416. if (type === 'del') {
  417. tasks = this.data.tasks.filter(t => t.id !== task.id)
  418. } else if (!hasTask) {
  419. tasks = [...this.data.tasks, task]
  420. } else {
  421. this.$message({
  422. message: '已经添加过该任务',
  423. type: 'error'
  424. })
  425. return
  426. }
  427. this.data = { ...this.data, tasks }
  428. },
  429. // 更新检查项到数据库
  430. async updateCheckItemHandle(item) {
  431. const { isCheck, id } = item
  432. const res = await updateTemplateCheckStatus({ isCheck, id, checkListId: this.checkListId })
  433. if (res.code === 200) {
  434. this.getRecordList()
  435. this.$message({
  436. message: '检查项状态更新成功',
  437. type: 'success'
  438. })
  439. }
  440. },
  441. // 修改线上问题模块
  442. onChangeModuleName: _.debounce(function(val, subIdx, index) {
  443. this.data.templates[index].onlineModule.tableContent[subIdx].module = val
  444. })
  445. }
  446. }
  447. </script>
  448. <style scoped lang="scss">
  449. @import '@/styles/detail-pages.scss';
  450. .editPublishTask {
  451. min-height: 400px;
  452. overflow-y: auto;
  453. padding-bottom: 20px;
  454. .step {
  455. position: fixed;
  456. top: 200px;
  457. right:150px;
  458. }
  459. .pubconfig {
  460. .control {
  461. padding: 20px 0px 20px 690px;
  462. }
  463. }
  464. .main-section {
  465. @include main-section;
  466. }
  467. .wrap{
  468. padding: 0 40px;
  469. }
  470. .moduleList {
  471. margin-top: 40px;
  472. padding-bottom: 16px;
  473. .title {
  474. font-weight: 400;
  475. color: #444444;
  476. font-size: 14px;
  477. margin-bottom: 16px;
  478. margin-top: 40px;
  479. }
  480. }
  481. }
  482. .empty {
  483. padding: 0px 30px 40px 30px;
  484. color: #444;
  485. font-size: 14px;
  486. .createBtn {
  487. color: #409EFF;
  488. margin-left: 5px;
  489. cursor: pointer;
  490. }
  491. }
  492. .main-title {
  493. @include main-title;
  494. }
  495. </style>