|
|
@@ -0,0 +1,275 @@
|
|
|
+<template>
|
|
|
+ <div class="git-graph-body">
|
|
|
+ <div class="command-container">
|
|
|
+ <div class="command-box" ref="command-box">
|
|
|
+ <b-field
|
|
|
+ v-for="c in commandHistory"
|
|
|
+ v-bind:key="c.id"
|
|
|
+ :type="c.result"
|
|
|
+ :message="c.info"
|
|
|
+ >
|
|
|
+ <b-input v-model="c.value" size="is-small" readOnly></b-input>
|
|
|
+ </b-field>
|
|
|
+ </div>
|
|
|
+ <b-field>
|
|
|
+ <!-- keypress事件 屏蔽中文输入法的enter -->
|
|
|
+ <b-input
|
|
|
+ id="command-input"
|
|
|
+ placeholder="git"
|
|
|
+ v-model="commandInput"
|
|
|
+ @keypress.enter.native="handleCommand"
|
|
|
+ ></b-input>
|
|
|
+ </b-field>
|
|
|
+ </div>
|
|
|
+ <!--分支图-->
|
|
|
+ <div class="gitgraph-container"><div id="gitgraph"></div></div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import { createGitgraph, templateExtend, TemplateName } from "@gitgraph/js";
|
|
|
+export default {
|
|
|
+ name: "GitGraph",
|
|
|
+ components: {},
|
|
|
+ props: {},
|
|
|
+ watch: {},
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ commandInput: "",
|
|
|
+ commandHistory: [],
|
|
|
+ fastCommandPointer: 0, // 上下按键访问历史命令
|
|
|
+ branchList: [],
|
|
|
+ currentBranchName: ""
|
|
|
+ };
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ /** 解析命令相关方法 */
|
|
|
+ handleCommand(event) {
|
|
|
+ //1 分词
|
|
|
+ let command = event.target.value;
|
|
|
+ command = command.trim();
|
|
|
+ let array = command.split(" ");
|
|
|
+ array = array.filter(i => i.length > 0);
|
|
|
+ console.log("array:", array);
|
|
|
+
|
|
|
+ //2 检测开头的 ‘git’
|
|
|
+ if (array.length < 1) {
|
|
|
+ this.commandWrong(command);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (array[0] !== "git") {
|
|
|
+ console.log("invalid command");
|
|
|
+ this.commandWrong(command);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ //3 检测第一个词
|
|
|
+ if (array.length < 2) {
|
|
|
+ this.commandWrong(command);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ //-*- git branch
|
|
|
+ if (array[1] === "branch") {
|
|
|
+ if (array.length === 3) {
|
|
|
+ // git branch master
|
|
|
+ this.makeBranch(array[2], command);
|
|
|
+ return;
|
|
|
+ } else {
|
|
|
+ this.commandWrong(command);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //-*- git commit
|
|
|
+ else if (array[1] === "commit") {
|
|
|
+ if (array.length === 2) {
|
|
|
+ this.makeCommit(this.currentBranchName, "", command);
|
|
|
+ return;
|
|
|
+ } else if (array.length === 4 && array[2] === "-m") {
|
|
|
+ this.makeCommit(this.currentBranchName, array[3], command);
|
|
|
+ return;
|
|
|
+ } else {
|
|
|
+ this.commandWrong(command);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //-*- git checkout
|
|
|
+ else if (array[1] === "checkout") {
|
|
|
+ if (array.length === 3) {
|
|
|
+ // git checkout master
|
|
|
+ this.makeCheckout(array[2], command);
|
|
|
+ } else if (array.length === 4 && array[2] === "-b") {
|
|
|
+ // git checkout -b dev
|
|
|
+ let step1 = this.makeBranch(array[3], command, true); // selfUse = true
|
|
|
+ if (step1) {
|
|
|
+ this.makeCheckout(array[3], command);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ this.commandWrong(command);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //-*- git merge
|
|
|
+ else if (array[1] === "merge") {
|
|
|
+ if (array.length === 3) {
|
|
|
+ // git merge dev
|
|
|
+ this.makeMerge(array[2], command);
|
|
|
+ } else {
|
|
|
+ this.commandWrong(command);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //-*- 不存在或暂时不支持的command
|
|
|
+ else {
|
|
|
+ this.commandWrong(command, "不存在或暂不支持的命令");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ commandCorrect(command) {
|
|
|
+ let cmd = {
|
|
|
+ id: this.commandHistory.length,
|
|
|
+ value: command,
|
|
|
+ result: "is-success"
|
|
|
+ };
|
|
|
+ this.recordCommand(cmd);
|
|
|
+ this.clearInput();
|
|
|
+ },
|
|
|
+ commandWrong(command, info = "invalid command") {
|
|
|
+ let cmd = {
|
|
|
+ id: this.commandHistory.length,
|
|
|
+ value: command,
|
|
|
+ result: "is-danger",
|
|
|
+ info: info
|
|
|
+ };
|
|
|
+ this.recordCommand(cmd);
|
|
|
+ this.clearInput();
|
|
|
+ },
|
|
|
+ clearInput() {
|
|
|
+ this.commandInput = "";
|
|
|
+ },
|
|
|
+ recordCommand(command) {
|
|
|
+ this.commandHistory.push(command);
|
|
|
+ this.fastCommandPointer = this.commandHistory.length - 1;
|
|
|
+ console.log(
|
|
|
+ this.$refs["command-box"].scrollTop,
|
|
|
+ this.$refs["command-box"].scrollHeight
|
|
|
+ );
|
|
|
+ this.$nextTick(() => {
|
|
|
+ this.$refs["command-box"].scrollTop = this.$refs[
|
|
|
+ "command-box"
|
|
|
+ ].scrollHeight;
|
|
|
+ });
|
|
|
+ },
|
|
|
+ /** 画图相关方法 */
|
|
|
+ makeBranch(branchName, command, selfUse) {
|
|
|
+ console.log("makeBranch", branchName);
|
|
|
+ let branchExist = this.branchList.find(item => item.name === branchName);
|
|
|
+ if (branchExist) {
|
|
|
+ this.commandWrong(command, "branch exist");
|
|
|
+ return false;
|
|
|
+ } else {
|
|
|
+ let newBranch = this.gitGraph.branch(branchName);
|
|
|
+ this.branchList.push(newBranch);
|
|
|
+ this.currentBranchName = branchName;
|
|
|
+ if (!selfUse) {
|
|
|
+ this.commandCorrect(command);
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ makeCommit(branchName, message, command) {
|
|
|
+ let branchExist = this.branchList.find(item => item.name === branchName);
|
|
|
+ if (branchExist) {
|
|
|
+ branchExist.commit(message);
|
|
|
+ this.commandCorrect(command);
|
|
|
+ } else {
|
|
|
+ this.commandWrong(command, "no branch name" + branchName);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ makeCheckout(branchName, command) {
|
|
|
+ let branchExist = this.branchList.find(item => item.name === branchName);
|
|
|
+ if (branchExist) {
|
|
|
+ this.currentBranchName = branchName;
|
|
|
+ this.commandCorrect(command);
|
|
|
+ } else {
|
|
|
+ this.commandWrong(command, "no branch name" + branchName);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ makePush() {},
|
|
|
+ makeMerge(branchName, command) {
|
|
|
+ let branchExist = this.branchList.find(item => item.name === branchName);
|
|
|
+ if (branchExist) {
|
|
|
+ let currentBranch = this.branchList.find(
|
|
|
+ item => item.name === this.currentBranchName
|
|
|
+ );
|
|
|
+ if (currentBranch) {
|
|
|
+ currentBranch.merge(branchExist);
|
|
|
+ this.commandCorrect(command);
|
|
|
+ } else {
|
|
|
+ this.commandWrong(command, "not on a branch ---should not happen");
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ this.commandWrong(command, "no branch name" + branchName);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ mounted() {
|
|
|
+ console.log("GitGraph mounted");
|
|
|
+ let self = this;
|
|
|
+ const myTemplate = templateExtend(TemplateName.BlackArrow, {
|
|
|
+ commit: {
|
|
|
+ message: {
|
|
|
+ displayHash: false,
|
|
|
+ displayAuthor: false
|
|
|
+ }
|
|
|
+ },
|
|
|
+ mode: "compact"
|
|
|
+ });
|
|
|
+ this.gitGraphContainer = document.getElementById("gitgraph");
|
|
|
+ this.gitGraph = createGitgraph(this.gitGraphContainer, {
|
|
|
+ template: myTemplate
|
|
|
+ });
|
|
|
+
|
|
|
+ // ⬆快捷键
|
|
|
+ document.onkeyup = function(e) {
|
|
|
+ if (e.key === "ArrowUp") {
|
|
|
+ self.fastCommandPointer = Math.max(self.fastCommandPointer - 1, 0);
|
|
|
+ self.commandInput = self.commandHistory[self.fastCommandPointer].value;
|
|
|
+ }
|
|
|
+ if (e.key === "ArrowDown") {
|
|
|
+ self.fastCommandPointer = Math.min(
|
|
|
+ self.fastCommandPointer + 1,
|
|
|
+ self.commandHistory.length - 1
|
|
|
+ );
|
|
|
+ self.commandInput = self.commandHistory[self.fastCommandPointer].value;
|
|
|
+ }
|
|
|
+ };
|
|
|
+ }
|
|
|
+};
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+@import "../../assets/scss/app";
|
|
|
+.git-graph-body {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ padding: 10px 20px;
|
|
|
+}
|
|
|
+.command-container {
|
|
|
+ width: 50%;
|
|
|
+ padding: 20px 20px 10px 20px;
|
|
|
+ border: $default-border;
|
|
|
+
|
|
|
+ .command-box {
|
|
|
+ margin: 0 0 50px 0;
|
|
|
+ max-height: 400px;
|
|
|
+ overflow: scroll;
|
|
|
+ padding: 0 10px;
|
|
|
+ }
|
|
|
+}
|
|
|
+.gitgraph-container {
|
|
|
+ width: 50%;
|
|
|
+ margin: 0 0 0 20px;
|
|
|
+ border: $default-border;
|
|
|
+}
|
|
|
+</style>
|