@@ -1999,3 +1999,16 @@ func IsErrJobNotExist(err error) bool { | |||
func (err ErrJobNotExist) Error() string { | |||
return fmt.Sprintf("the job does not exist") | |||
} | |||
type ErrTagNotExist struct { | |||
TagID int64 | |||
} | |||
func (err ErrTagNotExist) Error() string { | |||
return fmt.Sprintf("the tag does not exist") | |||
} | |||
func IsErrTagNotExist(err error) bool { | |||
_, ok := err.(ErrTagNotExist) | |||
return ok | |||
} |
@@ -134,6 +134,8 @@ func init() { | |||
new(BlockChain), | |||
new(RecommendOrg), | |||
new(AiModelManage), | |||
new(OfficialTag), | |||
new(OfficialTagRepos), | |||
) | |||
tablesStatistic = append(tablesStatistic, | |||
@@ -0,0 +1,165 @@ | |||
package models | |||
import ( | |||
"code.gitea.io/gitea/modules/log" | |||
"code.gitea.io/gitea/modules/timeutil" | |||
"fmt" | |||
) | |||
const DefaultOrgTagLimit = -1 | |||
type OfficialTag struct { | |||
ID int64 `xorm:"pk autoincr"` | |||
Name string `xorm:"NOT NULL"` | |||
Code string `xorm:"NOT NULL"` | |||
Limit int `xorm:"NOT NULL default(-1)"` | |||
Status int `xorm:"NOT NULL default(0)"` | |||
CreatedUnix timeutil.TimeStamp `xorm:"created"` | |||
UpdatedUnix timeutil.TimeStamp `xorm:"updated"` | |||
} | |||
type OfficialTagRepos struct { | |||
ID int64 `xorm:"pk autoincr"` | |||
OrgID int64 `xorm:"NOT NULL INDEX"` | |||
TagID int64 `xorm:"NOT NULL"` | |||
RepoID int64 `xorm:"NOT NULL INDEX"` | |||
CreatedUnix timeutil.TimeStamp `xorm:"created"` | |||
UpdatedUnix timeutil.TimeStamp `xorm:"updated"` | |||
} | |||
type TagReposBrief struct { | |||
RepoID int64 | |||
RepoName string | |||
TagID int64 | |||
} | |||
type TagReposSelected struct { | |||
RepoID int64 | |||
RepoName string | |||
Selected bool | |||
} | |||
type TagsDetail struct { | |||
TagId int64 | |||
TagName string | |||
TagLimit int | |||
RepoList []Repository | |||
} | |||
func GetTagByID(id int64) (*OfficialTag, error) { | |||
r := &OfficialTag{ | |||
ID: id, | |||
} | |||
has, err := x.Get(r) | |||
if err != nil { | |||
return nil, err | |||
} else if !has { | |||
return nil, ErrTagNotExist{0} | |||
} | |||
return r, nil | |||
} | |||
func UpdateTagReposByID(tagID, orgID int64, repoIdList []int64) error { | |||
sess := x.NewSession() | |||
defer sess.Close() | |||
if err := sess.Begin(); err != nil { | |||
return fmt.Errorf("UpdateTagReposByID[tagId: %d, orgID: %d,error:%v", tagID, orgID, err) | |||
} | |||
//delete old tag repos | |||
r := &OfficialTagRepos{ | |||
TagID: tagID, | |||
OrgID: orgID, | |||
} | |||
_, err := sess.Delete(r) | |||
if err != nil { | |||
return err | |||
} | |||
if len(repoIdList) == 0 { | |||
return sess.Commit() | |||
} | |||
//add new tag repos | |||
data := make([]*OfficialTagRepos, 0) | |||
for _, repoId := range repoIdList { | |||
data = append(data, &OfficialTagRepos{ | |||
OrgID: orgID, | |||
TagID: tagID, | |||
RepoID: repoId, | |||
}) | |||
} | |||
_, err = sess.Insert(&data) | |||
if err != nil { | |||
sess.Rollback() | |||
return err | |||
} | |||
return sess.Commit() | |||
} | |||
func GetTagRepos(tagID, orgID int64) ([]TagReposSelected, error) { | |||
t := make([]TagReposBrief, 0) | |||
const SQLCmd = "select t1.id as repo_id,t1.name as repo_name,t2.id as tag_id from repository t1 left join official_tag_repos t2 on (t1.id = t2.repo_id and t2.tag_id = ?) where t1.owner_id = ? and t1.is_private = false order by t1.updated_unix desc" | |||
if err := x.SQL(SQLCmd, tagID, orgID).Find(&t); err != nil { | |||
return nil, err | |||
} | |||
r := make([]TagReposSelected, 0) | |||
for _, v := range t { | |||
selected := false | |||
if v.TagID > 0 { | |||
selected = true | |||
} | |||
r = append(r, TagReposSelected{ | |||
RepoID: v.RepoID, | |||
RepoName: v.RepoName, | |||
Selected: selected, | |||
}) | |||
} | |||
return r, nil | |||
} | |||
func GetAllOfficialTagRepos(orgID int64, isOwner bool) ([]TagsDetail, error) { | |||
result := make([]TagsDetail, 0) | |||
tags, err := GetAllOfficialTags() | |||
if err != nil { | |||
return nil, err | |||
} | |||
for _, tag := range tags { | |||
repos, err := GetOfficialTagDetail(orgID, tag.ID) | |||
if err != nil { | |||
return nil, err | |||
} | |||
if len(repos) == 0 && !isOwner { | |||
continue | |||
} | |||
result = append(result, TagsDetail{ | |||
TagId: tag.ID, | |||
TagName: tag.Name, | |||
TagLimit: tag.Limit, | |||
RepoList: repos, | |||
}) | |||
} | |||
return result, nil | |||
} | |||
func GetOfficialTagDetail(orgID, tagId int64) ([]Repository, error) { | |||
t := make([]Repository, 0) | |||
const SQLCmd = "select t2.* from official_tag_repos t1 inner join repository t2 on t1.repo_id = t2.id where t1.org_id = ? and t1.tag_id=? order by t2.updated_unix desc" | |||
if err := x.SQL(SQLCmd, orgID, tagId).Find(&t); err != nil { | |||
return nil, err | |||
} | |||
return t, nil | |||
} | |||
func GetAllOfficialTags() ([]OfficialTag, error) { | |||
//todo redis? | |||
o := make([]OfficialTag, 0) | |||
err := x.Where("status = ?", 0).Find(&o) | |||
if err != nil { | |||
log.Error("GetAllOfficialTags error,%v", err) | |||
return nil, err | |||
} | |||
return o, nil | |||
} |
@@ -70,3 +70,7 @@ type CreateTeamForm struct { | |||
func (f *CreateTeamForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors { | |||
return validate(errs, ctx.Data, f, ctx.Locale) | |||
} | |||
type SubmitReposOfTagForm struct { | |||
RepoList []int64 | |||
} |
@@ -222,6 +222,7 @@ contributors = Contributors | |||
[explore] | |||
repos = Repositories | |||
select_repos = Select the project | |||
users = Users | |||
organizations = Organizations | |||
images = CloudImages | |||
@@ -234,6 +235,8 @@ org_no_results = No matching organizations found. | |||
code_no_results = No source code matching your search term found. | |||
code_search_results = Search results for '%s' | |||
code_last_indexed_at = Last indexed %s | |||
save=save | |||
cancel=cancel | |||
[auth] | |||
create_new_account = Register Account | |||
@@ -224,6 +224,7 @@ contributors=贡献者 | |||
[explore] | |||
repos=项目 | |||
select_repos=精选项目 | |||
users=用户 | |||
organizations=组织 | |||
images = 云脑镜像 | |||
@@ -238,6 +239,8 @@ org_no_results=未找到匹配的组织。 | |||
code_no_results=未找到与搜索字词匹配的源代码。 | |||
code_search_results=“%s” 的搜索结果是 | |||
code_last_indexed_at=最后索引于 %s | |||
save=保存 | |||
cancel=取消 | |||
[auth] | |||
create_new_account=注册帐号 | |||
@@ -130,5 +130,13 @@ func Home(ctx *context.Context) { | |||
pager.SetDefaultParams(ctx) | |||
ctx.Data["Page"] = pager | |||
//find org tag info | |||
tags, err := models.GetAllOfficialTagRepos(org.ID, ctx.Org.IsOwner) | |||
if err != nil { | |||
ctx.ServerError("GetAllOfficialTagRepos", err) | |||
return | |||
} | |||
ctx.Data["tags"] = tags | |||
ctx.HTML(200, tplOrgHome) | |||
} |
@@ -0,0 +1,98 @@ | |||
// Copyright 2014 The Gogs Authors. All rights reserved. | |||
// Copyright 2020 The Gitea Authors. | |||
// Use of this source code is governed by a MIT-style | |||
// license that can be found in the LICENSE file. | |||
package org | |||
import ( | |||
"code.gitea.io/gitea/models" | |||
"code.gitea.io/gitea/modules/auth" | |||
"code.gitea.io/gitea/modules/context" | |||
"errors" | |||
"strconv" | |||
) | |||
// SubmitTags submit repos of org tag | |||
func SubmitTags(ctx *context.Context, form auth.SubmitReposOfTagForm) { | |||
org, tag := getOrgAndTagFromContext(ctx) | |||
if ctx.Written() { | |||
return | |||
} | |||
err := models.UpdateTagReposByID(tag.ID, org.ID, form.RepoList) | |||
if err != nil { | |||
ctx.ServerError("UpdateTagReposByID", err) | |||
return | |||
} | |||
ctx.JSON(200, map[string]interface{}{ | |||
"code": "00", | |||
"msg": "success", | |||
}) | |||
} | |||
// GetTagRepos get repos under org tag | |||
func GetTagRepos(ctx *context.Context) { | |||
org, tag := getOrgAndTagFromContext(ctx) | |||
if ctx.Written() { | |||
return | |||
} | |||
r, err := models.GetTagRepos(tag.ID, org.ID) | |||
if err != nil { | |||
ctx.ServerError("GetTagRepos", err) | |||
return | |||
} | |||
ctx.JSON(200, map[string]interface{}{ | |||
"code": "00", | |||
"msg": "success", | |||
"data": r, | |||
}) | |||
} | |||
// getDashboardContextUser finds out dashboard is viewing as which context user. | |||
func getOrgAndTagFromContext(ctx *context.Context) (*models.User, *models.OfficialTag) { | |||
var org *models.User | |||
var tag *models.OfficialTag | |||
var err error | |||
orgName := ctx.Params(":org") | |||
if len(orgName) > 0 { | |||
// Organization. | |||
org, err = models.GetUserByName(orgName) | |||
if err != nil { | |||
if models.IsErrUserNotExist(err) { | |||
ctx.NotFound("GetUserByName", err) | |||
} else { | |||
ctx.ServerError("GetUserByName", err) | |||
} | |||
return nil, nil | |||
} | |||
if !org.IsOrganization() { | |||
ctx.ServerError("GetUserByName", errors.New("it is not an organization")) | |||
return nil, nil | |||
} | |||
} | |||
tagIdStr := ctx.Query("tagId") | |||
if len(tagIdStr) == 0 { | |||
ctx.ServerError("GetTagInfo", errors.New("tag is not exist")) | |||
return nil, nil | |||
} | |||
tagId, _ := strconv.ParseInt(tagIdStr, 10, 32) | |||
tag, err = models.GetTagByID(tagId) | |||
if err != nil { | |||
if models.IsErrTagNotExist(err) { | |||
ctx.NotFound("GetTagInfo", err) | |||
} else { | |||
ctx.ServerError("GetTagInfo", err) | |||
} | |||
return nil, nil | |||
} | |||
return org, tag | |||
} |
@@ -627,6 +627,10 @@ func RegisterRoutes(m *macaron.Macaron) { | |||
m.Group("/org", func() { | |||
m.Group("/:org", func() { | |||
m.Get("/members", org.Members) | |||
m.Group("/org_tag", func() { | |||
m.Get("/repo_list", org.GetTagRepos) | |||
m.Post("/repo_submit", bindIgnErr(auth.SubmitReposOfTagForm{}), org.SubmitTags) | |||
}) | |||
}, context.OrgAssignment()) | |||
}) | |||
m.Group("/org", func() { | |||
@@ -20,10 +20,11 @@ | |||
</div> | |||
<div class="ui container"> | |||
<div class="ui stackable grid"> | |||
{{template "org/navber" .}} | |||
<div class="ui fourteen wide computer column"> | |||
{{template "org/navber" .}} | |||
{{template "org/select_pro" .}} | |||
<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}} | |||
@@ -3,10 +3,11 @@ | |||
{{template "org/header" .}} | |||
<div class="ui container"> | |||
{{template "base/alert" .}} | |||
{{template "org/navber" .}} | |||
<div class="ui stackable grid"> | |||
{{template "org/navber" .}} | |||
<div class="ui fourteen wide computer column list"> | |||
<div class="ui sixteen wide computer column list"> | |||
{{ range .Members}} | |||
<div class="item ui grid"> | |||
<div class="ui two wide column"> | |||
@@ -1,4 +1,4 @@ | |||
<div class="tablet only mobile only sixteen wide mobile sixteen wide tablet column row"> | |||
<!-- <div class="tablet only mobile only sixteen wide mobile sixteen wide tablet column row"> | |||
<div class="ui secondary pointing tabular top attached borderless menu navbar"> | |||
<a class="{{if $.PageIsOrgHome}}active{{end}} item" href="{{.HomeLink}}"> | |||
{{svg "octicon-home" 16}} {{$.i18n.Tr "org.home"}} | |||
@@ -12,10 +12,10 @@ | |||
</a> | |||
{{end}} | |||
</div> | |||
</div> | |||
</div> --> | |||
<!--平板、移动端--> | |||
<div class="computer only two wide computer column"> | |||
<!-- <div class="computer only two wide computer column"> | |||
<div class="ui grid"> | |||
<div class="sixteen wide column ui secondary sticky pointing tabular vertical menu"> | |||
{{with .Org}} | |||
@@ -33,5 +33,37 @@ | |||
{{end}} | |||
</div> | |||
</div> | |||
</div> | |||
<!--电脑、宽屏--> | |||
</div> --> | |||
<!--电脑、宽屏--> | |||
<style> | |||
.dis{ | |||
margin-bottom: 10px; | |||
} | |||
.active{ | |||
color:#0366D6 !important; | |||
} | |||
.mleft{ | |||
margin-left: 30% !important; | |||
} | |||
.mbom{ | |||
margin-bottom: 10px !important; | |||
} | |||
</style> | |||
<div class="row"> | |||
<div class="ui secondary pointing tabular top attached borderless menu navbar mbom"> | |||
{{with .Org}} | |||
<a class="{{if $.PageIsOrgHome}}active{{end}} item mleft" href="{{.HomeLink}}"> | |||
{{svg "octicon-home" 16}} {{$.i18n.Tr "org.home"}} | |||
</a> | |||
{{end}} | |||
<a class="{{if $.PageIsOrgMembers}}active{{end}} item" href="{{$.OrgLink}}/members"> | |||
{{svg "octicon-organization" 16}} {{$.i18n.Tr "org.people"}} | |||
</a> | |||
{{if or ($.IsOrganizationMember) ($.IsOrganizationOwner)}} | |||
<a class="{{if $.PageIsOrgTeams}}active{{end}} item" href="{{$.OrgLink}}/teams"> | |||
{{svg "octicon-jersey" 16}} {{$.i18n.Tr "org.teams"}} | |||
</a> | |||
{{end}} | |||
</div> | |||
</div> |
@@ -0,0 +1,288 @@ | |||
<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:#0366D6 !important; | |||
margin: 10px 0; | |||
} | |||
.marg{ | |||
margin: 0 5px !important; | |||
} | |||
.content_list{ | |||
max-height: 200px; | |||
overflow: auto; | |||
} | |||
.Relist{ | |||
color:#0366D6 !important; | |||
} | |||
.descript_height{ | |||
color: #101010 !important; | |||
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%; | |||
} | |||
/deep/ ui.checkbox input[type=checkbox]::after{ | |||
border: 1px solid #0366D6 !important; | |||
} | |||
</style> | |||
<div class="ui stackable grid"> | |||
<div style="width: 100%;margin:15px 0;"> | |||
{{if .tags}} | |||
<span class="header"> | |||
精选项目 | |||
</span> | |||
<!-- {{.IsOrganizationOwner}} --> | |||
{{if .IsOrganizationOwner}} | |||
<a class="text-right" id="model" onclick="showcreate()" >{{svg "octicon-gear" 16}}自定义</a> | |||
{{end}} | |||
{{end}} | |||
</div> | |||
<div style="width: 100%;"> | |||
{{ range .tags}} | |||
{{if eq .TagName "精选项目"}} | |||
<div class="ui three cards" style="margin-bottom: 10px;"> | |||
{{ range .RepoList}} | |||
<div class="card" > | |||
<div class="extra full_height" > | |||
<div class=" header "> | |||
<a class="header_card" href="{{.Link}}"> {{.Name}}</a> | |||
</div> | |||
<div class='content descript_height'> | |||
{{.Description}} | |||
</div> | |||
<div class="content tags_height" style="margin-top: 5px;"> | |||
{{if .Topics }} | |||
<div class=" ui tags "> | |||
{{range .Topics}} | |||
{{if ne . "" }}<a href="{{AppSubUrl}}/explore/repos?q={{.}}&topic={{$.Topic}}"><div class="ui small label topic">{{.}}</div></a>{{end}} | |||
{{end}} | |||
</div> | |||
{{end}} | |||
</div> | |||
<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> | |||
{{end}} | |||
{{end}} | |||
</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: 30%;"> | |||
<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){ | |||
$('.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.DisplayName}}/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() | |||
} | |||
}); | |||
} | |||
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" checked="" onclick="checkedNum()" class="Relist" name ='select_pro_name' data-repoid="${data[i].RepoID}" data-reponame="${data[i].RepoName}" data-selected=${data[i].Selected} > <label> ${data[i].RepoName} </label></div>` | |||
pro_html += '</div>' | |||
} | |||
else{ | |||
pro_html += `<div class="ui checkbox" style="width: 33%;margin-bottom:10px" > <input type="checkbox" onclick="checkedNum()" class="Relist" name ='select_pro_name' data-repoid="${data[i].RepoID}" data-reponame="${data[i].RepoName}" data-selected= ${data[i].Selected}> <label> ${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)); | |||
}) | |||
// saveData = getSelecteDataID(); | |||
// console.log("数据:",saveData) | |||
$.ajax({ | |||
type:"POST", | |||
url:"/org/{{.Org.DisplayName}}/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(){ | |||
num=0; | |||
var inputs = document.getElementsByName("select_pro_name") | |||
for (var i=0;i<inputs.length;i++){ | |||
if(inputs[i].checked){ | |||
num++ | |||
} | |||
} | |||
var show_num = 9-num; | |||
document.getElementById("recommend").innerHTML="还能推荐"+show_num+"个" | |||
} | |||
</script> |
@@ -3,12 +3,12 @@ | |||
{{template "org/header" .}} | |||
<div class="ui container"> | |||
{{template "base/alert" .}} | |||
{{template "org/navber" .}} | |||
<div class="ui stackable grid"> | |||
{{template "org/navber" .}} | |||
<div class="ui fourteen wide computer column list"> | |||
<div class="ui sixteen wide computer column list"> | |||
<div class="ui two column grid"> | |||
{{range .Teams}} | |||
<div class="column"> | |||