CommitDetails.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. <template>
  2. <div>
  3. <el-button type="text" size="small" @click="goBack">
  4. <i class="el-icon-back">返回上一页</i>
  5. </el-button>
  6. <el-card shadow="never" class="description-card">
  7. <el-link
  8. target="_blank"
  9. class="commit-id description-card-text"
  10. @click.stop.prevent="copy(commitId.id)"
  11. >
  12. <span>{{ commitId }}</span>
  13. <i class="el-icon-document-copy"></i>
  14. </el-link>
  15. <el-row :gutter="20">
  16. <el-col :span="commitInfo.checkResult === 'none' ? 24:16">
  17. <div class="description-card-text">
  18. <el-row style="height: 25px; line-height: 25px">
  19. <el-col :span="2">
  20. <b>类型:</b>
  21. </el-col>
  22. <el-col :span="22">
  23. <span v-if="!typeEditMode">
  24. <el-tag v-if="commitInfo.relatedType === 'bug_id'" class="type-line type-tag" color="chocolate" size="medium">缺陷</el-tag>
  25. <el-tag v-else-if="commitInfo.relatedType === 'none'" class="type-line type-tag" color="#ccc" size="medium">无类型</el-tag>
  26. <el-tag v-else class="type-line type-tag" color="#42b983" size="medium">需求</el-tag>
  27. <span v-if="commitInfo.relatedType !== 'none'" class="type-line">关联节点ID: {{commitInfo.relatedId}}</span>
  28. <el-button type="primary" size="mini" class="type-line" @click="typeEditMode = true">修改关联</el-button>
  29. </span>
  30. <span v-if="typeEditMode">
  31. <el-radio v-model="relatedTypeEdit" label="TREE_ID" size="large">需求</el-radio>
  32. <el-radio v-model="relatedTypeEdit" label="BUG_ID" size="large">缺陷</el-radio>
  33. <el-radio v-model="relatedTypeEdit" label="NONE" size="large">空</el-radio>
  34. <el-select v-if="relatedTypeEdit!='NONE'" v-model="relatedIdEdit" class="m-2 type-line" size="small" placeholder="Select">
  35. <el-option
  36. v-for="item in (relatedTypeEdit === 'TREE_ID'?treeList:bugList)"
  37. :key="item.id"
  38. :label="item.id + ' ' +(item.title === ''?'默认节点':item.title)"
  39. :value="item.id"
  40. />
  41. </el-select>
  42. <el-button type="info" size="mini" class="type-line" @click="typeEditMode = false">取消</el-button>
  43. <el-button type="primary" size="mini" class="type-line" @click="saveRelated">保存</el-button>
  44. </span>
  45. </el-col>
  46. </el-row>
  47. </div>
  48. <div class="description-card-text">
  49. <el-row>
  50. <el-col :span="2">
  51. <b>信息:</b>
  52. </el-col>
  53. <el-col :span="22">
  54. <span>{{ commitInfo.message }}</span>
  55. </el-col>
  56. </el-row>
  57. </div>
  58. <div class="description-card-text">
  59. <el-row>
  60. <el-col :span="2">
  61. <b>时间:</b>
  62. </el-col>
  63. <el-col :span="22">
  64. <span>{{ commitInfo.timestamp }}</span>
  65. </el-col>
  66. </el-row>
  67. </div>
  68. <div class="description-card-text">
  69. <el-row>
  70. <el-col :span="2">
  71. <b>提交人:</b>
  72. </el-col>
  73. <el-col :span="22">
  74. <span>{{ commitInfo.gitlabUsername }}</span>
  75. </el-col>
  76. </el-row>
  77. </div>
  78. <div class="description-card-text">
  79. <el-row style="height: 35px; line-height: 35px">
  80. <el-col :span="2">
  81. <b>parent:</b>
  82. </el-col>
  83. <el-col :span="22">
  84. <el-tag v-for="(parent, index) in commitInfo.parents"
  85. :key="index"
  86. @click="onParentTagClick(parent)"
  87. >{{parent}}</el-tag>
  88. </el-col>
  89. </el-row>
  90. </div>
  91. </el-col>
  92. <el-col v-if="commitInfo.checkResult !== 'none'" :span="8" class="left-line">
  93. <i v-if="commitInfo.checkResult === 'pass'" class="el-icon-circle-check check-pass">质量检查通过</i>
  94. <i v-else-if="commitInfo.checkResult === 'fail'" class="el-icon-circle-close check-fail">质量检查失败</i>
  95. </el-col>
  96. </el-row>
  97. </el-card>
  98. <el-divider content-position="left">
  99. 变更详情
  100. </el-divider>
  101. <div v-if="parentsCount > 0">
  102. <el-row :gutter="20">
  103. <el-col :span="8">
  104. <el-row :gutter="20">
  105. <el-col :span="12">
  106. <div class="grid-content">
  107. <el-select v-model="currentParentIndex" style="width: 100%">
  108. <el-option
  109. v-for="(item, index) in commitInfo.parents"
  110. :key="index"
  111. :label="'相比于 parent ' + item.substring(0,8)"
  112. :value="index">
  113. </el-option>
  114. </el-select>
  115. </div>
  116. </el-col>
  117. <el-col :span="12">
  118. <el-input
  119. v-model="fileNameKeyword"
  120. class="w-50 m-2"
  121. placeholder="检索文件名"
  122. :prefix-icon="Search"
  123. >
  124. <template #append>
  125. <el-button :icon="Search" @click="searchFileName">搜索</el-button>
  126. </template>
  127. </el-input>
  128. </el-col>
  129. </el-row>
  130. <el-row>
  131. <el-table :data="displayDiff[currentParentIndex]"
  132. max-height="350px"
  133. style="width: 100%"
  134. highlight-current-row
  135. @current-change="handleCurrentChange">
  136. <el-table-column prop="newPath" label="文件"/>
  137. <el-table-column prop="state" label="状态" width="100">
  138. <template #default="scope">
  139. <el-tag
  140. :type="scope.row.state < 0 ? 'danger' : (scope.row.state === 0 ? 'success' : '')"
  141. disable-transitions>
  142. {{ scope.row.stateDes }}
  143. </el-tag>
  144. </template>
  145. </el-table-column>
  146. </el-table>
  147. </el-row>
  148. </el-col>
  149. <el-col :span="16" style="height: 500px">
  150. <el-empty v-if="diffHtml === ''" description="请在左侧选择文件查看" />
  151. <div v-html="diffHtml" v-cloak></div>
  152. </el-col>
  153. </el-row>
  154. </div>
  155. <div v-else>
  156. <el-empty description="本次提交为首次提交,无法比较" />
  157. </div>
  158. </div>
  159. <!-- {{commitInfo}}-->
  160. </template>
  161. <script>
  162. import { BugListAPI, ProjectAPI, RequirementAPI } from '@/api';
  163. import * as Diff2Html from 'diff2html';
  164. import 'diff2html/bundles/css/diff2html.min.css';
  165. import { copy } from '@/utils/clipboard';
  166. import { ref } from 'vue';
  167. import { ElMessage, ElMessageBox } from 'element-plus';
  168. import { formatter } from '../../utils/time';
  169. export default {
  170. name: 'CommitDetials.vue',
  171. data() {
  172. return {
  173. commitInfo: {},
  174. originAllDiffs: [],
  175. diffString: '',
  176. parentsCount: 0,
  177. currentParentIndex: 0,
  178. diffHtml: '',
  179. fileNameKeyword: '',
  180. displayDiff: [],
  181. currentFileRow: ref(),
  182. typeEditMode: false,
  183. relatedTypeEdit: 'TREE_ID',
  184. relatedIdEdit: 1,
  185. bugList: [],
  186. treeList: [],
  187. };
  188. },
  189. computed: {
  190. projectId() {
  191. return this.$route.params.projectId;
  192. },
  193. commitId() {
  194. return this.$route.query.id;
  195. },
  196. },
  197. async mounted() {
  198. await this.loadCommitInfo();
  199. await this.loadRelatedLists();
  200. },
  201. methods: {
  202. copy,
  203. async loadCommitInfo() {
  204. this.commitInfo = await ProjectAPI.getCommitByHash(this.$store.state.workspace.currentProjectId, this.commitId);
  205. this.commitInfo.timestamp = formatter(this.commitInfo.timestamp);
  206. this.parentsCount = this.commitInfo.parents.length;
  207. for (let i = 0; i < this.parentsCount; i += 1) {
  208. const parentHash = this.commitInfo.parents[i];
  209. // eslint-disable-next-line no-await-in-loop
  210. const diffFiles = await ProjectAPI.getCommitsDiff(this.$store.state.workspace.currentProjectId, parentHash, this.commitId);
  211. for (let j = 0; j < diffFiles.length; j += 1) {
  212. const diffFile = diffFiles[j];
  213. if (diffFile.deletedFile) {
  214. diffFile.state = -1;
  215. diffFile.stateDes = '删除';
  216. } else if (diffFile.newFile) {
  217. diffFile.state = 0;
  218. diffFile.stateDes = '新增';
  219. } else if (diffFile.renamedFile) {
  220. diffFile.state = 1;
  221. diffFile.stateDes = '改名';
  222. } else {
  223. diffFile.state = 2;
  224. diffFile.stateDes = '修改';
  225. }
  226. }
  227. this.originAllDiffs.push(diffFiles);
  228. }
  229. this.displayDiff = this.originAllDiffs;
  230. },
  231. async loadRelatedLists() {
  232. this.bugList = await BugListAPI.getBugListByProjectId(this.$store.state.workspace.currentProjectId);
  233. this.treeList = await RequirementAPI.getTasksByProjectId(this.$store.state.workspace.currentProjectId);
  234. },
  235. drawDiffHtml() {
  236. // this.diffString = this.diff[this.currentParentIndex][0].diff;
  237. this.diffString = this.currentFileRow.diff;
  238. this.diffHtml = Diff2Html.html(this.diffString, {
  239. drawFileList: false,
  240. matching: 'lines',
  241. outputFormat: 'line-by-line',
  242. // maxLineSizeInBlockForComparison: 10,
  243. });
  244. },
  245. goBack() {
  246. this.$router.go(-1);
  247. this.loadCommitInfo();
  248. },
  249. handleCurrentChange(val) {
  250. this.currentFileRow = val;
  251. this.drawDiffHtml();
  252. },
  253. onParentTagClick(id) {
  254. console.log(id);
  255. // this.$router.push({
  256. // path: `/project/${this.$store.state.workspace.currentProjectId}/commit-detail`,
  257. // query: {
  258. // id,
  259. // },
  260. // });
  261. // this.loadCommitInfo();
  262. },
  263. searchFileName() {
  264. this.displayDiff = [];
  265. for (let i = 0; i < this.parentsCount; i += 1) {
  266. this.displayDiff.push(this.originAllDiffs[i]
  267. .filter((diffFile) => diffFile.newPath.indexOf(this.fileNameKeyword) >= 0));
  268. }
  269. },
  270. async saveRelated() {
  271. const response = ProjectAPI.linkCommit(this.projectId, this.commitId, this.relatedTypeEdit, this.relatedIdEdit);
  272. ElMessage('success');
  273. await this.loadCommitInfo();
  274. this.typeEditMode = false;
  275. },
  276. },
  277. };
  278. </script>
  279. <style scoped>
  280. /* .el-row {
  281. margin-bottom: 20px;
  282. } */
  283. [v-cloak] {
  284. display: none;
  285. }
  286. .description-card {
  287. margin: 10px 0;
  288. }
  289. .description-card-text {
  290. margin-top: 8px;
  291. }
  292. .commit-id {
  293. font-size: 18px;
  294. font-weight: bold;
  295. }
  296. .commit-title {
  297. font-weight: bold;
  298. }
  299. .el-tag {
  300. margin: 3px 10px;
  301. }
  302. .bug {
  303. background-color: chocolate;
  304. }
  305. .none{
  306. background-color: #ccc;
  307. }
  308. .requirement {
  309. background-color: #42b983;
  310. }
  311. .check-pass {
  312. color: green;
  313. }
  314. .check-fail {
  315. color: red;
  316. }
  317. .left-line {
  318. border-left-style: solid;
  319. border-left-color: lightgrey;
  320. }
  321. .type-line{
  322. margin: 0;
  323. margin-right: 20px;
  324. /*color: #ffffff;*/
  325. }
  326. .type-tag{
  327. color: #ffffff;
  328. }
  329. </style>