feat: convert issue_repo_commit for tapd (#4824) (#4830)

diff --git a/backend/plugins/tapd/tasks/bug_commit_converter.go b/backend/plugins/tapd/tasks/bug_commit_converter.go
index a7cc318..a5550e8 100644
--- a/backend/plugins/tapd/tasks/bug_commit_converter.go
+++ b/backend/plugins/tapd/tasks/bug_commit_converter.go
@@ -25,7 +25,9 @@
 	"github.com/apache/incubator-devlake/core/plugin"
 	helper "github.com/apache/incubator-devlake/helpers/pluginhelper/api"
 	"github.com/apache/incubator-devlake/plugins/tapd/models"
+	"net/url"
 	"reflect"
+	"strings"
 )
 
 func ConvertBugCommit(taskCtx plugin.SubTaskContext) errors.Error {
@@ -49,14 +51,33 @@
 		Input:              cursor,
 		Convert: func(inputRow interface{}) ([]interface{}, errors.Error) {
 			toolL := inputRow.(*models.TapdBugCommit)
-			domainL := &crossdomain.IssueCommit{
+			results := make([]interface{}, 0, 2)
+			issueCommit := &crossdomain.IssueCommit{
 				IssueId:   issueIdGen.Generate(data.Options.ConnectionId, toolL.BugId),
 				CommitSha: toolL.CommitId,
 			}
+			results = append(results, issueCommit)
+			if toolL.WebURL != `` {
+				u, err := errors.Convert01(url.Parse(toolL.WebURL))
+				if err != nil {
+					return nil, err
+				}
+				repoUrl := toolL.WebURL
+				if !strings.HasSuffix(repoUrl, `.git`) {
+					repoUrl = repoUrl + `.git`
+				}
+				issueRepoCommit := &crossdomain.IssueRepoCommit{
+					IssueId:   issueIdGen.Generate(data.Options.ConnectionId, toolL.BugId),
+					RepoUrl:   repoUrl,
+					CommitSha: toolL.CommitId,
+					Host:      u.Host,
+					Namespace: strings.Split(u.Path, `/`)[1],
+					RepoName:  toolL.HookProjectName,
+				}
+				results = append(results, issueRepoCommit)
+			}
 
-			return []interface{}{
-				domainL,
-			}, nil
+			return results, nil
 		},
 	})
 	if err != nil {
diff --git a/backend/plugins/tapd/tasks/story_commit_converter.go b/backend/plugins/tapd/tasks/story_commit_converter.go
index 9b2cb2b..cf9c1e6 100644
--- a/backend/plugins/tapd/tasks/story_commit_converter.go
+++ b/backend/plugins/tapd/tasks/story_commit_converter.go
@@ -25,7 +25,9 @@
 	"github.com/apache/incubator-devlake/core/plugin"
 	helper "github.com/apache/incubator-devlake/helpers/pluginhelper/api"
 	"github.com/apache/incubator-devlake/plugins/tapd/models"
+	"net/url"
 	"reflect"
+	"strings"
 )
 
 func ConvertStoryCommit(taskCtx plugin.SubTaskContext) errors.Error {
@@ -47,14 +49,33 @@
 		Input:              cursor,
 		Convert: func(inputRow interface{}) ([]interface{}, errors.Error) {
 			toolL := inputRow.(*models.TapdStoryCommit)
-			domainL := &crossdomain.IssueCommit{
+			results := make([]interface{}, 0, 2)
+			issueCommit := &crossdomain.IssueCommit{
 				IssueId:   issueIdGen.Generate(data.Options.ConnectionId, toolL.StoryId),
 				CommitSha: toolL.CommitId,
 			}
+			results = append(results, issueCommit)
+			if toolL.WebURL != `` {
+				u, err := errors.Convert01(url.Parse(toolL.WebURL))
+				if err != nil {
+					return nil, err
+				}
+				repoUrl := toolL.WebURL
+				if !strings.HasSuffix(repoUrl, `.git`) {
+					repoUrl = repoUrl + `.git`
+				}
+				issueRepoCommit := &crossdomain.IssueRepoCommit{
+					IssueId:   issueIdGen.Generate(data.Options.ConnectionId, toolL.StoryId),
+					RepoUrl:   repoUrl,
+					CommitSha: toolL.CommitId,
+					Host:      u.Host,
+					Namespace: strings.Split(u.Path, `/`)[1],
+					RepoName:  toolL.HookProjectName,
+				}
+				results = append(results, issueRepoCommit)
+			}
 
-			return []interface{}{
-				domainL,
-			}, nil
+			return results, nil
 		},
 	})
 	if err != nil {
diff --git a/backend/plugins/tapd/tasks/task_commit_converter.go b/backend/plugins/tapd/tasks/task_commit_converter.go
index 7446997..53efe46 100644
--- a/backend/plugins/tapd/tasks/task_commit_converter.go
+++ b/backend/plugins/tapd/tasks/task_commit_converter.go
@@ -25,7 +25,9 @@
 	"github.com/apache/incubator-devlake/core/plugin"
 	helper "github.com/apache/incubator-devlake/helpers/pluginhelper/api"
 	"github.com/apache/incubator-devlake/plugins/tapd/models"
+	"net/url"
 	"reflect"
+	"strings"
 )
 
 func ConvertTaskCommit(taskCtx plugin.SubTaskContext) errors.Error {
@@ -50,14 +52,33 @@
 		Input:              cursor,
 		Convert: func(inputRow interface{}) ([]interface{}, errors.Error) {
 			toolL := inputRow.(*models.TapdTaskCommit)
-			domainL := &crossdomain.IssueCommit{
+			results := make([]interface{}, 0, 2)
+			issueCommit := &crossdomain.IssueCommit{
 				IssueId:   issueIdGen.Generate(data.Options.ConnectionId, toolL.TaskId),
 				CommitSha: toolL.CommitId,
 			}
+			results = append(results, issueCommit)
+			if toolL.WebURL != `` {
+				u, err := errors.Convert01(url.Parse(toolL.WebURL))
+				if err != nil {
+					return nil, err
+				}
+				repoUrl := toolL.WebURL
+				if !strings.HasSuffix(repoUrl, `.git`) {
+					repoUrl = repoUrl + `.git`
+				}
+				issueRepoCommit := &crossdomain.IssueRepoCommit{
+					IssueId:   issueIdGen.Generate(data.Options.ConnectionId, toolL.TaskId),
+					RepoUrl:   repoUrl,
+					CommitSha: toolL.CommitId,
+					Host:      u.Host,
+					Namespace: strings.Split(u.Path, `/`)[1],
+					RepoName:  toolL.HookProjectName,
+				}
+				results = append(results, issueRepoCommit)
+			}
 
-			return []interface{}{
-				domainL,
-			}, nil
+			return results, nil
 		},
 	})
 	if err != nil {
diff --git a/config-ui/src/plugins/register/zentao/config.ts b/config-ui/src/plugins/register/zentao/config.ts
index 2547c53..b75b36a 100644
--- a/config-ui/src/plugins/register/zentao/config.ts
+++ b/config-ui/src/plugins/register/zentao/config.ts
@@ -34,7 +34,7 @@
       'name',
       {
         key: 'endpoint',
-        subLabel: 'Provide the Zentao instance API endpoint (Opensource v16+). E.g. http://<host>:<port>/api.php/v1',
+        subLabel: 'Provide the Zentao instance API endpoint (Opensource v16+). E.g. http://<host>:<port>/api.php/v1 or http://<host>:<port>/zentao/api.php/v1',
       },
       'username',
       'password',