Commit.vue 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. <template>
  2. <div class="container">
  3. <el-row class="row-item title">
  4. <h2>commit记录</h2>
  5. </el-row>
  6. <div>
  7. <el-row :gutter="20">
  8. <el-col :span="6">
  9. <el-select v-model="currentBranch" class="m-2" placeholder="Select" size="large">
  10. <el-option
  11. v-for="(branch, index) in branches"
  12. :key="index"
  13. :label="branch.name"
  14. :value="branch.name"
  15. @change="onSearch"
  16. />
  17. </el-select>
  18. </el-col>
  19. <el-col :span="6">
  20. <el-select
  21. v-model="currentAuthors"
  22. multiple
  23. collapse-tags
  24. placeholder="选择处理人"
  25. >
  26. <el-option
  27. v-for="(author, index) in authors"
  28. :key="index"
  29. :label="author"
  30. :value="author"
  31. />
  32. </el-select>
  33. </el-col>
  34. <el-col :span="8">
  35. <el-input v-model="keyword" placeholder="输入检索message内容或Hash" clearable />
  36. </el-col>
  37. <el-col :span="2">
  38. <el-button type="primary" @click="onSearch">过滤</el-button>
  39. </el-col>
  40. <el-col v-if="!showGraph" :span="2">
  41. <el-button type="primary" @click="showGraph = canShowGraph">图形</el-button>
  42. </el-col>
  43. <el-col v-else :span="2">
  44. <el-button type="info" @click="showGraph = false">隐藏</el-button>
  45. </el-col>
  46. </el-row>
  47. <div v-if="originCommits.length === 0">
  48. <el-empty description="暂无commit记录!"></el-empty>
  49. </div>
  50. <div v-else>
  51. <el-row :gutter="20">
  52. <el-col style="padding-bottom: 20px; text-align: center; overflow: auto; transform: scaleY(-1)" v-show="(showGraph)" :span="6">
  53. <div style="transform: scaleY(-1)" id="graph-container"></div>
  54. </el-col>
  55. <el-col :span="(showGraph)?18:24">
  56. <ElTimeline>
  57. <ElTimelineItem
  58. v-for="(git, index) in displayCommits"
  59. :key="index"
  60. :timestamp="git.timestamp"
  61. placement="top"
  62. :color="git.relatedType === 'bug_id' ? 'chocolate' : (git.relatedType === 'none' ? '#ccc': '#42b983')"
  63. size="large">
  64. <ElCard shadow="hover"
  65. @click="clickCommitCard(git.id)"
  66. style="height: 35px;"
  67. body-style="padding: 5px 20px">
  68. <h3 class="view-text">{{git.title}}</h3>
  69. <div >
  70. <el-row style="padding: 0;margin: 0; border: 0">
  71. <el-col :span="6">
  72. <el-link
  73. target="_blank"
  74. type="info"
  75. @click.stop.prevent="copy(git.id)"
  76. >
  77. <span style="color: #888">{{git.id.substring(0, 8)}}</span>
  78. <i class="el-icon-document-copy"></i>
  79. </el-link>
  80. </el-col>
  81. <el-col :span="12">
  82. 处理人:<span style="font-weight: bold">{{git.gitlabUsername}}</span>
  83. </el-col>
  84. <el-col :span="6">
  85. 类型:
  86. <span v-if="git.relatedType === 'bug_id'" class="node bug">缺陷</span>
  87. <span v-else-if="git.relatedType === 'none'" class="node none">无类型</span>
  88. <span v-else class="node requirement">需求</span></el-col>
  89. </el-row>
  90. </div>
  91. </ElCard>
  92. </ElTimelineItem>
  93. </ElTimeline>
  94. </el-col>
  95. </el-row>
  96. </div>
  97. </div>
  98. </div>
  99. </template>
  100. <script>
  101. import { ProjectAPI } from '@/api';
  102. import { copy } from '@/utils/clipboard';
  103. import {
  104. createGitgraph, templateExtend, TemplateName, Mode,
  105. } from '@gitgraph/js';
  106. import { formatter } from '../../utils/time';
  107. export default {
  108. name: 'Commit.vue',
  109. data() {
  110. return {
  111. branches: [],
  112. originCommits: [],
  113. displayCommits: [],
  114. authors: [],
  115. lastBranch: '',
  116. currentBranch: '',
  117. currentAuthors: [],
  118. keyword: '',
  119. showGraph: true,
  120. canShowGraph: true,
  121. };
  122. },
  123. async mounted() {
  124. this.branches = await ProjectAPI.getAllBranches(this.$store.state.workspace.currentProjectId);
  125. if (this.branches.length !== 0) {
  126. this.currentBranch = this.branches[0].name;
  127. this.lastBranch = this.currentBranch;
  128. await this.loadBranch();
  129. await this.generateGitGraph();
  130. }
  131. },
  132. methods: {
  133. copy,
  134. async loadBranch() {
  135. this.originCommits = await ProjectAPI.getCommitsByBranch(this.$store.state.workspace.currentProjectId, this.currentBranch);
  136. // console.log(this.originCommits);
  137. this.authors = [];
  138. for (let i = 0; i < this.originCommits.length; i += 1) {
  139. this.originCommits[i].timestamp = formatter(this.originCommits[i].timestamp);
  140. const author = this.originCommits[i].gitlabUsername;
  141. if (this.authors.indexOf(author) === -1) {
  142. this.authors.push(author);
  143. }
  144. }
  145. this.displayCommits = this.originCommits;
  146. },
  147. clickCommitCard(id) {
  148. // console.log(id);
  149. this.$router.push({
  150. path: `/project/${this.$store.state.workspace.currentProjectId}/commit-detail`,
  151. query: {
  152. id,
  153. },
  154. });
  155. },
  156. async onSearch() {
  157. if (this.currentBranch !== this.lastBranch) {
  158. await this.loadBranch();
  159. this.lastBranch = this.currentBranch;
  160. await this.generateGitGraph();
  161. }
  162. this.displayCommits = this.originCommits
  163. .filter((commit) => (this.currentAuthors.length === 0 || this.currentAuthors.indexOf(commit.gitlabUsername) >= 0)
  164. && (commit.id.startsWith(this.keyword) || commit.title.indexOf(this.keyword) >= 0));
  165. this.canShowGraph = this.keyword === '' && this.currentAuthors.length === 0;
  166. this.showGraph = this.showGraph && this.canShowGraph;
  167. },
  168. async generateGitGraph() {
  169. if (this.originCommits.length === 0) {
  170. return;
  171. }
  172. const graphContainer = document.getElementById('graph-container');
  173. graphContainer.innerHTML = '';
  174. if (graphContainer == null) {
  175. console.log('null container');
  176. }
  177. const gitgraph = createGitgraph(graphContainer, {
  178. /* options */
  179. // mode: Mode.Compact, // compact 模式,在 tooltip 顯示提交信息
  180. template: templateExtend(TemplateName.Metro, {
  181. commit: {
  182. message: {
  183. displayAuthor: false,
  184. displayHash: false,
  185. },
  186. },
  187. branch: {
  188. label: {
  189. display: false,
  190. },
  191. },
  192. }),
  193. });
  194. // const gitgraph = createGitgraph(graphContainer);
  195. const sonMap = {};
  196. for (let i = 0; i < this.originCommits.length; i += 1) {
  197. const commit = this.originCommits[i];
  198. for (let j = 0; j < commit.parents.length; j += 1) {
  199. const parentCommit = commit.parents[j];
  200. if (!Object.prototype.hasOwnProperty.call(sonMap, parentCommit)) {
  201. sonMap[parentCommit] = [commit.id];
  202. } else {
  203. sonMap[parentCommit].push(commit.id);
  204. }
  205. }
  206. }
  207. let curBranchNum = 0;
  208. const branchPrefix = 'b';
  209. const graphCommits = [];
  210. for (let i = 0; i < this.originCommits.length; i += 1) {
  211. const originCommit = this.originCommits[i];
  212. const graphCommit = {};
  213. if (!Object.prototype.hasOwnProperty.call(sonMap, originCommit.id)) {
  214. const newBranchName = branchPrefix + curBranchNum;
  215. curBranchNum += 1;
  216. graphCommit.refs = [newBranchName];
  217. } else {
  218. graphCommit.refs = [];
  219. }
  220. graphCommit.hash = originCommit.id;
  221. graphCommit.parents = originCommit.parents;
  222. // const date = new Date(originCommit.timestamp);
  223. // const time = date.getTime();
  224. graphCommit.author = {
  225. name: originCommit.gitlabUsername,
  226. // timestamp: time,
  227. };
  228. graphCommit.subject = '';
  229. graphCommits.push(graphCommit);
  230. }
  231. gitgraph.import(graphCommits);
  232. },
  233. },
  234. };
  235. </script>
  236. <style scoped>
  237. .container {
  238. margin: 50px 100px;
  239. width: 80%;
  240. }
  241. .row-item {
  242. display: flex;
  243. flex-direction: row;
  244. align-items: center;
  245. margin-bottom: 10px;
  246. }
  247. .id {
  248. width: fit-content;
  249. height: 20px;
  250. background-color: #2185d0;
  251. color: #fff;
  252. border: 0 solid transparent;
  253. border-radius: .28571429rem;
  254. }
  255. .node {
  256. width: 15px;
  257. color: #FFFFFF;
  258. border-radius: 3px;
  259. font-size: 14px;
  260. text-align: center;
  261. }
  262. .bug {
  263. background-color: chocolate;
  264. }
  265. .none{
  266. background-color: #ccc;
  267. }
  268. .requirement {
  269. background-color: #42b983;
  270. }
  271. .view-text{
  272. display: inline-block;
  273. white-space: nowrap;
  274. width: 100%;
  275. overflow: hidden;
  276. text-overflow:ellipsis;
  277. }
  278. .el-row{
  279. margin-bottom: 20px;
  280. }
  281. </style>