index.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. <template>
  2. <el-drawer
  3. class="content-wrapper"
  4. :modal="false"
  5. size="100%"
  6. :class="drawerBox"
  7. destroy-on-close
  8. :visible.sync="drawer"
  9. :before-close="handleClose"
  10. @click.stop
  11. @open="setBoxShadow('')"
  12. @opened="setBoxShadow"
  13. @close="setBoxShadow('')"
  14. >
  15. <template slot="title">
  16. <div v-if="title" @click.stop>{{ title }}<span class="sub-title">{{ subTitle }}</span></div>
  17. </template>
  18. <!-- 时间线 -->
  19. <div
  20. v-if="openDrawer && baseModal && baseModal.timeline.one "
  21. class="drawer-padding drawer-header"
  22. :style="{paddingTop: baseModal.timeline.two ? '10px':'30px'}"
  23. @click.stop
  24. >
  25. <div id="index" ref="timeline1" class="drawer-scll">
  26. <timeline
  27. :num="timelineData.firstActive"
  28. bg-margin
  29. :data="baseModal.timeline.one"
  30. @update="(params) => timeLineClick(params, 1)"
  31. />
  32. </div>
  33. <div v-if="baseModal.timeline.two" ref="timeline2" class="drawer-scll">
  34. <timeline
  35. :num="timelineData.secondActive"
  36. :data="baseModal.timeline.two"
  37. bg-margin
  38. @update="(params)=>timeLineClick(params, 2)"
  39. />
  40. </div>
  41. </div>
  42. <!-- 表格 -->
  43. <dmTable
  44. v-if="openDrawer"
  45. v-loading="loading"
  46. :table-list="tableList"
  47. :total="tableList"
  48. :column="baseModal && baseModal.column || []"
  49. :table-height="baseModal && baseModal.tableHeight ? baseModal.tableHeight : 'auto' "
  50. size="mini"
  51. @click.stop
  52. @change="dmTableChange"
  53. >
  54. <!-- 改进项:级别 -->
  55. <template #improvementsOverRateColumnsPrioritySlot="{scope}">
  56. <div v-if="scope.row.caseName" @click.stop>
  57. <a target="_blank" :href="scope.row.url">{{ scope.row.caseName }}</a>
  58. </div>
  59. </template>
  60. </dmTable>
  61. <!-- 下拉 -->
  62. <div class="footer-laout" @click.stop>
  63. <div style="line-height: 60px;">
  64. <!-- <el-button type="primary" size="mini" @click="exportTable">导 出</el-button>-->
  65. </div>
  66. <el-pagination
  67. :current-page.sync="paging.curIndex"
  68. :page-size="paging.pageSize"
  69. :pager-count="5"
  70. layout="total, sizes, prev, pager, next, jumper"
  71. :page-sizes="[10, 15, 20, 30]"
  72. :total="paging.pageTotal"
  73. @size-change="handleSizeChange"
  74. @current-change="handleCurrentChange"
  75. />
  76. </div>
  77. </el-drawer>
  78. </template>
  79. <script>
  80. import _ from 'lodash'
  81. import moment from 'moment'
  82. import dmTable from '@/components/baseTable/table'
  83. import timeline from './components/timeline'
  84. import drawerModalData from './drawerModalData'
  85. import { EncryptId } from '@/utils/crypto-js'
  86. export default {
  87. name: 'DrawerModal',
  88. components: {
  89. dmTable, timeline
  90. },
  91. props: {
  92. modalType: {
  93. type: String,
  94. required: false,
  95. default: () => 'bug1' // 默认为缺陷
  96. },
  97. openDrawer: {
  98. type: Boolean,
  99. required: false,
  100. default: false
  101. },
  102. drawerData: {
  103. type: Array,
  104. required: false,
  105. default: () => {}
  106. }
  107. },
  108. data() {
  109. return {
  110. baseModal: null,
  111. drawer: false,
  112. loading: false,
  113. title: '',
  114. headerTitle: '',
  115. // timelineData,
  116. tableList: [],
  117. tableListOld: [],
  118. // tableHeight: 'auto',
  119. column: [],
  120. ids: [],
  121. label: '',
  122. activeLabel: '',
  123. drawerBox: '',
  124. subTitle: '',
  125. sourceData: null,
  126. /* S 新增缺陷*/
  127. priorityList: [],
  128. /* E 新增缺陷*/
  129. timelineData: {
  130. first: [],
  131. firstActive: 0,
  132. second: [],
  133. secondActive: 0
  134. },
  135. paging: {
  136. curIndex: 1,
  137. pageTotal: 0,
  138. pageSize: 10
  139. }
  140. }
  141. },
  142. watch: {
  143. drawerData(v, o) {
  144. this.init()
  145. },
  146. openDrawer(value) {
  147. this.drawer = value
  148. if (this.drawer) {
  149. this.init()
  150. }
  151. }
  152. },
  153. mounted() {
  154. this.drawer = false
  155. },
  156. methods: {
  157. moment,
  158. init() {
  159. this.baseModal = { ...drawerModalData[this.modalType] }
  160. this.title = this.baseModal.title
  161. this.pagingInit()
  162. this.setPageSize()
  163. this.column = this.baseModal.column
  164. this.tableList = []
  165. this.drawer = this.openDrawer
  166. // 初始化的时候使用 setIds
  167. this.paging = this.baseModal.setIds(this.paging, this.drawerData)
  168. this.setTableList()
  169. },
  170. // 设置页数
  171. setPageSize() {
  172. const pageSize = window.localStorage.getItem('pageSize') || 10
  173. const paging = _.cloneDeep(this.paging)
  174. paging.pageSize = Number.parseInt(pageSize)
  175. this.paging = _.cloneDeep(paging)
  176. },
  177. // 处理日期格式:JS - 2020-01-01T00:00:00.000000Z 日期格式转换
  178. rTime(date) {
  179. if (!date) return ''
  180. var json_date = new Date(date).toJSON()
  181. return new Date(new Date(json_date) + 8 * 3600 * 1000).toISOString().replace(/T/g, ' ').replace(/\.[\d]{3}Z/, '')
  182. },
  183. handleClose() {
  184. this.drawer = false
  185. this.$emit('update:openDrawer', this.drawer)
  186. },
  187. handleSizeChange(value) {
  188. this.paging.pageSize = value
  189. const paging = _.cloneDeep(this.paging)
  190. paging.pageSize = value
  191. this.paging = _.cloneDeep(paging)
  192. window.localStorage.setItem('pageSize', value)
  193. // 是否真实分页
  194. if (this.baseModal.isPagination) {
  195. this.setTableList()
  196. } else {
  197. this.tableListPagination()
  198. }
  199. },
  200. handleCurrentChange(value) {
  201. const paging = _.cloneDeep(this.paging)
  202. paging.curIndex = value
  203. this.paging = _.cloneDeep(paging)
  204. // 是否真实分页
  205. if (this.baseModal.isPagination) {
  206. this.setTableList()
  207. } else {
  208. this.tableListPagination()
  209. }
  210. },
  211. // 导出
  212. exportTable() {
  213. },
  214. // 格式化时间
  215. dateFomatter(date) {
  216. return date.substring(0, 10) + ' ' + date.substring(11, 19)
  217. },
  218. // 时间轴点击事件
  219. timeLineClick({ value, name }, index) {
  220. this.pagingInit()
  221. if (index === 1) {
  222. const { paging } = this.baseModal.timeline.oneClick({
  223. value, name, paging: this.paging, drawerData: this.drawerData
  224. })
  225. this.paging = { ...paging }
  226. }
  227. if (index === 2) {
  228. const { paging } = this.baseModal.timeline.twoClick({
  229. value, index, paging: this.paging
  230. })
  231. this.paging = { ...paging }
  232. }
  233. this.setTableList()
  234. },
  235. // 设置列表数据
  236. async setTableList() {
  237. this.tableList = []
  238. this.loading = true
  239. // 请求数据
  240. if (!this.drawerData.length) {
  241. this.loading = false
  242. return
  243. }
  244. const paging = this.paging
  245. this.baseModal.method({
  246. ...paging
  247. // idList: this.drawerData,
  248. // curIndex: this.paging.curIndex,
  249. // pageSize: this.paging.pageSize
  250. }).then(res => {
  251. if (res.code === 200) {
  252. // 暴露处理返回值的函数,通过 this.baseModal 调用
  253. const { tableList, oldTableList, paging } = this.baseModal.setTableList({
  254. tableList: this.tableList, // 表格展示时使用的数据
  255. oldTableList: this.oldTableList, // 假分页时使用的数据
  256. paging: this.paging, // 分页数据和部分给接口传参
  257. res
  258. })
  259. if (tableList) {
  260. this.tableList = [...tableList]
  261. }
  262. if (oldTableList) {
  263. this.oldTableList = [...oldTableList]
  264. }
  265. if (paging) {
  266. this.paging = { ...paging }
  267. }
  268. this.loading = false
  269. }
  270. })
  271. },
  272. // 前端分页
  273. tableListPagination() {
  274. if (this.tableListOld.length) {
  275. this.tableList = this.tableListOld.map(e => e).splice((this.paging.curIndex - 1 || 0) * this.paging.pageSize, this.paging.pageSize)
  276. }
  277. },
  278. // 分页数据初始化
  279. pagingInit() {
  280. const pageSize = window.localStorage.getItem('pageSize') || 10
  281. this.paging = {
  282. curIndex: 1,
  283. pageTotal: 0,
  284. pageSize: Number.parseInt(pageSize)
  285. }
  286. this.priorityList = []
  287. },
  288. // 设置表头
  289. // 表格跳转
  290. dmTableChange({ column, row }) {
  291. if (typeof this.baseModal.jumper === 'string') {
  292. this.jumper(row, this.baseModal.jumper)
  293. } else {
  294. this.baseModal.jumper({ column, row })
  295. }
  296. },
  297. // 设置表格样式
  298. setBoxShadow(key = 'drawer-box') {
  299. if (key) {
  300. setTimeout(() => {
  301. this.drawerBox = key
  302. }, 300)
  303. } else {
  304. this.drawerBox = key
  305. }
  306. },
  307. jumper(val, name) { // 需求、任务、缺陷跳转
  308. // const { bizId = null } = this.$store.state.global || {}
  309. const { bizId, id } = val
  310. const bizId_id = EncryptId(`${bizId}_${id}`)
  311. const newTab = this.$router.resolve({ name: name + '详情', query: { bizId_id: bizId_id }})
  312. window.open(newTab.href, '_blank')
  313. }
  314. }
  315. }
  316. </script>
  317. <style scoped lang='less'>
  318. .content-wrapper{
  319. /deep/.el-drawer__body{
  320. overflow: hidden;
  321. }
  322. }
  323. /deep/ .el-drawer__header {
  324. color: #444;
  325. font-size: 20px;
  326. font-weight: 500;
  327. margin-bottom: 0;
  328. padding: 20px 30px;
  329. border-bottom: 1px solid #E2E2E2;
  330. .sub-title {
  331. color: #444;
  332. font-size: 14px;
  333. margin-left: 20px;
  334. font-weight: 400;
  335. }
  336. }
  337. .drawer-box {
  338. box-shadow: 0 8px 10px -5px rgba(0, 0, 0, .2), 0 16px 24px 2px rgba(0, 0, 0, .14), 0 6px 30px 5px rgba(0, 0, 0, .12);
  339. }
  340. .el-drawer-fade-enter-active {
  341. animation: el-drawer-fade-in 10ms;
  342. }
  343. .el-drawer-fade-leave-active {
  344. animation: el-drawer-fade-in 10ms reverse;
  345. }
  346. .el-drawer__wrapper {
  347. width: 100%;
  348. position: fixed;
  349. top: 0;
  350. right: 0;
  351. bottom: 0;
  352. left: 50%;
  353. overflow: hidden;
  354. margin: 0;
  355. }
  356. /deep/.el-drawer__container {
  357. left: 0;
  358. right: 0;
  359. width: 50%;
  360. }
  361. /* S 时间轴 */
  362. .drawer-header {
  363. text-align: center;
  364. background: #F7F7F7;
  365. border-radius: 4px;
  366. min-height: 120px;
  367. margin: 20px 30px 10px;
  368. overflow: hidden;
  369. }
  370. .drawer-padding {
  371. padding: 20px 0;
  372. }
  373. .drawer-padding-s {
  374. padding: 1px 0;
  375. }
  376. .drawer-scll {
  377. overflow-x: scroll;
  378. }
  379. .drawer-scll::-webkit-scrollbar { width: 0 !important; height: 0 !important }
  380. .drawer-H {
  381. font-size: 16px;
  382. margin: 0 30px;
  383. color: #444444;
  384. }
  385. .drawer-scll {
  386. overflow-x: scroll;
  387. }
  388. .drawer-scll::-webkit-scrollbar { width: 0 !important; height: 0 !important }
  389. .drawer-H {
  390. font-size: 16px;
  391. margin: 0 30px;
  392. color: #444444;
  393. }
  394. /* E 时间轴 */
  395. .footer-laout {
  396. display: flex;
  397. justify-content: space-between;
  398. margin: 0 30px;
  399. }
  400. .drawer-name:hover {
  401. color: #409eff;
  402. cursor: pointer;
  403. }
  404. /deep/.el-table::before{
  405. display: none;
  406. }
  407. </style>