Browse Source

Merge branch 'computing' of git.openi.org.cn:OpenI/aiforge into computing

merge
pull/1425/head
ychao_1983 3 years ago
parent
commit
ffeaad2ec9
16 changed files with 1026 additions and 70 deletions
  1. +3
    -2
      models/action.go
  2. +1
    -1
      models/user_business_analysis.go
  3. +31
    -28
      options/locale/locale_en-US.ini
  4. +7
    -0
      options/locale/locale_zh-CN.ini
  5. +30
    -15
      public/home/home.js
  6. +16
    -9
      routers/repo/repo_statistic.go
  7. +1
    -1
      routers/repo/user_data_analysis.go
  8. +23
    -8
      services/socketwrap/clientManager.go
  9. +1
    -1
      templates/base/head_navbar.tmpl
  10. +1
    -1
      templates/home.tmpl
  11. +334
    -0
      templates/org/course_list.tmpl
  12. +479
    -0
      templates/org/home_courses.tmpl
  13. +0
    -0
      templates/org/member/course_members.tmpl
  14. +0
    -0
      templates/org/team/courseTeams.tmpl
  15. +98
    -0
      templates/repo/createCourse.tmpl
  16. +1
    -4
      web_src/js/components/UserAnalysis.vue

+ 3
- 2
models/action.go View File

@@ -364,11 +364,12 @@ func GetFeeds(opts GetFeedsOptions) ([]*Action, error) {
return actions, nil
}

func GetLast20PublicFeeds() ([]*Action, error) {
func GetLast20PublicFeeds(opTypes []int) ([]*Action, error) {
cond := builder.NewCond()
cond = cond.And(builder.Eq{"is_private": false})
cond = cond.And(builder.Eq{"is_deleted": false})

cond = cond.And(builder.Expr("user_id=act_user_id"))
cond = cond.And(builder.In("op_type", opTypes))

actions := make([]*Action, 0, 20)



+ 1
- 1
models/user_business_analysis.go View File

@@ -387,7 +387,7 @@ func refreshUserStaticTable(wikiCountMap map[string]int, CommitCodeSizeMap map[s

OpenIIndexMap := queryUserRepoOpenIIndex(startTime.Unix(), end_unix)

DataDate := currentTimeNow.Format("2006-01-02")
DataDate := currentTimeNow.Format("2006-01-02") + " 00:01"

cond := "type != 1 and is_active=true"
count, err := sess.Where(cond).Count(new(User))


+ 31
- 28
options/locale/locale_en-US.ini View File

@@ -222,42 +222,42 @@ issues.in_your_repos = In your repositories
contributors = Contributors

page_title=Explore Better AI
page_small_title=OpenI AI development cooperation platform
page_small_title=OpenI AI Development Cooperation Platform
page_description=The one-stop collaborative development environment for AI field provides AI development pipeline integrating code development, data management, model debugging, reasoning and evaluation
page_use=Use Now
page_only_dynamic=Show only open source project dynamics
page_recommend_org=Recommended organization
page_recommend_org_desc=These excellent organizations are using Qizhi AI to develop collaboration platforms; Your organization also wants to show here,
page_recommend_org_commit=Click here to submit
page_recommend_org_more=More organizations
page_recommend_repo=Recommended projects
page_recommend_repo_desc=Excellent AI project recommendation; Your project also wants to show here,
page_recommend_repo_commit=Click here to submit
page_recommend_repo_go=. Click here
page_recommend_repo_more=Project Square
page_dev_env=Collaborative development environment
page_dev_env_desc=The biggest difference between Qizhi AI collaborative development platform and traditional git platform is that it provides a collaborative development environment for AI development
page_dev_env_desc_title=Unified management of development elements
page_dev_env_desc_desc=The platform provides four elements of AI development: unified management of model code, data set, model and execution environment
page_dev_env_desc1_title=Data collaboration and sharing
page_dev_env_desc1_desc=By uploading data sets in the project, many project members cooperate to complete data preprocessing; You can also establish a better model with community developers by setting the data as a public dataset
page_dev_env_desc2_title=Model management and sharing
page_dev_env_desc2_desc=Associate the model with the code version, adjust the model in different ways based on the code history version, and save the results; The trained model can be open and shared, so that more people can use the model to test and give feedback
page_dev_env_desc3_title=One configuration, multiple use
page_dev_env_desc3_desc=Provide execution environment sharing, one-time configuration and multiple use, reduce the threshold of model development, and avoid spending repeated time configuring complex environments
page_dev_yunlao=PengCheng Cloudbrain open source collaboration
page_dev_yunlao_desc1=The platform has been connected with Pengcheng Cloudbrain and can use the rich computing resources of Pengcheng Cloudbrain to complete AI development tasks
page_dev_yunlao_desc2=Pengcheng Cloudbrain's existing AI computing power is 100p FLOPS@FP16 (billions of half precision floating-point calculations per second), the main hardware infrastructure is composed of GPU server equipped with NVIDIA Tesla V100 and Atlas 900 AI cluster equipped with Kunpeng and shengteng processors
page_dev_yunlao_desc3=Developers can freely choose the corresponding computing resources according to the use requirements, and can test the adaptability, performance and stability of the model in different hardware environments
page_dev_yunlao_desc4=If your model needs more computing resources, you can also apply separately
page_dev_yunlao_apply=Separate apply
page_only_dynamic=Only show the dynamics of open source projects
page_recommend_org=Recommended Organization
page_recommend_org_desc=These excellent organizations are using the OpenI AI Collaboration Platform for collaborative development of projects. To show your organization here,
page_recommend_org_commit=Click here to submit.
page_recommend_org_more=More Organizations
page_recommend_repo=Recommended Projects
page_recommend_repo_desc=Excellent AI projects recommendation. To show your project here,
page_recommend_repo_commit=Click here to submit.
page_recommend_repo_go=Click here to
page_recommend_repo_more=explore more projects.
page_dev_env=Collaborative Development Environment
page_dev_env_desc=Provide a collaborative development environment for AI development, which is the biggest highlight that distinguishes the OpenI AI Collaboration Platform from other traditional Git platforms.
page_dev_env_desc_title=Unified Management of Development Elements
page_dev_env_desc_desc=The platform provides four elements of AI development: unified management of model code, data set, model and execution environment.
page_dev_env_desc1_title=Data Collaboration and Sharing
page_dev_env_desc1_desc=By uploading data sets in the project, many project members cooperate to complete data preprocessing. You can also establish a better model with community developers by setting the data as a public dataset.
page_dev_env_desc2_title=Model Management and Sharing
page_dev_env_desc2_desc=Associate the model with the code version, you can adjust the model in different ways based on the historical version of the code and save the results. The trained model can be open and shared, so that more people can use the model to test and give feedback.
page_dev_env_desc3_title=Once Configuration, Multiple Reuse
page_dev_env_desc3_desc=Provide execution environment sharing, Once Configuration, Multiple Reuse. Lower the threshold of model development, and avoid spending repetitive time configuring complex environments.
page_dev_yunlao=PengCheng Cloudbrain Open Source Collaboration
page_dev_yunlao_desc1=The platform has been connected with Pengcheng Cloudbrain and can use the rich computing resources of Pengcheng Cloudbrain to complete AI development tasks.
page_dev_yunlao_desc2=Pengcheng Cloudbrain's existing AI computing power is 100p FLOPS@FP16 (billions of half precision floating-point calculations per second), the main hardware infrastructure is composed of GPU server equipped with NVIDIA Tesla V100 and Atlas 900 AI cluster equipped with Kunpeng and Ascend processors.
page_dev_yunlao_desc3=Developers can freely choose the corresponding computing resources according to their needs, and can test the adaptability, performance, stability of the model in different hardware environments.
page_dev_yunlao_desc4=If your model requires more computing resources, you can also apply for it separately.
page_dev_yunlao_apply=Apply Separately

[explore]
repos = Repositories
select_repos = Select the project
users = Users
organizations = Organizations
images = CloudImages
images = Cloudbrain Mirror
search = Search
code = Code
repo_no_results = No matching repositories found.
@@ -348,6 +348,8 @@ modify = Update
[form]
UserName = Username
Alias = Repository name
courseAlias = Course Name
courseAdress = Course Path
RepoPath = Repository path
RepoAdress = Repository Adress
Email = Email address
@@ -2703,6 +2705,7 @@ error.unit_not_allowed = You are not allowed to access this repository section.
head.community = Community
head.project = Repositories
head.openi = OpenI
head.openi.repo = OpenI Projects
head.dataset = Datasets
foot.council = Council
foot.technical_committee = Technical Committee


+ 7
- 0
options/locale/locale_zh-CN.ini View File

@@ -353,6 +353,8 @@ modify=更新
UserName=用户名
RepoName=项目路径
Alias=项目名称
courseAlias=课程名称
courseAdress=课程地址
RepoPath=项目路径
RepoAdress=项目地址
Email=邮箱地址
@@ -802,6 +804,7 @@ generate_from=生成自
repo_desc=项目描述
repo_lang=项目语言
repo_gitignore_helper=选择 .gitignore 模板。
repo_label_helpe=输入完成后回车键完成标签确定。
issue_labels=任务标签
issue_labels_helper=选择一个任务标签集
license=授权许可
@@ -2050,6 +2053,7 @@ team_access_desc=项目权限
team_permission_desc=权限
team_unit_desc=允许访问项目单元
team_unit_disabled=(已禁用)
selected_couse=精选课程

form.name_reserved=组织名称 '%s' 是被保留的。
form.name_pattern_not_allowed=组织名称中不允许使用 "%s"。
@@ -2136,6 +2140,9 @@ teams.all_repositories_read_permission_desc=此团队授予<strong>读取</stron
teams.all_repositories_write_permission_desc=此团队授予<strong>修改</strong><strong>所有项目</strong>的访问权限: 成员可以查看和推送至项目。
teams.all_repositories_admin_permission_desc=该团队拥有 <strong>管理</strong> <strong>所有项目</strong>的权限:团队成员可以读取、克隆、推送以及添加其它项目协作者。

teams.join_teams=加入该组织


[admin]
dashboard=管理面板
users=帐户管理


+ 30
- 15
public/home/home.js View File

@@ -42,10 +42,10 @@ if(document.location.host == "git.openi.org.cn" || document.URL.startsWith("http
var socket = new WebSocket(url);

socket.onopen = function () {
messageQueue = [];
console.log("message has connected.");
};

var messageQueue = [];
var maxSize = 20;
var html =document.documentElement;
var lang = html.attributes["lang"]
@@ -165,12 +165,12 @@ function getTime(UpdatedUnix,currentTime){
var seconds= leave3;

if(hours == 0 && minutes == 0){
return seconds + getRepoOrOrg(6,isZh);
return seconds + getRepoOrOrg(6,isZh,seconds);
}else{
if(hours > 0){
return hours + getRepoOrOrg(4,isZh);
return hours + getRepoOrOrg(4,isZh,hours);
}else{
return minutes + getRepoOrOrg(5,isZh);
return minutes + getRepoOrOrg(5,isZh,minutes);
}
}
}
@@ -239,7 +239,7 @@ var actionNameZH={
"5":"推送了 {branch} 分支的代码到",
"6":"创建了任务",
"7":"创建了合并请求",
"9":"推送了 {branch} 分支的代码到",
"9":"推送了标签 {branch} 到",
"10":"评论了任务",
"11":"合并了合并请求",
"12":"关闭了任务",
@@ -257,7 +257,7 @@ var actionNameEN={
"5":" pushed to {branch} at",
"6":" opened issue",
"7":" created pull request",
"9":" pushed to {branch} at",
"9":" pushed tag {branch} to ",
"10":" commented on issue",
"11":" merged pull request",
"12":" closed issue",
@@ -273,18 +273,30 @@ var repoAndOrgZH={
"1":"项目",
"2":"成员",
"3":"团队",
"11":"项目",
"21":"成员",
"31":"团队",
"4":"小时前",
"5":"分钟前",
"6":"秒前"
"6":"秒前",
"41":"小时前",
"51":"分钟前",
"61":"秒前"
};

var repoAndOrgEN={
"1":"repository",
"2":"Members ",
"3":"Teams",
"4":" hours ago",
"5":" minutes ago",
"6":" seconds ago"
"1":"Repository",
"2":"Member ",
"3":"Team",
"11":"Repositorys",
"22":"Members ",
"31":"Teams",
"4":" hour ago",
"5":" minute ago",
"6":" second ago",
"41":" hours ago",
"51":" minutes ago",
"61":" seconds ago"
};


@@ -415,7 +427,10 @@ function displayRepo(json){
//var repoAndOrgEN = new Map([['1', "Repository"], ['2', "Members"], ['3', "Teams"]]);


function getRepoOrOrg(key,isZhLang){
function getRepoOrOrg(key,isZhLang,numbers=1){
if(numbers > 1){
key+="1";
}
if(isZhLang){
return repoAndOrgZH[key];
}else{
@@ -436,7 +451,7 @@ function displayOrg(json){
html += " <img class=\"ui image\" src=\"" + record["Avatar"] + "\">";
html += " <div class=\"content nowrap\">";
html += " <span class=\"ui blue\">" + record["Name"] + "</span> " + record["FullName"];
html += " <div class=\"sub header\">" + record["NumRepos"] +" " + getRepoOrOrg(1,isZh) + " ・ " + record["NumMembers"] +" " + getRepoOrOrg(2,isZh) + " ・ " + record["NumTeams"] + " " + getRepoOrOrg(3,isZh) + "</div>";
html += " <div class=\"sub header\">" + record["NumRepos"] +" " + getRepoOrOrg(1,isZh,record["NumRepos"]) + " ・ " + record["NumMembers"] +" " + getRepoOrOrg(2,isZh,record["NumMembers"]) + " ・ " + record["NumTeams"] + " " + getRepoOrOrg(3,isZh,record["NumTeams"]) + "</div>";
html += " </div>";
html += " </div>";
html += " </div>";


+ 16
- 9
routers/repo/repo_statistic.go View File

@@ -51,12 +51,14 @@ func RepoStatisticDaily(date string) {

isInitMinMaxRadar := false

var error_projects = make([]string, 0)
for _, repo := range repos {
log.Info("start statistic: %s", getDistinctProjectName(repo))
projectName := getDistinctProjectName(repo)
log.Info("start statistic: %s", projectName)
var numDevMonths, numWikiViews, numContributor, numKeyContributor, numCommitsGrowth, numCommitLinesGrowth, numContributorsGrowth, numCommits int64
repoGitStat, err := models.GetRepoKPIStats(repo)
if err != nil {
log.Error("GetRepoKPIStats failed: %s", getDistinctProjectName(repo))
log.Error("GetRepoKPIStats failed: %s", projectName)
} else {
numDevMonths = repoGitStat.DevelopAge
numKeyContributor = repoGitStat.KeyContributors
@@ -79,26 +81,26 @@ func RepoStatisticDaily(date string) {
var numVersions int64
numVersions, err = models.GetReleaseCountByRepoID(repo.ID, models.FindReleasesOptions{})
if err != nil {
log.Error("GetReleaseCountByRepoID failed(%s): %v", getDistinctProjectName(repo), err)
log.Error("GetReleaseCountByRepoID failed(%s): %v", projectName, err)
}

var datasetSize int64
datasetSize, err = getDatasetSize(repo)
if err != nil {
log.Error("getDatasetSize failed(%s): %v", getDistinctProjectName(repo), err)
log.Error("getDatasetSize failed(%s): %v", projectName, err)
}

var numComments int64
numComments, err = models.GetCommentCountByRepoID(repo.ID)
if err != nil {
log.Error("GetCommentCountByRepoID failed(%s): %v", getDistinctProjectName(repo), err)
log.Error("GetCommentCountByRepoID failed(%s): %v", projectName, err)
}

beginTime, endTime := getStatTime(date)
var numVisits int
numVisits, err = repository.AppointProjectView(repo.OwnerName, repo.Name, beginTime, endTime)
if err != nil {
log.Error("AppointProjectView failed(%s): %v", getDistinctProjectName(repo), err)
log.Error("AppointProjectView failed(%s): %v", projectName, err)
}

repoStat := models.RepoStatistic{
@@ -162,9 +164,10 @@ func RepoStatisticDaily(date string) {
}

if _, err = models.InsertRepoStat(&repoStat); err != nil {
log.Error("InsertRepoStat failed(%s): %v", getDistinctProjectName(repo), err)
log.Error("failed statistic: %s", getDistinctProjectName(repo))
mailer.SendWarnNotifyMail(setting.Warn_Notify_Mails, warnEmailMessage)
log.Error("InsertRepoStat failed(%s): %v", projectName, err)
log.Error("failed statistic: %s", projectName)
error_projects = append(error_projects, projectName)

continue
}

@@ -247,6 +250,10 @@ func RepoStatisticDaily(date string) {
log.Info("finish statistic: %s", getDistinctProjectName(repo))
}

if len(error_projects) > 0 {
mailer.SendWarnNotifyMail(setting.Warn_Notify_Mails, warnEmailMessage)
}

//radar map
log.Info("begin statistic radar")
for _, radarInit := range reposRadar {


+ 1
- 1
routers/repo/user_data_analysis.go View File

@@ -88,7 +88,7 @@ func queryUserDataPage(ctx *context.Context, tableName string, queryObj interfac
xlsx.SetCellValue(sheetName, "P"+rows, formatTime[0:len(formatTime)-3])

formatTime = userRecord.DataDate
xlsx.SetCellValue(sheetName, "Q"+rows, formatTime+" 00:01")
xlsx.SetCellValue(sheetName, "Q"+rows, formatTime)
}

//设置默认打开的表单


+ 23
- 8
services/socketwrap/clientManager.go View File

@@ -10,6 +10,8 @@ import (
"github.com/elliotchance/orderedmap"
)

var opTypes = []int{1, 2, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 17, 22, 23}

type ClientsManager struct {
Clients *orderedmap.OrderedMap
Register chan *Client
@@ -47,13 +49,15 @@ func (h *ClientsManager) Run() {
close(client.Send)
}
case message := <-models.ActionChan:
LastActionsQueue.Push(message)
for _, client := range h.Clients.Keys() {
select {
case client.(*Client).Send <- message:
default:
close(client.(*Client).Send)
h.Clients.Delete(client)
if isInOpTypes(opTypes, message.OpType) {
LastActionsQueue.Push(message)
for _, client := range h.Clients.Keys() {
select {
case client.(*Client).Send <- message:
default:
close(client.(*Client).Send)
h.Clients.Delete(client)
}
}
}
case s := <-sig:
@@ -71,8 +75,19 @@ func (h *ClientsManager) Run() {
}
}

func isInOpTypes(types []int, opType models.ActionType) bool {
isFound := false
for _, value := range types {
if value == int(opType) {
isFound = true
break
}
}
return isFound
}

func initActionQueue() {
actions, err := models.GetLast20PublicFeeds()
actions, err := models.GetLast20PublicFeeds(opTypes)
if err == nil {
for i := len(actions) - 1; i >= 0; i-- {



+ 1
- 1
templates/base/head_navbar.tmpl View File

@@ -43,7 +43,7 @@
{{if .IsOperator}}
<a class="item" href="{{AppSubUrl}}/explore/data_analysis">{{.i18n.Tr "explore.data_analysis"}}</a>
{{end}}
<a class="item" href="{{AppSubUrl}}/OpenI">{{.i18n.Tr "custom.head.openi"}}</a>
<a class="item" href="{{AppSubUrl}}/OpenI">{{.i18n.Tr "custom.head.openi.repo"}}</a>
</div>
</div>
{{else if .IsLandingPageHome}}


+ 1
- 1
templates/home.tmpl View File

@@ -57,7 +57,7 @@
<div class="leftline02-2"></div>
<div class="ui center homepro-tit am-mb-20">
<h2>{{.page_recommend_repo}}</h2>
<p><span class="ui text grey">{{.page_recommend_repo_desc}}</span><a href="{{.RecommendURL}}">{{.page_recommend_repo_commit}}</a>{{.page_recommend_repo_go}}<a href="{{AppSubUrl}}/explore/">{{.page_recommend_repo_more}}</a></p>
<p><span class="ui text grey">{{.page_recommend_repo_desc}}</span><a href="{{.RecommendURL}}">{{.page_recommend_repo_commit}}</a>{{.page_recommend_repo_go}}&nbsp;<a href="{{AppSubUrl}}/explore/">{{.page_recommend_repo_more}}</a></p>
</div>

<div class="homepro-list">


+ 334
- 0
templates/org/course_list.tmpl View File

@@ -0,0 +1,334 @@
<style>
.text-right{
float:right !important;
}
.header{
font-weight:bold;
font-size: 18px;
font-family: SourceHanSansSC-medium;
}
.cor{
color:#0366D6 !important;
}
.header_card{
/* color:#003A8C !important; */
color:#101010 !important;
margin: 10px 0 0px 0;
height: 25px;
font-size: 18px;
}
.marg{
margin: 0 5px !important;
}

.content_list{
max-height: 130px;
overflow: auto;
}
.Relist{
color:#0366D6 !important;
}
.descript_height{
color: #101010 !important;
margin: 10px 0;
height: 40px !important;
word-break:break-all;
line-height: 20px;
overflow: hidden;
/* overflow: hidden!important;
word-wrap:break-word!important; */


}

.tags_height{
height: 30px !important;
}
.full_height{
height: 100%;
}
.omit{
overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
}
/deep/ ui.checkbox input[type=checkbox]::after{
border: 1px solid #0366D6 !important;
}
.nowrap-2 {
/* height: 2.837em; */
/* line-height: 1.4285em; */
overflow: hidden;
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
.ui.label{
color:#0366D6 !important;
background-color: #B3DBDB !important;
font-weight:normal !important
}


</style>
<div class="ui stackable grid">
<!-- <div style="width: 100%;margin:15px 0;">
{{if .tags}}
<span class="header">
精选项目
</span>
{{if .IsOrganizationOwner}}
<a class="text-right" id="model" onclick="showcreate()" >{{svg "octicon-gear" 16}}自定义</a>
{{end}}
{{end}}
</div> -->

<div style="width: 100%;">
<div class="ui three cards" style="margin-bottom: 10px;">
{{range .Repos}}
<div class="card" >
<div class="extra full_height cor" >
<div class="content " >
{{if .Topics }}
<div class=" tags " style="position: relative;">
{{range .Topics}}
{{if ne . "" }}<a style="max-width:100%;margin: 5px 0;display:inline-flex;" href="{{AppSubUrl}}/explore/repos?q={{.}}&topic={{$.Topic}}" ><span class="ui small label topic omit" >{{.}}</span></a>{{end}}
{{end}}
</div>
{{end}}
</div>

<div class=" header header_card omit" >
<a class="header_card image poping up " href="{{.Link}}" data-content="{{.Alias}}" data-position="top left" data-variation="tiny inverted"> {{.Alias}}</a>
</div>
<div class='content descript_height nowrap-2'>
{{.Description}}
<!-- <p class="time">
{{$.i18n.Tr "org.repo_updated"}} {{TimeSinceUnix .UpdatedUnix $.i18n.Lang}}
{{if .PrimaryLanguage }}
<span class="text grey"><i class="color-icon" style="background-color: {{.PrimaryLanguage.Color}}"></i>{{ .PrimaryLanguage.Language }}</span>
{{end}}
</p> -->
</div>
</div>
<div class=" extra " style="color:#888888;border-top: none !important">
<p class="time">
{{$.i18n.Tr "org.repo_updated"}}{{.CreatedUnix.FormatShort}} {{TimeSinceUnix .UpdatedUnix $.i18n.Lang}}
<!-- {{if .PrimaryLanguage }}
<span class="text grey"><i class="color-icon" style="background-color: {{.PrimaryLanguage.Color}}"></i>{{ .PrimaryLanguage.Language }}</span>
{{end}} -->
</p>
<!-- <div class="ui mini right compact marg" >
<a class="item marg ">
{{svg "octicon-eye" 16}} {{.NumWatches}}
</a>
<a class="item marg">
{{svg "octicon-star" 16}} {{.NumStars}}
</a>
<a class="item marg">
{{svg "octicon-git-branch" 16}} {{.NumForks}}
</a>
</div> -->
</div>
</div>
{{end}}
</div>
</div>

</div>

<!-- <div class="ui modal">
<div class="header" style="padding: 1rem;background-color: rgba(240, 240, 240, 100);">
<h4 id="model_header">自定义精选课程</h4>
</div>
<div class="content content-padding" style="color: black;">
<p>最多可选9个公开项目</p>
<div class="ui search" >
<div class="ui input" style="width: 100%;">
<input type="text" id = 'search_selectPro' placeholder="Search ..." value = '' oninput="search()">
</div>
</div>
<div style="margin: 10px ;">
<div id ='org_list' style="margin-bottom: 20px;"class="content_list" >

</div>
</div>
<p id='recommend'></p>
<div class="inline field" style="margin-left: 37%;">
<div class="actions">
<button id="submitId" type="button" class="ui create_train_job green deny button" onclick="saveSeletedPro(1)">
{{.i18n.Tr "explore.save"}}
</button>
<button class="ui button cancel" >{{.i18n.Tr "explore.cancel"}}</button>
</div>
</div>
</div>

</div> -->

<script>
var data;
var filterData=[];
var num=0;

function showcreate(obj){
document.getElementById("search_selectPro").value=''
$('.ui.modal')
.modal({
centered: false,
onShow:function(){
$("#org_list").empty()
getPro(1)
},
onHide:function(){
}
})
.modal('show')
}
function getPro(typeTag){

$.ajax({
type:"GET",
url:"/org/{{.Org.Name}}/org_tag/repo_list?tagId="+typeTag,
dataType:"json",
async:false,
success:function(json){
data = json.data;
var n_length = data.length
pro_html = getHTML(data)
$("#org_list").append(pro_html)
// console.log('原始',data)
checkedNum(0)
}
});
}
function getHTML(data){
let pro_html=''
for (let i=0;i<data.length;i++){
if (data[i].Selected==true){
console.log("data[i]:",data[i])
pro_html += `<div class="ui checkbox" style="width: 33%;margin-bottom:10px" > <input type="checkbox" id = " ${i}" checked="" onclick="checkedNum(${i})" class="Relist" name ='select_pro_name' data-repoid="${data[i].RepoID}" data-reponame="${data[i].RepoName}" data-selected=${data[i].Selected} > <label class='omit image poping up' data-content=${data[i].RepoName}  data-position="top left " data-variation="mini"> ${data[i].RepoName}</label></div>`
pro_html += '</div>'
}
else{
pro_html += `<div class="ui checkbox" style="width: 33%;margin-bottom:10px" > <input type="checkbox" id = "${i}" onclick="checkedNum(${i})" class="Relist" name ='select_pro_name' data-repoid="${data[i].RepoID}" data-reponame="${data[i].RepoName}" data-selected= ${data[i].Selected}> <label class='omit image poping up' data-content=${data[i].RepoName}  data-position="top left " data-variation="mini"> ${data[i].RepoName} </label></div>`
pro_html += '</div>'
}
}
return pro_html
}
function saveSeletedPro(typeTag){
var saveData=[];
$('input[name="select_pro_name"]:checked').each(function(){
console.log('值',this.dataset.repoid)

saveData.push(parseInt(this.dataset.repoid));
})
if(saveData.length>9){
alert("最多可选9个,保存失败")
return
}
// saveData = getSelecteDataID();
// console.log("数据:",saveData)
$.ajax({
type:"POST",
url:"/org/{{.Org.Name}}/org_tag/repo_submit?tagId="+typeTag,
contentType:'application/json',
dataType:"json",
async:false,
data:JSON.stringify({'repoList':saveData
}),
success:function(res){
console.log('保存成功');
location.reload()

}
});
}

function getSelecteData(){
var selectedData=[];
$('input[name="select_pro_name"]:checked').each(function(){
// console.log(this)
// console.log('值',this.dataset.selected)

selectedData.push({"RepoID":parseInt(this.dataset.repoid),"RepoName":this.dataset.reponame,"Selected":JSON.parse(this.dataset.selected)});
})
return selectedData
}
function search(){
var selectedData = getSelecteData();
var searchValue = document.getElementById("search_selectPro").value;
filterData=[];
console.log("searchValue:",searchValue)
for (let i=0;i<data.length;i++){
var isInclude=false;
if(data[i].RepoName.toLowerCase().includes(searchValue.toLowerCase())){
filterData.push(data[i])
}
}
console.log("选中的值:",selectedData)
console.log("筛选包括选中的值:",filterData)
var showData=[];
for(i=0;i<selectedData.length;i++){
filterData =filterData.filter((item)=>{
return item.RepoID!=selectedData[i].RepoID
});
}
console.log("筛选后不包括选中的值:",filterData)
$("#org_list").empty()
if(searchValue!=""){
if (filterData.length!=0){
var pro_html = getHTML(selectedData);
console.log("selectedData_pro_html:",pro_html)
$("#org_list").append(pro_html)
pro_html= getHTML(filterData);
$("#org_list").append(pro_html)
}else{
var pro_html = getHTML(selectedData);
$("#org_list").append(pro_html)
}
}else{
var pro_html = getHTML(data);
$("#org_list").append(pro_html)
}
}

function checkedNum(id){

num=0;
var inputs = document.getElementsByName("select_pro_name")
for (var i=0;i<inputs.length;i++){
if(inputs[i].checked){
num++
if(num>9){
document.getElementById(id).checked=false
alert("选择超过9个,请重新选择!")
return
}
}
}

var show_num = 9-num;
document.getElementById("recommend").innerHTML="还能推荐"+show_num+"个"

}

</script>

+ 479
- 0
templates/org/home_courses.tmpl View File

@@ -0,0 +1,479 @@
<style>
.organization-info_1000{
background: #F5F5F6 !important;

}
.organization-info >.container {
overflow: auto;
background: #f5f5f6 !important;
padding-top: 30px;
padding-bottom: 20px;
background-size: cover;
border-radius: 5px;
border: none !important
}

.organization.profile #org-avatar {
border:none !important
}
.desc {
font-size: 14px;
margin-bottom: 10px !important;
}
.item {
display: inline-block;
margin-right: 10px;
}
.item .icon {
margin-right: 5px;
}
.organization-info >.container {
padding-bottom:0px !important;
}
.tag_bg{
background-color: #0366D6 !important;
color:#FFFFFF !important;
}
.course{
padding: 10px 15px !important;
}
.course_color{
color: #FA8C16;
}
.tag_lable{
border: 1px solid rgba(232, 232, 232, 100) ;
border-radius: 4px;
color: rgba(65, 80, 88, 100);
font-family: Microsoft Yahei;
font-size: 14px;
padding: 0.3em 0.5em;
height: 30px;
text-align: center;
margin: 0.2em;
}
.tag_lable_first{
border: 1px solid rgba(232, 232, 232, 100) ;
border-radius: 4px;
color: rgba(65, 80, 88, 100);
font-family: Microsoft Yahei;
font-size: 14px;
padding: 0.3em 0.5em;
height: 30px;
text-align: center;
margin: 0.2em;
margin-left: none;
}

</style>
{{template "base/head" .}}
<div class="organization profile">
{{/* overflow: auto is the clearfix - this avoids the image going beyond
the container where it is supposed to stay inside. */}}
<!-- <div class="organization-info">
<div class="ui center aligned container " style="overflow: auto">
<img class="ui circular image" id="org-avatar" src="{{.Org.SizedRelAvatarLink 140}}"/>
<div id="org-info">
<div class="ui header">
{{.Org.DisplayName}}
{{if .IsOrganizationOwner}}<a class="middle text grey" href="{{.OrgLink}}/settings">{{svg "octicon-gear" 16}}</a>{{end}}
</div>
{{if .Org.Description}}<p class="text grey desc">{{.Org.Description}}</p>{{end}}
<div class="meta">
{{if .Org.Location}}<div class="item">{{svg "octicon-location" 16}} <span>{{.Org.Location}}</span></div>{{end}}
{{if .Org.Website}}<div class="item">{{svg "octicon-link" 16}} <a target="_blank" rel="noopener noreferrer" href="{{.Org.Website}}">{{.Org.Website}}</a></div>{{end}}
</div>
</div>
</div>
</div> -->

<div class="organization-info organization-info_1000">
<div class="ui center aligned container " style="overflow: auto">
<img class="ui left image" id="org-avatar" src="{{.Org.SizedRelAvatarLink 140}}"/>
<div class="content" style="text-align: left;margin-left:100px" >
<div class="ui header" >
{{.Org.DisplayName}}
<!-- {{if .IsOrganizationOwner}}<a class="middle text grey" href="{{.OrgLink}}/settings">{{svg "octicon-gear" 16}}</a>{{end}} -->
</div>
<div class="description" >
{{if .Org.Description}}<p class="text grey desc">{{.Org.Description}}</p>{{end}}
</div>
<div class="meta" style="display: inline-flex;">
{{if .Org.Location}}<div class="item">{{svg "octicon-location" 16}} <span>{{.Org.Location}}</span></div>{{end}}
{{if .Org.Website}}<div class="item">{{svg "octicon-link" 16}} <a target="_blank" rel="noopener noreferrer" href="{{.Org.Website}}">{{.Org.Website}}</a></div>{{end}}
</div>
</div>
</div>
<div class="ui tabs container">
<div class="ui tabular stackable menu navbar">
{{with .Org}}
<a class="{{if $.PageIsOrgHome}}active{{end}} item " href="{{.HomeLink}}">
{{svg "octicon-home" 16}}&nbsp;{{$.i18n.Tr "org.home"}}
</a>
{{end}}
<a class="{{if $.PageIsOrgMembers}}active{{end}} item" href="{{$.OrgLink}}/members">
{{svg "octicon-organization" 16}}&nbsp;{{$.i18n.Tr "org.people"}}
</a>
{{if or ($.IsOrganizationMember) ($.IsOrganizationOwner)}}
<a class="{{if $.PageIsOrgTeams}}active{{end}} item" href="{{$.OrgLink}}/teams">
{{svg "octicon-jersey" 16}}&nbsp;{{$.i18n.Tr "org.teams"}}
</a>
{{end}}
{{if .IsOrganizationOwner}}<a class="right text grey item" href="{{.OrgLink}}/settings">{{svg "octicon-gear" 16}} &nbsp;组织设置</a>{{end}}
</div>

</div>

</div>
<!-- <div class="ui container " style="overflow: auto">
<img class="ui left image" id="org-avatar" src="{{.Org.SizedRelAvatarLink 140}}"/>
<p id="org-info">
<div class="ui header">
{{.Org.DisplayName}}
{{if .IsOrganizationOwner}}<a class="middle text grey" href="{{.OrgLink}}/settings">{{svg "octicon-gear" 16}}</a>{{end}}
</div>
{{if .Org.Description}}<p class="text grey desc">{{.Org.Description}}</p>{{end}}
<div class="meta">
{{if .Org.Location}}<div class="item">{{svg "octicon-location" 16}} <span>{{.Org.Location}}</span></div>{{end}}
{{if .Org.Website}}<div class="item">{{svg "octicon-link" 16}} <a target="_blank" rel="noopener noreferrer" href="{{.Org.Website}}">{{.Org.Website}}</a></div>{{end}}
</div>
</p>
</div> -->

<div class="ui container">

<!-- 新增 -->
<div class="ui stackable grid">
<div class="ui sixteen wide computer column">
<div class="ui mobile reversed stackable grid">
<div class="ui ten wide tablet eleven wide computer column" id='tag'>
<a class="ui small lable tag_lable topic tag_bg" style="margin-left: 0px;" >全部关键字</a>
{{range .CoursesKeywords}}
<a class="ui small lable tag_lable topic" >{{.}}</a>
{{end}}
</div>
<div class="ui sixteen wide mobile six wide tablet five wide computer column">
<!-- {{if .CanCreateOrgRepo}} -->
<div class="text center" style="margin-left: 10px;">
<a class="ui green button" href="{{AppSubUrl}}/repo/create?org={{.Org.ID}}"><i class="ri-folder-add-line" style="vertical-align: middle;"></i> &nbsp;发布课程{{.i18n.Tr "new_repo"}} </a>
</div>
<!-- {{end}} -->
</div>
</div>
</div>
</div>

<!-- 全部 -->

<div class="ui stackable grid">
<div class="ui sixteen wide computer column">
<div class="ui mobile reversed stackable grid">
<div class="ui ten wide tablet eleven wide computer column">
<!-- {{if .CanCreateOrgRepo}}
<div class="text right">
<a class="ui green button" href="{{AppSubUrl}}/repo/create?org={{.Org.ID}}">{{.i18n.Tr "new_repo"}}</a>
</div>
{{end}} -->
{{template "org/course_list" .}}
{{template "base/paginate" .}}
</div>

<div class="ui sixteen wide mobile six wide tablet five wide computer column">

<h4 class="ui top attached header">
<strong>{{.i18n.Tr "org.selected_couse"}}</strong>
<div class="ui right">
<a class="text grey" id="model" onclick="showcreate()">{{svg "octicon-gear" 16}}</a>
</div>
<!-- {{if .IsOrganizationMember}} -->
<!-- {{end}} -->
</h4>
<div class="ui attached table segment course items">
{{range $i, $v := .RecommendCourses}}
{{if gt $i 0}}
<div class="ui divider" style="margin-bottom:10px;"></div>
{{end}}
<div class="item">
<i class="ri-bookmark-3-line course_color" ></i>
<div class="content" style="margin-left: 10px;">
<a href="{{$.OrgLink}}/teams/{{.LowerName}}"><strong class="team-name">{{.Alias}}</strong></a>
<p class="text grey">
贡献者:{{.Creator.Name}}
</p>
</div>
</div>
<!-- <div class="ui divider"></div> -->
{{end}}
</div>

<h4 class="ui top attached header">
<strong>{{.i18n.Tr "org.people"}}</strong>
<div class="ui right">
<a class="text grey" href="{{.OrgLink}}/members">{{.MembersTotal}} {{svg "octicon-chevron-right" 16}}</a>
</div>
<!-- {{if .IsOrganizationMember}} -->
<!-- {{end}} -->
</h4>
<div class="ui attached segment members">
{{$isMember := .IsOrganizationMember}}
{{range .Members}}
{{if or $isMember (.IsPublicMember $.Org.ID)}}
<a href="{{.HomeLink}}" title="{{.Name}}{{if .FullName}} ({{.FullName}}){{end}}"><img class="ui avatar" src="{{.RelAvatarLink}}"></a>
{{end}}
{{end}}

<div style="text-align: center;margin-top: 5px;">
<a class="ui blue basic button" href="{{.OrgLink}}/teams/new"> <i class="ri-user-add-line"></i> {{.i18n.Tr "org.teams.join_teams"}}</a>
</div>
</div>

{{if .IsOrganizationMember}}
<div class="ui top attached header">
<strong>{{.i18n.Tr "org.teams"}}</strong>
<div class="ui right">
<a class="text grey" href="{{.OrgLink}}/teams"><span>{{.Org.NumTeams}}</span> {{svg "octicon-chevron-right" 16}}</a>
</div>
</div>
<div class="ui attached table segment teams">
{{range .Teams}}
<div class="item">
<a href="{{$.OrgLink}}/teams/{{.LowerName}}"><strong class="team-name">{{.Name}}</strong></a>
<p class="text grey">
<a href="{{$.OrgLink}}/teams/{{.LowerName}}"><strong>{{.NumMembers}}</strong> {{$.i18n.Tr "org.lower_members"}}</a> ·
<a href="{{$.OrgLink}}/teams/{{.LowerName}}/repositories"><strong>{{.NumRepos}}</strong> {{$.i18n.Tr "org.lower_repositories"}}</a>
</p>
</div>
{{end}}
</div>
{{if .IsOrganizationOwner}}
<div class="ui bottom attached segment">
<a class="ui blue small button" href="{{.OrgLink}}/teams/new">{{.i18n.Tr "org.create_new_team"}}</a>
</div>
{{end}}
{{end}}
</div>
</div>
</div>
</div>
</div>
</div>

<div class="ui modal">
<div class="header" style="padding: 1rem;background-color: rgba(240, 240, 240, 100);">
<h4 id="model_header">自定义精选课程</h4>
</div>
<div class="content content-padding" style="color: black;">
<p>最多可选9个公开项目</p>
<div class="ui search" >
<div class="ui input" style="width: 100%;">
<input type="text" id = 'search_selectPro' placeholder="Search ..." value = '' oninput="search()">
</div>
</div>
<div style="margin: 10px ;">
<div id ='org_list' style="margin-bottom: 20px;"class="content_list" >

</div>
</div>
<p id='recommend'></p>
<div class="inline field" style="margin-left: 37%;">
<div class="actions">
<button id="submitId" type="button" class="ui create_train_job green deny button" onclick="saveSeletedPro(1)">
{{.i18n.Tr "explore.save"}}
</button>
<button class="ui button cancel" >{{.i18n.Tr "explore.cancel"}}</button>
</div>
</div>
</div>

</div>

{{template "base/footer" .}}
<script>
// var div = document.getElementsByClassName("ui ten wide tablet eleven wide computer column").getElementsByTagName("a");
// function changeBgcolor(){

// document.getElementsByClassName("ui small lable tag_lable topic tag_bg").className= "ui small lable tag_lable topic";
// // this.classList.add("tag_bg")
// }

window.onload = function ()
{
var atag =document.getElementById("tag").getElementsByTagName("a");

var i = 0;
for (i = 0; i < atag.length; i++)
{
atag[i].onclick = function ()
{
for (i = 0; i < atag.length; i++)
atag[i].className = "ui small lable tag_lable topic";
this.className = "ui small lable tag_lable topic tag_bg";
};
}
};

var data;
var filterData=[];
var num=0;

function showcreate(obj){
document.getElementById("search_selectPro").value=''
$('.ui.modal')
.modal({
centered: false,
onShow:function(){
$("#org_list").empty()
getPro(1)
},
onHide:function(){
}
})
.modal('show')
}
function getPro(typeTag){

$.ajax({
type:"GET",
url:"/org/{{.Org.Name}}/org_tag/repo_list?tagId="+typeTag,
dataType:"json",
async:false,
success:function(json){
data = json.data;
var n_length = data.length
pro_html = getHTML(data)
$("#org_list").append(pro_html)
// console.log('原始',data)
checkedNum(0)
}
});
}
function getHTML(data){
let pro_html=''
for (let i=0;i<data.length;i++){
if (data[i].Selected==true){
console.log("data[i]:",data[i])
pro_html += `<div class="ui checkbox" style="width: 33%;margin-bottom:10px" > <input type="checkbox" id = " ${i}" checked="" onclick="checkedNum(${i})" class="Relist" name ='select_pro_name' data-repoid="${data[i].RepoID}" data-reponame="${data[i].RepoName}" data-selected=${data[i].Selected} > <label class='omit image poping up' data-content=${data[i].RepoName}  data-position="top left " data-variation="mini"> ${data[i].RepoName}</label></div>`
pro_html += '</div>'
}
else{
pro_html += `<div class="ui checkbox" style="width: 33%;margin-bottom:10px" > <input type="checkbox" id = "${i}" onclick="checkedNum(${i})" class="Relist" name ='select_pro_name' data-repoid="${data[i].RepoID}" data-reponame="${data[i].RepoName}" data-selected= ${data[i].Selected}> <label class='omit image poping up' data-content=${data[i].RepoName}  data-position="top left " data-variation="mini"> ${data[i].RepoName} </label></div>`
pro_html += '</div>'
}
}
return pro_html
}
function saveSeletedPro(typeTag){
var saveData=[];
$('input[name="select_pro_name"]:checked').each(function(){
console.log('值',this.dataset.repoid)

saveData.push(parseInt(this.dataset.repoid));
})
if(saveData.length>9){
alert("最多可选9个,保存失败")
return
}
// saveData = getSelecteDataID();
// console.log("数据:",saveData)
$.ajax({
type:"POST",
url:"/org/{{.Org.Name}}/org_tag/repo_submit?tagId="+typeTag,
contentType:'application/json',
dataType:"json",
async:false,
data:JSON.stringify({'repoList':saveData
}),
success:function(res){
console.log('保存成功');
location.reload()

}
});
}

function getSelecteData(){
var selectedData=[];
$('input[name="select_pro_name"]:checked').each(function(){
// console.log(this)
// console.log('值',this.dataset.selected)

selectedData.push({"RepoID":parseInt(this.dataset.repoid),"RepoName":this.dataset.reponame,"Selected":JSON.parse(this.dataset.selected)});
})
return selectedData
}
function search(){
var selectedData = getSelecteData();
var searchValue = document.getElementById("search_selectPro").value;
filterData=[];
console.log("searchValue:",searchValue)
for (let i=0;i<data.length;i++){
var isInclude=false;
if(data[i].RepoName.toLowerCase().includes(searchValue.toLowerCase())){
filterData.push(data[i])
}
}
console.log("选中的值:",selectedData)
console.log("筛选包括选中的值:",filterData)
var showData=[];
for(i=0;i<selectedData.length;i++){
filterData =filterData.filter((item)=>{
return item.RepoID!=selectedData[i].RepoID
});
}
console.log("筛选后不包括选中的值:",filterData)
$("#org_list").empty()
if(searchValue!=""){
if (filterData.length!=0){
var pro_html = getHTML(selectedData);
console.log("selectedData_pro_html:",pro_html)
$("#org_list").append(pro_html)
pro_html= getHTML(filterData);
$("#org_list").append(pro_html)
}else{
var pro_html = getHTML(selectedData);
$("#org_list").append(pro_html)
}
}else{
var pro_html = getHTML(data);
$("#org_list").append(pro_html)
}
}

function checkedNum(id){

num=0;
var inputs = document.getElementsByName("select_pro_name")
for (var i=0;i<inputs.length;i++){
if(inputs[i].checked){
num++
if(num>9){
document.getElementById(id).checked=false
alert("选择超过9个,请重新选择!")
return
}
}
}

var show_num = 9-num;
document.getElementById("recommend").innerHTML="还能推荐"+show_num+"个"

}

</script>

+ 0
- 0
templates/org/member/course_members.tmpl View File


+ 0
- 0
templates/org/team/courseTeams.tmpl View File


+ 98
- 0
templates/repo/createCourse.tmpl View File

@@ -0,0 +1,98 @@
{{template "base/head" .}}
<div class="repository new repo" style="margin-top: 40px;">
<div class="ui middle very relaxed page grid">
<div class="column">
<form class="ui form" action="{{.Link}}" method="post" id="create_repo_form">
{{.CsrfTokenHtml}}
<h3 class="ui top attached header">
{{.i18n.Tr "new_course"}}
</h3>
<div class="ui attached segment">
{{template "base/alert" .}}
<div class="inline required field" >
<label for="Alias">{{.i18n.Tr "form.courseAlias"}}</label>
<input id="alias" name="Alias" value="" autofocus required>
<span class="help">{{.i18n.Tr "form.reponame_dash_dot_error"}}</span>
</div>
<div class="inline required fields" style="margin-bottom: 0;">
<label style="text-align: right;width: 250px!important;word-wrap: break-word;">{{.i18n.Tr "form.courseAdress"}}</label>
<div class="required field {{if .Err_Owner}}error{{end}}" style="padding: 0;">
<div class="ui selection owner dropdown" id="ownerDropdown">
<input type="hidden" id="uid" name="uid" value="{{.Owner.Name}}" required>
<div class="text" title="{{.Owner.Name}}">
<img class="ui mini image" src="{{.Owner.RelAvatarLink}}">
{{$.Owner.Name}}
</div>
</div>
</div>
<div class="ui interval" style="width: 0.6em;font-size: 2rem;line-height: 0px;text-align: center;">/</div>
<div class="required field {{if .Err_RepoName}}error{{end}}">
<input style="width: 100% !important;" id="repo_name" name="RepoName" value="{{.repo_name}}" autofocus required>
</div>
</div>
<span style="display: block;margin-bottom: 1em;" class="help">{{.i18n.Tr "form.repoadd_dash_dot_error"}}</span>
<div class="inline field" id="repoAdress" style="display: none;word-break: break-all;">
<label for="">{{.i18n.Tr "form.RepoAdress"}}:</label>
<span></span>
</div>

<div class="inline required field">
<label>{{.i18n.Tr "repo.model.manage.label"}}</label>
<div class="ui multiple search selection dropdown">
<input type="hidden" name="Topics" value="">
<div class="default text">{{.i18n.Tr "repo.repo_label_helpe"}}</div>
<div class="menu" id="course_label_item">
</div>
</div>
</div>

<div class="inline field {{if .Err_Description}}error{{end}}">
<label for="description">{{.i18n.Tr "repo.repo_desc"}}</label>
<textarea id="description" name="Description" maxlength="254">{{.description}}</textarea>
</div>
<div class="inline field">
<label></label>
<button class="ui green button" id="submit_reponame">
{{.i18n.Tr "new_course"}}
</button>
<a class="ui button" href="{{AppSubUrl}}/">{{.i18n.Tr "cancel"}}</a>
</div>
</div>
</form>
</div>
</div>
</div>
{{template "base/footer" .}}

<script>

$(document).ready(function(){
$('.ui.multiple.search.selection.dropdown')
.dropdown({
allowAdditions: true,
onChange: function(value, text, $selectedItem) {
$('#course_label_item').empty()
}
})
$('input.search').bind('input propertychange', function (event) {
const query = $('input.search').val()
if(!query){
$('#course_label_item').empty()
}else{
$.get(`/api/v1/topics/search?q=${query}`,(data)=>{
console.log(data)
if(data.topics.length!==0){
let html=''
$('#course_label_item').empty()
data.topics.forEach(element => {
html += `<div class="item" data-value="${element.topic_name}">${element.topic_name}</div>`
});
$('#course_label_item').append(html)
}
})
}
});
})

</script>

+ 1
- 4
web_src/js/components/UserAnalysis.vue View File

@@ -135,13 +135,10 @@
</template>
</el-table-column>
<el-table-column
prop="CountDate"
prop="DataDate"
label="系统统计时间"
width="120px"
align="center">
<template slot-scope="scope">
{{scope.row.CountDate | transformTimestamp}}
</template>
</el-table-column>
</el-table>
</div>


Loading…
Cancel
Save