Browse Source

Merge pull request 'V20210910' (#420) from V20210910 into develop

Reviewed-on: https://git.openi.org.cn/OpenI/aiforge/pulls/420
Reviewed-by: zouap <zouap@pcl.ac.cn>
tags/v1.21.9.1
zouap 3 years ago
parent
commit
9bc69d762d
84 changed files with 19320 additions and 183 deletions
  1. +43
    -20
      README.md
  2. BIN
      assets/OPENI平台系统架构图.jpg
  3. BIN
      assets/架构图.png
  4. +28
    -3
      models/attachment.go
  5. +1
    -0
      models/blockchain.go
  6. +36
    -0
      models/custom_migrations.go
  7. +24
    -0
      models/file_chunk.go
  8. +3
    -0
      models/models.go
  9. +65
    -0
      models/recommend_org.go
  10. +23
    -0
      models/repo.go
  11. +2
    -0
      models/repo_list.go
  12. +4
    -3
      models/topic.go
  13. +1
    -0
      models/user.go
  14. +1
    -1
      modules/auth/modelarts.go
  15. +10
    -0
      modules/context/auth.go
  16. +27
    -0
      modules/labelmsg/label_redis_service.go
  17. +57
    -0
      modules/labelmsg/redismsgsender.go
  18. +25
    -5
      modules/modelarts/modelarts.go
  19. +16
    -5
      modules/setting/setting.go
  20. +14
    -0
      modules/storage/obs.go
  21. +3
    -2
      options/locale/locale_en-US.ini
  22. +4
    -3
      options/locale/locale_zh-CN.ini
  23. BIN
      public/img/loading.png
  24. BIN
      public/img/org-baai@2x-80.jpg
  25. BIN
      public/img/org-engineclub@2x-80.jpg
  26. BIN
      public/img/org-modelzoo@2x-80.jpg
  27. BIN
      public/img/org-openi@2x-80.jpg
  28. BIN
      public/img/org-platform@2x-80.jpg
  29. BIN
      public/img/org-tensorlayer@2x-80.jpg
  30. +7
    -0
      public/self/css/bootstrap.min.css
  31. +4
    -0
      public/self/css/font-awesome.min.css
  32. +6
    -0
      public/self/css/ionicons.min.css
  33. +117
    -0
      public/self/css/jquery.yhhDataTable.css
  34. +4263
    -0
      public/self/css/style.css
  35. +754
    -0
      public/self/dataset_preview.js
  36. BIN
      public/self/fonts/FontAwesome.otf
  37. BIN
      public/self/fonts/fontawesome-webfont.eot
  38. +2671
    -0
      public/self/fonts/fontawesome-webfont.svg
  39. BIN
      public/self/fonts/fontawesome-webfont.ttf
  40. BIN
      public/self/fonts/fontawesome-webfont.woff
  41. BIN
      public/self/fonts/fontawesome-webfont.woff2
  42. +269
    -0
      public/self/func.js
  43. +2938
    -0
      public/self/js/Director/detection.js
  44. +2209
    -0
      public/self/js/Director/labelingSelfDefine.js
  45. +739
    -0
      public/self/js/app.js
  46. +7
    -0
      public/self/js/bootstrap.min.js
  47. +1541
    -0
      public/self/js/jquery.jscrollpane.js
  48. +2
    -0
      public/self/js/jquery.min.js
  49. +221
    -0
      public/self/js/jquery.mousewheel.js
  50. +965
    -0
      public/self/labelTaskPage.js
  51. +879
    -0
      public/self/labeling.html
  52. +23
    -3
      routers/home.go
  53. +2
    -0
      routers/init.go
  54. +64
    -0
      routers/operation/orgs.go
  55. +37
    -0
      routers/private/cmd.go
  56. +28
    -0
      routers/private/hook.go
  57. +1
    -0
      routers/private/internal.go
  58. +46
    -3
      routers/repo/attachment.go
  59. +47
    -2
      routers/repo/dataset.go
  60. +105
    -16
      routers/repo/dir.go
  61. +37
    -0
      routers/repo/label.go
  62. +13
    -0
      routers/routes/routes.go
  63. +2
    -0
      templates/base/head.tmpl
  64. +76
    -0
      templates/explore/repo_left.tmpl
  65. +148
    -60
      templates/explore/repo_list.tmpl
  66. +123
    -0
      templates/explore/repo_orgtop.tmpl
  67. +39
    -1
      templates/explore/repo_right.tmpl
  68. +7
    -2
      templates/explore/repo_search.tmpl
  69. +5
    -4
      templates/explore/repos.tmpl
  70. +11
    -2
      templates/repo/cloudbrain/index.tmpl
  71. +6
    -2
      templates/repo/datasets/dataset_list.tmpl
  72. +11
    -0
      templates/repo/datasets/dirs/dir_list.tmpl
  73. +212
    -0
      templates/repo/datasets/dirs/dir_preview.tmpl
  74. +29
    -20
      templates/repo/datasets/dirs/index.tmpl
  75. +13
    -1
      templates/repo/datasets/index.tmpl
  76. +209
    -0
      templates/repo/datasets/label/index.tmpl
  77. +2
    -4
      templates/repo/header.tmpl
  78. +11
    -2
      templates/repo/modelarts/index.tmpl
  79. +24
    -4
      templates/repo/modelarts/new.tmpl
  80. +1
    -0
      web_src/js/components/MinioUploader.vue
  81. +1
    -0
      web_src/js/components/ObsUploader.vue
  82. +2
    -6
      web_src/js/index.js
  83. +1
    -1
      web_src/less/_repository.less
  84. +5
    -8
      web_src/less/openi.less

+ 43
- 20
README.md View File

@@ -1,25 +1,48 @@
[English](README.md)

<h1><img src="public/img/favicon.png" alt="logo" width="30" height="30"> OpenData - open data project management</h1>

[![Build Status](https://drone.gitea.io/api/badges/go-gitea/gitea/status.svg)](https://drone.gitea.io/go-gitea/gitea)
[![Join the Discord chat at https://discord.gg/Gitea](https://img.shields.io/discord/322538954119184384.svg)](https://discord.gg/Gitea)
[![](https://images.microbadger.com/badges/image/gitea/gitea.svg)](https://microbadger.com/images/gitea/gitea "Get your own image badge on microbadger.com")
[![codecov](https://codecov.io/gh/go-gitea/gitea/branch/master/graph/badge.svg)](https://codecov.io/gh/go-gitea/gitea)
[![GoDoc](https://godoc.org/code.gitea.io/gitea?status.svg)](https://godoc.org/code.gitea.io/gitea)
[![GitHub release](https://img.shields.io/github/release/go-gitea/gitea.svg)](https://github.com/go-gitea/gitea/releases/latest)
[![Help Contribute to Open Source](https://www.codetriage.com/go-gitea/gitea/badges/users.svg)](https://www.codetriage.com/go-gitea/gitea)
[![Become a backer/sponsor of gitea](https://opencollective.com/gitea/tiers/backers/badge.svg?label=backers&color=brightgreen)](https://opencollective.com/gitea)
<!--[English](README_EN.md)-->

<h1><img src="public/img/favicon.png" alt="logo" width="30" height="30">AiForge - 启智AI开发协作平台</h1>

[![release](https://img.shields.io/badge/release-V1.21.8-blue)](https://git.openi.org.cn/OpenI/aiforge/releases/latest)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT) [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
[![Crowdin](https://badges.crowdin.net/gitea/localized.svg)](https://crowdin.com/project/gitea)


## 目标


OpenData 的首要目标是提供对开源数据的大存储支持和管理,旨在为国家开源项目的建设贡献力量。为软件行业中的开源项目的发展提供助力。
## AiForge

启智AI开发协作平台是一个在线Web应用,旨在为人工智能算法、模型开发提供在线协同工作环境,它提供了<b>代码托管、数据集管理与共享、免费云端算力资源支持(GPU/NPU)、共享镜像</b>等功能。

[启智AI开发协作平台](https://git.openi.org.cn) 是使用本项目构建的在线服务,您可以直接点击链接访问试用。

本项目是基于[Gitea](https://github.com/go-gitea/gitea)发展而来的,我们对其进行了Fork并基于此扩展了人工智能开发中需要的功能,如数据集管理和模型训练等。对于和代码托管相关的功能,您可以参考[Gitea的文档](https://docs.gitea.io/zh-cn/)。

### 系统总体架构
下图展示了系统总体架构,本项目分为Web前端和服务后端,Web页面面向算法开发者、应用开发者、科研工作者、学生等用户群体,通过统一的Web页面入口,使用系统提供的系统服务。

后端服务涵盖了AI模型开发流水线,包括代码协同开发、数据管理、模型调试、训练、推理和部署等(*目前尚未支持模型部署*)。在不同的开发阶段,我们还将提供丰富的开发工具供用户使用,如数据标注、数据筛选、模型转换、模型压缩、代码检测等。我们也欢迎社区提供更多丰富的工具接入,提高利用平台进行开发的效率。
![系统架构图](assets/架构图.png)
## 在线服务使用
本项目的在线服务平台的详细使用帮助文档,可参阅本项目[百科](https://git.openi.org.cn/OpenI/aiforge/wiki)内容。
- 如何创建账号
- 如何创建组织及管理成员权限
- 如何创建项目仓库
- 如何使用数据集功能
- 如何使用计算资源进行模型调试和训练
- 使用小技巧
- 常见问题(FAQ)
## 安装
您也可以基于本项目代码,在本地环境安装部署服务。
### 数据库准备
[数据库准备说明](https://docs.gitea.io/zh-cn/database-prep/)
### 从源代码安装
- node版本 >= v10.13.0
- golang版本 >= 1.13.3

[从源代码安装说明](https://docs.gitea.io/zh-cn/install-from-source/)


## 我们所提供的
## 授权许可
本项目采用 MIT 开源授权许可证,完整的授权说明已放置在 [LICENSE](https://git.openi.org.cn/OpenI/aiforge/src/branch/develop/LICENSE) 文件中。


- 项目管理
- git代码管理
- <strong>大数据集存储管理,最高单个数据集限制为1TB</strong>
- 初期为社区项目免费提供30PB的算力,后续根据使用情况逐步增加
## 需要帮助?
如果您在使用或者开发过程中遇到问题,可以在以下渠道咨询:
- 点击[这里](https://git.openi.org.cn/OpenI/aiforge/issues)在线提交问题(点击页面右上角绿色按钮**创建任务**)
- 加入微信群实时交流,获得进一步的支持
<img src="https://git.openi.org.cn/OpenI/aiforge/wiki/raw/img/wechatgroup.jpg" width=200px />

BIN
assets/OPENI平台系统架构图.jpg View File

Before After
Width: 868  |  Height: 398  |  Size: 44 kB

BIN
assets/架构图.png View File

Before After
Width: 1909  |  Height: 857  |  Size: 159 kB

+ 28
- 3
models/attachment.go View File

@@ -6,11 +6,12 @@ package models


import ( import (
"bytes" "bytes"
"code.gitea.io/gitea/modules/log"
"fmt" "fmt"
"io" "io"
"path" "path"


"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/obs"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/storage" "code.gitea.io/gitea/modules/storage"
api "code.gitea.io/gitea/modules/structs" api "code.gitea.io/gitea/modules/structs"
@@ -253,9 +254,33 @@ func DeleteAttachments(attachments []*Attachment, remove bool) (int, error) {


if remove { if remove {
for i, a := range attachments { for i, a := range attachments {
if err := storage.Attachments.Delete(a.RelativePath()); err != nil {
return i, err
if a.Type == TypeCloudBrainOne {
if err := storage.Attachments.Delete(a.RelativePath()); err != nil {
return i, err
}
} }
if a.Type == TypeCloudBrainTwo {
input := &obs.DeleteObjectInput{}
input.Bucket = setting.Bucket
input.Key = setting.BasePath + path.Join(a.UUID[0:1], a.UUID[1:2], a.UUID, a.Name)
log.Info("delete obs file:" + input.Key)
output, err := storage.ObsCli.DeleteObject(input)
if err == nil {
log.Info("RequestId:%s\n", output.RequestId)
} else if obsError, ok := err.(obs.ObsError); ok {
log.Info("Code:%s\n", obsError.Code)
log.Info("Message:%s\n", obsError.Message)
}
}

//rf := path.Join(a.UUID[0:1], a.UUID[1:2])
/*
files, err := repo.GetDatasetDirs(a.UUID, "")
if err != nil {
log.Info("No files in attachment dirs.")
}
log.Info("files=" + files)
*/
} }
} }
return int(cnt), nil return int(cnt), nil


+ 1
- 0
models/blockchain.go View File

@@ -91,6 +91,7 @@ func GetBlockChainUnSuccessCommits() ([]*BlockChain, error) {
blockChains := make([]*BlockChain, 0, 10) blockChains := make([]*BlockChain, 0, 10)
return blockChains, x. return blockChains, x.
Where("status != ?", BlockChainCommitSuccess). Where("status != ?", BlockChainCommitSuccess).
Limit(100).
Find(&blockChains) Find(&blockChains)
} }




+ 36
- 0
models/custom_migrations.go View File

@@ -0,0 +1,36 @@
package models

import (
"code.gitea.io/gitea/modules/log"
"xorm.io/xorm"
)

type CustomMigration struct {
Description string
Migrate func(*xorm.Engine) error
}

var customMigrations = []CustomMigration{
{"Custom v1 Topic struct change to support chinese", syncTopicStruct},
}

func MigrateCustom(x *xorm.Engine) {

for _, m := range customMigrations {
log.Info("Migration: %s", m.Description)
if err := m.Migrate(x); err != nil {

log.Error("Migration: %v", err)

}
}

}

func syncTopicStruct(x *xorm.Engine) error {

query := "ALTER TABLE topic ALTER COLUMN name TYPE varchar(105);"

_, err := x.Exec(query)
return err
}

+ 24
- 0
models/file_chunk.go View File

@@ -1,6 +1,9 @@
package models package models


import ( import (
"fmt"

"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/timeutil"
"xorm.io/xorm" "xorm.io/xorm"
) )
@@ -87,6 +90,27 @@ func InsertFileChunk(fileChunk *FileChunk) (_ *FileChunk, err error) {
return fileChunk, nil return fileChunk, nil
} }


func DeleteFileChunkById(uuid string) (*FileChunk, error) {
return deleteFileChunkById(x, uuid)
}

func deleteFileChunkById(e Engine, uuid string) (*FileChunk, error) {
fileChunk := new(FileChunk)
if has, err := e.Where("uuid = ?", uuid).Get(fileChunk); err != nil {
return nil, err
} else if !has {
return nil, ErrFileChunkNotExist{"", uuid}
}

err := deleteFileChunk(e, fileChunk)
log.Info("delete the filechunk,id=" + fmt.Sprint(fileChunk.ID))
if err != nil {
return nil, err
} else {
return fileChunk, nil
}
}

// UpdateFileChunk updates the given file_chunk in database // UpdateFileChunk updates the given file_chunk in database
func UpdateFileChunk(fileChunk *FileChunk) error { func UpdateFileChunk(fileChunk *FileChunk) error {
return updateFileChunk(x, fileChunk) return updateFileChunk(x, fileChunk)


+ 3
- 0
models/models.go View File

@@ -129,6 +129,7 @@ func init() {
new(Cloudbrain), new(Cloudbrain),
new(FileChunk), new(FileChunk),
new(BlockChain), new(BlockChain),
new(RecommendOrg),
) )


gonicNames := []string{"SSL", "UID"} gonicNames := []string{"SSL", "UID"}
@@ -185,6 +186,8 @@ func SetEngine() (err error) {
x.SetMaxOpenConns(setting.Database.MaxOpenConns) x.SetMaxOpenConns(setting.Database.MaxOpenConns)
x.SetMaxIdleConns(setting.Database.MaxIdleConns) x.SetMaxIdleConns(setting.Database.MaxIdleConns)
x.SetConnMaxLifetime(setting.Database.ConnMaxLifetime) x.SetConnMaxLifetime(setting.Database.ConnMaxLifetime)
x.Sync2(tables...)
MigrateCustom(x)
return nil return nil
} }




+ 65
- 0
models/recommend_org.go View File

@@ -0,0 +1,65 @@
package models

import (
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/timeutil"
)

type RecommendOrg struct {
ID int64 `xorm:"pk autoincr"`
Order int64 `xorm:"INDEX NOT NULL unique"`
OrgID int64 `xorm:"INDEX NOT NULL unique"`
CreatedUnix timeutil.TimeStamp `xorm:"created"`
}

type RecommendOrgInfo struct {
RecommendOrg `xorm:"extends"`
User `xorm:"extends"`
}

type RecommendOrgList []*RecommendOrg
type RecommendOrgInfoList []*RecommendOrgInfo

func getRecommendOrgs(e Engine) (RecommendOrgList, error) {
orgs := make(RecommendOrgList, 0, 10)
err := e.Asc("order").
Find(&orgs)
return orgs, err
}

func GetRecommendOrgs() (RecommendOrgList, error) {
return getRecommendOrgs(x)
}

func getRecommendOrgInfos(e Engine) (RecommendOrgInfoList, error) {
orgs := make(RecommendOrgInfoList, 0, 10)
if err := e.Table(&RecommendOrg{}).Join("INNER", "`user`", "`user`.id = `recommend_org`.org_id").
OrderBy("recommend_org.order").Find(&orgs); err != nil {
return orgs, err
}
return orgs, nil
}

func GetRecommendOrgInfos() (RecommendOrgInfoList, error) {
return getRecommendOrgInfos(x)
}

func delRecommendOrgs(e Engine) error {
sql := "delete from recommend_org"
_, err := e.Exec(sql)
return err
}

func UpdateRecommendOrgs(orgs RecommendOrgList) error {
if err := delRecommendOrgs(x); err != nil {
log.Error("delRecommendOrgs failed:%v", err.Error())
return err
}

if _, err := x.Insert(&orgs); err != nil {
log.Error("Insert failed:%v", err.Error())
return err
}

return nil
}

+ 23
- 0
models/repo.go View File

@@ -175,6 +175,7 @@ type Repository struct {
NumMilestones int `xorm:"NOT NULL DEFAULT 0"` NumMilestones int `xorm:"NOT NULL DEFAULT 0"`
NumClosedMilestones int `xorm:"NOT NULL DEFAULT 0"` NumClosedMilestones int `xorm:"NOT NULL DEFAULT 0"`
NumOpenMilestones int `xorm:"-"` NumOpenMilestones int `xorm:"-"`
NumCommit int64 `xorm:"NOT NULL DEFAULT 0"`


IsPrivate bool `xorm:"INDEX"` IsPrivate bool `xorm:"INDEX"`
IsEmpty bool `xorm:"INDEX"` IsEmpty bool `xorm:"INDEX"`
@@ -213,6 +214,9 @@ type Repository struct {


CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`

Hot int64 `xorm:"-"`
Active int64 `xorm:"-"`
} }


// SanitizedOriginalURL returns a sanitized OriginalURL // SanitizedOriginalURL returns a sanitized OriginalURL
@@ -1411,6 +1415,15 @@ func GetRepositoriesByForkID(forkID int64) ([]*Repository, error) {
return getRepositoriesByForkID(x, forkID) return getRepositoriesByForkID(x, forkID)
} }


func getALLRepositories(e Engine) ([]*Repository, error) {
repos := make([]*Repository, 0, 1000)
return repos, e.Find(&repos)
}

func GetAllRepositories() ([]*Repository, error) {
return getALLRepositories(x)
}

func updateRepository(e Engine, repo *Repository, visibilityChanged bool) (err error) { func updateRepository(e Engine, repo *Repository, visibilityChanged bool) (err error) {
repo.LowerName = strings.ToLower(repo.Name) repo.LowerName = strings.ToLower(repo.Name)


@@ -2413,6 +2426,7 @@ func updateRepositoryCols(e Engine, repo *Repository, cols ...string) error {
} }


// UpdateRepositoryCols updates repository's columns // UpdateRepositoryCols updates repository's columns
// Notice: it will update the updated_unix automatically, be careful to use this
func UpdateRepositoryCols(repo *Repository, cols ...string) error { func UpdateRepositoryCols(repo *Repository, cols ...string) error {
return updateRepositoryCols(x, repo, cols...) return updateRepositoryCols(x, repo, cols...)
} }
@@ -2421,6 +2435,7 @@ func GetBlockChainUnSuccessRepos() ([]*Repository, error) {
repos := make([]*Repository, 0, 10) repos := make([]*Repository, 0, 10)
return repos, x. return repos, x.
Where("block_chain_status != ?", RepoBlockChainSuccess). Where("block_chain_status != ?", RepoBlockChainSuccess).
Limit(100).
Find(&repos) Find(&repos)
} }


@@ -2441,3 +2456,11 @@ func (repo *Repository) IncreaseCloneCnt() {


return return
} }

func UpdateRepositoryCommitNum(repo *Repository) error {
if _,err := x.Exec("UPDATE `repository` SET num_commit = ? where id = ?", repo.NumCommit, repo.ID); err != nil {
return err
}

return nil
}

+ 2
- 0
models/repo_list.go View File

@@ -198,6 +198,8 @@ const (
SearchOrderByForks SearchOrderBy = "num_forks ASC" SearchOrderByForks SearchOrderBy = "num_forks ASC"
SearchOrderByForksReverse SearchOrderBy = "num_forks DESC" SearchOrderByForksReverse SearchOrderBy = "num_forks DESC"
SearchOrderByDownloadTimes SearchOrderBy = "download_times DESC" SearchOrderByDownloadTimes SearchOrderBy = "download_times DESC"
SearchOrderByHot SearchOrderBy = "(num_watches + num_stars + num_forks + clone_cnt) DESC"
SearchOrderByActive SearchOrderBy = "(num_issues + num_pulls + num_commit) DESC"
) )


// SearchRepositoryCondition creates a query condition according search repository options // SearchRepositoryCondition creates a query condition according search repository options


+ 4
- 3
models/topic.go View File

@@ -8,6 +8,7 @@ import (
"fmt" "fmt"
"regexp" "regexp"
"strings" "strings"
"unicode/utf8"


"code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/timeutil"


@@ -21,12 +22,12 @@ func init() {
) )
} }


var topicPattern = regexp.MustCompile(`^[a-z0-9][a-z0-9-]*$`)
var topicPattern = regexp.MustCompile(`^[\x{4e00}-\x{9fa5}a-z0-9][\x{4e00}-\x{9fa5}a-z0-9-]*$`)


// Topic represents a topic of repositories // Topic represents a topic of repositories
type Topic struct { type Topic struct {
ID int64 ID int64
Name string `xorm:"UNIQUE VARCHAR(25)"`
Name string `xorm:"UNIQUE VARCHAR(105)"`
RepoCount int RepoCount int
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
@@ -56,7 +57,7 @@ func (err ErrTopicNotExist) Error() string {


// ValidateTopic checks a topic by length and match pattern rules // ValidateTopic checks a topic by length and match pattern rules
func ValidateTopic(topic string) bool { func ValidateTopic(topic string) bool {
return len(topic) <= 35 && topicPattern.MatchString(topic)
return utf8.RuneCountInString(topic) <= 35 && topicPattern.MatchString(topic)
} }


// SanitizeAndValidateTopics sanitizes and checks an array or topics // SanitizeAndValidateTopics sanitizes and checks an array or topics


+ 1
- 0
models/user.go View File

@@ -2047,6 +2047,7 @@ func GetBlockChainUnSuccessUsers() ([]*User, error) {
users := make([]*User, 0, 10) users := make([]*User, 0, 10)
err := x.Where("public_key = ''"). err := x.Where("public_key = ''").
Or("private_key = ''"). Or("private_key = ''").
Limit(100).
Find(&users) Find(&users)
return users, err return users, err
} }

+ 1
- 1
modules/auth/modelarts.go View File

@@ -7,7 +7,7 @@ import (


type CreateModelArtsForm struct { type CreateModelArtsForm struct {
JobName string `form:"job_name" binding:"Required"` JobName string `form:"job_name" binding:"Required"`
Attachment string `form:"attachment" binding:"Required"`
Attachment string `form:"attachment"`
Description string `form:"description"` Description string `form:"description"`
} }




+ 10
- 0
modules/context/auth.go View File

@@ -26,6 +26,7 @@ type ToggleOptions struct {
AdminRequired bool AdminRequired bool
DisableCSRF bool DisableCSRF bool
BasicAuthRequired bool BasicAuthRequired bool
OperationRequired bool
} }


// Toggle returns toggle options as middleware // Toggle returns toggle options as middleware
@@ -142,6 +143,15 @@ func Toggle(options *ToggleOptions) macaron.Handler {
return return
} }
} }

if options.OperationRequired {
//todo: add isOperator judgement
if !ctx.User.IsAdmin {
ctx.Error(403)
return
}
ctx.Data["PageIsOperation"] = true
}
} }
} }




+ 27
- 0
modules/labelmsg/label_redis_service.go View File

@@ -0,0 +1,27 @@
package labelmsg

import (
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
redigo "github.com/gomodule/redigo/redis"
)

var pool *redigo.Pool

func Init() {
redisBroker := setting.Broker
pool_size := 20
log.Info("start to connect redis.")
pool = redigo.NewPool(func() (redigo.Conn, error) {
c, err := redigo.DialURL(redisBroker)
if err != nil {
return nil, err
}
return c, nil
}, pool_size)

}

func Get() redigo.Conn {
return pool.Get()
}

+ 57
- 0
modules/labelmsg/redismsgsender.go View File

@@ -0,0 +1,57 @@
package labelmsg

import (
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
)

// 方法名

func SendAddAttachToLabelSys(attach string) error {

redisclient := Get()

//记得销毁本次链连接
defer redisclient.Close()

_, err := redisclient.Do("Publish", setting.LabelTaskName, attach)
if err != nil {
log.Critical("redis Publish failed.")
}

log.Info("LabelRedisQueue(%s) success", attach)

return nil
}

func SendDeleteAttachToLabelSys(attach string) error {

redisclient := Get()

//记得销毁本次链连接
defer redisclient.Close()

_, err := redisclient.Do("Publish", setting.LabelDatasetDeleteQueue, attach)
if err != nil {
log.Critical("redis Publish failed.")
}

log.Info("LabelDatasetDeleteQueue(%s) success", attach)

return nil
}

func SendDecompressAttachToLabelOBS(attach string) error {

redisclient := Get()
//记得销毁本次链连接
defer redisclient.Close()

_, err := redisclient.Do("Publish", setting.DecompressOBSTaskName, attach)
if err != nil {
log.Critical("redis Publish failed.")
}

log.Info("LabelDecompressOBSQueue(%s) success", attach)
return nil
}

+ 25
- 5
modules/modelarts/modelarts.go View File

@@ -1,13 +1,13 @@
package modelarts package modelarts


import ( import (
"code.gitea.io/gitea/modules/setting"
"encoding/json"
"path"

"code.gitea.io/gitea/models" "code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/storage"
"encoding/json"
"path"
) )


const ( const (
@@ -25,7 +25,27 @@ var (
) )


func GenerateTask(ctx *context.Context, jobName, uuid, description string) error { func GenerateTask(ctx *context.Context, jobName, uuid, description string) error {
dataActualPath := setting.Bucket + "/" + setting.BasePath + path.Join(uuid[0:1], uuid[1:2]) + "/" + uuid + "/"
var dataActualPath string
if uuid != "" {
dataActualPath = setting.Bucket + "/" + setting.BasePath + path.Join(uuid[0:1], uuid[1:2]) + "/" + uuid + "/"
} else {
userPath := setting.UserBasePath + ctx.User.Name + "/"
isExist, err := storage.ObsHasObject(userPath)
if err != nil {
log.Error("ObsHasObject failed:%v", err.Error(), ctx.Data["MsgID"])
return err
}

if !isExist {
if err = storage.ObsCreateObject(userPath); err != nil {
log.Error("ObsCreateObject failed:%v", err.Error(), ctx.Data["MsgID"])
return err
}
}

dataActualPath = setting.Bucket + "/" + userPath
}

if poolInfos == nil { if poolInfos == nil {
json.Unmarshal([]byte(setting.PoolInfos), &poolInfos) json.Unmarshal([]byte(setting.PoolInfos), &poolInfos)
} }


+ 16
- 5
modules/setting/setting.go View File

@@ -431,6 +431,11 @@ var (
AuthUser string AuthUser string
AuthPassword string AuthPassword string


//labelsystem config
LabelTaskName string
LabelDatasetDeleteQueue string
DecompressOBSTaskName string

//cloudbrain config //cloudbrain config
CBAuthUser string CBAuthUser string
CBAuthPassword string CBAuthPassword string
@@ -463,7 +468,7 @@ var (
Bucket string Bucket string
Location string Location string
BasePath string BasePath string
//RealPath string
UserBasePath string


//modelarts config //modelarts config
ModelArtsHost string ModelArtsHost string
@@ -473,10 +478,10 @@ var (
ModelArtsUsername string ModelArtsUsername string
ModelArtsPassword string ModelArtsPassword string
ModelArtsDomain string ModelArtsDomain string
ProfileID string
PoolInfos string
Flavor string
FlavorInfos string
ProfileID string
PoolInfos string
Flavor string
FlavorInfos string
) )


// DateLang transforms standard language locale name to corresponding value in datetime plugin. // DateLang transforms standard language locale name to corresponding value in datetime plugin.
@@ -1145,6 +1150,11 @@ func NewContext() {
AuthUser = sec.Key("USER").MustString("cW4cMtH24eoWPE7X") AuthUser = sec.Key("USER").MustString("cW4cMtH24eoWPE7X")
AuthPassword = sec.Key("PASSWORD").MustString("4BPmgvK2hb2Eywwyp4YZRY4B7yQf4DAC") AuthPassword = sec.Key("PASSWORD").MustString("4BPmgvK2hb2Eywwyp4YZRY4B7yQf4DAC")


sec = Cfg.Section("labelsystem")
LabelTaskName = sec.Key("LabelTaskName").MustString("LabelRedisQueue")
LabelDatasetDeleteQueue = sec.Key("LabelDatasetDeleteQueue").MustString("LabelDatasetDeleteQueue")
DecompressOBSTaskName = sec.Key("DecompressOBSTaskName").MustString("LabelDecompressOBSQueue")

sec = Cfg.Section("cloudbrain") sec = Cfg.Section("cloudbrain")
CBAuthUser = sec.Key("USER").MustString("cW4cMtH24eoWPE7X") CBAuthUser = sec.Key("USER").MustString("cW4cMtH24eoWPE7X")
CBAuthPassword = sec.Key("PWD").MustString("4BPmgvK2hb2Eywwyp4YZRY4B7yQf4DAC") CBAuthPassword = sec.Key("PWD").MustString("4BPmgvK2hb2Eywwyp4YZRY4B7yQf4DAC")
@@ -1177,6 +1187,7 @@ func NewContext() {
Bucket = sec.Key("BUCKET").MustString("testopendata") Bucket = sec.Key("BUCKET").MustString("testopendata")
Location = sec.Key("LOCATION").MustString("cn-south-222") Location = sec.Key("LOCATION").MustString("cn-south-222")
BasePath = sec.Key("BASE_PATH").MustString("attachment/") BasePath = sec.Key("BASE_PATH").MustString("attachment/")
UserBasePath = sec.Key("BASE_PATH_USER").MustString("users/")


sec = Cfg.Section("modelarts") sec = Cfg.Section("modelarts")
ModelArtsHost = sec.Key("ENDPOINT").MustString("112.95.163.80") ModelArtsHost = sec.Key("ENDPOINT").MustString("112.95.163.80")


+ 14
- 0
modules/storage/obs.go View File

@@ -143,3 +143,17 @@ func ObsGetPreSignedUrl(uuid, fileName string) (string, error) {


return output.SignedUrl, nil return output.SignedUrl, nil
} }

func ObsCreateObject(path string) error {
input := &obs.PutObjectInput{}
input.Bucket = setting.Bucket
input.Key = path

_, err := ObsCli.PutObject(input)
if err != nil {
log.Error("PutObject failed:", err.Error())
return err
}

return nil
}

+ 3
- 2
options/locale/locale_en-US.ini View File

@@ -647,7 +647,8 @@ public = public
dir = directory dir = directory
back = back back = back
copy_url=copy download url copy_url=copy download url
directory=check directory of the datasets
directory=preview of the datasets
create_label_task=create label task
visibility = visibility visibility = visibility
visibility_description = Only the owner or the organization members if they have rights, will be able to see it. visibility_description = Only the owner or the organization members if they have rights, will be able to see it.
visibility_helper = Make Dataset Private visibility_helper = Make Dataset Private
@@ -1815,7 +1816,7 @@ branch.included = Included
topic.manage_topics = Manage Topics topic.manage_topics = Manage Topics
topic.done = Done topic.done = Done
topic.count_prompt = You can not select more than 25 topics topic.count_prompt = You can not select more than 25 topics
topic.format_prompt = Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
topic.format_prompt = Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.


[org] [org]
org_name_holder = Organization Name org_name_holder = Organization Name


+ 4
- 3
options/locale/locale_zh-CN.ini View File

@@ -335,7 +335,7 @@ SSPIDefaultLanguage=默认语言


require_error=不能为空。 require_error=不能为空。
alpha_dash_error=应该只包含字母数字、破折号 ('-') 和下划线 ('_') 字符。 alpha_dash_error=应该只包含字母数字、破折号 ('-') 和下划线 ('_') 字符。
alpha_dash_dot_error=' 应该只包含字母数字, 破折号 ('-'), 下划线 ('_') 和点 ('. ') 。
alpha_dash_dot_error=应该只包含字母数字, 破折号 ('-'), 下划线 ('_') 和点 ('. ') 。
git_ref_name_error=` 必须是格式良好的 git 引用名称。` git_ref_name_error=` 必须是格式良好的 git 引用名称。`
size_error=长度必须为 %s。 size_error=长度必须为 %s。
min_size_error=长度最小为 %s 个字符。 min_size_error=长度最小为 %s 个字符。
@@ -649,7 +649,8 @@ dir=目录
back=返回 back=返回
copy_url=复制下载链接 copy_url=复制下载链接
copy_md5=复制文件MD5 copy_md5=复制文件MD5
directory=查看数据集目录结构
directory=数据集预览
create_label_task=创建标注任务
visibility=可见性 visibility=可见性
visibility_description=只有组织所有人或拥有权利的组织成员才能看到。 visibility_description=只有组织所有人或拥有权利的组织成员才能看到。
visibility_helper=将数据集设为私有 visibility_helper=将数据集设为私有
@@ -1817,7 +1818,7 @@ branch.included=已包含
topic.manage_topics=管理主题 topic.manage_topics=管理主题
topic.done=保存 topic.done=保存
topic.count_prompt=您最多选择25个主题 topic.count_prompt=您最多选择25个主题
topic.format_prompt=主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
topic.format_prompt=主题必须以中文、字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符


[org] [org]
org_name_holder=组织名称 org_name_holder=组织名称


BIN
public/img/loading.png View File

Before After
Width: 332  |  Height: 206  |  Size: 13 kB Width: 320  |  Height: 380  |  Size: 70 kB

BIN
public/img/org-baai@2x-80.jpg View File

Before After
Width: 201  |  Height: 80  |  Size: 3.5 kB

BIN
public/img/org-engineclub@2x-80.jpg View File

Before After
Width: 201  |  Height: 80  |  Size: 7.4 kB

BIN
public/img/org-modelzoo@2x-80.jpg View File

Before After
Width: 201  |  Height: 80  |  Size: 5.1 kB

BIN
public/img/org-openi@2x-80.jpg View File

Before After
Width: 201  |  Height: 80  |  Size: 9.0 kB

BIN
public/img/org-platform@2x-80.jpg View File

Before After
Width: 201  |  Height: 80  |  Size: 5.8 kB

BIN
public/img/org-tensorlayer@2x-80.jpg View File

Before After
Width: 201  |  Height: 80  |  Size: 4.9 kB

+ 7
- 0
public/self/css/bootstrap.min.css
File diff suppressed because it is too large
View File


+ 4
- 0
public/self/css/font-awesome.min.css
File diff suppressed because it is too large
View File


+ 6
- 0
public/self/css/ionicons.min.css
File diff suppressed because it is too large
View File


+ 117
- 0
public/self/css/jquery.yhhDataTable.css View File

@@ -0,0 +1,117 @@
.yhh-data-table-frame{
color:inherit;font-family:inherit;font-size:14px;font-weight:normal;
border:0;margin:0;padding:0;background-color:#FFFFFF;
}
/*table样式*/
.yhh-data-table-frame>table.yhh-data-table{
width:100%;border-collapse:collapse;border-spacing:0;empty-cells:show;
}
.yhh-data-table-frame>table.yhh-data-table td,
.yhh-data-table-frame>table.yhh-data-table th{
vertical-align:middle;text-align:left;border:1px solid #DDDDDD;
}
.yhh-data-table-frame>table.yhh-data-table.dataTable-theme-a td,
.yhh-data-table-frame>table.yhh-data-table.dataTable-theme-a th{
border:0;
}
.yhh-data-table-frame>table.yhh-data-table.dataTable-theme-a tr{
border-bottom:1px solid #DDDDDD;
}
.yhh-data-table-frame>table.yhh-data-table td{
background-color:#FFFFFF;color:inherit;
}
.yhh-data-table-frame>table.yhh-data-table th,
.yhh-data-table-frame>table.yhh-data-table thead td,
.yhh-data-table-frame>table.yhh-data-table tfoot td{
background-color:#DDDDDD;color:inherit;font-weight:bold;
}
.yhh-data-table-frame>table.yhh-data-table.dataTable-theme-a th,
.yhh-data-table-frame>table.yhh-data-table.dataTable-theme-a thead td,
.yhh-data-table-frame>table.yhh-data-table.dataTable-theme-a tfoot td{
background-color:#FFFFFF;
}
.yhh-data-table-frame>table.yhh-data-table tbody th,
.yhh-data-table-frame>table.yhh-data-table tbody td{
padding:10px 10px;
}
.yhh-data-table-frame>table.yhh-data-table thead th,
.yhh-data-table-frame>table.yhh-data-table thead td,
.yhh-data-table-frame>table.yhh-data-table tfoot th,
.yhh-data-table-frame>table.yhh-data-table tfoot td{
padding:10px 10px;
}
.yhh-data-table-frame>table.yhh-data-table tr.odd td{}
.yhh-data-table-frame>table.yhh-data-table tr.even td{background-color:#F6F6F6;}
.yhh-data-table-frame>table.yhh-data-table tr.hover-row td{
background-color:#F0F8FF;color:#00BFFF;
}
.yhh-data-table-frame>table.yhh-data-table tr.selected-row td{
background-color:#E6E6FA;
}
/*table上下功能行公共样式*/
.yhh-data-table-frame>.data-table-top-box,
.yhh-data-table-frame>.data-table-bottom-box{
position:relative;
}
.yhh-data-table-frame>.data-table-top-box,
.yhh-data-table-frame>.data-table-bottom-box,
.yhh-data-table-frame>.data-table-top-box>.per-length-box,
.yhh-data-table-frame>.data-table-bottom-box>.info-box,
.yhh-data-table-frame>.data-table-bottom-box>.paginate-box{
height:35px;
}
.yhh-data-table-frame>.data-table-top-box>.per-length-box,
.yhh-data-table-frame>.data-table-bottom-box>.info-box,
.yhh-data-table-frame>.data-table-bottom-box>.paginate-box{
line-height:35px;position:absolute;
}
/*改变每页显示数目功能样式*/
.yhh-data-table-frame>.data-table-top-box>.per-length-box{
top:0;right:2px;padding-right:50px;z-index:8;
}
.yhh-data-table-frame>.data-table-top-box>.per-length-box>.per-length-select{
position:absolute;top:1.5px;right:0;width:50px;margin:0;
}
.yhh-data-table-frame>.data-table-top-box>.per-length-box dt.sel-choosen-box,
.yhh-data-table-frame>.data-table-top-box>.per-length-box dd.sel-list{
border:1px solid #DDDDDD;border-radius:0;
}
.yhh-data-table-frame>.data-table-top-box>.per-length-box dt.sel-choosen-box{
height:30px;line-height:30px;cursor:pointer;background-color:#F0F8FF;
position:relative;padding-right:13px;padding-left:8px;
}
.yhh-data-table-frame>.data-table-top-box>.per-length-box dt.sel-choosen-box.expand{
border-radius:0;
}
.yhh-data-table-frame>.data-table-top-box>.per-length-box dd.sel-list.expand{
border-radius:0;border-top:0;margin:0;
}
.yhh-data-table-frame>.data-table-top-box>.per-length-box i.sel-icon{
height:30px;line-height:30px;position:absolute;top:0;right:2px;color:#AAAAAA;
}
.yhh-data-table-frame>.data-table-top-box>.per-length-box dd.sel-list{
z-index:10;max-height:200px;height:auto;
border-radius:0;border-top:0;
}
.yhh-data-table-frame>.data-table-top-box>.per-length-box .sel-option{
display:block;border-bottom:1px solid #CCCCCC;line-height:normal;
background-color:#FFFFFF;padding:6.5px 0;padding-left:8px;cursor:pointer;
}
.yhh-data-table-frame>.data-table-top-box>.per-length-box .sel-option:hover{
background-color:#DDE4FE;
}
.yhh-data-table-frame>.data-table-top-box>.per-length-box .sel-option:active{
background-color:#DA70D6;
}
.yhh-data-table-frame>.data-table-top-box>.per-length-box .sel-option.last-option{
border-bottom:0;
}
/*显示数据信息功能样式*/
.yhh-data-table-frame>.data-table-bottom-box>.info-box{
top:0;left:2px;
}
.yhh-data-table-frame>.data-table-bottom-box>.info-box .info-num{color:#F5A523;padding:0 5px;}
/*翻页按钮功能样式*/
.yhh-data-table-frame>.data-table-bottom-box>.paginate-box{
top:3px;right:0;overflow:hidden;
}

+ 4263
- 0
public/self/css/style.css
File diff suppressed because it is too large
View File


+ 754
- 0
public/self/dataset_preview.js View File

@@ -0,0 +1,754 @@
var img=new Image();

var ip = getIp();



var token = getCookie("_csrf");

canvas = document.getElementById("myCanvas");
context = canvas.getContext("2d");
// canvas.width = document.getElementById("myCanvas").offsetWidth;
// canvas.height = document.getElementById("myCanvas").offsetWidth/1280*720;

canvas.width = document.getElementById("win_canvas").offsetWidth;
canvas.height = document.getElementById("win_canvas").offsetHeight;




var color_dict = {"car":"#0099CC", "person":"#FF99CC","point":"#00cc00","pointselected":"red"};
var color_person = {"0":"#13c90c","1":"#fc0707","2":"#FF99CC","3":"#fceb07"};

var rects=[];
var masks=[];
var pointShapes =[];

var fileindex =0;
var lastindex=false;
var labeltastresult;

var pageSize = 12;
var tableData;
var tablePageData;
var dataset_id = $('#hide_uuidid').val();
var dbdatasetid = dataset_id;
var textContent;
var labelInfo;

page(0,pageSize);


function getCookie(name)
{
var arr,reg=new RegExp("(^| )"+name+"=([^;]*)(;|$)");
if(arr=document.cookie.match(reg))
return unescape(arr[2]);
else
return null;
}

function list(current,pageSize){
$.ajax({
type:"GET",
url:ip + "/gitea-dateset-item-page",
headers: {
authorization:token,
},
dataType:"json",
data:{
'datasetId':dbdatasetid,
'startPage':current,
'pageSize':pageSize},
async:false,
success:function(json){
tablePageData = json;
tableData = json.data;
labeltastresult = tableData;
fileindex=0;
if(lastindex){
fileindex = pageSize - 1;
}
},
error:function(response) {
}
});
}



function getTextContent(uuid,filename){
$.ajax({
type:"GET",
url:ip + "/getgiteatext",
headers: {
authorization:token,
},
dataType:"text",
data:{
'uuid':uuid,
'filename':filename
},
async:false,
success:function(json){
textContent = json;
},
error:function(response) {
}
});
}



/*
function previewDataSetFile(uuid,filename){
console.log('uuid=' + uuid + " filename=" + filename);
loadimg(uuid,filename);
}

function loadimg(uuid,filename){
img.src = ip + "/getgiteaimage?uuid=" + uuid + "&filename=" + filename;
var fname = filename.substring(filename.lastIndexOf('/') + 1);
$("#filename").text(fname);
}
*/

function loadimg(){
var length = labeltastresult[fileindex].pic_image_field.length;
 if(labeltastresult[fileindex].pic_image_field.substring(length - 5) == ".json" 
     || labeltastresult[fileindex].pic_image_field.substring(length - 4) == ".xml"
     || labeltastresult[fileindex].pic_image_field.substring(length - 4) == ".txt"
     || labeltastresult[fileindex].pic_image_field.substring(length - 4) == ".csv"
     || labeltastresult[fileindex].pic_image_field.substring(length - 3) == ".md"
     || labeltastresult[fileindex].pic_image_field.substring(length - 3) == ".py"
     || labeltastresult[fileindex].pic_image_field.substring(length - 3) == ".sh"){
//文本
canvas.style.display="none";
document.getElementById("textcontent").style.display="block";
getTextContent(dataset_id,labeltastresult[fileindex].pic_image_field);
$('#textcontent').height(canvas.height-40)
$("#textcontent").text(textContent);
}else{
if(labeltastresult[fileindex].pic_image_field.substring(length - 5) == ".jpeg" 
    || labeltastresult[fileindex].pic_image_field.substring(length - 4) == ".jpg"
    || labeltastresult[fileindex].pic_image_field.substring(length - 4) == ".bmp"
    || labeltastresult[fileindex].pic_image_field.substring(length - 4) == ".gif"
    || labeltastresult[fileindex].pic_image_field.substring(length - 4) == ".png"){
canvas.style.display="block";
document.getElementById("textcontent").style.display="none";
img.src = ip + "/getgiteaimage?uuid=" + dataset_id + "&filename=" + labeltastresult[fileindex].pic_image_field;
}else{
canvas.style.display="none";
document.getElementById("textcontent").style.display="block";
$('#textcontent').height(canvas.height)
$("#textcontent").text("暂不支持预览");

}
}
var fname = tableData[fileindex].pic_image_field.substring(tableData[fileindex].pic_image_field.lastIndexOf('/') + 1);
$("#filename").text(fname);
}

img.onload = function(){

canvas.width = document.getElementById("win_canvas").offsetWidth;
canvas.height = document.getElementById("win_canvas").offsetHeight-40;
//调整画布大小
// if ((img.width/img.height)<(canvas.width/canvas.height)){
// canvas.width=canvas.height * img.width / img.height;
// }
// else{
// canvas.height=canvas.width * img.height / img.width;
// }
drawimage();
}

function isEmpty(str){
if(typeof str == "undefined" || str == null || str == ""){
return true;
}
return false;
}
function drawimage() {
parse_labelinfo(labeltastresult[fileindex].label_info);
// 清除画布,准备绘制
context.clearRect(0, 0, canvas.width, canvas.heigth);
// modal_context.cleararc
context.drawImage(img,0,0,img.width,img.height,0,0,canvas.width, canvas.height);
for(var i=0; i<rects.length; i++) {
var rect = rects[i];
rectxywh = new Array(4);
rectxywh_tmp = rect.getXYWH();
rectxywh[0] = rectxywh_tmp[0] / canvas.width * canvas.width;
rectxywh[1] = rectxywh_tmp[1] / canvas.height * canvas.height;
rectxywh[2] = rectxywh_tmp[2] / canvas.width * canvas.width;
rectxywh[3] = rectxywh_tmp[3] / canvas.height * canvas.height;
// 绘制矩形

context.lineWidth = 3;
if(rect.type == "person"){
context.strokeStyle = color_person[ i % 4];
}else{
context.strokeStyle=color_dict[rect.type];
}
context.strokeRect(rectxywh[0],rectxywh[1],rectxywh[2],rectxywh[3]);
context.font = "15px Georgia";
context.fillStyle= context.strokeStyle;

context.fillText(rect.type, rectxywh[0],rectxywh[1]-5);
for(var j=0; j<4; j++){
var p_tmp = rect.points[j];
var p = new point(0,0);
p.x = p_tmp.x/ canvas.width * canvas.width;;
p.y = p_tmp.y / canvas.height * canvas.height;
context.fillStyle = color_dict["point"];
context.fillRect(p.x-2,p.y-2,4,4);
}
}
for (var i=0; i<masks.length; i++){
context.strokeStyle="purple"
var mask =masks[i];
context.lineWidth = 2;
for (var j=1; j<mask.points.length; j++){
context.beginPath();
context.moveTo(mask.points[j-1].x, mask.points[j-1].y);
context.lineTo(mask.points[j].x,mask.points[j].y);
context.stroke();
// modal_context.closePath();
}
context.moveTo(mask.points[mask.points.length-1].x,mask.points[mask.points.length-1].y);
context.lineTo(mask.points[0].x,mask.points[0].y);
context.stroke();
context.closePath();
for (var j=0; j<mask.points.length; j++){
var p = mask.points[j]
context.fillStyle = color_dict["point"];
context.fillRect(p.x-2,p.y-2,4,4);
}
}
}
function parse_labelinfo(labelinfo){
rects.length = 0;
masks.length = 0;
pointShapes.length = 0;
if(!isEmpty(labelinfo)){
var label_arr = JSON.parse(labelinfo);
for(var i=0;i<label_arr.length;i++){
if(!isEmpty(label_arr[i].mask)){
cls=label_arr[i].class_name;
var tmpMask = new maskar(getCanvasLocationX(label_arr[i].mask[0]),getCanvasLocationY(label_arr[i].mask[1]),cls);
for(var j = 2; j < label_arr[i].mask.length; j+=2){
tmpMask.points.push(new point(getCanvasLocationX(label_arr[i].mask[j]),getCanvasLocationY(label_arr[i].mask[j+1])));
}
if(!isEmpty(label_arr[i].id)){
tmpMask.id= label_arr[i].id;
}
if(!isEmpty(label_arr[i].blurred)){
tmpMask.blurred = label_arr[i].blurred;
}
if(!isEmpty(label_arr[i].goodIllumination)){
tmpMask.goodIllumination = label_arr[i].goodIllumination;
}
if(!isEmpty(label_arr[i].frontview)){
tmpMask.frontview = label_arr[i].frontview;
}
tmpMask.finish = true;
masks.push(tmpMask);
}else if(!isEmpty(label_arr[i].box)){
x1 = getCanvasLocationX(label_arr[i].box[0]);
y1 = getCanvasLocationY(label_arr[i].box[1]);
x2 = getCanvasLocationX(label_arr[i].box[2]);
y2 = getCanvasLocationY(label_arr[i].box[3]);
cls=label_arr[i].class_name;
score = label_arr[i].score;
rect = new rectar(x1,y1,x2,y2,cls,score);
if(!isEmpty(label_arr[i].id)){
rect.id= label_arr[i].id;
}
if(!isEmpty(label_arr[i].blurred)){
rect.blurred = label_arr[i].blurred;
}
if(!isEmpty(label_arr[i].goodIllumination)){
rect.goodIllumination = label_arr[i].goodIllumination;
}
if(!isEmpty(label_arr[i].frontview)){
rect.frontview = label_arr[i].frontview;
}
rects.push(rect);
}else if(!isEmpty(label_arr[i].keypoints)){
cls=label_arr[i].class_name;
score = label_arr[i].score;
var pointShapeObj = new pointShape(getCanvasLocationX(label_arr[i].keypoints[0]),getCanvasLocationY(label_arr[i].keypoints[1]),cls,score);
pointShapes.push(pointShapeObj);
}
}
}
}

function point(x,y){
this.x = x;
this.y = y;
this.isSelected = false;
};

function pointShape(x,y,type,score=1.0){
this.x = x;
this.y = y;
this.isSelected = false;
this.type = type;
this.score = score;
this.id =""; //标识
this.blurred=false;//模糊不清的; 记不清的; 难以区分的; 模棱两可的
this.goodIllumination = false; //照明
this.frontview = false;//正面图
}

function rectar(x1,y1,x2,y2, type, score=1.0){
// this.x = x;
// this.y = y;
// this.width = width;
// this.height = height;
this.type = type;
this.score = score;
//0--1,
//| |
//2--3
this.points = [new point(x1,y1), new point(x1, y2),new point(x2, y1),new point(x2, y2)];
this.getXYWH = function(){
var x_min=Math.min(this.points[0].x,this.points[1].x,this.points[2].x,this.points[3].x);
var x_max=Math.max(this.points[0].x,this.points[1].x,this.points[2].x,this.points[3].x);
var y_min=Math.min(this.points[0].y,this.points[1].y,this.points[2].y,this.points[3].y);
var y_max=Math.max(this.points[0].y,this.points[1].y,this.points[2].y,this.points[3].y);
return [x_min,y_min,x_max-x_min,y_max-y_min];
}
this.getX1Y1X2Y2 = function(){
var x_min=Math.min(this.points[0].x,this.points[1].x,this.points[2].x,this.points[3].x);
var x_max=Math.max(this.points[0].x,this.points[1].x,this.points[2].x,this.points[3].x);
var y_min=Math.min(this.points[0].y,this.points[1].y,this.points[2].y,this.points[3].y);
var y_max=Math.max(this.points[0].y,this.points[1].y,this.points[2].y,this.points[3].y);
return [x_min,y_min,x_max,y_max];
}
this.getdiapid = function(pid){//获取对角点
var twooverlapped,fouroverlapped;
for (var i=0;i<4;i++){
if ((this.points[pid].x!=this.points[i].x)&&(this.points[pid].y!=this.points[i].y)){
return i;
}
if ((this.points[pid].x!=this.points[i].x)||(this.points[pid].y!=this.points[i].y)){
twooverlapped=i;
}
if (i!=pid) fouroverlapped=i;

}
if (twooverlapped)
return twooverlapped;
return fouroverlapped;
}
this.mouseonpoint = false;
this.mouseonrect = false;
this.isSelected = false;
this.id =""; //标识
this.blurred=false;//模糊不清的; 记不清的; 难以区分的; 模棱两可的
this.goodIllumination = true; //照明
this.frontview = true;//正面图
};



function maskar(x0,y0,type){
this.type = type;
this.points = [new point(x0,y0)];
this.finish = false;
this.mouseonpoint = false;
this.mouseonmask = false;
this.isSelected = false;
this.getX1Y1 = function(){return [this.points[0].x,this.points[0].y]}
this.getBound = function(){
mlen = this.points.length;
var minX = 999999999, minY = 999999999, maxX = -1, maxY = -1;
for (var i = 0; i < mlen; i ++){
if(minX > this.points[i].x){
minX = this.points[i].x;
}
if(maxX < this.points[i].x){
maxX = this.points[i].x;
}
if(minY > this.points[i].y){
minY = this.points[i].y;
}
if(maxY < this.points[i].y){
maxY = this.points[i].y;
}
}
return [minX, minY, maxX, maxY];
}
this.id =""; //标识
this.blurred=false;//模糊不清的; 记不清的; 难以区分的; 模棱两可的
this.goodIllumination = true; //照明
this.frontview = true;//正面图
}

function getCanvasLocationX(num){
return Math.round(num * canvas.width/parseInt(img.width));
}

function getCanvasLocationY(num){
return Math.round(num * canvas.height/parseInt(img.height));
}


function page(current,pageSize){
list(current,pageSize);
showfilelist();
breadFiles();
loadimg();
setPage(tablePageData,pageSize);
}


getLabelInfo(dataset_id);
showlabelflist();


function nextPage(){
var current = $('#displayPage1').text();
page(current,pageSize);
}

function prePage(){
var current =$('#displayPage1').text();
if(current > 1){
page(current - 2,pageSize);
}
}

function goPage(){
var goNum = $('#goNum').val();

var pageTotal = $("#totalNum").text();
var pageNum = parseInt(pageTotal/pageSize);
if(pageTotal%pageSize!=0){
pageNum += 1;
}else {
pageNum = pageNum;
}
if (goNum<=0){
alert("请输入大于0的数值");
}
else if(goNum<=pageNum){
page(goNum - 1,pageSize);
}
else{
alert("不能超出总页码!");
}
}

$("#goNum").keydown(function (e) {
if (e.keyCode == 13) {
goPage();
}
});

function setPage(pageData,pageSize){
if (isEmpty(pageData)){
return;
}
var startIndex = pageData.current * pageSize;
if(pageData.total > 0){
startIndex = startIndex + 1;
}
if(startIndex < 10){
$('#startIndex').text(" " + (startIndex));
}else{
$('#startIndex').text(startIndex);
}
var endIndex = pageData.current * pageSize + pageData.data.length;
if(endIndex < 10){
$('#endIndex').text(" " + (endIndex));
}else{
$('#endIndex').text(endIndex);
}
$('#totalNum').text(pageData.total);
$('#displayPage1').text(pageData.current + 1);


if(pageData.current == 0){
$('#prePage').removeAttr("href");
$('#prePage').attr('style','color:#f5f5f6;');
}
else{
$('#prePage').attr("href","javascript:prePage()");
$('#prePage').attr('style','color:#000;');
}

if((pageData.current + 1) * pageSize >= pageData.total){
$('#nextPage').removeAttr("href");
$('#nextPage').attr('style','color:#f5f5f6;')
}
else{
$('#nextPage').attr("href","javascript:nextPage()");
$('#nextPage').attr('style','color:#000;');
}

var pageTotal = pageData.total;
var pageNum = parseInt(pageTotal/pageSize);
if(pageTotal%pageSize!=0){
pageNum += 1;
}else {
pageNum = pageNum;
}
$("#totalPageNum").text(pageNum);
}

function clickfilelist(index){
fileindex=index;
loadimg();
//drawimage();
breadFiles()
showfilelist();
}

function clickNext(){
if(fileindex<tableData.length-1) {
next();
}else{
if((tablePageData.current + 1) * pageSize >= tablePageData.total){
return;
}
nextPage();
}
}


function next(){
if(fileindex<tableData.length-1) {fileindex=fileindex+1;}
loadimg();
//drawimage();
breadFiles()
showfilelist();
}

function clickLast(){
if(fileindex == 0){
lastindex=true;
prePage();
lastindex=false;

}else{
last();
}
}

function last(){

if(fileindex>0) {fileindex=fileindex-1;}
loadimg();
//drawimage();
breadFiles();
showfilelist();
}


// function showfilelist(){
// var htmlstr="";
// for (var i=0;i<labeltastresult.length;i++){
// var fname = labeltastresult[i].pic_image_field.substring(labeltastresult[i].pic_image_field.lastIndexOf('/') + 1);
// var lablebg=" style=\"cursor:pointer\"";
// if (i==fileindex){lablebg=" style=\"background:#eee;color:#5a5a5a;cursor:pointer;\"";}
// htmlstr = htmlstr+"<tr onclick=\"clickfilelist("+i+");\""+ lablebg+"><td>"+ fname+ "</td></tr>";
// };
// document.getElementById("filelist").innerHTML=htmlstr;
// }


function showfilelist(){
// var filename_title = $('a.section:first').text()
// filename_title = filename_title.substring(0,filename_title.lastIndexOf('.'))
var filename_index = labeltastresult[0].pic_image_field.indexOf("/",70);
filename_title = labeltastresult[0].pic_image_field.substring(filename_index + 1);
filename_title = filename_title.substring(0,filename_title.indexOf('/'))
var htmlstr = '';
// htmlstr += '<div class="ui list">';
htmlstr += '<div class="item" style="padding:1.2em;border-bottom:0;display: table;width: 100%;">'
htmlstr += '<i class="caret down icon"></i>'
htmlstr += '<div class="content" style="background:#fff">'
htmlstr += '<div class="header" style="color: rgba(0,0,0,.8);font-size: 12px;font-weight: 600;">'+filename_title+'</div>'
htmlstr += '<div class="list" style="padding:1.2em">'
for (var i=0;i<labeltastresult.length;i++){
var fname = labeltastresult[i].pic_image_field.substring(labeltastresult[i].pic_image_field.lastIndexOf('/') + 1);
console.log(labeltastresult[i])
if(labeltastresult[i].pic_image_field.length > 70){
var tmpIndex = labeltastresult[i].pic_image_field.indexOf("/",70);
console.log(tmpIndex)
if(tmpIndex != -1){
fname = labeltastresult[i].pic_image_field.substring(tmpIndex + 1);
fname = fname.substring(fname.indexOf('/')+1);
}
}
htmlstr += '<div class="item" onclick=\"clickfilelist('+i+');\" style="border-bottom:0;padding-bottom:0.9em;cursor:pointer">'
htmlstr += '<div class="content" style="background:#fff;padding:0;">'
if(i==fileindex){
htmlstr += '<div class="header" style="color: rgba(0,0,0,.8);font-size: 12px;font-weight: 100;color:#0366d6;overflow: hidden;text-overflow:ellipsis;">'+fname+'</div>'
}
else{
htmlstr += '<div class="header" style="color: rgba(0,0,0,.8);font-size: 12px;font-weight: 100;overflow: hidden;text-overflow:ellipsis;">'+fname+'</div>'
}
htmlstr += '</div>'
htmlstr += '</div>'
};
htmlstr += '</div>'
htmlstr += '</div>'
htmlstr += '</div>'
document.getElementById("filelist").innerHTML=htmlstr;
}


function breadFiles(){

// for (var i=0;i<labeltastresult.length;i++){
// var fname_full_path=""
// if(labeltastresult[i].pic_image_field.length > 70){
// var tmp_index = labeltastresult[i].pic_image_field.indexOf("/",70);
// if(tmp_index != -1){
// fname_full_path = labeltastresult[i].pic_image_field.substring(tmp_index + 1);
// }
// var fname_path = fname_full_path.split('/')
// html_breadFile += '<div class="section">'+fname_full_path+'.zip'+'</div>'
// for(var i=1;i<fname_path.length;i++){
// html_breadFile += '<div class="divider" style="opacity:0.8"> / </div>'
// html_breadFile += '<div class="section">'+fname_path[i]+'</div>'

// }
// }
// else{


// }
// }
var fname_full_path=""
var filename_title = $('a.section:first').text()
filename_title = filename_title.substring(0,filename_title.lastIndexOf('.'))
var tmp_index = tableData[fileindex].pic_image_field.indexOf("/",70);
if(tmp_index != -1){
fname_full_path = tableData[fileindex].pic_image_field.substring(tmp_index + 1);
}
var fname_path = fname_full_path.split('/')
console.log(fname_path)
// var filename_text = tableData[fileindex].pic_image_field.substring(tableData[fileindex].pic_image_field.lastIndexOf('/')+1)
var html_breadFile = ''
// var source_name = filename_title+'.zip'
// html_breadFile += '<div class="section">'+source_name+'</div>'
// html_breadFile += '<div class="divider" style="opacity:0.8"> / </div>'
html_breadFile += '<div class="section">'+filename_title+'</div>'
html_breadFile += '<div class="divider" style="opacity:0.8"> / </div>'
for (var i=0;i<fname_path.length;i++){
html_breadFile += '<div class="section">'+fname_path[i]+'</div>'
html_breadFile += '<div class="divider" style="opacity:0.8"> / </div>'
}
document.getElementById("breadFile").innerHTML=html_breadFile

}

function showlabelflist(){
if(!isEmpty(labelInfo)){
var resLabelInfo = JSON.parse(labelInfo)
var textInfo = resLabelInfo["type"]
var html_labelFile = ''
for (var i=0;i<textInfo.length;i++){

html_labelFile += `<span style="display:block;width:70%;margin:0.6em 15%;padding-left:1.5em;padding-top:0.4em;padding-bottom:0.4em;font-size:12px;" class="labelInfo">${textInfo[i]}</span>`

}
document.getElementById("labellist").innerHTML=html_labelFile
setColor()
}
else{
return
}

}
function setColor(){
colorinfo1 = ['rgba(0, 199, 255, 0.4)','rgba(114, 46, 209, 0.4)','rgba(188, 100, 164, 0.4)','rgba(153, 204, 0, 0.4)','rgba(51, 204, 153, 0.4)','rgba(255, 204, 51, 0.4)',
'rgba(71, 255, 71, 0.4)','rgba(255, 154, 71, 0.4)','rgba(71, 126, 255, 0.4)','rgba(71, 255, 255, 0.4)','rgba(255, 247, 71, 0.4)','rgba(196, 127, 255, 0.4)','rgba(233, 84, 100, 0.4)',
'rgba(255, 71, 204, 0.4)',' rgba(43, 199, 160, 0.4)']
colorinfo2 = ['#00C7FF','#722ED1','#BC64A4','#99CC00','#33CC99','#FFCC33','#47FF47','#FF9A47','#477EFF','#47FFFF','#FFF747','#C47FFF','#E95464','#FF47CC','#2BC7A0']
var el_span = document.querySelectorAll("span.labelInfo")
for (var i=0;i<el_span.length;i++){
// var colorinfo = ~~(Math.random()*(1<<24))
// var colorinfo1 = '#'+(colorinfo).toString(16)
// var colorinfo2 = '#'+(colorinfo+100).toString(16)
el_span[i].style.backgroundColor = colorinfo1[i]
el_span[i].style.borderLeft = '5px solid'+ colorinfo2[i]
}

}
function getLabelInfo(uuid){
$.ajax({
type:"GET",
url:ip + "/getlabelinfo",
headers: {
authorization:token,
},
dataType:"text",
data:{
'uuid':uuid
},
async:false,
success:function(json){
labelInfo = json;
},
error:function(response) {
}
});

}

BIN
public/self/fonts/FontAwesome.otf View File


BIN
public/self/fonts/fontawesome-webfont.eot View File


+ 2671
- 0
public/self/fonts/fontawesome-webfont.svg
File diff suppressed because it is too large
View File


BIN
public/self/fonts/fontawesome-webfont.ttf View File


BIN
public/self/fonts/fontawesome-webfont.woff View File


BIN
public/self/fonts/fontawesome-webfont.woff2 View File


+ 269
- 0
public/self/func.js View File

@@ -0,0 +1,269 @@
function getIp(){
return "/labelsystem";

}


function isEmpty(str){
if(typeof str == "undefined" || str == null || str == ""){
return true;
}
return false;
}

function redirect(response){
if("REDIRECT" == response.getResponseHeader("REDIRECT")){ //若HEADER中含有REDIRECT说明后端想重定向,
var win = window;
while(win != win.top){
win = win.top;
}
win.location.href = getIp() +"/login.html";//使用win.location.href去实现重定向到登录页面
}
}

function setCookie(name,value)
{
var Days = 7;
var exp = new Date();
exp.setTime(exp.getTime() + Days*24*60*60*1000);
document.cookie = name + "="+ escape (value) + ";expires=" + exp.toGMTString();
}

//读取cookies
function getCookie(name)
{
var arr,reg=new RegExp("(^| )"+name+"=([^;]*)(;|$)");
if(arr=document.cookie.match(reg))
return unescape(arr[2]);
else
return null;
}

function delCookie(name)
{
var exp = new Date();
exp.setTime(exp.getTime() - 1);
var cval=getCookie(name);
if(cval!=null)
document.cookie= name + "="+cval+";expires="+exp.toGMTString();
}

//检查是否都符合 注册 要求
function check_reg()
{
if(check_email(document.getElementById('email')) && check_web(document.getElementById('web')))
{
return true;
}else{
return false;
}
}
//检查密码长度不能少于6
function check_len(thisObj){
if(thisObj.value.length==0)
{
document.getElementById('show_pass').innerHTML="密码不能为空";
return false;
}else{
if (thisObj.value.length<6)
{
document.getElementById('show_pass').innerHTML="密码长度不少于6";
return false;
}
document.getElementById('show_pass').innerHTML="";
return true;
}
}
//检查俩次密码输入是否一致
function check_pass(thisObj){
var psw=document.getElementById('pass');
if(psw.value.length==0)
{
document.getElementById('show_pass').innerHTML="密码不能为空";
return false;
}else{
document.getElementById('show_pass').innerHTML="";
if (thisObj.value!=psw.value)
{
document.getElementById('show_repass').innerHTML="两次密码输入不正确";
return false;
}
document.getElementById('show_repass').innerHTML="";
return true;
}
}
//检查email是否正确
function check_email(thisObj){
var reg=/^([a-zA-Z\d][a-zA-Z0-9_]+@[a-zA-Z\d]+(\.[a-zA-Z\d]+)+)$/gi;
var rzt=thisObj.value.match(reg);
if(thisObj.value.length==0){
document.getElementById('show_e').innerHTML="Email不能为空";
return false;
}else{
if (rzt==null)
{
document.getElementById('show_e').innerHTML="Email地址不正确";
return false;
}
document.getElementById('show_e').innerHTML="";
return true;
}
}
//检查web是否正确
function check_web(thisObj){
//var reg=/^\w+([\.\-]\w)*$/;
//var rzt=thisObj.value.match(reg);
if(thisObj.value.length==0){
document.getElementById('show_web').innerHTML="主页不能为空";
return false;
}else{
/*if (rzt==null)
{
document.getElementById('show_web').innerHTML="主页地址不正确";
return false;
} */
var strRegex = "^((https|http|ftp|rtsp|mms)?://)"
+ "?(([0-9a-z_!~*'().&=+$%-]+: )?[0-9a-z_!~*'().&=+$%-]+@)?" //ftp的user@
+ "(([0-9]{1,3}\.){3}[0-9]{1,3}" // IP形式的URL- 199.194.52.184
+ "|" // 允许IP和DOMAIN(域名)
+ "([0-9a-z_!~*'()-]+\.)*" // 域名- www.
+ "([0-9a-z][0-9a-z-]{0,61})?[0-9a-z]\." // 二级域名
+ "[a-z]{2,6})" // first level domain- .com or .museum
+ "(:[0-9]{1,4})?" // 端口- :80
+ "((/?)|" // a slash isn't required if there is no file name
+ "(/[0-9a-z_!~*'().;?:@&=+$,%#-]+)+/?)$";
var re=new RegExp(strRegex);
if(!re.test(thisObj.value))
{
document.getElementById('show_web').innerHTML="主页地址不正确";
return false;
}
document.getElementById('show_web').innerHTML="";
return true;
}
}

function isRightLatitude(lat){
var latreg = /^(\-|\+)?([0-8]?\d{1}\.\d{0,6}|90\.0{0,6}|[0-8]?\d{1}|90)$/;
if(!latreg.test(lat)){
return false;
//console.log("纬度整数部分为0-90,小数部分为0到6位!");
}
return true;
}

function isRightLongitude(longitude){
var longrg = /^(\-|\+)?(((\d|[1-9]\d|1[0-7]\d|0{1,3})\.\d{0,6})|(\d|[1-9]\d|1[0-7]\d|0{1,3})|180\.0{0,6}|180)$/;
if(!longrg.test(longitude)){
return false;
//console.log("经度整数部分为0-180,小数部分为0到6位!");
}
return true;
}

function isRightDateTime_dot(time){
//2020-05-20 14:20:20
if(time.length != 19){
return false;
}
return strDateTime(time);
}

function strDateTime(str)
{
var reg = /^(\d{1,4})(-|\/)(\d{1,2})\2(\d{1,2}) (\d{1,2}):(\d{1,2}):(\d{1,2})$/;
var r = str.match(reg);
if(r==null){
return false;
}
var d= new Date(r[1], r[3]-1,r[4],r[5],r[6],r[7]);
return (d.getFullYear()==r[1]&&(d.getMonth()+1)==r[3]&&d.getDate()==r[4]&&d.getHours()==r[5]&&d.getMinutes()==r[6]&&d.getSeconds()==r[7]);
}

function isRightDateTime_yyyyMMddHHmmss(time){
//20200520142020
if(time.length != 14){
return false;
}
var year = time.substring(0,4);
var month = time.substring(4,6);
var day = time.substring(6,8);
var hour = time.substring(8,10);
var minute = time.substring(10,12);
var second = time.substring(12,14);
console.log("year=" + year + " month=" + month + "day=" + day);
var d= new Date(year,month-1,day,hour,minute,second);
return (d.getFullYear()==year && (d.getMonth()+1)== month&& d.getDate()== day && d.getHours()==hour && d.getMinutes()==minute && d.getSeconds()==second);
}

function isDateString(strDate){
var strSeparator = "-"; //日期分隔符
var strDateArray;
var intYear;
var intMonth;
var intDay;
var boolLeapYear;
var ErrorMsg = ""; //出错信息
strDateArray = strDate.split(strSeparator);
//没有判断长度,其实2008-8-8也是合理的//strDate.length != 10 ||
if(strDateArray.length != 3) {
ErrorMsg += "日期格式必须为: yyyy-MM-dd";
return ErrorMsg;
}
intYear = parseInt(strDateArray[0],10);
intMonth = parseInt(strDateArray[1],10);
intDay = parseInt(strDateArray[2],10);
if(isNaN(intYear)||isNaN(intMonth)||isNaN(intDay)) {
ErrorMsg += "日期格式错误: 年月日必须为纯数字";
return ErrorMsg;
}
if(intMonth>12 || intMonth<1) {
ErrorMsg += "日期格式错误: 月份必须介于1和12之间";
return ErrorMsg;
}
if((intMonth==1||intMonth==3||intMonth==5||intMonth==7
||intMonth==8||intMonth==10||intMonth==12)
&&(intDay>31||intDay<1)) {
ErrorMsg += "日期格式错误: 大月的天数必须介于1到31之间";
return ErrorMsg;
}
if((intMonth==4||intMonth==6||intMonth==9||intMonth==11)
&&(intDay>30||intDay<1)) {
ErrorMsg += "日期格式错误: 小月的天数必须介于1到31之间";
return ErrorMsg;
}
if(intMonth==2){
if(intDay < 1) {
ErrorMsg += "日期格式错误: 日期必须大于或等于1";
return ErrorMsg;
}
boolLeapYear = false;
if((intYear%100) == 0){
if((intYear%400) == 0)
boolLeapYear = true;
}
else{
if((intYear % 4) == 0)
boolLeapYear = true;
}
if(boolLeapYear){
if(intDay > 29) {
ErrorMsg += "日期格式错误: 闰年的2月份天数不能超过29";
return ErrorMsg;
}
} else {
if(intDay > 28) {
ErrorMsg += "日期格式错误: 非闰年的2月份天数不能超过28";
return ErrorMsg;
}
}
}
return ErrorMsg;
}

+ 2938
- 0
public/self/js/Director/detection.js
File diff suppressed because it is too large
View File


+ 2209
- 0
public/self/js/Director/labelingSelfDefine.js
File diff suppressed because it is too large
View File


+ 739
- 0
public/self/js/app.js View File

@@ -0,0 +1,739 @@
/*!
* Author: Abdullah A Almsaeed
* Date: 4 Jan 2014
* Description:
* This file should be included in all pages
!**/

/*
* Global variables. If you change any of these vars, don't forget
* to change the values in the less files!
*/
var left_side_width = 220; //Sidebar width in pixels

$(function() {
"use strict";

//Enable sidebar toggle
$("[data-toggle='offcanvas']").click(function(e) {
e.preventDefault();

//If window is small enough, enable sidebar push menu
if ($(window).width() <= 992) {
$('.row-offcanvas').toggleClass('active');
$('.left-side').removeClass("collapse-left");
$(".right-side").removeClass("strech");
$('.row-offcanvas').toggleClass("relative");
} else {
//Else, enable content streching
$('.left-side').toggleClass("collapse-left");
$(".right-side").toggleClass("strech");
}
});

//Add hover support for touch devices
$('.btn').bind('touchstart', function() {
$(this).addClass('hover');
}).bind('touchend', function() {
$(this).removeClass('hover');
});

//Activate tooltips
$("[data-toggle='tooltip']").tooltip();

/*
* Add collapse and remove events to boxes
*/
$("[data-widget='collapse']").click(function() {
//Find the box parent
var box = $(this).parents(".box").first();
//Find the body and the footer
var bf = box.find(".box-body, .box-footer");
if (!box.hasClass("collapsed-box")) {
box.addClass("collapsed-box");
//Convert minus into plus
$(this).children(".fa-minus").removeClass("fa-minus").addClass("fa-plus");
bf.slideUp();
} else {
box.removeClass("collapsed-box");
//Convert plus into minus
$(this).children(".fa-plus").removeClass("fa-plus").addClass("fa-minus");
bf.slideDown();
}
});

/*
* ADD SLIMSCROLL TO THE TOP NAV DROPDOWNS
* ---------------------------------------
*/
$(".navbar .menu").slimscroll({
height: "200px",
alwaysVisible: false,
size: "3px"
}).css("width", "100%");

/*
* INITIALIZE BUTTON TOGGLE
* ------------------------
*/
$('.btn-group[data-toggle="btn-toggle"]').each(function() {
var group = $(this);
$(this).find(".btn").click(function(e) {
group.find(".btn.active").removeClass("active");
$(this).addClass("active");
e.preventDefault();
});

});

$("[data-widget='remove']").click(function() {
//Find the box parent
var box = $(this).parents(".box").first();
box.slideUp();
});

/* Sidebar tree view */
$(".sidebar .treeview").tree();

/*
* Make sure that the sidebar is streched full height
* ---------------------------------------------
* We are gonna assign a min-height value every time the
* wrapper gets resized and upon page load. We will use
* Ben Alman's method for detecting the resize event.
*
**/
function _fix() {
//Get window height and the wrapper height
var height = $(window).height() - $("body > .header").height() - ($("body > .footer").outerHeight() || 0);
$(".wrapper").css("min-height", height + "px");
var content = $(".wrapper").height();
//If the wrapper height is greater than the window
if (content > height){

//then set sidebar height to the wrapper
$(".left-side, html, body").css("min-height", content + "px");
$(".pull-height, html, body").css("min-height", content + "px");
}
else {
//Otherwise, set the sidebar to the height of the window
$(".left-side, html, body").css("min-height", height + "px");
$(".pull-height, html, body").css("min-height", content + "px");
}
}
//Fire upon load
_fix();
//Fire when wrapper is resized
$(".wrapper").resize(function() {
_fix();
fix_sidebar();
});

//Fix the fixed layout sidebar scroll bug
fix_sidebar();

/*
* We are gonna initialize all checkbox and radio inputs to
* iCheck plugin in.
* You can find the documentation at http://fronteed.com/iCheck/
*/
// $("input[type='checkbox']:not(.simple), input[type='radio']:not(.simple)").iCheck({
// checkboxClass: 'icheckbox_minimal',
// radioClass: 'iradio_minimal'
// });

});
function fix_sidebar() {
//Make sure the body tag has the .fixed class
if (!$("body").hasClass("fixed")) {
return;
}

//Add slimscroll
$(".sidebar").slimscroll({
height: ($(window).height() - $(".header").height()) + "px",
color: "rgba(0,0,0,0.2)"
});
}


/*
* BOX REFRESH BUTTON
* ------------------
* This is a custom plugin to use with the compenet BOX. It allows you to add
* a refresh button to the box. It converts the box's state to a loading state.
*
* USAGE:
* $("#box-widget").boxRefresh( options );
* */
(function($) {
"use strict";

$.fn.boxRefresh = function(options) {

// Render options
var settings = $.extend({
//Refressh button selector
trigger: ".refresh-btn",
//File source to be loaded (e.g: ajax/src.php)
source: "",
//Callbacks
onLoadStart: function(box) {
}, //Right after the button has been clicked
onLoadDone: function(box) {
} //When the source has been loaded

}, options);

//The overlay
var overlay = $('<div class="overlay"></div><div class="loading-img"></div>');

return this.each(function() {
//if a source is specified
if (settings.source === "") {
if (console) {
console.log("Please specify a source first - boxRefresh()");
}
return;
}
//the box
var box = $(this);
//the button
var rBtn = box.find(settings.trigger).first();

//On trigger click
rBtn.click(function(e) {
e.preventDefault();
//Add loading overlay
start(box);

//Perform ajax call
box.find(".box-body").load(settings.source, function() {
done(box);
});


});

});

function start(box) {
//Add overlay and loading img
box.append(overlay);

settings.onLoadStart.call(box);
}

function done(box) {
//Remove overlay and loading img
box.find(overlay).remove();

settings.onLoadDone.call(box);
}

};

})(jQuery);

/*
* SIDEBAR MENU
* ------------
* This is a custom plugin for the sidebar menu. It provides a tree view.
*
* Usage:
* $(".sidebar).tree();
*
* Note: This plugin does not accept any options. Instead, it only requires a class
* added to the element that contains a sub-menu.
*
* When used with the sidebar, for example, it would look something like this:
* <ul class='sidebar-menu'>
* <li class="treeview active">
* <a href="#>Menu</a>
* <ul class='treeview-menu'>
* <li class='active'><a href=#>Level 1</a></li>
* </ul>
* </li>
* </ul>
*
* Add .active class to <li> elements if you want the menu to be open automatically
* on page load. See above for an example.
*/
(function($) {
"use strict";

$.fn.tree = function() {

return this.each(function() {
var btn = $(this).children("a").first();
var menu = $(this).children(".treeview-menu").first();
var isActive = $(this).hasClass('active');

//initialize already active menus
if (isActive) {
menu.show();
btn.children(".fa-angle-left").first().removeClass("fa-angle-left").addClass("fa-angle-down");
}
//Slide open or close the menu on link click
btn.click(function(e) {
e.preventDefault();
if (isActive) {
//Slide up to close menu
menu.slideUp();
isActive = false;
btn.children(".fa-angle-down").first().removeClass("fa-angle-down").addClass("fa-angle-left");
btn.parent("li").removeClass("active");
} else {
//Slide down to open menu
menu.slideDown();
isActive = true;
btn.children(".fa-angle-left").first().removeClass("fa-angle-left").addClass("fa-angle-down");
btn.parent("li").addClass("active");
}
});

/* Add margins to submenu elements to give it a tree look */
menu.find("li > a").each(function() {
var pad = parseInt($(this).css("margin-left")) + 10;

$(this).css({"margin-left": pad + "px"});
});

});

};


}(jQuery));

/*
* TODO LIST CUSTOM PLUGIN
* -----------------------
* This plugin depends on iCheck plugin for checkbox and radio inputs
*/
(function($) {
"use strict";

$.fn.todolist = function(options) {
// Render options
var settings = $.extend({
//When the user checks the input
onCheck: function(ele) {
},
//When the user unchecks the input
onUncheck: function(ele) {
}
}, options);

return this.each(function() {
$('input', this).on('ifChecked', function(event) {
var ele = $(this).parents("li").first();
ele.toggleClass("done");
settings.onCheck.call(ele);
});

$('input', this).on('ifUnchecked', function(event) {
var ele = $(this).parents("li").first();
ele.toggleClass("done");
settings.onUncheck.call(ele);
});
});
};

}(jQuery));

/* CENTER ELEMENTS */
(function($) {
"use strict";
jQuery.fn.center = function(parent) {
if (parent) {
parent = this.parent();
} else {
parent = window;
}
this.css({
"position": "absolute",
"top": ((($(parent).height() - this.outerHeight()) / 2) + $(parent).scrollTop() + "px"),
"left": ((($(parent).width() - this.outerWidth()) / 2) + $(parent).scrollLeft() + "px")
});
return this;
}
}(jQuery));

/*
* jQuery resize event - v1.1 - 3/14/2010
* http://benalman.com/projects/jquery-resize-plugin/
*
* Copyright (c) 2010 "Cowboy" Ben Alman
* Dual licensed under the MIT and GPL licenses.
* http://benalman.com/about/license/
*/
(function($, h, c) {
var a = $([]), e = $.resize = $.extend($.resize, {}), i, k = "setTimeout", j = "resize", d = j + "-special-event", b = "delay", f = "throttleWindow";
e[b] = 250;
e[f] = true;
$.event.special[j] = {setup: function() {
if (!e[f] && this[k]) {
return false;
}
var l = $(this);
a = a.add(l);
$.data(this, d, {w: l.width(), h: l.height()});
if (a.length === 1) {
g();
}
}, teardown: function() {
if (!e[f] && this[k]) {
return false
}
var l = $(this);
a = a.not(l);
l.removeData(d);
if (!a.length) {
clearTimeout(i);
}
}, add: function(l) {
if (!e[f] && this[k]) {
return false
}
var n;
function m(s, o, p) {
var q = $(this), r = $.data(this, d);
r.w = o !== c ? o : q.width();
r.h = p !== c ? p : q.height();
n.apply(this, arguments)
}
if ($.isFunction(l)) {
n = l;
return m
} else {
n = l.handler;
l.handler = m
}
}};
function g() {
i = h[k](function() {
a.each(function() {
var n = $(this), m = n.width(), l = n.height(), o = $.data(this, d);
if (m !== o.w || l !== o.h) {
n.trigger(j, [o.w = m, o.h = l])
}
});
g()
}, e[b])
}}
)(jQuery, this);

/*!
* SlimScroll https://github.com/rochal/jQuery-slimScroll
* =======================================================
*
* Copyright (c) 2011 Piotr Rochala (http://rocha.la) Dual licensed under the MIT
*/
(function(f) {
jQuery.fn.extend({slimScroll: function(h) {
var a = f.extend({width: "auto", height: "100%", size: "7px", color: "#000", position: "right", distance: "1px", start: "top", opacity: 0.4, alwaysVisible: !0, disableFadeOut: !1, railVisible: !1, railColor: "#333", railOpacity: 0.2, railDraggable: !0, railClass: "slimScrollRail", barClass: "slimScrollBar", wrapperClass: "slimScrollDiv", allowPageScroll: !1, wheelStep: 20, touchScrollStep: 200, borderRadius: "5px", railBorderRadius: "5px"}, h);
this.each(function() {
function r(d) {
if (s) {
d = d ||
window.event;
var c = 0;
d.wheelDelta && (c = -d.wheelDelta / 120);
d.detail && (c = d.detail / 3);
f(d.target || d.srcTarget || d.srcElement).closest("." + a.wrapperClass).is(b.parent()) && m(c, !0);
d.preventDefault && !k && d.preventDefault();
k || (d.returnValue = !1)
}
}
function m(d, f, h) {
k = !1;
var e = d, g = b.outerHeight() - c.outerHeight();
f && (e = parseInt(c.css("top")) + d * parseInt(a.wheelStep) / 100 * c.outerHeight(), e = Math.min(Math.max(e, 0), g), e = 0 < d ? Math.ceil(e) : Math.floor(e), c.css({top: e + "px"}));
l = parseInt(c.css("top")) / (b.outerHeight() - c.outerHeight());
e = l * (b[0].scrollHeight - b.outerHeight());
h && (e = d, d = e / b[0].scrollHeight * b.outerHeight(), d = Math.min(Math.max(d, 0), g), c.css({top: d + "px"}));
b.scrollTop(e);
b.trigger("slimscrolling", ~~e);
v();
p()
}
function C() {
window.addEventListener ? (this.addEventListener("DOMMouseScroll", r, !1), this.addEventListener("mousewheel", r, !1), this.addEventListener("MozMousePixelScroll", r, !1)) : document.attachEvent("onmousewheel", r)
}
function w() {
u = Math.max(b.outerHeight() / b[0].scrollHeight * b.outerHeight(), D);
c.css({height: u + "px"});
var a = u == b.outerHeight() ? "none" : "block";
c.css({display: a})
}
function v() {
w();
clearTimeout(A);
l == ~~l ? (k = a.allowPageScroll, B != l && b.trigger("slimscroll", 0 == ~~l ? "top" : "bottom")) : k = !1;
B = l;
u >= b.outerHeight() ? k = !0 : (c.stop(!0, !0).fadeIn("fast"), a.railVisible && g.stop(!0, !0).fadeIn("fast"))
}
function p() {
a.alwaysVisible || (A = setTimeout(function() {
a.disableFadeOut && s || (x || y) || (c.fadeOut("slow"), g.fadeOut("slow"))
}, 1E3))
}
var s, x, y, A, z, u, l, B, D = 30, k = !1, b = f(this);
if (b.parent().hasClass(a.wrapperClass)) {
var n = b.scrollTop(),
c = b.parent().find("." + a.barClass), g = b.parent().find("." + a.railClass);
w();
if (f.isPlainObject(h)) {
if ("height"in h && "auto" == h.height) {
b.parent().css("height", "auto");
b.css("height", "auto");
var q = b.parent().parent().height();
b.parent().css("height", q);
b.css("height", q)
}
if ("scrollTo"in h)
n = parseInt(a.scrollTo);
else if ("scrollBy"in h)
n += parseInt(a.scrollBy);
else if ("destroy"in h) {
c.remove();
g.remove();
b.unwrap();
return
}
m(n, !1, !0)
}
} else {
a.height = "auto" == a.height ? b.parent().height() : a.height;
n = f("<div></div>").addClass(a.wrapperClass).css({position: "relative",
overflow: "hidden", width: a.width, height: a.height});
b.css({overflow: "hidden", width: a.width, height: a.height});
var g = f("<div></div>").addClass(a.railClass).css({width: a.size, height: "100%", position: "absolute", top: 0, display: a.alwaysVisible && a.railVisible ? "block" : "none", "border-radius": a.railBorderRadius, background: a.railColor, opacity: a.railOpacity, zIndex: 90}), c = f("<div></div>").addClass(a.barClass).css({background: a.color, width: a.size, position: "absolute", top: 0, opacity: a.opacity, display: a.alwaysVisible ?
"block" : "none", "border-radius": a.borderRadius, BorderRadius: a.borderRadius, MozBorderRadius: a.borderRadius, WebkitBorderRadius: a.borderRadius, zIndex: 99}), q = "right" == a.position ? {right: a.distance} : {left: a.distance};
g.css(q);
c.css(q);
b.wrap(n);
b.parent().append(c);
b.parent().append(g);
a.railDraggable && c.bind("mousedown", function(a) {
var b = f(document);
y = !0;
t = parseFloat(c.css("top"));
pageY = a.pageY;
b.bind("mousemove.slimscroll", function(a) {
currTop = t + a.pageY - pageY;
c.css("top", currTop);
m(0, c.position().top, !1)
});
b.bind("mouseup.slimscroll", function(a) {
y = !1;
p();
b.unbind(".slimscroll")
});
return!1
}).bind("selectstart.slimscroll", function(a) {
a.stopPropagation();
a.preventDefault();
return!1
});
g.hover(function() {
v()
}, function() {
p()
});
c.hover(function() {
x = !0
}, function() {
x = !1
});
b.hover(function() {
s = !0;
v();
p()
}, function() {
s = !1;
p()
});
b.bind("touchstart", function(a, b) {
a.originalEvent.touches.length && (z = a.originalEvent.touches[0].pageY)
});
b.bind("touchmove", function(b) {
k || b.originalEvent.preventDefault();
b.originalEvent.touches.length &&
(m((z - b.originalEvent.touches[0].pageY) / a.touchScrollStep, !0), z = b.originalEvent.touches[0].pageY)
});
w();
"bottom" === a.start ? (c.css({top: b.outerHeight() - c.outerHeight()}), m(0, !0)) : "top" !== a.start && (m(f(a.start).position().top, null, !0), a.alwaysVisible || c.hide());
C()
}
});
return this
}});
jQuery.fn.extend({slimscroll: jQuery.fn.slimScroll})
})(jQuery);

/*! iCheck v1.0.1 by Damir Sultanov, http://git.io/arlzeA, MIT Licensed */
(function(h) {
function F(a, b, d) {
var c = a[0], e = /er/.test(d) ? m : /bl/.test(d) ? s : l, f = d == H ? {checked: c[l], disabled: c[s], indeterminate: "true" == a.attr(m) || "false" == a.attr(w)} : c[e];
if (/^(ch|di|in)/.test(d) && !f)
D(a, e);
else if (/^(un|en|de)/.test(d) && f)
t(a, e);
else if (d == H)
for (e in f)
f[e] ? D(a, e, !0) : t(a, e, !0);
else if (!b || "toggle" == d) {
if (!b)
a[p]("ifClicked");
f ? c[n] !== u && t(a, e) : D(a, e)
}
}
function D(a, b, d) {
var c = a[0], e = a.parent(), f = b == l, A = b == m, B = b == s, K = A ? w : f ? E : "enabled", p = k(a, K + x(c[n])), N = k(a, b + x(c[n]));
if (!0 !== c[b]) {
if (!d &&
b == l && c[n] == u && c.name) {
var C = a.closest("form"), r = 'input[name="' + c.name + '"]', r = C.length ? C.find(r) : h(r);
r.each(function() {
this !== c && h(this).data(q) && t(h(this), b)
})
}
A ? (c[b] = !0, c[l] && t(a, l, "force")) : (d || (c[b] = !0), f && c[m] && t(a, m, !1));
L(a, f, b, d)
}
c[s] && k(a, y, !0) && e.find("." + I).css(y, "default");
e[v](N || k(a, b) || "");
B ? e.attr("aria-disabled", "true") : e.attr("aria-checked", A ? "mixed" : "true");
e[z](p || k(a, K) || "")
}
function t(a, b, d) {
var c = a[0], e = a.parent(), f = b == l, h = b == m, q = b == s, p = h ? w : f ? E : "enabled", t = k(a, p + x(c[n])),
u = k(a, b + x(c[n]));
if (!1 !== c[b]) {
if (h || !d || "force" == d)
c[b] = !1;
L(a, f, p, d)
}
!c[s] && k(a, y, !0) && e.find("." + I).css(y, "pointer");
e[z](u || k(a, b) || "");
q ? e.attr("aria-disabled", "false") : e.attr("aria-checked", "false");
e[v](t || k(a, p) || "")
}
function M(a, b) {
if (a.data(q)) {
a.parent().html(a.attr("style", a.data(q).s || ""));
if (b)
a[p](b);
a.off(".i").unwrap();
h(G + '[for="' + a[0].id + '"]').add(a.closest(G)).off(".i")
}
}
function k(a, b, d) {
if (a.data(q))
return a.data(q).o[b + (d ? "" : "Class")]
}
function x(a) {
return a.charAt(0).toUpperCase() +
a.slice(1)
}
function L(a, b, d, c) {
if (!c) {
if (b)
a[p]("ifToggled");
a[p]("ifChanged")[p]("if" + x(d))
}
}
var q = "iCheck", I = q + "-helper", u = "radio", l = "checked", E = "un" + l, s = "disabled", w = "determinate", m = "in" + w, H = "update", n = "type", v = "addClass", z = "removeClass", p = "trigger", G = "label", y = "cursor", J = /ipad|iphone|ipod|android|blackberry|windows phone|opera mini|silk/i.test(navigator.userAgent);
h.fn[q] = function(a, b) {
var d = 'input[type="checkbox"], input[type="' + u + '"]', c = h(), e = function(a) {
a.each(function() {
var a = h(this);
c = a.is(d) ?
c.add(a) : c.add(a.find(d))
})
};
if (/^(check|uncheck|toggle|indeterminate|determinate|disable|enable|update|destroy)$/i.test(a))
return a = a.toLowerCase(), e(this), c.each(function() {
var c = h(this);
"destroy" == a ? M(c, "ifDestroyed") : F(c, !0, a);
h.isFunction(b) && b()
});
if ("object" != typeof a && a)
return this;
var f = h.extend({checkedClass: l, disabledClass: s, indeterminateClass: m, labelHover: !0, aria: !1}, a), k = f.handle, B = f.hoverClass || "hover", x = f.focusClass || "focus", w = f.activeClass || "active", y = !!f.labelHover, C = f.labelHoverClass ||
"hover", r = ("" + f.increaseArea).replace("%", "") | 0;
if ("checkbox" == k || k == u)
d = 'input[type="' + k + '"]';
-50 > r && (r = -50);
e(this);
return c.each(function() {
var a = h(this);
M(a);
var c = this, b = c.id, e = -r + "%", d = 100 + 2 * r + "%", d = {position: "absolute", top: e, left: e, display: "block", width: d, height: d, margin: 0, padding: 0, background: "#fff", border: 0, opacity: 0}, e = J ? {position: "absolute", visibility: "hidden"} : r ? d : {position: "absolute", opacity: 0}, k = "checkbox" == c[n] ? f.checkboxClass || "icheckbox" : f.radioClass || "i" + u, m = h(G + '[for="' + b + '"]').add(a.closest(G)),
A = !!f.aria, E = q + "-" + Math.random().toString(36).replace("0.", ""), g = '<div class="' + k + '" ' + (A ? 'role="' + c[n] + '" ' : "");
m.length && A && m.each(function() {
g += 'aria-labelledby="';
this.id ? g += this.id : (this.id = E, g += E);
g += '"'
});
g = a.wrap(g + "/>")[p]("ifCreated").parent().append(f.insert);
d = h('<ins class="' + I + '"/>').css(d).appendTo(g);
a.data(q, {o: f, s: a.attr("style")}).css(e);
f.inheritClass && g[v](c.className || "");
f.inheritID && b && g.attr("id", q + "-" + b);
"static" == g.css("position") && g.css("position", "relative");
F(a, !0, H);
if (m.length)
m.on("click.i mouseover.i mouseout.i touchbegin.i touchend.i", function(b) {
var d = b[n], e = h(this);
if (!c[s]) {
if ("click" == d) {
if (h(b.target).is("a"))
return;
F(a, !1, !0)
} else
y && (/ut|nd/.test(d) ? (g[z](B), e[z](C)) : (g[v](B), e[v](C)));
if (J)
b.stopPropagation();
else
return!1
}
});
a.on("click.i focus.i blur.i keyup.i keydown.i keypress.i", function(b) {
var d = b[n];
b = b.keyCode;
if ("click" == d)
return!1;
if ("keydown" == d && 32 == b)
return c[n] == u && c[l] || (c[l] ? t(a, l) : D(a, l)), !1;
if ("keyup" == d && c[n] == u)
!c[l] && D(a, l);
else if (/us|ur/.test(d))
g["blur" ==
d ? z : v](x)
});
d.on("click mousedown mouseup mouseover mouseout touchbegin.i touchend.i", function(b) {
var d = b[n], e = /wn|up/.test(d) ? w : B;
if (!c[s]) {
if ("click" == d)
F(a, !1, !0);
else {
if (/wn|er|in/.test(d))
g[v](e);
else
g[z](e + " " + w);
if (m.length && y && e == B)
m[/ut|nd/.test(d) ? z : v](C)
}
if (J)
b.stopPropagation();
else
return!1
}
})
})
}
})(window.jQuery || window.Zepto);

+ 7
- 0
public/self/js/bootstrap.min.js
File diff suppressed because it is too large
View File


+ 1541
- 0
public/self/js/jquery.jscrollpane.js
File diff suppressed because it is too large
View File


+ 2
- 0
public/self/js/jquery.min.js
File diff suppressed because it is too large
View File


+ 221
- 0
public/self/js/jquery.mousewheel.js View File

@@ -0,0 +1,221 @@
/*!
* jQuery Mousewheel 3.1.13
*
* Copyright jQuery Foundation and other contributors
* Released under the MIT license
* http://jquery.org/license
*/

(function (factory) {
if ( typeof define === 'function' && define.amd ) {
// AMD. Register as an anonymous module.
define(['jquery'], factory);
} else if (typeof exports === 'object') {
// Node/CommonJS style for Browserify
module.exports = factory;
} else {
// Browser globals
factory(jQuery);
}
}(function ($) {

var toFix = ['wheel', 'mousewheel', 'DOMMouseScroll', 'MozMousePixelScroll'],
toBind = ( 'onwheel' in document || document.documentMode >= 9 ) ?
['wheel'] : ['mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'],
slice = Array.prototype.slice,
nullLowestDeltaTimeout, lowestDelta;

if ( $.event.fixHooks ) {
for ( var i = toFix.length; i; ) {
$.event.fixHooks[ toFix[--i] ] = $.event.mouseHooks;
}
}

var special = $.event.special.mousewheel = {
version: '3.1.12',

setup: function() {
if ( this.addEventListener ) {
for ( var i = toBind.length; i; ) {
this.addEventListener( toBind[--i], handler, false );
}
} else {
this.onmousewheel = handler;
}
// Store the line height and page height for this particular element
$.data(this, 'mousewheel-line-height', special.getLineHeight(this));
$.data(this, 'mousewheel-page-height', special.getPageHeight(this));
},

teardown: function() {
if ( this.removeEventListener ) {
for ( var i = toBind.length; i; ) {
this.removeEventListener( toBind[--i], handler, false );
}
} else {
this.onmousewheel = null;
}
// Clean up the data we added to the element
$.removeData(this, 'mousewheel-line-height');
$.removeData(this, 'mousewheel-page-height');
},

getLineHeight: function(elem) {
var $elem = $(elem),
$parent = $elem['offsetParent' in $.fn ? 'offsetParent' : 'parent']();
if (!$parent.length) {
$parent = $('body');
}
return parseInt($parent.css('fontSize'), 10) || parseInt($elem.css('fontSize'), 10) || 16;
},

getPageHeight: function(elem) {
return $(elem).height();
},

settings: {
adjustOldDeltas: true, // see shouldAdjustOldDeltas() below
normalizeOffset: true // calls getBoundingClientRect for each event
}
};

$.fn.extend({
mousewheel: function(fn) {
return fn ? this.bind('mousewheel', fn) : this.trigger('mousewheel');
},

unmousewheel: function(fn) {
return this.unbind('mousewheel', fn);
}
});


function handler(event) {
var orgEvent = event || window.event,
args = slice.call(arguments, 1),
delta = 0,
deltaX = 0,
deltaY = 0,
absDelta = 0,
offsetX = 0,
offsetY = 0;
event = $.event.fix(orgEvent);
event.type = 'mousewheel';

// Old school scrollwheel delta
if ( 'detail' in orgEvent ) { deltaY = orgEvent.detail * -1; }
if ( 'wheelDelta' in orgEvent ) { deltaY = orgEvent.wheelDelta; }
if ( 'wheelDeltaY' in orgEvent ) { deltaY = orgEvent.wheelDeltaY; }
if ( 'wheelDeltaX' in orgEvent ) { deltaX = orgEvent.wheelDeltaX * -1; }

// Firefox < 17 horizontal scrolling related to DOMMouseScroll event
if ( 'axis' in orgEvent && orgEvent.axis === orgEvent.HORIZONTAL_AXIS ) {
deltaX = deltaY * -1;
deltaY = 0;
}

// Set delta to be deltaY or deltaX if deltaY is 0 for backwards compatabilitiy
delta = deltaY === 0 ? deltaX : deltaY;

// New school wheel delta (wheel event)
if ( 'deltaY' in orgEvent ) {
deltaY = orgEvent.deltaY * -1;
delta = deltaY;
}
if ( 'deltaX' in orgEvent ) {
deltaX = orgEvent.deltaX;
if ( deltaY === 0 ) { delta = deltaX * -1; }
}

// No change actually happened, no reason to go any further
if ( deltaY === 0 && deltaX === 0 ) { return; }

// Need to convert lines and pages to pixels if we aren't already in pixels
// There are three delta modes:
// * deltaMode 0 is by pixels, nothing to do
// * deltaMode 1 is by lines
// * deltaMode 2 is by pages
if ( orgEvent.deltaMode === 1 ) {
var lineHeight = $.data(this, 'mousewheel-line-height');
delta *= lineHeight;
deltaY *= lineHeight;
deltaX *= lineHeight;
} else if ( orgEvent.deltaMode === 2 ) {
var pageHeight = $.data(this, 'mousewheel-page-height');
delta *= pageHeight;
deltaY *= pageHeight;
deltaX *= pageHeight;
}

// Store lowest absolute delta to normalize the delta values
absDelta = Math.max( Math.abs(deltaY), Math.abs(deltaX) );

if ( !lowestDelta || absDelta < lowestDelta ) {
lowestDelta = absDelta;

// Adjust older deltas if necessary
if ( shouldAdjustOldDeltas(orgEvent, absDelta) ) {
lowestDelta /= 40;
}
}

// Adjust older deltas if necessary
if ( shouldAdjustOldDeltas(orgEvent, absDelta) ) {
// Divide all the things by 40!
delta /= 40;
deltaX /= 40;
deltaY /= 40;
}

// Get a whole, normalized value for the deltas
delta = Math[ delta >= 1 ? 'floor' : 'ceil' ](delta / lowestDelta);
deltaX = Math[ deltaX >= 1 ? 'floor' : 'ceil' ](deltaX / lowestDelta);
deltaY = Math[ deltaY >= 1 ? 'floor' : 'ceil' ](deltaY / lowestDelta);

// Normalise offsetX and offsetY properties
if ( special.settings.normalizeOffset && this.getBoundingClientRect ) {
var boundingRect = this.getBoundingClientRect();
offsetX = event.clientX - boundingRect.left;
offsetY = event.clientY - boundingRect.top;
}

// Add information to the event object
event.deltaX = deltaX;
event.deltaY = deltaY;
event.deltaFactor = lowestDelta;
event.offsetX = offsetX;
event.offsetY = offsetY;
// Go ahead and set deltaMode to 0 since we converted to pixels
// Although this is a little odd since we overwrite the deltaX/Y
// properties with normalized deltas.
event.deltaMode = 0;

// Add event and delta to the front of the arguments
args.unshift(event, delta, deltaX, deltaY);

// Clearout lowestDelta after sometime to better
// handle multiple device types that give different
// a different lowestDelta
// Ex: trackpad = 3 and mouse wheel = 120
if (nullLowestDeltaTimeout) { clearTimeout(nullLowestDeltaTimeout); }
nullLowestDeltaTimeout = setTimeout(nullLowestDelta, 200);

return ($.event.dispatch || $.event.handle).apply(this, args);
}

function nullLowestDelta() {
lowestDelta = null;
}

function shouldAdjustOldDeltas(orgEvent, absDelta) {
// If this is an older event and the delta is divisable by 120,
// then we are assuming that the browser is treating this as an
// older mouse wheel event and that we should divide the deltas
// by 40 to try and get a more usable deltaFactor.
// Side note, this actually impacts the reported scroll distance
// in older browsers and can cause scrolling to be slower than native.
// Turn this off by setting $.event.special.mousewheel.settings.adjustOldDeltas to false.
return special.settings.adjustOldDeltas && orgEvent.type === 'mousewheel' && absDelta % 120 === 0;
}

}));

+ 965
- 0
public/self/labelTaskPage.js View File

@@ -0,0 +1,965 @@
var token;
if(isEmpty(token)){
var meta = $("meta[name=_uid]");
if(!isEmpty(meta)){
token = meta.attr("content");
console.log("token is uid:" + token);
}
}
var authorMeta = $("meta[name=author]");
var userName;
if(!isEmpty(authorMeta)){
userName = authorMeta.attr("content");
console.log("user name=" + userName);
}
var userType;
if(isEmpty(userType)){
userType =1;
}
var ip = getIp();

var pageSize = 10;

var tableData;
var tablePageData;

var preDictTaskData;
var dataSetTaskData;

var userInfoData;
var labelPropertyData;
var repoId = $('#repoId').val();


console.log("repoId=" + repoId);

function setDataSetTask(){
dataset_task_list();
display_createdatasetlabel(0);
//getUser();
//dislpayUser();
getLabelPropertyTask();
displayLabelPropertyTask();
$(".ui.dataset.modal").modal("show");
}

function getLabelPropertyTask(){
$.ajax({
type:"GET",
url:ip + "/api/label-property-task-all/",
headers: {
authorization:token,
},
dataType:"json",
async:false,
success:function(json){
labelPropertyData = json;
console.log(json);
},
error:function(response) {
redirect(response);
}
});
}

function displayLabelPropertyTask(){
var html="<option value=\"\" selected=\"\">请选择</option>";
for (var i=0;i<labelPropertyData.length;i++){
var row = "<option value=\""+labelPropertyData[i].id+
"\">"+labelPropertyData[i].task_name +
"</option>";
html=html+row;
}
console.log(html);
document.getElementById('labelpropertytask_dataset').innerHTML=html;
document.getElementById('labelpropertytask_auto').innerHTML=html;
}

function dataset_task_list(){
$.ajax({
type:"GET",
url:ip + "/gitea-dataset/",
headers: {
authorization:token,
},
dataType:"json",
data:{
'repoId':repoId,
'dateset_type':'[1]'
},
async:false,
success:function(json){
dataSetTaskData = json;
console.log(json);
// return json.token;
},
error:function(response) {
redirect(response);
}
});
}

function countLabel(){
$.ajax({
type:"GET",
url:ip + "/gitea/label-count/",
headers: {
authorization:token,
},
dataType:"json",
async:false,
success:function(json){
alert("请等待几分钟,服务端正在加紧统计。");
},
error:function(response) {
redirect(response);
}
});
}

function display_createdatasetlabel(sindex=-1){
var html="";
for (var i=0;i<dataSetTaskData.length;i++){
if (i==sindex){
var row = "<option value=\""+dataSetTaskData[i].id+
"\" selected=\"\">"+dataSetTaskData[i].task_name+
"</option>";
$("#datasetlabeltaskname").attr({value:dataSetTaskData[i].task_name + "-人工标注"});
}else{
var row = "<option value=\""+dataSetTaskData[i].id+
"\">"+dataSetTaskData[i].task_name+
"</option>";
}
html=html+row;
}
console.log(html);
document.getElementById('dataset_list').innerHTML=html;
}


function setPredictTask(){
pre_predict_task_list();
display_createlabel(0);
getUser();
dislpayUser();
getLabelPropertyTask();
displayLabelPropertyTask();
}

function pre_predict_task_list(){
$.ajax({
type:"GET",
url:ip + "/api/pre-predict-taskforLabel/",
headers: {
authorization:token,
},
dataType:"json",
async:false,
success:function(json){
preDictTaskData = json;
console.log(json);
// return json.token;
},
error:function(response) {
redirect(response);
}
});
}

function sele_Change(sele){
var predictTaskName = $('#pre_predict_task_for_label option:selected').text();
console.log("select predictTaskName =" + predictTaskName);
$("#labeltaskname").attr({value:predictTaskName+"-人工标注"});
}

function sele_export_Change(sele){

var isNeedPicture = $('#isNeedPicture option:selected').val();

if(isNeedPicture == 3){
document.getElementById("maxscore_div").style.display="block";
document.getElementById("minscore_div").style.display="block";
$('#maxscore').val("1.0");
$('#minscore').val("0.6");
}else{
document.getElementById("maxscore_div").style.display="none";
document.getElementById("minscore_div").style.display="none";
$('#maxscore').val("");
$('#minscore').val("");
}
}


function dataset_sele_Change(sele){
var dataset_listName = $('#dataset_list option:selected').text();
console.log("select dataset_list =" + dataset_listName);
$("#datasetlabeltaskname").attr({value:dataset_listName+"-人工标注"});
}



function display_createlabel(sindex=-1){
var html="";
for (var i=0;i<preDictTaskData.length;i++){
if (i==sindex){
var row = "<option value=\""+preDictTaskData[i].id+
"\" selected=\"\">"+preDictTaskData[i].task_name+
"</option>";
$("#labeltaskname").attr({value:preDictTaskData[i].task_name + "-人工标注"});
}else{
var row = "<option value=\""+preDictTaskData[i].id+
"\">"+preDictTaskData[i].task_name+
"</option>";
}
html=html+row;
}
console.log(html);
document.getElementById('pre_predict_task_for_label').innerHTML=html;
}

var createsucced;

function submit_datasettask(){
console.log($('#datasetlabeltaskname').val());
var task_name = $('#datasetlabeltaskname').val();
if (isEmpty(task_name) || task_name.length > 32){
alert("人工标注任务名称不能为空或者不能超过32个字符。");
return;
}
var assign_user_id = $('#assign_user option:selected').val();
if(isEmpty(assign_user_id)){
assign_user_id = token;
}
var relate_task_id = $('#dataset_list option:selected').val();
if(isEmpty(relate_task_id)){
alert("数据集对象不能为空。");
return;
}
var labelpropertytaskid = $('#labelpropertytask_dataset option:selected').val();
createsucced = true;
label_task_create(task_name, relate_task_id, 2,assign_user_id,labelpropertytaskid);
if(createsucced){
$(".ui.dataset.modal").modal("hide");
//$("#labelDataModal").modal('hide');
}
page(0,pageSize);
}

function submit_labeltask(){
console.log($('#labeltaskname').val());
var task_name = $('#labeltaskname').val();
if (isEmpty(task_name) || task_name.length > 32){
alert("人工标注任务名称不能为空或者不能超过32个字符。");
return;
}
var relate_task_id = $('#pre_predict_task_for_label option:selected').val();
if(isEmpty(relate_task_id)){
alert("关联的自动标注任务不能为空。");
return;
}
var assign_user_id = $('#label_assign_user option:selected').val();
if(isEmpty(assign_user_id)){
assign_user_id = token;
}
var labelpropertytaskid = $('#labelpropertytask_dataset option:selected').val();
createsucced = true;
label_task_create(task_name, relate_task_id, 1,assign_user_id,labelpropertytaskid);
if(createsucced){
$("#labelModal").modal('hide');
}
page(0,pageSize);
}


function label_task_create(task_name, relate_task_id, taskType,assign_user_id,labelpropertytaskid){
var task_flow_type = $('#task_flow_type option:selected').val();
var relate_other_label_task = [];
if(task_flow_type == 2){
var items = document.getElementsByName("category");
for (i = 0; i < items.length; i++) {
if (items[i].checked) {
relate_other_label_task.push(items[i].value);
}
}
}
relate_other_label_task_jsonstr = JSON.stringify(relate_other_label_task);
console.log("relate_task_id=" + relate_task_id);
$.ajax({
type:"POST",
contentType:'application/json',
url:ip + "/gitea/label-task/",
dataType:"json",
async:false,
headers: {
authorization:token,
},
beforeSend: function (xhr) {
      xhr.withCredentials = true
    },
data:JSON.stringify({'task_name':task_name,
'assign_user_id':assign_user_id,
'task_flow_type':task_flow_type,
'relate_task_id':relate_task_id,//task id
'relate_other_label_task': relate_other_label_task_jsonstr,
"taskType": taskType,
"appid": repoId,
"createUserName":userName,
"labelPropertyTaskId":labelpropertytaskid
}),
success:function(res){
console.log(res);
if(res.code == 0){
alert("人工校验任务创建成功!");
createsucced = true;
}
else{
alert("创建人工标注任务失败," + res.message);
createsucced = false;
}
},
error:function(response) {
redirect(response);
}
});
}

function list(current,pageSize){
$.ajax({
type:"GET",
url:ip + "/gitea/label-task-page/",
headers: {
authorization:token,
},
dataType:"json",
data:{'startPage':current,
'pageSize':pageSize},
async:false,
success:function(json){
tablePageData = json;
tableData = json.data;
//console.log(json);
},
error:function(response) {
redirect(response);
}
});
}

var otherUserLabelTaskData;

function flow_type_sele_Change(sele){
var task_flow_type = $('#task_flow_type option:selected').val();
if(task_flow_type == 2){
var datasetid = $('#dataset_list option:selected').val();
getOtherUserLabelTaskByDataSetId(datasetid);
var html = "<p>请选择该数据集要审核的标注任务</p>";
for(var i = 0; i < otherUserLabelTaskData.length; i++){
html += "<p><input type=\"checkbox\" name=\"category\" value=\"" + otherUserLabelTaskData[i].id + "\"/>" + otherUserLabelTaskData[i].task_name + "(标注人:" + otherUserLabelTaskData[i].assign_user + ")" + "</p>";
}
document.getElementById('related_task_list').innerHTML=html;
}else{
document.getElementById('related_task_list').innerHTML= "";
}
}

function getOtherUserLabelTaskByDataSetId(datasetid){
$.ajax({
type:"GET",
url:ip + "/gitea/label-related-task/" + datasetid + "/",
headers: {
authorization:token,
},
dataType:"json",
async:false,
success:function(json){
otherUserLabelTaskData = json;
console.log(json);
},
error:function(response) {
redirect(response);
}
});
}

function dislpayUser(){
var html="<option value=\"\" selected=\"\">请选择</option>";
for (var i=0;i<userInfoData.length;i++){
var row = "<option value=\""+userInfoData[i].id+
"\">"+userInfoData[i].username+
"</option>";
html=html+row;
}
console.log(html);
document.getElementById('assign_user').innerHTML=html;
document.getElementById('label_assign_user').innerHTML=html;
}


function getUser(){
$.ajax({
type:"GET",
url:ip + "/api/queryAllUser/",
headers: {
authorization:token,
},
dataType:"json",
async:false,
success:function(json){
userInfoData = json;
console.log(json);
},
error:function(response) {
redirect(response);
}
});
}


function delete_labeltask(){
var stop = del();
if (stop){
return;
}
var Check = $("table[id='label_task_list'] input[type=checkbox]:checked");//在table中找input下类型为checkbox属性为选中状态的数据
      Check.each(function () {//遍历
            var row = $(this).parent("td").parent("tr");//获取选中行
            var id = row.find("[id='labeltask_id']").html();//获取name='Sid'的值
            delete_labeltask_byid(id);
        });
page(0,pageSize);
}

function del(){
if($("table[id='label_task_list'] input[type=checkbox]").is(":checked")) {
if (confirm("确实要删除吗?")) {
// alert("已经删除!");
return false;
} else {
// alert("已经取消了删除操作");
return true;
}
}else if($("table[id='label_task_list']").find("input").length=="0"){
alert("暂无可删的数据!");
return true;
}else{
alert("请先选择需要删除的选项!");
return true;
}
}

function delete_labeltask_byid(label_task_id){
$.ajax({
type:"DELETE",
url:ip + "/gitea/label-task/",
headers: {
authorization:token,
},
dataType:"json",
async:false,
data:{'label_task_id': label_task_id},
success:function(json){
console.log(json);
},
error:function(response) {
redirect(response);
}
});
}

function getTaskTypeDesc(task_type){
if(task_type == 1){
return "自动标注结果";
}else if(task_type == 2){
return "原始数据集-图片";
}else if(task_type == 3){
return "原始数据集-CT影像";
}else if(task_type == 4){
return "原始数据集-视频";
}
return "其它";
}

function getLabelDesc(task_flow_type){
if(task_flow_type == 2){
return "审核";
}else{
return "人工"
}
}

function getTaskSataus(task_status,task_status_desc){
if(task_status == 0){
return "标注中:" + task_status_desc;
}else if(task_status == 1){
return "审核中:" + task_status_desc;
}
else if(task_status == -1){
return "关联的数据集已经被删除。"
}
}

function getVerify(task_status,id,task_type){
console.log("task_status=" + task_status + " userType=" + userType);
if(task_status == 0 && (userType == 1 || userType == 0) ){
return "<a onclick=\"startToVerify(\'"+id+"\',\'" + task_type +"\');\" class=\"btn btn-xs btn-success\">转审核</a>&nbsp;&nbsp;&nbsp;";
}else if(task_status == 1 && userType == 2){
return "<a onclick=\"goVerify(\'"+id+"\',\'" + task_type +"\');\" class=\"btn btn-xs btn-success\">进入审核</a>&nbsp;&nbsp;&nbsp;" + "<a onclick=\"startToLabel(\'"+id+"\',\'" + task_type +"\');\" class=\"btn btn-xs btn-success\">转标注</a>&nbsp;&nbsp;&nbsp;";
}else{
return "";
}
}

function getLabel(task_status,id,task_type,task_flow_type){
if(task_status == 0 && (userType == 1 || userType == 0)){
return "<a onclick=\"personLabel(\'" + id + "\'," + task_type + ")\"><b>" + getLabelDesc(task_flow_type) + "标注</b></a><br>";
}else{
return "";
}
}


function display_list(){

var html="<tr>\
<th></th>\
<th id=\"labeltask_head\"></th>\
<th>标注任务名称</th>\
<th>关联的数据集名称</th>\
<th>数据类型</th>\
<th>标注人员</th>\
<th>审核人员</th>\
<th>任务开始时间</th>\
<th>任务状态</th>\
<th>总标注数量</th>\
<th>操作</th>\
</tr>";
for (var i=0;i<tableData.length;i++){
var row = "<tr>\
<td><input type=\"checkbox\" class=\"flat-grey list-child\"/></td>\
<td id=\"labeltask_id\">"+tableData[i].id+"</td>\
<td>"+tableData[i].task_name+"</td>\
<td>"+tableData[i].relate_task_name+"</td>\
<td>"+ getTaskTypeDesc(tableData[i].task_type) +"</td>\
<td>"+tableData[i].assign_user+"</td>\
<td>"+tableData[i].verify_user+"</td>\
<td>"+tableData[i].task_add_time+"</td>\
<td>"+getTaskSataus(tableData[i].task_status,tableData[i].task_status_desc)+"</td>\
<td>"+tableData[i].total_label+"</td>\
<td>" +
getLabel(tableData[i].task_status,tableData[i].id,tableData[i].task_type,tableData[i].task_flow_type) + "<a onclick=\"setTaskId(\'"+tableData[i].id+"\');\"><b>导出标注</b></a>"
+
"</td>\
</tr>";

html=html+row;
}
//console.log(html);
document.getElementById('label_task_list').innerHTML=html;

$('#label_task_list tr').find('td:eq(1)').hide();
$('#label_task_list tr').find('th:eq(1)').hide();
}


function startToLabel(taskid, task_type){//从审核转回标注,标注人不变。
$.ajax({
type:"PATCH",
url:ip + "/gitea/label-task-status/",
dataType:"json",
async:false,
headers: {
authorization:token,
},
data:{
"label_task_id" : taskid,
"verify_user_id" : 0,
"task_status" : 0
},
success:function(res){
console.log(res);
},
error:function(response) {
redirect(response);
}
});
var current =$('#displayPage1').text();
page(current - 1,pageSize);
}

function startToVerify(taskid, task_type){
$("#hide_labeltasktoverifyid").val(taskid);
$.ajax({
type:"GET",
url:ip + "/api/queryVerifyUser/",
headers: {
authorization:token,
},
dataType:"json",
async:false,
success:function(json){
console.log(json);
var html="<option value=\"\" selected=\"\">请选择</option>";
for (var i=0;i<json.length; i++){
var row = "<option value=\""+json[i].id+"\">" + json[i].username + "</option>";
html=html+row;
}
document.getElementById('label_verify_user').innerHTML=html;
},
error:function(response) {
redirect(response);
}
});
$("#startToVerify").modal('show');
}

function submit_labeltask_toverify(){
var label_task_id = $('#hide_labeltasktoverifyid').val();
console.log("label_task_id=" +label_task_id);
var verify_user_id = $('#label_verify_user option:selected').val();
//修改状态
$.ajax({
type:"PATCH",
url:ip + "/gitea/label-task-status/",
dataType:"json",
async:false,
headers: {
authorization:token,
},
data:{
"label_task_id" : label_task_id,
"verify_user_id" : verify_user_id,
"task_status" : 1
},
success:function(res){
console.log(res);
},
error:function(response) {
redirect(response);
}
});
$("#startToVerify").modal('hide');
var current =$('#displayPage1').text();
page(current - 1,pageSize);
}
function goVerify(taskid, task_type){
sessionStorage.setItem('label_task',taskid);
sessionStorage.setItem('label_task_status',1);//审核
console.log("task_type=" + task_type);
if(task_type == 2 || task_type == 1 || task_type == 4){
window.location.href="labeling.html";
}else if(task_type == 3){
window.location.href="labelingDcm.html";
}
}


function personLabel(taskid, task_type){
sessionStorage.setItem('label_task',taskid);
sessionStorage.setItem('token',token);
sessionStorage.setItem('userType',1);
var pathname = window.location.pathname;
var search = window.location.search
var url_name = pathname + search
sessionStorage.setItem('return_url',url_name);
console.log("task_type=" + task_type);
if(task_type == 2 || task_type == 1 || task_type == 4){
window.open("/self/labeling.html?","标注"+new Date().getMilliseconds());
//window.location.href="/self/labeling.html";
}else if(task_type == 3){
window.location.href="labelingDcm.html";
}
}

function setMultiTaskId(){
var Check = $("table[id='label_task_list'] input[type=checkbox]:checked");//在table中找input下类型为checkbox属性为选中状态的数据
if(Check.length == 0){
alert("请选择一个或者多个标注数据进行导出。");
return;
}
var taskList = [];
  Check.each(function () {//遍历
      var row = $(this).parent("td").parent("tr");//获取选中行
      var id = row.find("[id='labeltask_id']").html();//获取name='Sid'的值
taskList.push(id);
      //$('#hide_labeltaskid').val(id);
  });
setTaskId(JSON.stringify(taskList));
}



function setTaskId(labeltaskid){
$('#hide_labeltaskid').val(labeltaskid);
console.log("go here1");
bar.style.width='1%';
document.getElementById('text-progress').innerHTML="0%";
document.getElementById("predtask_id").removeAttribute("disabled");
console.log("go here2");
$(".ui.export.modal").modal("show");
}

function isBeetween(score_threshhold){
if(isEmpty(score_threshhold)){
return true;
}
var regPos = /^\d+(\.\d+)?$/; //非负浮点数
if(!regPos.test(score_threshhold)){
return false;
}else{
if(score_threshhold >1 || score_threshhold < 0){
return false;
}
}
return true;
}


function downloadFile(){

var labeltaskid = $('#hide_labeltaskid').val();
var isNeedPicture = $('#isNeedPicture option:selected').val();
var maxscore = $('#maxscore').val();
var minscore = $('#minscore').val();
var exportFormat = $('#exportFormat option:selected').val();
if(isNeedPicture == 3){
if(!isBeetween(maxscore)){
alert("标注得分最大值应该填写0--1.0之间的数值。");
return;
}
if(!isBeetween(minscore)){
alert("标注得分最小值应该填写0--1.0之间的数值。");
return;
}
if(!isEmpty(maxscore) && !isEmpty(minscore)){
if(minscore>maxscore){
alert("标注得分最小值应该小于标注得分最大值。");
return;
}
}
}
document.getElementById("predtask_id").setAttribute("disabled", true);
var taskreturnid = "";
$.ajax({
type:"GET",
url:ip + "/gitea-label-task-export/",
headers: {
authorization:token,
},
dataType:"json",
data:{
"label_task_id" : labeltaskid,
"needPicture" : isNeedPicture,
"exportFormat":exportFormat,
"maxscore":maxscore,
"minscore":minscore
},
async:false,
success:function(json){
taskreturnid = json.message;
console.log(json);
},
error:function(response) {
redirect(response);
}
});
console.log("taskreturnid=" +taskreturnid);
if(!isEmpty(taskreturnid)){
setIntervalToDo(taskreturnid);
}
}


var timeId=[];
var count;
var progress;

function setIntervalToDo(taskreturnid){
count=0;
var tmpTimeId = self.setInterval("clock('" + taskreturnid +"')",1000);//5秒刷新
timeId.push(tmpTimeId);
console.log("开始刷新。timeId=" + tmpTimeId);
}

function clock(taskreturnid){
count++;
if(count > 600 ){
for(var i = 0;i < timeId.length; i++){
console.log("清除定时器1。exportTimeId=" + timeId[i]);
window.clearInterval(timeId[i]);
}
timeId = [];
$(".ui.export.modal").modal("hide");
return;
}
$.ajax({
type:"GET",
url:ip + "/api/query-download-progress/",
headers: {
authorization:token,
},
dataType:"json",
data:{'taskId': taskreturnid},
async:false,
success:function(json){
progress = json;
console.log(json);
},
error:function(response) {
progress = null;
console.log('query return null.');
redirect(response);
}
});
if(!isEmpty(progress)){
if(progress.progress >= 100){

var iSpeed = progress.progress;
bar.style.width=iSpeed+'%';
document.getElementById('text-progress').innerHTML=iSpeed+'%' + ",开始下载文件。"
for(var i = 0;i < timeId.length; i++){
console.log("清除定时器2。exportTimeId=" + timeId[i]);
window.clearInterval(timeId[i]);
}
timeId = [];
var url = ip + "/api/label-file-download/";
var $iframe = $('<iframe />');
var $form = $('<form method="get" target="_self"/>');
$form.attr('action', url); //设置get的url地址

$form.append('<input type="hidden" name="taskId" value="' + taskreturnid + '" />');
$iframe.append($form);
$(document.body).append($iframe);
$form[0].submit();//提交表单
$iframe.remove();//移除框架
$(".ui.export.modal").modal("hide");
}else{
//更新进度
var iSpeed = progress.progress;
bar.style.width=iSpeed+'%';
document.getElementById('text-progress').innerHTML=iSpeed+'%'
}
}else{
count = 600;
}
}


function page(current,pageSize){
list(current,pageSize);
display_list();
setPage(tablePageData,pageSize);
sessionStorage.setItem('label_task_page',current);
}

function nextPage(){
var current = $('#displayPage1').text();
console.log("current=" + current);
page(current,pageSize);
}

function prePage(){
var current =$('#displayPage1').text();
console.log("current=" + current);
if(current > 1){
console.log("current=" + (current - 2));
page(current - 2,pageSize);
}
}


function goPage(){
var goNum = $('#goNum').val();

var pageTotal = $("#totalNum").text();
var pageNum = parseInt(pageTotal/pageSize);
if(pageTotal%pageSize!=0){
pageNum += 1;
}else {
pageNum = pageNum;
}
if (goNum<=0){
alert("请输入大于0的数值");
}
else if(goNum<=pageNum){
page(goNum - 1,pageSize);
}
else{
alert("不能超出总页码!");
}
}

$("#goNum").keydown(function (e) {
if (e.keyCode == 13) {
goPage();
}
});



function setPage(pageData,pageSize){
if (isEmpty(pageData)){
return;
}
var startIndex = pageData.current * pageSize;
if(pageData.total > 0){
startIndex = startIndex + 1;
}
$('#startIndex').text(startIndex);
$('#endIndex').text(pageData.current * pageSize + pageData.data.length);
$('#totalNum').text(pageData.total);
$('#displayPage1').text(pageData.current + 1);

console.log("set prePage status, pageData.current=" + pageData.current);

if(pageData.current == 0){
console.log("set prePage disabled.");
$('#prePage').removeAttr("href");
$('#prePage').attr('style','color:#f5f5f6;');
}
else{
$('#prePage').attr("href","javascript:prePage()");
$('#prePage').attr('style','color:#000;');
}

if((pageData.current + 1) * pageSize >= pageData.total){
console.log("set nextPage disabled.");
$('#nextPage').removeAttr("href");
}
else{
$('#nextPage').attr("href","javascript:nextPage()");
}

var pageTotal = pageData.total;
var pageNum = parseInt(pageTotal/pageSize);
if(pageTotal%pageSize!=0){
pageNum += 1;
}else {
pageNum = pageNum;
}
$("#totalPageNum").text(pageNum);
}
var tmpCurrent = sessionStorage.getItem("label_task_page");
if(isEmpty(tmpCurrent)){
tmpCurrent = 0;
}
page(tmpCurrent,pageSize);


+ 879
- 0
public/self/labeling.html View File

@@ -0,0 +1,879 @@
<!-- <!DOCTYPE html> -->
<!DOCTYPE html>
<html >
<head>
<meta charset="UTF-8">
<title>数据标注平台</title>
<meta content='width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no' name='viewport'>
<meta name="description" content="Developed By M Abdur Rokib Promy">
<meta name="keywords" content="Admin, Bootstrap 3, Template, Theme, Responsive">
<!-- bootstrap 3.0.2 -->
<link href="/self/css/bootstrap.min.css" rel="stylesheet" type="text/css" />
<!-- font Awesome -->
<link href="/self/css/font-awesome.min.css" rel="stylesheet" type="text/css" />
<!-- Ionicons -->
<link href="/self/css/ionicons.min.css" rel="stylesheet" type="text/css" />
<!-- google font -->
<!-- Theme style -->
<link href="/self/css/style.css" rel="stylesheet" type="text/css" />

<link href="/self/css/jquery.yhhDataTable.css" rel="stylesheet" type="text/css" />

<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<![endif]-->
<script>
window.config={
AppSubUrl:'',
StaticUrlPrefix: '',
csrf: '',
}

var title_text = sessionStorage.getItem('return_url').split('/')[2]
console.log(sessionStorage.getItem('return_url').split('/'))
title_text = "数据标注-" + title_text + '-OpenI'
document.title = title_text
</script>
<style>

html body{ height: 100%;margin: 0;padding: 0;}
.containers{
height: 100%;
}
.table-define td{border-bottom: 1px solid #222324;padding-top: 5px !important;padding-bottom:5px !important;border-top: 0px !important;padding-left: 20px !important;vertical-align: middle !important;}
.btn:hover{background: transparent;}
.display_area_content { } /* this class is used to clear the display area content */
.force_small_font { font-size:small !important; }
.draw_tool{padding:0;color:#fff}
.draw_li {padding: 0.2em;border: 0.5px solid rgba(34,35,36,0.2);border-bottom: 0;border-radius: 3px;cursor: pointer;}

ul.region_shape { font-size:xx-large; list-style-type:none; overflow:hidden; padding:0.4em 0; margin:0; }
/*ul.region_shape li { float:left; padding:0 0.2em; fill:#ffffff; stroke:#000000; }*/
ul.region_shape li { float:right; padding:0 0.2em; fill:#ffffff; stroke:#000000; }
ul.region_shape li:hover { cursor:pointer; fill:#ffffff; stroke:#ff0000; }
ul.region_shape .selected { fill:#ffffff; stroke:#ff0000; }

/*.toolbar { display:inline-block; margin-left:1rem; }*/
.toolbar { display:inline-block; margin-right:1rem; }
.toolbar svg { fill:white; margin: 0.2rem 0.1rem; height:1.2rem; -moz-user-select:none; -webkit-user-select:none; -ms-user-select:none;}
.toolbar svg:hover { fill:yellow; cursor:pointer; }
.toolbar svg:active { fill:white; }
.toolbar ul { display:inline-block; padding:0.2rem; margin:0; }
/*.toolbar li { display:inline; float:left; padding:0rem 0.3rem; border:1px solid white;} *//* main menu items */
.toolbar li { display:inline; float:right; padding:0rem 0.3rem; border:1px solid white;}
.toolbar li:hover { color:red; cursor:pointer; }

/* Top panel : #navbar, #toolbar */
.top_panel { font-size:0.9rem; display:block; background-color:#212121; color:#ffffff; z-index:1001; margin-bottom:1rem;}

/* Navigation menu bar that appear at the top */
.menubar { display:inline-block; height:1.8rem; } /* height needed to avoid extra bottom border */
.menubar a:link { color:#eeeeee; text-decoration:none; }
.menubar a:visited { color:#eeeeee; text-decoration:none; }
.menubar ul { display:block; padding:0; margin:0; }
/*.menubar li { display:inline; float:left; padding:0.45rem 1rem; }*/
.menubar li { display:inline; float:right; padding:0.45rem 1rem; }
.menubar li:hover { background-color:#616161; cursor:default; }

.menubar li ul { display:none; background-color:#212121; border:1px solid #616161; min-width:10rem; position:absolute; z-index:100; margin:0.4rem -1rem;}
.menubar li ul li { display:block; float:none; color:#eeeeee; margin:0; padding:0.6rem 1rem; }
.menubar li ul li:hover { cursor:pointer; }
.menubar li ul li.submenu_divider { margin:0 0.4rem; padding:0; height:1px; border-bottom:1px solid #424242; }
.menubar li:hover ul { display:block; }

/* toolbar containing small icons for tools */
.toolbar { display:inline-block; margin-right:1rem; }
/*.toolbar { display:inline-block; margin-left:1rem; }*/
.toolbar svg { fill:white; margin: 0.2rem 0.1rem; height:1.2rem; -moz-user-select:none; -webkit-user-select:none; -ms-user-select:none;}
.toolbar svg:hover { fill:yellow; cursor:pointer; }
.toolbar svg:active { fill:white; }
.toolbar ul { display:inline-block; padding:0.2rem; margin:0; }
/*.toolbar li { display:inline; float:left; padding:0rem 0.3rem; border:1px solid white;} *//* main menu items */
.toolbar li { display:inline; float:right; padding:0rem 0.3rem; border:1px solid white;}
.toolbar li:hover { color:red; cursor:pointer; }

/* Middle panel: containing #image_panel, #leftsidebar */
/*.middle_panel { display:table; table-layout:fixed; width:100%; z-index:1; padding:0;}*/
.middle_panel { display:table; table-layout:fixed; right:0px,width:100%; z-index:1; padding:0;}
/*#leftsidebar { display:none; z-index:10; vertical-align:top;}*/
#leftsidebar { display:none; z-index:10; vertical-align:top;}
/*#rightsidebar { z-index:-10; vertical-align:left;}*/
/*#display_area { display:table-cell; width:100%; z-index:1; margin:0; padding-left:1em; vertical-align:top; }*/
#display_area { display:table-cell; width:100%; z-index:1; margin:0; padding-right:1em; vertical-align:top; }
/* layers of canvas */
/*#image_panel { position:relative; outline:none; }
#image_panel img { visibility:hidden; opacity:0; position:absolute; top:0px; left:0px; width:100%; height:100%; outline:none; }*/
#image_panel { position:relative; outline:none; }
#image_panel img { visibility:hidden; opacity:0; position:absolute; top:0px; right:0px; width:100%; height:100%; outline:none; }
#image_panel canvas { position:absolute; top:0px; left:0px; outline:none;}
#image_panel .visible { visibility:visible !important; opacity:1 !important; }
#image_panel label>img { visibility:visible; opacity:1; position:relative; width:auto; height:4em; outline:none; }



#leftsidebar_collapse_panel { display:none; position:relative; z-index:10; vertical-align:top; }
/*#leftsidebar_show_button { font-size:large; margin-left:0.1rem; }*/
#leftsidebar_show_button { font-size:large; margin-right:0.1rem; }
#leftsidebar_show_button:hover { color:red; cursor: pointer; }

/* Left sidebar accordion */
button.leftsidebar_accordion { font-size:large; background-color:#f2f2f2; cursor:pointer; padding:0.5em 0.5em; width:100%; text-align:left; border:0; outline:none; }
button.leftsidebar_accordion:focus { outline: none; }
button.leftsidebar_accordion.active, button.leftsidebar_accordion:hover { background-color: #e6e6e6; }
button.leftsidebar_accordion:after { content:'\02795'; color:#4d4d4d; float:right; }
button.leftsidebar_accordion.active:after { content: '\2796'; }
.leftsidebar_accordion_panel { display:none; padding:0 0.5em; font-size:small; border-right:0px solid #f2f2f2; border-bottom:0px solid #f2f2f2; }
.leftsidebar_accordion_panel.show { display:block; }

/* Keyboard shortcut panel */
.leftsidebar_accordion_panel table { border-collapse:collapse; }
.leftsidebar_accordion_panel td { border:1px solid #f2f2f2; padding:0.2rem 0.4rem; }

/* buttons */
/*.button_panel { display:inline-block; width:100%; margin:0.2rem 0; }*/
.button_panel { display:inline-block; width:100%; margin:0.2rem 0; }
.button_panel .text_button, .text_button { color: #0000ff; padding: 0.2rem 0.2rem; -moz-user-select:none; -webkit-user-select:none; -ms-user-select:none; }
.button_panel .flush_right { float:right; }
.button_panel .text_button:hover, .text_button:hover { cursor:pointer; }
.button_panel .text_button:active, .text_button:active { color: #000000; }
.button_panel .active { border-bottom:1px solid black; }
.button_panel .button { display:inline-block; padding:0.35rem 0.5rem; margin:0 0.05rem; cursor:pointer; background-color:#cccccc; border-radius:0.2rem; -moz-user-select:none; -webkit-user-select:none; -ms-user-select:none; }
.button_panel .button:hover { background-color:black; color:white; }

/* Attributes properties: name, description, type, ... */
#attribute_properties { display:table; right:200;width:100%; border-collapse:collapse; margin:1rem 0; border:1px solid #cccccc; }
/*#attribute_properties { display:table; border-collapse:collapse; margin:1rem 0; border:1px solid #cccccc; }*/
#attribute_properties .property { display:table-row;}
#attribute_properties .property span { display:table-cell; padding: 0.2rem 0.4rem; }
#attribute_properties .property span input { width: 100%; border:1px solid #cccccc; margin: 0;}
#attribute_properties .property span input:focus { border:1px solid black; }
#attribute_properties .property span select { width: 100%; border:1px solid #cccccc; margin: 0;}

/* Attributes options: options for attribute type={checkbox,radio,...} */
#attribute_options { display:table; width:100%; border-collapse:collapse; margin:1rem 0; border:1px solid #cccccc; table-layout:fixed; }
#attribute_options .new_option_id_entry { display:inline-block; padding:1rem 0.2rem; }
#attribute_options .new_option_id_entry input {border:none; border-bottom:1px solid #cccccc; margin: 0; font-size: 1.3rem;}
#attribute_options .property { display:table-row;}
#attribute_options .property span { display:table-cell; padding: 0.2rem 0.2rem; font-weight:bold; }
/*#attribute_options .property input { display:table-cell; width:100%; border:none; border-bottom:1px solid #cccccc; margin: 0; font-size: 0.8rem;}*/
#attribute_options .property input { display:table-cell; width:100%; border:none; border-bottom:1px solid #cccccc; margin: 0; font-size: 1.3rem;}
#attribute_options .property input:focus { border-bottom:1px solid #000000; background-color:#f2f2f2; color:#000000; }
#attribute_options .property span input[type=checkbox] { vertical-align:middle; }
#attribute_options .property span input[type=radio] { vertical-align:middle; }


#user_input_panel { position:fixed; display:none; width:100%; height:100%; top:0; left:50; right:0; bottom:0; background-color: rgba(0,0,0,0.6); z-index:1002; }
/*#user_input_panel .content { position:fixed; background-color:white; top:50%; left:50%; transform:translate(-50%,-50%); -webkit-transform: translate(-50%, -50%); -moz-transform: translate(-50%, -50%); -o-transform: translate(-50%, -50%); -ms-transform: translate(-50%, -50%); padding:2rem 4rem;}*/
#user_input_panel .content { position:fixed; background-color:white; top:50%; left:50%; transform:translate(-50%,-50%); -webkit-transform: translate(-50%, -50%); -moz-transform: translate(-50%, -50%); -o-transform: translate(-50%, -50%); -ms-transform: translate(-50%, -50%); padding:2rem 4rem;}
#user_input_panel .content .title { font-size:large; font-weight:bold; }
#user_input_panel .content .user_inputs { display:table; width:100%; border-collapse:collapse;}
#user_input_panel .content .user_inputs .row { display:table-row; }
#user_input_panel .content .user_inputs .cell { display:table-cell; padding:1rem 0.5rem; vertical-align:middle; border:1px solid #f2f2f2; }
#user_input_panel .content .user_confirm { display:table; width:100%; text-align:center; margin:2rem 0;}
#user_input_panel .content .user_confirm .ok { display:table-cell; width:48%; }
#user_input_panel .content .user_confirm .cancel { display:table-cell; width:48%; }
#user_input_panel .content .warning { color:red; }

/* Attribute editor */
#annotation_editor_panel { position:fixed; display:none; width:100%; right:0; bottom:0; background-color:white; border-top:2px solid #cccccc; padding:0.2em 1em; overflow:auto; z-index:1001; box-shadow: 0 0 1em #cccccc;}
/*#annotation_editor { display:table; margin-bottom:3em; border-collapse:collapse; font-size:inherit; position: absolute; top:500px;left:800px; background-color:white; }*/
#annotation_editor { display:table; margin-bottom:3em; border-collapse:collapse; font-size:inherit; background-color:white; z-index:10024;}
#annotation_editor .row { display:table-row; }
#annotation_editor .highlight .col { background-color:#e6e6e6;}

#annotation_editor .col { display:table-cell; padding:0.4em 0.6em; border:1px solid #000000; vertical-align:middle; font-size:inherit; }
#annotation_editor .header { font-weight:bold; white-space:nowrap}
#annotation_editor .id { font-weight:bold; }
#annotation_editor .col input[type=checkbox] { vertical-align:middle; }
#annotation_editor .col input[type=radio] { vertical-align:middle; font-size:inherit; }
#annotation_editor .col label { vertical-align:middle; font-size:inherit; }
#annotation_editor .col textarea { border:0.1em solid #cccccc; padding:0; margin:0; font-size:inherit; background-color:#ffffff;height:20px;width: 80px}
#annotation_editor .col textarea:focus { border:0.1em dashed #cccccc; }
#annotation_editor .col span { display:block; }
#annotation_editor .col horizontal_container { display:inline-block; }

#annotation_editor .col .img_options { display:inline; }
#annotation_editor .col .img_options .imrow { display:block; }
#annotation_editor .col .img_options span { display:inline-block; margin: 0.2rem 0.4rem;}
#annotation_editor .col .img_options span img { height:4em; }
#annotation_editor .col .img_options p { margin:0; padding:0; font-size:inherit; }
#annotation_editor .col .img_options input[type=radio] { display:none; }
#annotation_editor .col .img_options input[type=radio] + label { display:block; cursor:pointer; text-align:center;}
#annotation_editor .col .img_options input[type=radio]:checked + label { border: 0.1em solid black; background-color:#cccccc; cursor:default; font-size:inherit; }

/* Region shape selection panel inside leftsidebar */
ul.region_shape { font-size:xx-large; list-style-type:none; overflow:hidden; padding:0.4em 0; margin:0; }
ul.region_shape li { float:left; padding:0 0.2em; fill:#ffffff; stroke:#000000; }
/*ul.region_shape li { float:right; padding:0 0.2em; fill:#ffffff; stroke:#000000; }*/
ul.region_shape li:hover { cursor:pointer; fill:#ffffff; stroke:#ff0000; }
ul.region_shape .selected { fill:#ffffff; stroke:#ff0000; }

/* cursor coordinates inside region shape selection panel in leftsidebar */
#region_info { font-size:0.8em; margin-bottom:0.4em; }

/*#message_panel { display:block; width:100%; position:fixed; bottom:300px; z-index:9999; text-align:center; }*/
#message_panel { display:block; width:100%; position:fixed; bottom:30px; right:0;z-index:9999; text-align:center; }
#message_panel .content { display:inline; margin:auto; background-color:#000000; color:#ffff00; font-size:small; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; line-height:2rem; padding: 0.5rem 2rem;}

.text_panel { display:none; margin:auto; font-size:medium; line-height:1.3em; margin: 0; max-width:700px; }
/*.text_panel li { margin:1em 0; text-align:left; }
.text_panel p { text-align:left; }*/
.text_panel li { margin:1em 0; text-align:right; }
.text_panel p { text-align:right; }

.svg_button:hover { cursor:pointer; }

/* Loading spinbar */
.loading_spinbox { display:inline-block; border:0.4em solid #cccccc; border-radius:50%; border-top:0.4em solid black; border-bottom:0.4em solid black;-webkit-animation:spin 2s linear infinite; animation:spin 2s linear infinite; }
@-webkit-keyframes spin { 0% { -webkit-transform: rotate(0deg); } 100% { -webkit-transform: rotate(360deg); } }
@keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }

#invisible_file_input { width:0.1px; height:0.1px; opacity:0; overflow:hidden; position:absolute; z-index:-1; }

.display_none { display:none !important; }
.display_block { display:block !important; }

.display_area_content { } /* this class is used to clear the display area content */
.narrow_page_content li { font-size:0.9rem; margin: 0.4rem 0; }
.narrow_page_content { width:60%; }

.force_small_font { font-size:small !important; }
.key { font-family:monospace; padding:1px 6px; background:linear-gradient(to bottom,#f0f0f0,#fcfcfc);; border:1px solid #e0e0e0; white-space:nowrap; color:#303030; border-bottom-width:2px; border-radius:3px; font-size:1.2em; }

#progress{
width: 100%;
height: 20px;
background: rgb(255, 255, 255);
}
#bar{
width: 1%;
height: 20px;
margin-top: 1px;
background: green;
}

</style>
</head>
<body>
<svg style="display:none;" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<symbol id="via_logo">
<!-- Logo designed by Abhishek Dutta <adutta@robots.ox.ac.uk>, May 2018 -->
<title>VGG Image Annotator Logo</title>
<rect width="400" height="160" x="0" y="0" fill="#212121"></rect>

<text x="56" y="130" font-family="Serif" font-size="100" fill="white">V</text>
<text x="180" y="130" font-family="Serif" font-size="100" fill="white">I</text>
<text x="270" y="130" font-family="Serif" font-size="100" fill="white">A</text>

<rect width="80" height="100" x="52" y="40" stroke="yellow" fill="none" stroke-width="2"></rect>
<text x="72" y="30" font-family="'Comic Sans MS', cursive, sans-serif" font-size="18" fill="yellow">VGG</text>

<rect width="50" height="100" x="175" y="45" stroke="yellow" fill="none" stroke-width="2"></rect>
<text x="175" y="35" font-family="'Comic Sans MS', cursive, sans-serif" font-size="18" fill="yellow">Image</text>

<rect width="80" height="100" x="265" y="40" stroke="yellow" fill="none" stroke-width="2"></rect>
<text x="265" y="30" font-family="'Comic Sans MS', cursive, sans-serif" font-size="18" fill="yellow">Annotator</text>
</symbol>
<symbol id="shape_rectangle">
<rect width="20" height="12" x="6" y="10" stroke-width="2"></rect>
</symbol>
<symbol id="shape_circle">
<title>Circular region shape</title>
<circle r="10" cx="16" cy="16" stroke-width="2"></circle>
</symbol>
<symbol id="shape_ellipse">
<title>Elliptical region shape</title>
<ellipse rx="12" ry="8" cx="16" cy="16" stroke-width="2"></ellipse>
</symbol>
<symbol id="shape_polygon">
<path d="M 15.25,2.2372 3.625,11.6122 6,29.9872 l 20.75,-9.625 2.375,-14.75 z" stroke-width="2"></path>
</symbol>
<symbol id="shape_point">
<circle r="3" cx="16" cy="16" stroke-width="2"></circle>
</symbol>
<symbol id="shape_polyline">
<title>Polyline region shape</title>
<path d="M 2,12 10,24 18,12 24,18" stroke-width="2"></path>
<circle r="1" cx="2" cy="12" stroke-width="2"></circle>
<circle r="1" cx="10" cy="24" stroke-width="2"></circle>
<circle r="1" cx="18" cy="12" stroke-width="2"></circle>
<circle r="1" cx="24" cy="18" stroke-width="2"></circle>
</symbol>

<!-- Material icons downloaded from https://material.io/icons -->
<symbol id="icon_settings">
<path d="M19.43 12.98c.04-.32.07-.64.07-.98s-.03-.66-.07-.98l2.11-1.65c.19-.15.24-.42.12-.64l-2-3.46c-.12-.22-.39-.3-.61-.22l-2.49 1c-.52-.4-1.08-.73-1.69-.98l-.38-2.65C14.46 2.18 14.25 2 14 2h-4c-.25 0-.46.18-.49.42l-.38 2.65c-.61.25-1.17.59-1.69.98l-2.49-1c-.23-.09-.49 0-.61.22l-2 3.46c-.13.22-.07.49.12.64l2.11 1.65c-.04.32-.07.65-.07.98s.03.66.07.98l-2.11 1.65c-.19.15-.24.42-.12.64l2 3.46c.12.22.39.3.61.22l2.49-1c.52.4 1.08.73 1.69.98l.38 2.65c.03.24.24.42.49.42h4c.25 0 .46-.18.49-.42l.38-2.65c.61-.25 1.17-.59 1.69-.98l2.49 1c.23.09.49 0 .61-.22l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.65zM12 15.5c-1.93 0-3.5-1.57-3.5-3.5s1.57-3.5 3.5-3.5 3.5 1.57 3.5 3.5-1.57 3.5-3.5 3.5z"></path>
</symbol>
<symbol id="icon_save">
<path d="M17 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V7l-4-4zm-5 16c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3zm3-10H5V5h10v4z"></path>
</symbol>
<symbol id="icon_open">
<path d="M20 6h-8l-2-2H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm0 12H4V8h16v10z"></path>
</symbol>
<symbol id="icon_gridon">
<path d="M20 2H4c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zM8 20H4v-4h4v4zm0-6H4v-4h4v4zm0-6H4V4h4v4zm6 12h-4v-4h4v4zm0-6h-4v-4h4v4zm0-6h-4V4h4v4zm6 12h-4v-4h4v4zm0-6h-4v-4h4v4zm0-6h-4V4h4v4z"></path>
</symbol>
<symbol id="icon_gridoff">
<path d="M8 4v1.45l2 2V4h4v4h-3.45l2 2H14v1.45l2 2V10h4v4h-3.45l2 2H20v1.45l2 2V4c0-1.1-.9-2-2-2H4.55l2 2H8zm8 0h4v4h-4V4zM1.27 1.27L0 2.55l2 2V20c0 1.1.9 2 2 2h15.46l2 2 1.27-1.27L1.27 1.27zM10 12.55L11.45 14H10v-1.45zm-6-6L5.45 8H4V6.55zM8 20H4v-4h4v4zm0-6H4v-4h3.45l.55.55V14zm6 6h-4v-4h3.45l.55.54V20zm2 0v-1.46L17.46 20H16z"></path>
</symbol>
<symbol id="icon_next">
<path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"></path>
</symbol>
<symbol id="icon_prev">
<path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z"></path>
</symbol>
<symbol id="icon_list">
<path d="M3 13h2v-2H3v2zm0 4h2v-2H3v2zm0-8h2V7H3v2zm4 4h14v-2H7v2zm0 4h14v-2H7v2zM7 7v2h14V7H7z"></path>
</symbol>
<symbol id="icon_zoomin">
<path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"></path>
<path d="M12 10h-2v2H9v-2H7V9h2V7h1v2h2v1z"/>
</symbol>
<symbol id="icon_zoomout">
<path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14zM7 9h5v1H7z"></path>
</symbol>
<symbol id="icon_copy">
<path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"></path>
</symbol>
<symbol id="icon_paste">
<path d="M19 2h-4.18C14.4.84 13.3 0 12 0c-1.3 0-2.4.84-2.82 2H5c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm7 18H5V4h2v3h10V4h2v16z"></path>
</symbol>
<symbol id="icon_pasten">
<path d="M19 2h-4.18C14.4.84 13.3 0 12 0c-1.3 0-2.4.84-2.82 2H5c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm7 18H5V4h2v3h10V4h2v16z"></path>
<text x="8" y="18">n</text>
</symbol>
<symbol id="icon_pasteundo">
<path d="M19 2h-4.18C14.4.84 13.3 0 12 0c-1.3 0-2.4.84-2.82 2H5c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm7 18H5V4h2v3h10V4h2v16z"></path>
<text x="8" y="18">x</text>
</symbol>
<symbol id="icon_selectall">
<path d="M3 5h2V3c-1.1 0-2 .9-2 2zm0 8h2v-2H3v2zm4 8h2v-2H7v2zM3 9h2V7H3v2zm10-6h-2v2h2V3zm6 0v2h2c0-1.1-.9-2-2-2zM5 21v-2H3c0 1.1.9 2 2 2zm-2-4h2v-2H3v2zM9 3H7v2h2V3zm2 18h2v-2h-2v2zm8-8h2v-2h-2v2zm0 8c1.1 0 2-.9 2-2h-2v2zm0-12h2V7h-2v2zm0 8h2v-2h-2v2zm-4 4h2v-2h-2v2zm0-16h2V3h-2v2zM7 17h10V7H7v10zm2-8h6v6H9V9z"></path>
</symbol>
<symbol id="icon_close">
<path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"></path>
</symbol>
<symbol id="icon_insertcomment">
<path d="M20 2H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h14l4 4V4c0-1.1-.9-2-2-2zm-2 12H6v-2h12v2zm0-3H6V9h12v2zm0-3H6V6h12v2z"></path>
</symbol>
<symbol id="icon_checkbox">
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"></path>
</symbol>
<symbol id="icon_fileupload">
<path d="M9 16h6v-6h4l-7-7-7 7h4zm-4 2h14v2H5z"></path>
</symbol>
<symbol id="icon_filedownload">
<path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"></path>
</symbol>

</defs>
</svg>

<!-- header logo: style can be found in header.less -->
<!-- <header class="header" >
<div class="logo">
人工标注
</div>
<nav class="navbar navbar-static-top" role="navigation">
<span style="font-size:28px" id="title_id">通用图片标注</span>
</nav>
</header> -->
<div style="height:100vh;display:flex;flex-flow:column nowrap;overflow:hidden;position: relative;">
<header class="header">
<div class="row" style="background-color: #020004;">
<div class="col-lg-1">
<a id="return_url" href="" style="margin: 8px;display: inline-block;"><i class="fa fa-home fa-fw" style="color: #E1E3E6;font-size: 24px;"></i></a>
</div>
<div class="col-lg-9">
<div class="row">
<div class="col-lg-5" style=" padding-left: 0;">
<!-- <button type="button" class="btn" style="background:#3291F8;margin:8px 12px 8px 0;color: #fff;border-radius: 0;padding: 4px 12px;font-size: 12px;">返回任务</button>
<button type="button" class="btn" style="margin: 8px 12px;background:#74818D;color: #fff;border-radius: 0;padding: 4px 12px;font-size: 12px;">跳过</button>
<button type="button" class="btn" style="margin: 8px 12px;background:#FF6200;color: #fff;border-radius: 0;padding: 4px 12px;font-size: 12px;">提交</button> -->
</div>
<div class="col-lg-3" style="text-align: center;;line-height: 42px;color: #fff;">
<span id="float_text"></span>
</div>
</div>
</div>
<div class="col-lg-2"></div>
</div>
</header>
<div class="box1" style="float:left;position: absolute;z-index: 9999;left: 0.4em;top: 3.5em;">
<ul class="draw_tool" style="font-size: 18px;background-color: rgba(12,13,13,0.3);color: rgba(225,227,230,0.8);">
<li id="region_shape_rect" class="selected draw_li" onclick="createRectLabel()" title="新建矩形标注(W)"><i class="fa fa-square-o"></i></li>
<li id="region_shape_polygon" class="draw_li" onclick="createMaskLabel()" title="新建多边形标注"><i class="fa fa-first-order" aria-hidden="true"></i> </li>
<li id="region_shape_point" class="draw_li" onclick="createPointLabel()" title="新建点标注"><i class="fa fa-dot-circle-o" aria-hidden="true"></i></li>
<li id="delete_shape" class="draw_li" onclick="deleterect()" title="删除选中的标注(D)"><i class="fa fa-times-circle-o" aria-hidden="true"></i></li>
<li id="delete_all_shape" class="draw_li" onclick="deleteAllRect()" title="删除所有的标注框"><i class="fa fa-times" aria-hidden="true"></i></li>
<li id="save_shape" class="draw_li" onclick="save()" title="保存标注(S)"><i class="fa fa-floppy-o" aria-hidden="true"></i></li>
<li id="previous_shape"class="draw_li" onclick="last()" title="上一张(Q)"><i class="fa fa-arrow-circle-left" aria-hidden="true"></i></li>
<li id="next_shape" class="draw_li" onclick="next()" title="下一张(E)"><i class="fa fa-arrow-circle-right" aria-hidden="true"></i></li>
<li id="copy_shape" class="draw_li" onclick="copyOneBox()" title="复制单个选中的标注(C)"><i class="fa fa-file-o" aria-hidden="true"></i></li>
<li id="copy_shape" class="draw_li" onclick="copy()" title="复制所有的标注"><i class="fa fa-clone" aria-hidden="true"></i></li>
<li id="paste_shape" class="draw_li" onclick="paste()" title="粘贴复制的标注(V)"><i class="fa fa-clipboard" aria-hidden="true"></i></li>
<li id="arrow-left" class="draw_li" onclick="moveLeftOnePx()" title="标注左移一个像素"><i class="fa fa-arrow-left" aria-hidden="true"></i> </li>
<li id="arrow-right" class="draw_li" onclick="moveRightOnePx()" title="标注右移一个像素"><i class="fa fa-arrow-right" aria-hidden="true"></i> </li>
<li id="arrow-up" class="draw_li" onclick="moveUpOnePx()" title="标注上移一个像素"><i class="fa fa-arrow-up" aria-hidden="true"></i></li>
<li id="arrow-down" class="draw_li" onclick="moveDownOnePx()" title="标注下移一个像素"><i class="fa fa-arrow-down" aria-hidden="true"></i></li>
<li id="setting" class="draw_li" onclick="updateSetting()" title="设置" href="#labeldefine"><i class="fa fa-cog" aria-hidden="true"></i> </li>
<li id="skip" class="draw_li" onclick="skipLast()" title="跳转至上次标注的地方"><i class="fa fa-reply" aria-hidden="true"></i></li>
<!-- <li class="draw_li" onclick="setAutoModel()" title="自动标注" href="#autoLabel" data-toggle="modal" data-backdrop="static" ><i class="fa fa-cube" aria-hidden="true"></i></li> -->
<li class="draw_li" onclick="undo()" title="撤销上次标注(Z)" ><i class="fa fa-reply-all" aria-hidden="true"></i></li>
<li style="padding: 0.2em;border: 0.5px solid rgba(34,35,36,0.2);border-radius: 3px;cursor: pointer;" title="清空指定文件的标注" href="#deleteLabel" data-toggle="modal" data-backdrop="static" ><i class="fa fa-eraser" aria-hidden="true"></i></li>
</ul>
</div>
<div class="containers" style="flex: 1;">
<!-- <aside class="left-side sidebar-offcanvas" ></aside> -->
<div class="row" style="height: 100%;">

<!-- left-side -->
<!-- <div class="col-lg-1" style="background-color: #020004;height: 100%;border-top: 1px solid #222324;padding: 0;">
<div style="line-height: 3em;text-align: center;font-size: 16px;">
<span style="color: #fff;float: left;padding-left: 1.5em;">动物-狗</span>
<a style="float: right;padding-right: 1em;"><i class="fa fa-cog" style="color: #74818D;font-size: 18px;cursor: pointer;"></i></a>
</div>
<div style="clear: both;">
<input type="text" placeholder="搜索标签" style="width: 80%;margin: 0 10%;background-color: transparent;border-radius: 6px;border: 0.5px solid #43474B;outline: none;color: #74818D;padding: 0.1em;">
</div>
</div> -->

<!-- canvas -->
<div class="col-lg-10" id="showPic" style="background-color: #222324;height: 100%;padding: 0;padding-left: 4em;">

<!-- <nav class="navbar navbar-default" role="navigation" id="tool0" style="margin-bottom: 0;">
<div class="leftsidebar_accordion_panel show">
<ul class="region_shape" style="padding: 0;">
<li id="region_shape_rect" class="selected" onclick="createRectLabel()" title="新建矩形标注(W)"><svg height="28" viewbox="0 0 28 28"><use xlink:href="#shape_rectangle"></use></svg></li>
<li id="region_shape_polygon" onclick="createMaskLabel()" title="新建多边形标注"><svg height="28" viewbox="0 0 28 28"><use xlink:href="#shape_polygon"></use></svg></li>
<li id="region_shape_point" onclick="createPointLabel()" title="新建点标注"><svg height="28" viewbox="0 0 28 28"><use xlink:href="#shape_point"></use></svg></li>
<li id="delete_shape" onclick="deleterect()" title="删除选中的标注(D)"><svg height="24" viewbox="0 0 28 28"><use xlink:href="#icon_close"></use></svg></li>
<li id="save_shape" onclick="save()" title="保存标注(S)"><svg height="24" viewbox="0 0 28 28"><use xlink:href="#icon_save"></use></svg></li>
<li id="previous_shape" onclick="last()" title="上一张(Q)"><svg height="24" viewbox="0 0 28 28"><use xlink:href="#icon_prev"></use></svg></li>
<li id="next_shape" onclick="next()" title="下一张(E)"><svg height="24" viewbox="0 0 28 28"><use xlink:href="#icon_next"></use></svg></li>
<li id="copy_shape" onclick="copy()" title="复制所有的标注"><svg height="24" viewbox="0 0 28 28"><use xlink:href="#icon_copy"></use></svg></li>
<li id="paste_shape" onclick="paste()" title="粘贴复制的标注(V)"><svg height="24" viewbox="0 0 28 28"><use xlink:href="#icon_pasten"></use></svg></li>
<li id="copy_shape" style="font-size: 20px;" onclick="copyOneBox()" title="复制单个选中的标注(C)"><i class="fa fa-files-o" style="vertical-align: bottom;" aria-hidden="true"></i></li>
<li id="arrow-left" style="font-size: 26px" onclick="moveLeftOnePx()" title="标注左移一个像素"><i class="fa fa-long-arrow-left" aria-hidden="true" ></i></li>
<li id="arrow-right" style="font-size: 26px" onclick="moveRightOnePx()" title="标注右移一个像素"><i class="fa fa-long-arrow-right" aria-hidden="true"></i></li>
<li id="arrow-up" style="font-size: 26px" onclick="moveUpOnePx()" title="标注上移一个像素"><i class="fa fa-long-arrow-up" aria-hidden="true"></i></li>
<li id="arrow-down" style="font-size: 26px" onclick="moveDownOnePx()" title="标注下移一个像素"><i class="fa fa-long-arrow-down" aria-hidden="true"></i></li>
<li id="delete_all_shape" style="font-size: 22px;" onclick="deleteAllRect()" title="删除所有的标注框"><i class="fa fa-window-close-o" style="vertical-align: middle;" aria-hidden="true" ></i></li>
<li id="setting" onclick="updateSetting()" title="设置" href="#labeldefine"><svg height="24" viewbox="0 0 28 28"><use xlink:href="#icon_settings"></use></svg></li>
<li id="skip" style="font-size: 22px" onclick="skipLast()" title="跳转至上次标注的地方"><i class="fa fa-share" aria-hidden="true"></i></li>
<li style="font-size: 22px" onclick="setAutoModel()" title="自动标注" href="#autoLabel" data-toggle="modal" data-backdrop="static" ><i class="fa fa-tag" aria-hidden="true"></i></li>
<li style="font-size: 22px" onclick="undo()" title="撤销上次标注(Z)" ><i class="fa fa-undo" aria-hidden="true"></i></li>
<li style="font-size: 22px" title="清空指定文件的标注" href="#deleteLabel" data-toggle="modal" data-backdrop="static" ><i class="fa fa-eraser" aria-hidden="true"></i></li>
</ul>
</div>
<div id=labeldefine>
</div>
</nav> -->
<div id="labelwin" width="100%" style="display: flex;justify-content: center;align-content: center;" >
<input type="hidden" class="form-control" id="postmessage" >
<div id = "show_region" style="z-index: 50000;width: 0px;height: 0px"></div>
<canvas id="myCanvas" style="border:1px solid #5a5a5a;"></canvas>
<div id="float_text"></div>
</div>
</div>




<!-- right side -->
<div class="col-lg-2" style="background-color: #020004;height: 100%;border-top: 1px solid #222324;padding: 0;">
<div style="line-height: 3em;text-align: center;font-size: 14px;">
<span id="task_info" style="color: #fff;float: left;padding-left: 1.5em;">train数据集标注任务</span>
<!-- <a style="float: right;padding-right: 2em;"><i class="fa fa-cog" style="color: #74818D;font-size: 18px;cursor: pointer;"></i></a> -->
</div>
<div class="progress" style="clear: both;margin: 0 2em 0 1em;height: 0.5em;">
<div class="progress-bar" role="progressbar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100" style="width: 60%;background-color: #389E0D;">
<span class="sr-only">60% Complete</span>
</div>
</div>
<div style="margin: 1em 1.5em;font-size: 10px;">
<span style="color: #7092BE;margin-right: 1em;">任务标注进度</span><span id="task_progress" style="color:#7092BE;"></span>
</div>
<div class="panel" style="margin-bottom: 1em;">
<div id = "labelStatus"></div>
</div>

<div id="nav" style="height:100%">
<ul style="display: flex;padding: 0;margin: 0;color:#7092BE;">
<li id="0" class="active">文件列表</li>
<li id="1">标签列表</li>
</ul>
<div class="tabpannel" style="height: 100%;">
<!-- <h4 class="ui top attached header">
文件列表
</h4> -->
<!-- <table class="ui single line table" id="filelist" style="table-layout:fixed;word-break: break-all;word-wrap: break-word;">
</table> -->
<div class="panel-body no-padding" id="filepanel" style="height: 100%;">
<div style="display: flex;padding: 0.3em 0;border-bottom: 1px solid #222324 ;">
<span style="flex: 3;padding-left: 20px;color: #7092BE;">文件名</span>
<div class="btn-group" style="flex:1">
<button type="button" class="btn-default dropdown-toggle"
data-toggle="dropdown" style="background: transparent;padding: 0;border: 0;vertical-align: top;line-height: 1;color: #7092BE;">
...
</button>
<ul class="dropdown-menu" role="menu" style="left:-90px;background: #020004;border: 1px solid #222324;border-radius: 0;width:2em;min-width: 8em;color: #fff;">
<li value="1" onclick="showOrder($(this).attr('value'))" style="font-size: 8px;color: #fff;padding: 0.3em 0 0.3em 2em;width: 100%;text-align: start;border-bottom: 0.5px solid #222324;">按文件名排序</li>
<li value="2" onclick="showOrder($(this).attr('value'))" style="font-size: 8px;color: #fff;padding: 0.3em 0 0.3em 2em;width: 100%;text-align: start;">未标注</li>
</ul>
</div>
</div>
<table class="table table-condensed table-define" id="filelist" style="table-layout:fixed;overflow:auto;word-break: break-all;word-wrap: break-word;color:#7092BE;font-size: 10px;">
</table>
</div>
<div class="panel-body" id="filepanel" style='position: absolute;bottom: 0;padding: 0.9em 0;width: 100%;border-top: 1px #ccc solid; color: #7092BE;'>
<div style="width: 80%; margin: 0 10%;">
<a id="prePage" href="" style="margin-right: 0.2em;"><i class="fa fa-angle-left"></i></a>
<span id="startIndex">0</span>-<span id="endIndex">0</span>/<span id="totalNum">0</span>
<span style="margin-left: 0.2em;">第</span><span id="displayPage1">1</span><span style="margin-right: 0.2em;">页</span>
<span>跳到</span><input type="text" id="goNum" style="width: 2em;border-radius: 4px;padding: 0 0.4em;margin: 0 0.4em;height: 1.2em;border: 1px solid;" maxlength="5" oninput="value=value.replace(/[^\d]/g,'')"><span>页</span>
<a style="margin-left: 0.4em;" id="nextPage" href=""><i class="fa fa-angle-right"></i></a>
</div>
</div>
</div>
<div class="hide1 tabpannel">
<div class="panel-body no-padding" id="labelpanel">
<table class="table table-condensed table-define" style="color: #fff;" >
<tbody id="boxlabels">
</tbody>
</table>
</div><!-- /.panel-body -->
<div class="panel-body no-padding" id="labelcountpanel" style="display: none;">
<table class="table table-condensed" id="labelcounttable">
</table>
</div><!-- /.panel-body -->
</div>

</div>
</div>
</div>



<div class="panel" id="set_attributes" class="force_small_font display_area_content" style="display:none;">
<button class="close" onclick="close_attribute()" style=" padding: .3em 0.8em;"> × </button>
<div id="user_input_panel"></div>
<div id="message_panel">
<div id="message_panel_content" class="content"></div>
</div>
<div id="leftsidebar_collapse_panel">
<span class="text_button" onclick="leftsidebar_toggle()" title="Show left sidebar">&rtrif;</span>
</div>
<div id="leftsidebar">
<div class="leftsidebar_accordion_panel show" id="attributes_editor_panel">
<div class="button_panel" style="padding:1rem 0;">
<h4 class="modal-title">设置</h4>
</div>
<div id="attributes_update_panel">
<div class="button_panel">
<input style="width:50%" type="text" placeholder="attribute name" id="user_input_attribute_id" value="">
<span id="button_add_new_attribute" class="button" onclick="add_new_attribute_from_user_input()" title="Add new attribute">&plus;</span>
</div>
<div class="button_panel" style="margin:0.1rem 0;width:70%;" >
<table class="table table-hover" id="attributes_name_list">
</table>
</div>
<div id="atttibute_child" >
<div id="type_car" style="display: none;">
<span class= "btn btn-xs btn-success" style="margin-left:5px" onclick="show_tpye_attribute();">点击此处快速添加常用车辆类别</span>
</div>
<div id="type_color" style="display: none;">
<span class= "btn btn-xs btn-success" style="margin-left:5px" onclick="show_color_attribute();">点击此处快速添加常用颜色</span>
</div>
<div id="attribute_properties"> </div>
<div id="attribute_options"></div>
<p style="text-align:center"></p>
</div>
</div>
<div>
<button type="button" class="btn btn-default" onclick="save_attribute()" id="save" style=" margin:0.5rem 0.3rem "> 保存属性值</button>
<button type="button" class="btn btn-default" onclick="export_attribute()" id="export" style=" margin:0.5rem 0.3rem;float:right"> 导出属性值</button>
<button type="button" class="btn btn-default" onclick="import_attribute()" id="import" style=" margin:0.5rem 0.3rem;float:right"> 导入属性值</button>
</div>

</div>
</div> <!-- Dialog setAttribute -->
<div style="width: 100%;" id="vertical_space"></div>
</div><!-- /.panel -->


<div aria-hidden="true" aria-labelledby="myModalLabel" role="dialog" tabindex="-1" id="autoLabel" class="modal fade">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button aria-hidden="true" data-dismiss="modal" class="close" type="button">×</button>
<h4 class="modal-title">自动标注</h4>
</div>
<div class="modal-body">
<form role="form">
<div class="form-group">
<label for="exampleInputPassword1">自动标注任务使用的模型</label>
<select class="form-control" name="预检模型" id="predict_model" onchange="model_sele_Change(this)">
<option value="" >请选择</option>
<!--<option value="1" selected="">Faster RCNN</option> -->
</select>
</div>
<div id="tracking_startid_div" class="form-group" style="display:none">
<label for="exampleInputEmail1">追踪起始图片ID</label>
<input type="" class="form-control" id="tracking_startid" placeholder="追踪起始图片ID">
</div>
<div id="tracking_endid_div" class="form-group" style="display:none">
<label for="exampleInputEmail1">追踪结束图片ID</label>
<input type="" class="form-control" id="tracking_endid" placeholder="追踪结束图片ID">
</div>
<div id="label_id_div" class="form-group">
<label for="exampleInputEmail1">标注框ID</label>
<input type="" class="form-control" id="label_id" placeholder="标注框ID">
</div>
<div id="labelOption_div" class="form-group">
<label for="exampleInputEmail1">标注信息选项</label>
<select class="form-control" name="labelOption" id="labelOption">
<option value="4">请选择</option>
<!--<option value="0" selected="">合并已有的标注信息</option>
<option value="1">删除已有的标注信息</option>
<option value="2">识别车的颜色及车的类型</option> -->
</select>
</div>
<div id="progress">
<div id="bar"></div>
</div>
<div><h5 id="text-progress">0%</h3></div>
<button id="predtask_id" type="button" onclick="submit_predtask();">提交</button>
</form>
</div>
</div>
</div>
</div>
<div aria-hidden="true" aria-labelledby="myModalLabel" role="dialog" tabindex="-1" id="deleteLabel" class="modal fade">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button aria-hidden="true" data-dismiss="modal" class="close" type="button">×</button>
<h4 class="modal-title">清空指定文件的标注</h4>
</div>
<div class="modal-body">
<form role="form">
<div id="delete_startid_div" class="form-group">
<label for="exampleInputEmail1">起始文件ID(对应文件列表中第几条)</label>
<input type="" class="form-control" id="delete_startid" placeholder="起始文件ID">
</div>
<div id="delete_endid_div" class="form-group">
<label for="exampleInputEmail1">结束文件ID(对应文件列表中第几条)</label>
<input type="" class="form-control" id="delete_endid" placeholder="结束文件ID">
</div>
<button id="predtask_id" type="button" onclick="submit_deletelabel();">提交</button>
</form>
</div>
</div>
</div>
</div>


<div aria-hidden="true" aria-labelledby="myModalLabelc" role="dialog" tabindex="-1" id="datasetModal" class="modal fade">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button aria-hidden="true" data-dismiss="modal" class="close" type="button">×</button>
<h4 class="modal-title">导入标注属性</h4>
</div>
<div class="modal-body">
<div class="form-group">
<label id = "labelInfo" for="exampleInputFile">请输入符合格式Json字符串<font color=red>*</font> </label>
<div>
<textarea id="jsoninput" rows="8" cols="70"> </textarea>
</div>
</div>
<button id="btnSubmit" type="button" onclick="submit_import_property();">提交</button>
</div>
</div>
</div>
</div>
</div>




<script>
// back to label table
var back_url = sessionStorage.getItem('return_url')
document.getElementById('return_url').setAttribute('href',back_url);


var ulObj = document.getElementById('nav').getElementsByTagName('ul')[0];
var divObj = document.getElementsByClassName('tabpannel');
var liObj = document.getElementById('nav').getElementsByTagName('li')
ulObj.onclick = function(event){
var ev = window.event || event;
var item = ev.srcElement || ev.target;

var id = item.getAttribute("id")
for (var i=0; i<divObj.length;i++){
if(i == id){
divObj[i].style.display = 'block'
liObj[i].classList.add('active')
}
else{
divObj[i].style.display = 'none'
liObj[i].classList.remove('active')
}
}
}
</script>
<script>
var box = document.getElementsByClassName("box1")[0]; //获取元素
var x, y; //鼠标相对与div左边,上边的偏移
var isDrop = false; //移动状态的判断鼠标按下才能移动
box.onmousedown = function(e) {
var e = e || window.event; //要用event这个对象来获取鼠标的位置
x = e.clientX - box.offsetLeft;
y = e.clientY - box.offsetTop;
isDrop = true; //设为true表示可以移动
}

document.onmousemove = function(e) {
//是否为可移动状态                    
if(isDrop) {    
var e = e || window.event;   
var moveX = e.clientX - x; //得到距离左边移动距离   
var moveY = e.clientY - y; //得到距离上边移动距离
//可移动最大距离
var maxX = document.documentElement.clientWidth - box.offsetWidth;
var maxY = document.documentElement.clientHeight - box.offsetHeight;

//范围限定 当移动的距离最小时取最大 移动的距离最大时取最小
//范围限定方法一
/*if(moveX < 0) {
moveX = 0
} else if(moveX > maxX) {
moveX = maxX;
}

if(moveY < 0) {
moveY = 0;
} else if(moveY > maxY) {
moveY = maxY;
} */
//范围限定方法二 
moveX=Math.min(maxX, Math.max(0,moveX));
moveY=Math.min(maxY, Math.max(0,moveY));
box.style.left = moveX + "px";  
box.style.top = moveY + "px";          
} else {
return;          
}

}

document.onmouseup = function() {
isDrop = false; //设置为false不可移动
}
</script>
<script src="/self/func.js" type="text/javascript"></script>
<!-- jQuery 2.0.2 -->
<!-- -->
<script src="/self/js/jquery.min.js" type="text/javascript"></script>
<script src="/self/js/jquery.mousewheel.js"></script>
<script src="/self/js/jquery.jscrollpane.js"></script>

<!-- Bootstrap -->
<script src="/self/js/bootstrap.min.js" type="text/javascript"></script>
<script src="/self/js/app.js" type="text/javascript" ></script>
<script src="/self/js/Director/labelingSelfDefine.js" type="text/javascript"></script>
<script src="/self/js/Director/detection.js" type="text/javascript" ></script>
<!-- <script src="../js/labelx.js"></script> -->

</body>
</html>


+ 23
- 3
routers/home.go View File

@@ -7,6 +7,7 @@ package routers


import ( import (
"bytes" "bytes"
"net/http"
"strings" "strings"


"code.gitea.io/gitea/models" "code.gitea.io/gitea/models"
@@ -136,11 +137,17 @@ func RenderRepoSearch(ctx *context.Context, opts *RepoSearchOptions) {
orderBy = models.SearchOrderByForksReverse orderBy = models.SearchOrderByForksReverse
case "fewestforks": case "fewestforks":
orderBy = models.SearchOrderByForks orderBy = models.SearchOrderByForks
case "hot":
orderBy = models.SearchOrderByHot
case "active":
orderBy = models.SearchOrderByActive

default: default:
ctx.Data["SortType"] = "recentupdate"
orderBy = models.SearchOrderByRecentUpdated
ctx.Data["SortType"] = "hot"
orderBy = models.SearchOrderByHot
} }


//todo:support other topics
keyword := strings.Trim(ctx.Query("q"), " ") keyword := strings.Trim(ctx.Query("q"), " ")
topicOnly := ctx.QueryBool("topic") topicOnly := ctx.QueryBool("topic")
ctx.Data["TopicOnly"] = topicOnly ctx.Data["TopicOnly"] = topicOnly
@@ -164,6 +171,11 @@ func RenderRepoSearch(ctx *context.Context, opts *RepoSearchOptions) {
ctx.ServerError("SearchRepository", err) ctx.ServerError("SearchRepository", err)
return return
} }

for _, repo := range repos {
repo.Hot = int64(repo.NumWatches) + int64(repo.NumStars) + int64(repo.NumForks) + int64(repo.CloneCnt)
repo.Active = int64(repo.NumIssues) + int64(repo.NumPulls) + int64(repo.NumCommit)
}
ctx.Data["Keyword"] = keyword ctx.Data["Keyword"] = keyword
ctx.Data["Total"] = count ctx.Data["Total"] = count
ctx.Data["Repos"] = repos ctx.Data["Repos"] = repos
@@ -174,7 +186,15 @@ func RenderRepoSearch(ctx *context.Context, opts *RepoSearchOptions) {
pager.AddParam(ctx, "topic", "TopicOnly") pager.AddParam(ctx, "topic", "TopicOnly")
ctx.Data["Page"] = pager ctx.Data["Page"] = pager


ctx.HTML(200, opts.TplName)
recommendOrgs, err := models.GetRecommendOrgInfos()
if err != nil {
log.Error("GetRecommendOrgInfos failed:%v", err.Error(), ctx.Data["MsgID"])
ctx.ServerError("GetRecommendOrgInfos", err)
return
}
ctx.Data["RecommendOrgs"] = recommendOrgs

ctx.HTML(http.StatusOK, opts.TplName)
} }


// ExploreRepos render explore repositories page // ExploreRepos render explore repositories page


+ 2
- 0
routers/init.go View File

@@ -22,6 +22,7 @@ import (
code_indexer "code.gitea.io/gitea/modules/indexer/code" code_indexer "code.gitea.io/gitea/modules/indexer/code"
issue_indexer "code.gitea.io/gitea/modules/indexer/issues" issue_indexer "code.gitea.io/gitea/modules/indexer/issues"
stats_indexer "code.gitea.io/gitea/modules/indexer/stats" stats_indexer "code.gitea.io/gitea/modules/indexer/stats"
"code.gitea.io/gitea/modules/labelmsg"
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/markup" "code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/markup/external" "code.gitea.io/gitea/modules/markup/external"
@@ -63,6 +64,7 @@ func NewServices() {
_ = cache.NewContext() _ = cache.NewContext()
notification.NewContext() notification.NewContext()
decompression.NewContext() decompression.NewContext()
labelmsg.Init()
} }


// In case of problems connecting to DB, retry connection. Eg, PGSQL in Docker Container on Synology // In case of problems connecting to DB, retry connection. Eg, PGSQL in Docker Container on Synology


+ 64
- 0
routers/operation/orgs.go View File

@@ -0,0 +1,64 @@
// 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 operation

import (
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/routers"
)

const (
tplOrgs base.TplName = "admin/org/list"
)

type UpdateRecommendOrgs struct {
OrgInfos string `binding:"required"`
}

type OrgInfo struct {
OrgID int64 `json:"org_id"`
Order int64 `json:"order"`
}

type OrgInfos struct {
OrgInfo []OrgInfo `json:"org_infos"`
}

// Organizations show all the organizations recommended
func Organizations(ctx *context.Context) {
ctx.Data["PageIsAdmin"] = true
ctx.Data["PageIsAdminOrganizations"] = true

routers.RenderUserSearch(ctx, &models.SearchUserOptions{
Type: models.UserTypeOrganization,
ListOptions: models.ListOptions{
PageSize: setting.UI.Admin.OrgPagingNum,
},
Visible: []structs.VisibleType{structs.VisibleTypePublic, structs.VisibleTypeLimited, structs.VisibleTypePrivate},
}, tplOrgs)
}

// UpdateRecommendOrganizations update the organizations recommended
func UpdateRecommendOrganizations(ctx *context.Context, req OrgInfos) {
orgs := make(models.RecommendOrgList, 0, 10)
for _, org := range req.OrgInfo {
orgs = append(orgs, &models.RecommendOrg{
OrgID: org.OrgID,
Order: org.Order,
})
}

if err := models.UpdateRecommendOrgs(orgs); err != nil {
log.Error("UpdateRecommendOrgs failed:%v", err.Error(), ctx.Data["MsgID"])
ctx.ServerError("UpdateRecommendOrgs failed", err)
return
}
}

+ 37
- 0
routers/private/cmd.go View File

@@ -0,0 +1,37 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package private

import (
"gitea.com/macaron/macaron"
"net/http"

"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/log"
)

func UpdateAllRepoCommitCnt(ctx *macaron.Context) {
repos, err := models.GetAllRepositories()
if err != nil {
log.Error("GetAllRepositories failed:%v", err.Error(), ctx.Data["MsgID"])
ctx.JSON(http.StatusInternalServerError, map[string]string{
"error_msg": "GetAllRepositories failed",
})
return
}

for i, repo := range repos {
log.Info("%d:begin updateRepoCommitCnt(id = %d, name = %s)", i, repo.ID, repo.Name)
if err = updateRepoCommitCnt(ctx, repo); err != nil {
log.Error("updateRepoCommitCnt(id = %d, name = %s) failed:%v", repo.ID, repo.Name, err.Error(), ctx.Data["MsgID"])
continue
}
log.Info("%d:finish updateRepoCommitCnt(id = %d, name = %s)", i, repo.ID, repo.Name)
}

ctx.JSON(http.StatusOK, map[string]string{
"error_msg": "",
})
}

+ 28
- 0
routers/private/hook.go View File

@@ -520,12 +520,40 @@ func HookPostReceive(ctx *macaron.Context, opts private.HookOptions) {
} }
} }
} }

if err := updateRepoCommitCnt(ctx, repo); err != nil {
log.Error("updateRepoCommitCnt failed:%v", err.Error(), ctx.Data["MsgID"])
}

ctx.JSON(http.StatusOK, private.HookPostReceiveResult{ ctx.JSON(http.StatusOK, private.HookPostReceiveResult{
Results: results, Results: results,
RepoWasEmpty: wasEmpty, RepoWasEmpty: wasEmpty,
}) })
} }


func updateRepoCommitCnt(ctx *macaron.Context, repo *models.Repository) error {
gitRepo, err := git.OpenRepository(repo.RepoPath())
if err != nil {
log.Error("OpenRepository failed:%v", err.Error(), ctx.Data["MsgID"])
return err
}
defer gitRepo.Close()

count, err := gitRepo.GetAllCommitsCount()
if err != nil {
log.Error("GetAllCommitsCount failed:%v", err.Error(), ctx.Data["MsgID"])
return err
}

repo.NumCommit = count
if err = models.UpdateRepositoryCommitNum(repo); err != nil {
log.Error("UpdateRepositoryCommitNum failed:%v", err.Error(), ctx.Data["MsgID"])
return err
}

return nil
}

// SetDefaultBranch updates the default branch // SetDefaultBranch updates the default branch
func SetDefaultBranch(ctx *macaron.Context) { func SetDefaultBranch(ctx *macaron.Context) {
ownerName := ctx.Params(":owner") ownerName := ctx.Params(":owner")


+ 1
- 0
routers/private/internal.go View File

@@ -42,6 +42,7 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Post("/manager/shutdown", Shutdown) m.Post("/manager/shutdown", Shutdown)
m.Post("/manager/restart", Restart) m.Post("/manager/restart", Restart)
m.Post("/manager/flush-queues", bind(private.FlushOptions{}), FlushQueues) m.Post("/manager/flush-queues", bind(private.FlushOptions{}), FlushQueues)
m.Post("/cmd/update_all_repo_commit_cnt", UpdateAllRepoCommitCnt)


}, CheckInternalToken) }, CheckInternalToken)
} }

+ 46
- 3
routers/repo/attachment.go View File

@@ -17,6 +17,7 @@ import (


"code.gitea.io/gitea/models" "code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/labelmsg"
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/minio_ext" "code.gitea.io/gitea/modules/minio_ext"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
@@ -131,7 +132,19 @@ func DeleteAttachment(ctx *context.Context) {
ctx.Error(403) ctx.Error(403)
return return
} }
err = models.DeleteAttachment(attach, false)

err = models.DeleteAttachment(attach, true)
if err != nil {
ctx.Error(500, fmt.Sprintf("DeleteAttachment: %v", err))
return
}

attachjson, _ := json.Marshal(attach)
labelmsg.SendDeleteAttachToLabelSys(string(attachjson))

DeleteAllUnzipFile(attach, "")

_, err = models.DeleteFileChunkById(attach.UUID)
if err != nil { if err != nil {
ctx.Error(500, fmt.Sprintf("DeleteAttachment: %v", err)) ctx.Error(500, fmt.Sprintf("DeleteAttachment: %v", err))
return return
@@ -416,6 +429,21 @@ func UpdateAttachmentDecompressState(ctx *context.Context) {
log.Error("UpdateAttachment(%s) failed:%s", uuid, err.Error()) log.Error("UpdateAttachment(%s) failed:%s", uuid, err.Error())
return return
} }
log.Info("start to send msg to labelsystem ")

dataset, _ := models.GetDatasetByID(attach.DatasetID)

var labelMap map[string]string
labelMap = make(map[string]string)
labelMap["UUID"] = uuid
labelMap["Type"] = fmt.Sprint(attach.Type)
labelMap["UploaderID"] = fmt.Sprint(attach.UploaderID)
labelMap["RepoID"] = fmt.Sprint(dataset.RepoID)
labelMap["AttachName"] = attach.Name
attachjson, _ := json.Marshal(labelMap)
labelmsg.SendAddAttachToLabelSys(string(attachjson))

log.Info("end to send msg to labelsystem ")


ctx.JSON(200, map[string]string{ ctx.JSON(200, map[string]string{
"result_code": "0", "result_code": "0",
@@ -738,8 +766,8 @@ func CompleteMultipart(ctx *context.Context) {
} }


if attachment.DatasetID != 0 { if attachment.DatasetID != 0 {
if typeCloudBrain == models.TypeCloudBrainOne {
if strings.HasSuffix(attachment.Name, ".zip") {
if strings.HasSuffix(attachment.Name, ".zip") {
if typeCloudBrain == models.TypeCloudBrainOne {
err = worker.SendDecompressTask(contexExt.Background(), uuid) err = worker.SendDecompressTask(contexExt.Background(), uuid)
if err != nil { if err != nil {
log.Error("SendDecompressTask(%s) failed:%s", uuid, err.Error()) log.Error("SendDecompressTask(%s) failed:%s", uuid, err.Error())
@@ -751,6 +779,21 @@ func CompleteMultipart(ctx *context.Context) {
} }
} }
} }
if typeCloudBrain == models.TypeCloudBrainTwo {
attachjson, _ := json.Marshal(attachment)
labelmsg.SendDecompressAttachToLabelOBS(string(attachjson))
}
} else {
dataset, _ := models.GetDatasetByID(attachment.DatasetID)
var labelMap map[string]string
labelMap = make(map[string]string)
labelMap["UUID"] = uuid
labelMap["Type"] = fmt.Sprint(attachment.Type)
labelMap["UploaderID"] = fmt.Sprint(attachment.UploaderID)
labelMap["RepoID"] = fmt.Sprint(dataset.RepoID)
labelMap["AttachName"] = attachment.Name
attachjson, _ := json.Marshal(labelMap)
labelmsg.SendAddAttachToLabelSys(string(attachjson))
} }
} }




+ 47
- 2
routers/repo/dataset.go View File

@@ -1,13 +1,14 @@
package repo package repo


import ( import (
"sort"

"code.gitea.io/gitea/models" "code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/auth" "code.gitea.io/gitea/modules/auth"
"code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"sort"
) )


const ( const (
@@ -60,19 +61,62 @@ func newFilterPrivateAttachments(ctx *context.Context, list []*models.Attachment
} }
} }


func QueryDataSet(ctx *context.Context) []*models.Attachment {
repo := ctx.Repo.Repository

dataset, err := models.GetDatasetByRepo(repo)
if err != nil {
log.Error("zou not found dataset 1")
ctx.NotFound("GetDatasetByRepo", err)
return nil
}

if ctx.Query("type") == "" {
log.Error("zou not found type 2")
ctx.NotFound("type error", nil)
return nil
}
err = models.GetDatasetAttachments(ctx.QueryInt("type"), dataset)
if err != nil {
ctx.ServerError("GetDatasetAttachments", err)
return nil
}
attachments := newFilterPrivateAttachments(ctx, dataset.Attachments, repo)

ctx.Data["SortType"] = ctx.Query("sort")
switch ctx.Query("sort") {
case "newest":
sort.Slice(attachments, func(i, j int) bool {
return attachments[i].CreatedUnix > attachments[j].CreatedUnix
})
case "oldest":
sort.Slice(attachments, func(i, j int) bool {
return attachments[i].CreatedUnix < attachments[j].CreatedUnix
})
default:
ctx.Data["SortType"] = "newest"
sort.Slice(attachments, func(i, j int) bool {
return attachments[i].CreatedUnix > attachments[j].CreatedUnix
})
}
return attachments
}

func DatasetIndex(ctx *context.Context) { func DatasetIndex(ctx *context.Context) {
log.Info("dataset index 1")
MustEnableDataset(ctx) MustEnableDataset(ctx)


repo := ctx.Repo.Repository repo := ctx.Repo.Repository


dataset, err := models.GetDatasetByRepo(repo) dataset, err := models.GetDatasetByRepo(repo)
if err != nil { if err != nil {
log.Error("query dataset, not found repo.")
ctx.NotFound("GetDatasetByRepo", err) ctx.NotFound("GetDatasetByRepo", err)
return return
} }


if ctx.Query("type") == "" { if ctx.Query("type") == "" {
log.Error("not found param type")
log.Error("query dataset, not found param type")
ctx.NotFound("type error", nil) ctx.NotFound("type error", nil)
return return
} }
@@ -81,6 +125,7 @@ func DatasetIndex(ctx *context.Context) {
ctx.ServerError("GetDatasetAttachments", err) ctx.ServerError("GetDatasetAttachments", err)
return return
} }

attachments := newFilterPrivateAttachments(ctx, dataset.Attachments, repo) attachments := newFilterPrivateAttachments(ctx, dataset.Attachments, repo)


ctx.Data["SortType"] = ctx.Query("sort") ctx.Data["SortType"] = ctx.Query("sort")


+ 105
- 16
routers/repo/dir.go View File

@@ -5,13 +5,16 @@ import (
"errors" "errors"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"path"
"strings" "strings"


"code.gitea.io/gitea/models" "code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/obs"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/storage"
) )


const ( const (
@@ -32,6 +35,87 @@ type RespGetDirs struct {
FileInfos string `json:"fileInfos"` FileInfos string `json:"fileInfos"`
} }


func DeleteAllUnzipFile(attachment *models.Attachment, parentDir string) {
uuid := attachment.UUID
dirArray := strings.Split(parentDir, "/")

if !strings.HasSuffix(attachment.Name, ".zip") {
log.Error("The file is not zip file, can not query the dir")
return
} else if attachment.DecompressState != models.DecompressStateDone {
log.Error("The file has not been decompressed completely now")
return
}

dirArray = append([]string{attachment.Name}, dirArray...)
if parentDir == "" {
dirArray = []string{attachment.Name}
}
if attachment.Type == models.TypeCloudBrainOne {
dirs, err := GetDatasetDirs(uuid, parentDir)
if err != nil {
log.Error("getDatasetDirs failed:", err.Error())
return
}

var fileInfos []FileInfo
err = json.Unmarshal([]byte(dirs), &fileInfos)
if err != nil {
log.Error("json.Unmarshal failed:", err.Error())
return
}

for _, fileInfo := range fileInfos {
log.Info("fileName=" + fileInfo.FileName)
log.Info("parentDir=" + fileInfo.ParenDir)
if fileInfo.IsDir {
DeleteAllUnzipFile(attachment, fileInfo.FileName)
} else {
absolutepath := path.Join(attachment.RelativePath()+attachment.UUID, fileInfo.ParenDir)
log.Info("absolutepath=" + absolutepath)
storage.Attachments.Delete(absolutepath)
}
}
}
if attachment.Type == models.TypeCloudBrainTwo {

input := &obs.ListObjectsInput{}
input.Bucket = setting.Bucket
// 设置每页100个对象
input.MaxKeys = 100
input.Prefix = setting.BasePath + attachment.RelativePath() + attachment.UUID
index := 1
log.Info("prefix=" + input.Prefix)
for {
output, err := storage.ObsCli.ListObjects(input)
if err == nil {
log.Info("Page:%d\n", index)
index++
for _, val := range output.Contents {
log.Info("delete obs file:" + val.Key)
delObj := &obs.DeleteObjectInput{}
delObj.Bucket = setting.Bucket
delObj.Key = val.Key
storage.ObsCli.DeleteObject(delObj)
}
if output.IsTruncated {
input.Marker = output.NextMarker
} else {
break
}
} else {
if obsError, ok := err.(obs.ObsError); ok {
log.Info("Code:%s\n", obsError.Code)
log.Info("Message:%s\n", obsError.Message)
}
break
}
}

}

}

func DirIndex(ctx *context.Context) { func DirIndex(ctx *context.Context) {
uuid := ctx.Params("uuid") uuid := ctx.Params("uuid")
parentDir := ctx.Query("parentDir") parentDir := ctx.Query("parentDir")
@@ -58,30 +142,35 @@ func DirIndex(ctx *context.Context) {
dirArray = []string{attachment.Name} dirArray = []string{attachment.Name}
} }


dirs, err := getDatasetDirs(uuid, parentDir)
if err != nil {
log.Error("getDatasetDirs failed:", err.Error())
ctx.ServerError("getDatasetDirs failed:", err)
return
}

var fileInfos []FileInfo
err = json.Unmarshal([]byte(dirs), &fileInfos)
if err != nil {
log.Error("json.Unmarshal failed:", err.Error())
ctx.ServerError("json.Unmarshal failed:", err)
return
}
/*
dirs, err := GetDatasetDirs(uuid, parentDir)
if err != nil {
log.Error("getDatasetDirs failed:", err.Error())
ctx.ServerError("getDatasetDirs failed:", err)
return
}
*/

//var fileInfos []FileInfo

/*
err = json.Unmarshal([]byte(dirs), &fileInfos)
if err != nil {
log.Error("json.Unmarshal failed:", err.Error())
ctx.ServerError("json.Unmarshal failed:", err)
return
}
*/


ctx.Data["Path"] = dirArray ctx.Data["Path"] = dirArray
ctx.Data["Dirs"] = fileInfos
ctx.Data["Dirs"] = true
ctx.Data["Uuid"] = uuid ctx.Data["Uuid"] = uuid
ctx.Data["PageIsDataset"] = true ctx.Data["PageIsDataset"] = true


ctx.HTML(200, tplDirIndex) ctx.HTML(200, tplDirIndex)
} }


func getDatasetDirs(uuid string, parentDir string) (string, error) {
func GetDatasetDirs(uuid string, parentDir string) (string, error) {
var req string var req string
dataActualPath := setting.Attachment.Minio.RealPath + dataActualPath := setting.Attachment.Minio.RealPath +
setting.Attachment.Minio.Bucket + "/" + setting.Attachment.Minio.Bucket + "/" +


+ 37
- 0
routers/repo/label.go View File

@@ -0,0 +1,37 @@
package repo

import (
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
)

const (
tplLabelIndex base.TplName = "repo/datasets/label/index"
)

func LabelIndex(ctx *context.Context) {

log.Info("Go Here LabelIndex.")
uuid := ctx.Params("uuid")
attach, err := models.GetAttachmentByUUID(uuid)
if err != nil {
log.Info("query attach error")
} else {
dataset, err := models.GetDatasetByID(attach.DatasetID)
if err != nil {
log.Info("query dataset error")
} else {
ctx.Data["repoId"] = dataset.RepoID
}
}

attachments := QueryDataSet(ctx)

ctx.Data["uuid"] = uuid
ctx.Data["Attachments"] = attachments

ctx.HTML(200, tplLabelIndex)

}

+ 13
- 0
routers/routes/routes.go View File

@@ -6,6 +6,7 @@ package routes


import ( import (
"bytes" "bytes"
"code.gitea.io/gitea/routers/operation"
"encoding/gob" "encoding/gob"
"net/http" "net/http"
"path" "path"
@@ -539,6 +540,15 @@ func RegisterRoutes(m *macaron.Macaron) {
}, adminReq) }, adminReq)
// ***** END: Admin ***** // ***** END: Admin *****


operationReq := context.Toggle(&context.ToggleOptions{SignInRequired: true, OperationRequired: true})

// ***** START: Operation *****
m.Group("/operation", func() {
m.Get("/config/recommend_org", operation.Organizations)
m.Post("/config/recommend_org", bindIgnErr(operation.OrgInfos{}), operation.UpdateRecommendOrganizations)
}, operationReq)
// ***** END: Operation *****

m.Group("", func() { m.Group("", func() {
m.Get("/:username", user.Profile) m.Get("/:username", user.Profile)
}, ignSignIn) }, ignSignIn)
@@ -926,6 +936,9 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Group("/dirs", func() { m.Group("/dirs", func() {
m.Get("/:uuid", reqRepoDatasetReader, repo.DirIndex) m.Get("/:uuid", reqRepoDatasetReader, repo.DirIndex)
}) })
m.Group("/label", func() {
m.Get("/:uuid", reqRepoDatasetReader, repo.LabelIndex)
})
}, context.RepoRef()) }, context.RepoRef())


m.Group("/cloudbrain", func() { m.Group("/cloudbrain", func() {


+ 2
- 0
templates/base/head.tmpl View File

@@ -185,6 +185,8 @@ var _hmt = _hmt || [];
s.parentNode.insertBefore(hm, s); s.parentNode.insertBefore(hm, s);
})(); })();
</script> </script>
<script src="/self/func.js" type="text/javascript"></script>

</head> </head>
<body> <body>
{{template "custom/body_outer_pre" .}} {{template "custom/body_outer_pre" .}}


+ 76
- 0
templates/explore/repo_left.tmpl View File

@@ -0,0 +1,76 @@
<div class="ui tablet only computer only four wide tablet three wide computer column">
<div class="leftnav ui fluid vertical menu">
<a class="{{if .PageIsExploreRepositories}}active {{end}}item" href="/explore/repos?sort={{.SortType}}" style="background: #5BB973; color: #FFF;">
<svg class="svg octicon-inbox" width="16" height="16" viewBox="0 0 24 24">
<path fill="currentColor" d="M16,20H20V16H16M16,14H20V10H16M10,8H14V4H10M16,8H20V4H16M10,14H14V10H10M4,14H8V10H4M4,20H8V16H4M10,20H14V16H10M4,8H8V4H4V8Z" />
</svg>
全部领域
</a>
<a class="{{if eq $.Keyword "大模型"}}active {{end}}item" href="/explore/repos?q=大模型&topic=1&sort={{.SortType}}">
<svg class="svg octicon-inbox" width="16" height="16" viewBox="0 0 24 24">
<path fill="currentColor" d="M19 3H5C3.89 3 3 3.89 3 5V19C3 20.11 3.9 21 5 21H19C20.11 21 21 20.11 21 19V5C21 3.89 20.1 3 19 3M16.1 15.9C15.07 15.9 14.09 15.5 13.35 14.76L12.71 14.12L14.13 12.71L14.76 13.34C15.12 13.7 15.6 13.9 16.11 13.9C17.15 13.9 18 13.05 18 12S17.15 10.1 16.1 10.1C15.6 10.1 15.12 10.3 14.76 10.66L10.65 14.76C9.91 15.5 8.94 15.9 7.9 15.9C5.75 15.9 4 14.15 4 12S5.75 8.1 7.9 8.1C8.94 8.1 9.91 8.5 10.65 9.24L11.29 9.88L9.87 11.3L9.24 10.66C8.88 10.3 8.4 10.1 7.9 10.1C6.85 10.1 6 10.95 6 12S6.85 13.9 7.9 13.9C8.4 13.9 8.88 13.7 9.24 13.34L13.35 9.24C14.09 8.5 15.06 8.1 16.1 8.1C18.25 8.1 20 9.85 20 12S18.25 15.9 16.1 15.9Z" />
</svg>
大模型
</a>
<a class="{{if eq $.Keyword "AI开发工具"}}active {{end}}item" href="/explore/repos?q=AI开发工具&topic=1&sort={{.SortType}}">
<svg class="svg octicon-inbox" width="16" height="16" viewBox="0 0 24 24">
<path fill="currentColor" d="M19 3H5C3.9 3 3 3.9 3 5V19C3 20.1 3.9 21 5 21H19C20.1 21 21 20.1 21 19V5C21 3.9 20.1 3 19 3M11 8H9V10C9 11.1 8.1 12 7 12C8.1 12 9 12.9 9 14V16H11V18H9C7.9 18 7 17.1 7 16V15C7 13.9 6.1 13 5 13V11C6.1 11 7 10.1 7 9V8C7 6.9 7.9 6 9 6H11V8M19 13C17.9 13 17 13.9 17 15V16C17 17.1 16.1 18 15 18H13V16H15V14C15 12.9 15.9 12 17 12C15.9 12 15 11.1 15 10V8H13V6H15C16.1 6 17 6.9 17 8V9C17 10.1 17.9 11 19 11V13Z" />
</svg>
AI开发工具
</a>
<a class="{{if eq $.Keyword "计算机视觉"}}active {{end}}item" href="/explore/repos?q=计算机视觉&topic=1&sort={{.SortType}}">
<svg class="svg octicon-inbox" width="16" height="16" viewBox="0 0 24 24">
<path fill="currentColor" d="M12,9A3,3 0 0,0 9,12A3,3 0 0,0 12,15A3,3 0 0,0 15,12A3,3 0 0,0 12,9M12,17A5,5 0 0,1 7,12A5,5 0 0,1 12,7A5,5 0 0,1 17,12A5,5 0 0,1 12,17M12,4.5C7,4.5 2.73,7.61 1,12C2.73,16.39 7,19.5 12,19.5C17,19.5 21.27,16.39 23,12C21.27,7.61 17,4.5 12,4.5Z" />
</svg>
计算机视觉
</a>
<a class="{{if eq $.Keyword "自然语言处理"}}active {{end}}item" href="/explore/repos?q=自然语言处理&topic=1&sort={{.SortType}}">
<svg class="svg octicon-inbox" width="16" height="16" viewBox="0 0 24 24">
<path fill="currentColor" d="M9,5A4,4 0 0,1 13,9A4,4 0 0,1 9,13A4,4 0 0,1 5,9A4,4 0 0,1 9,5M9,15C11.67,15 17,16.34 17,19V21H1V19C1,16.34 6.33,15 9,15M16.76,5.36C18.78,7.56 18.78,10.61 16.76,12.63L15.08,10.94C15.92,9.76 15.92,8.23 15.08,7.05L16.76,5.36M20.07,2C24,6.05 23.97,12.11 20.07,16L18.44,14.37C21.21,11.19 21.21,6.65 18.44,3.63L20.07,2Z" />
</svg>
自然语言处理
</a>
<a class="{{if eq $.Keyword "机器学习"}}active {{end}}item" href="/explore/repos?q=机器学习&topic=1&sort={{.SortType}}">
<svg class="svg octicon-inbox" width="16" height="16" viewBox="0 0 24 24">
<path fill="currentColor" d="M19,12V13.5A4,4 0 0,1 23,17.5C23,18.32 22.75,19.08 22.33,19.71L21.24,18.62C21.41,18.28 21.5,17.9 21.5,17.5A2.5,2.5 0 0,0 19,15V16.5L16.75,14.25L19,12M19,23V21.5A4,4 0 0,1 15,17.5C15,16.68 15.25,15.92 15.67,15.29L16.76,16.38C16.59,16.72 16.5,17.1 16.5,17.5A2.5,2.5 0 0,0 19,20V18.5L21.25,20.75L19,23M12,3C16.42,3 20,4.79 20,7C20,9.21 16.42,11 12,11C7.58,11 4,9.21 4,7C4,4.79 7.58,3 12,3M4,9C4,11.21 7.58,13 12,13C13.11,13 14.17,12.89 15.14,12.68C14.19,13.54 13.5,14.67 13.18,15.96L12,16C7.58,16 4,14.21 4,12V9M20,9V11H19.5L18.9,11.03C19.6,10.43 20,9.74 20,9M4,14C4,16.21 7.58,18 12,18L13,17.97C13.09,19.03 13.42,20 13.95,20.88L12,21C7.58,21 4,19.21 4,17V14Z" />
</svg>
机器学习
</a>
<a class="{{if eq $.Keyword "神经网络"}}active {{end}}item" href="/explore/repos?q=神经网络&topic=1&sort={{.SortType}}">
<svg class="svg octicon-inbox" width="16" height="16" viewBox="0 0 24 24">
<path fill="currentColor" d="M13 3C9.23 3 6.19 5.95 6 9.66L4.08 12.19C3.84 12.5 4.08 13 4.5 13H6V16C6 17.11 6.89 18 8 18H9V21H16V16.31C18.37 15.19 20 12.8 20 10C20 6.14 16.88 3 13 3M17.06 9.57L15.1 10.09L16.54 11.54C16.89 11.88 16.89 12.46 16.54 12.81C16.19 13.16 15.61 13.16 15.27 12.81L13.81 11.37L13.3 13.33C13.18 13.82 12.68 14.1 12.21 13.97C11.72 13.84 11.44 13.35 11.57 12.87L12.1 10.9L10.13 11.43C9.65 11.56 9.15 11.28 9.03 10.79C8.9 10.32 9.18 9.82 9.67 9.7L11.63 9.19L10.19 7.73C9.84 7.39 9.84 6.82 10.19 6.46C10.54 6.11 11.12 6.11 11.46 6.46L12.91 7.9L13.43 5.94C13.55 5.46 14.04 5.18 14.5 5.3C15 5.43 15.28 5.92 15.16 6.41L14.63 8.37L16.59 7.84C17.08 7.72 17.57 8 17.7 8.5C17.82 8.96 17.54 9.45 17.06 9.57Z" />
</svg>
神经网络
</a>
<a class="{{if eq $.Keyword "自动驾驶"}}active {{end}}item" href="/explore/repos?q=自动驾驶&topic=1&sort={{.SortType}}">
<svg class="svg octicon-inbox" width="16" height="16" viewBox="0 0 24 24">
<path fill="currentColor" d="M5,14H19L17.5,9.5H6.5L5,14M17.5,19A1.5,1.5 0 0,0 19,17.5A1.5,1.5 0 0,0 17.5,16A1.5,1.5 0 0,0 16,17.5A1.5,1.5 0 0,0 17.5,19M6.5,19A1.5,1.5 0 0,0 8,17.5A1.5,1.5 0 0,0 6.5,16A1.5,1.5 0 0,0 5,17.5A1.5,1.5 0 0,0 6.5,19M18.92,9L21,15V23A1,1 0 0,1 20,24H19A1,1 0 0,1 18,23V22H6V23A1,1 0 0,1 5,24H4A1,1 0 0,1 3,23V15L5.08,9C5.28,8.42 5.85,8 6.5,8H17.5C18.15,8 18.72,8.42 18.92,9M12,0C14.12,0 16.15,0.86 17.65,2.35L16.23,3.77C15.11,2.65 13.58,2 12,2C10.42,2 8.89,2.65 7.77,3.77L6.36,2.35C7.85,0.86 9.88,0 12,0M12,4C13.06,4 14.07,4.44 14.82,5.18L13.4,6.6C13.03,6.23 12.53,6 12,6C11.5,6 10.97,6.23 10.6,6.6L9.18,5.18C9.93,4.44 10.94,4 12,4Z" />
</svg>
自动驾驶
</a>
<a class="{{if eq $.Keyword "机器人"}}active {{end}}item" href="/explore/repos?q=机器人&topic=1&sort={{.SortType}}">
<svg class="svg octicon-inbox" width="16" height="16" viewBox="0 0 24 24">
<path fill="currentColor" d="M12,2A2,2 0 0,1 14,4C14,4.74 13.6,5.39 13,5.73V7H14A7,7 0 0,1 21,14H22A1,1 0 0,1 23,15V18A1,1 0 0,1 22,19H21V20A2,2 0 0,1 19,22H5A2,2 0 0,1 3,20V19H2A1,1 0 0,1 1,18V15A1,1 0 0,1 2,14H3A7,7 0 0,1 10,7H11V5.73C10.4,5.39 10,4.74 10,4A2,2 0 0,1 12,2M7.5,13A2.5,2.5 0 0,0 5,15.5A2.5,2.5 0 0,0 7.5,18A2.5,2.5 0 0,0 10,15.5A2.5,2.5 0 0,0 7.5,13M16.5,13A2.5,2.5 0 0,0 14,15.5A2.5,2.5 0 0,0 16.5,18A2.5,2.5 0 0,0 19,15.5A2.5,2.5 0 0,0 16.5,13Z" />
</svg>
机器人
</a>
<a class="{{if eq $.Keyword "联邦学习"}}active {{end}}item" href="/explore/repos?q=联邦学习&topic=1&sort={{.SortType}}">
<svg class="svg octicon-inbox" width="16" height="16" viewBox="0 0 24 24">
<path fill="currentColor" d="M3 11H11V3H3M5 5H9V9H5M13 21H21V13H13M15 15H19V19H15M3 21H11V13H3M5 15H9V19H5M13 3V11H21V3M19 9H15V5H19Z" />
</svg>
联邦学习
</a>
<a class="{{if eq $.Keyword "数据挖掘"}}active {{end}}item" href="/explore/repos?q=数据挖掘&topic=1&sort={{.SortType}}">
<svg class="svg octicon-inbox" width="16" height="16" viewBox="0 0 24 24">
<path fill="currentColor" d="M18.36,2.64C20,2.64 21.36,4 21.36,5.64C21.36,7.29 20,8.64 18.36,8.64C16.71,8.64 15.36,7.29 15.36,5.64C15.36,5.34 15.41,5.06 15.5,4.8C14.43,4.29 13.25,4 12,4A8,8 0 0,0 4,12L4.04,12.84L2.05,13.05L2,12A10,10 0 0,1 12,2C13.69,2 15.28,2.42 16.67,3.16C17.16,2.83 17.74,2.64 18.36,2.64M18.36,4.64A1,1 0 0,0 17.36,5.64A1,1 0 0,0 18.36,6.64C18.92,6.64 19.36,6.19 19.36,5.64C19.36,5.08 18.92,4.64 18.36,4.64M5.64,15.36C7.29,15.36 8.64,16.71 8.64,18.36C8.64,18.66 8.59,18.94 8.5,19.2C9.57,19.71 10.75,20 12,20A8,8 0 0,0 20,12L19.96,11.16L21.95,10.95L22,12A10,10 0 0,1 12,22C10.31,22 8.72,21.58 7.33,20.84C6.84,21.17 6.26,21.36 5.64,21.36C4,21.36 2.64,20 2.64,18.36C2.64,16.71 4,15.36 5.64,15.36M5.64,17.36C5.08,17.36 4.64,17.81 4.64,18.36C4.64,18.92 5.08,19.36 5.64,19.36A1,1 0 0,0 6.64,18.36A1,1 0 0,0 5.64,17.36M12,8A4,4 0 0,1 16,12A4,4 0 0,1 12,16A4,4 0 0,1 8,12A4,4 0 0,1 12,8Z" />
</svg>
数据挖掘
</a>
<a class="{{if eq $.Keyword "RISC-V"}}active {{end}}item" href="/explore/repos?q=RISC-V&topic=1&sort={{.SortType}}">
<svg class="svg octicon-inbox" width="16" height="16" viewBox="0 0 24 24">
<path fill="currentColor" d="M17,17H7V7H17M21,11V9H19V7C19,5.89 18.1,5 17,5H15V3H13V5H11V3H9V5H7C5.89,5 5,5.89 5,7V9H3V11H5V13H3V15H5V17A2,2 0 0,0 7,19H9V21H11V19H13V21H15V19H17A2,2 0 0,0 19,17V15H21V13H19V11M13,13H11V11H13M15,9H9V15H15V9Z" />
</svg>
RISC-V开发
</a>
</div>
</div>

+ 148
- 60
templates/explore/repo_list.tmpl View File

@@ -1,70 +1,158 @@
<h2 class="ui left floated medium header">
{{.i18n.Tr "explore.repos"}}
</h2>
<div class="ui right floated secondary filter menu">
<!-- Sort -->
<div class="ui right dropdown type jump item">
<span class="text">
{{.i18n.Tr "repo.issues.filter_sort"}}
<i class="dropdown icon"></i>
</span>
<div class="menu">
<a class="{{if eq .SortType "newest"}}active{{end}} item" href="{{$.Link}}?sort=newest&q={{$.Keyword}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.latest"}}</a>
<a class="{{if eq .SortType "oldest"}}active{{end}} item" href="{{$.Link}}?sort=oldest&q={{$.Keyword}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.oldest"}}</a>
<a class="{{if eq .SortType "alphabetically"}}active{{end}} item" href="{{$.Link}}?sort=alphabetically&q={{$.Keyword}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.label.filter_sort.alphabetically"}}</a>
<a class="{{if eq .SortType "reversealphabetically"}}active{{end}} item" href="{{$.Link}}?sort=reversealphabetically&q={{$.Keyword}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.label.filter_sort.reverse_alphabetically"}}</a>
<a class="{{if eq .SortType "recentupdate"}}active{{end}} item" href="{{$.Link}}?sort=recentupdate&q={{$.Keyword}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.recentupdate"}}</a>
<a class="{{if eq .SortType "leastupdate"}}active{{end}} item" href="{{$.Link}}?sort=leastupdate&q={{$.Keyword}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.leastupdate"}}</a>
<a class="{{if eq .SortType "moststars"}}active{{end}} item" href="{{$.Link}}?sort=moststars&q={{$.Keyword}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.moststars"}}</a>
<a class="{{if eq .SortType "feweststars"}}active{{end}} item" href="{{$.Link}}?sort=feweststars&q={{$.Keyword}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.feweststars"}}</a>
<a class="{{if eq .SortType "mostforks"}}active{{end}} item" href="{{$.Link}}?sort=mostforks&q={{$.Keyword}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.mostforks"}}</a>
<a class="{{if eq .SortType "fewestforks"}}active{{end}} item" href="{{$.Link}}?sort=fewestforks&q={{$.Keyword}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.fewestforks"}}</a>
</div>
</div>
</div>
<style>
.ui.repository.list>.item{
position: relative;
border: 1px solid #E1E3E6;
border-radius: 0.8rem;
margin-bottom: 1.0rem;
padding: 1.0rem !important;
}
.ui.repository.list>.item .header {
font-size: 1.4rem !important;
font-weight: 200;
}
.ui.list>.item>.content{
margin-left: 36px;
}
.ui.list .list>.item>img.image+.content, .ui.list>.item>img.image+.content{
width:calc(100% - 30px);
margin-left: 0;
}
.ui.repository.list>.item::before{
position: absolute;
left: 0;
right: 0;
content: "";
height: 1px;
background-color: #E1E3E6;
bottom: 2.8rem;
}
.repository .ui.mini.menu{
font-size: .6rem;
}
.repository .ui.right.compact .item{
padding-top: 0;
padding-bottom: 0;
}
.ui.repository.list .item .time {
margin-top: 1.5rem;
}
</style>

<div class="ui secondary pointing tabular top attached borderless menu navbar">
<a class="{{if eq .SortType "hot"}}active{{end}} item" href="{{$.Link}}?sort=hot&q={{$.Keyword}}&tab={{$.TabName}}">
<svg class="svg octicon-repo" width="16" height="16" aria-hidden="true">
<use xlink:href="#octicon-repo" />
</svg>
热门{{.i18n.Tr "explore.repos"}}
</a>
<a class="{{if eq .SortType "active"}}active{{end}} item" href="{{$.Link}}?sort=active&q={{$.Keyword}}&tab={{$.TabName}}">
<svg class="svg octicon-inbox" width="16" height="16" aria-hidden="true">
<use xlink:href="#octicon-inbox" />
</svg>
活跃{{.i18n.Tr "explore.repos"}}
</a>


<div class="ui clearing divider"></div>
<a class="{{if eq .SortType "recentupdate"}}active{{end}} item" href="{{$.Link}}?sort=recentupdate&q={{$.Keyword}}&tab={{$.TabName}}">
<svg class="svg octicon-organization" width="16" height="16" aria-hidden="true">
<use xlink:href="#octicon-organization" />
</svg> {{.i18n.Tr "repo.issues.filter_sort.recentupdate"}}
</a>

<div class="ui right floated secondary filter menu">
<!-- Sort -->
<div class="ui right dropdown type jump item">
<span class="text">
{{.i18n.Tr "repo.issues.filter_sort"}}
<i class="dropdown icon"></i>
</span>
<div class="menu">
<a class="{{if eq .SortType "newest"}}active{{end}} item" href="{{$.Link}}?sort=newest&q={{$.Keyword}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.latest"}}</a>
<a class="{{if eq .SortType "oldest"}}active{{end}} item" href="{{$.Link}}?sort=oldest&q={{$.Keyword}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.oldest"}}</a>
<a class="{{if eq .SortType "alphabetically"}}active{{end}} item" href="{{$.Link}}?sort=alphabetically&q={{$.Keyword}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.label.filter_sort.alphabetically"}}</a>
<a class="{{if eq .SortType "reversealphabetically"}}active{{end}} item" href="{{$.Link}}?sort=reversealphabetically&q={{$.Keyword}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.label.filter_sort.reverse_alphabetically"}}</a>
<a class="{{if eq .SortType "recentupdate"}}active{{end}} item" href="{{$.Link}}?sort=recentupdate&q={{$.Keyword}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.recentupdate"}}</a>
<a class="{{if eq .SortType "leastupdate"}}active{{end}} item" href="{{$.Link}}?sort=leastupdate&q={{$.Keyword}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.leastupdate"}}</a>
<a class="{{if eq .SortType "moststars"}}active{{end}} item" href="{{$.Link}}?sort=moststars&q={{$.Keyword}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.moststars"}}</a>
<a class="{{if eq .SortType "feweststars"}}active{{end}} item" href="{{$.Link}}?sort=feweststars&q={{$.Keyword}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.feweststars"}}</a>
<a class="{{if eq .SortType "mostforks"}}active{{end}} item" href="{{$.Link}}?sort=mostforks&q={{$.Keyword}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.mostforks"}}</a>
<a class="{{if eq .SortType "fewestforks"}}active{{end}} item" href="{{$.Link}}?sort=fewestforks&q={{$.Keyword}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.fewestforks"}}</a>
</div>
</div>
</div>
</div>


<div class="ui repository list"> <div class="ui repository list">
{{range .Repos}} {{range .Repos}}
<div class="item"> <div class="item">
<div class="ui header">
{{if .RelAvatarLink}}
<img class="ui avatar image" src="{{.RelAvatarLink}}">
{{end}}
<a class="name" href="{{.Link}}">
{{if or $.PageIsExplore $.PageIsProfileStarList }}{{if .Owner}}{{.Owner.Name}} <span>/</span> {{end}}{{end}}<strong>{{.Name}}</strong>
{{if .IsArchived}}<i class="archive icon archived-icon"></i>{{end}}
</a>
{{if .IsPrivate}}
<span class="middle text gold">{{svg "octicon-lock" 16}}</span>
{{else if .IsFork}}
<span class="middle">{{svg "octicon-repo-forked" 16}}</span>
{{else if .IsMirror}}
<span class="middle">{{svg "octicon-repo-clone" 16}}</span>
{{else if .Owner}}
{{if .Owner.Visibility.IsPrivate}}
<span class="text gold">{{svg "octicon-lock" 16}}</span>
{{end}}
{{end}}
<div class="ui right metas">
{{if .PrimaryLanguage }}
<span class="text grey"><i class="color-icon" style="background-color: {{.PrimaryLanguage.Color}}"></i>{{ .PrimaryLanguage.Language }}</span>
{{end}}
<span class="text grey">{{svg "octicon-star" 16}} {{.NumStars}}</span>
<span class="text grey">{{svg "octicon-git-branch" 16}} {{.NumForks}}</span>
{{if .RelAvatarLink}}
<img class="ui avatar image" src="{{.RelAvatarLink}}">
{{end}}
<div class="content">
<div class="ui header">
<div class="ui grid">
<div class="ui sixteen wide mobile ten wide tablet twelve wide computer column">
<a class="name" href="{{.Link}}">
{{if or $.PageIsExplore $.PageIsProfileStarList }}{{if .Owner}}{{.Owner.Name}} <span>/</span> {{end}}{{end}}<strong>{{.Name}}</strong>
{{if .IsArchived}}<i class="archive icon archived-icon"></i>{{end}}
</a>
{{if .IsPrivate}}
<span class="middle text gold">{{svg "octicon-lock" 16}}</span>
{{else if .IsFork}}
<span class="middle">{{svg "octicon-repo-forked" 16}}</span>
{{else if .IsMirror}}
<span class="middle">{{svg "octicon-repo-clone" 16}}</span>
{{else if .Owner}}
{{if .Owner.Visibility.IsPrivate}}
<span class="text gold">{{svg "octicon-lock" 16}}</span>
{{end}}
{{end}}
</div>
<div class="ui sixteen wide mobile six wide tablet four wide computer column">
<div class="ui mini right compact menu">
{{if eq $.SortType "hot"}}
<a class="item">
<svg class="svg octicon-inbox" width="16" height="16" viewBox="0 0 24 24">
<path fill="currentColor" d="M17.66 11.2C17.43 10.9 17.15 10.64 16.89 10.38C16.22 9.78 15.46 9.35 14.82 8.72C13.33 7.26 13 4.85 13.95 3C13 3.23 12.17 3.75 11.46 4.32C8.87 6.4 7.85 10.07 9.07 13.22C9.11 13.32 9.15 13.42 9.15 13.55C9.15 13.77 9 13.97 8.8 14.05C8.57 14.15 8.33 14.09 8.14 13.93C8.08 13.88 8.04 13.83 8 13.76C6.87 12.33 6.69 10.28 7.45 8.64C5.78 10 4.87 12.3 5 14.47C5.06 14.97 5.12 15.47 5.29 15.97C5.43 16.57 5.7 17.17 6 17.7C7.08 19.43 8.95 20.67 10.96 20.92C13.1 21.19 15.39 20.8 17.03 19.32C18.86 17.66 19.5 15 18.56 12.72L18.43 12.46C18.22 12 17.66 11.2 17.66 11.2M14.5 17.5C14.22 17.74 13.76 18 13.4 18.1C12.28 18.5 11.16 17.94 10.5 17.28C11.69 17 12.4 16.12 12.61 15.23C12.78 14.43 12.46 13.77 12.33 13C12.21 12.26 12.23 11.63 12.5 10.94C12.69 11.32 12.89 11.7 13.13 12C13.9 13 15.11 13.44 15.37 14.8C15.41 14.94 15.43 15.08 15.43 15.23C15.46 16.05 15.1 16.95 14.5 17.5H14.5Z" />
</svg>
{{.Hot}}
</a>
{{else if eq $.SortType "active"}}
<a class="item">
<svg class="svg octicon-inbox" width="16" height="16" viewBox="0 0 24 24">
<path fill="currentColor" d="M13.13 22.19L11.5 18.36C13.07 17.78 14.54 17 15.9 16.09L13.13 22.19M5.64 12.5L1.81 10.87L7.91 8.1C7 9.46 6.22 10.93 5.64 12.5M21.61 2.39C21.61 2.39 16.66 .269 11 5.93C8.81 8.12 7.5 10.53 6.65 12.64C6.37 13.39 6.56 14.21 7.11 14.77L9.24 16.89C9.79 17.45 10.61 17.63 11.36 17.35C13.5 16.53 15.88 15.19 18.07 13C23.73 7.34 21.61 2.39 21.61 2.39M14.54 9.46C13.76 8.68 13.76 7.41 14.54 6.63S16.59 5.85 17.37 6.63C18.14 7.41 18.15 8.68 17.37 9.46C16.59 10.24 15.32 10.24 14.54 9.46M8.88 16.53L7.47 15.12L8.88 16.53M6.24 22L9.88 18.36C9.54 18.27 9.21 18.12 8.91 17.91L4.83 22H6.24M2 22H3.41L8.18 17.24L6.76 15.83L2 20.59V22M2 19.17L6.09 15.09C5.88 14.79 5.73 14.47 5.64 14.12L2 17.76V19.17Z" />
</svg> {{.Active}}
</a>
{{else}}
<a class="item">
{{svg "octicon-eye" 16}} {{.NumWatches}}
</a>
<a class="item">
{{svg "octicon-git-branch" 16}} {{.NumForks}}
</a>
{{end}}
<a class="item">
{{svg "octicon-star" 16}} {{.NumStars}}
</a>
</div>
</div>
</div>
</div> </div>
</div>
<div class="description">
{{if .DescriptionHTML}}<p class="has-emoji">{{.DescriptionHTML}}</p>{{end}}
{{if .Topics }}
<div class="ui tags">
{{range .Topics}}
{{if ne . "" }}<a href="{{AppSubUrl}}/explore/repos?q={{.}}&topic=1"><div class="ui small label topic">{{.}}</div></a>{{end}}
<div class="description">
{{if .DescriptionHTML}}<p class="has-emoji">{{.DescriptionHTML}}</p>{{end}}
{{if .Topics }}
<div class="ui tags">
{{range .Topics}}
{{if ne . "" }}<a href="{{AppSubUrl}}/explore/repos?q={{.}}&topic=1"><div class="ui small label topic">{{.}}</div></a>{{end}}
{{end}}
</div>
{{end}} {{end}}
</div>
{{end}}
<p class="time">{{$.i18n.Tr "org.repo_updated"}} {{TimeSinceUnix .UpdatedUnix $.i18n.Lang}}</p>
<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>
</div> </div>
{{else}} {{else}}


+ 123
- 0
templates/explore/repo_orgtop.tmpl View File

@@ -0,0 +1,123 @@
<script src="https://cdn.bootcdn.net/ajax/libs/Swiper/6.8.0/swiper-bundle.min.js"></script>
<link href="https://cdn.bootcdn.net/ajax/libs/Swiper/6.8.0/swiper-bundle.min.css" rel="stylesheet">
<style>
.explore .repos--seach{
border-bottom:none;
}
.repos--orgtop {
margin-top: -2.2rem;
}
.repos--orgtop p{
margin-bottom:0.5rem
}

.repos--orgtop .ui.card {
box-shadow: none;
border: none;
}

.repos--orgtop .ui.card .content {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}

.repos--orgtop .swiper-pagination {
position: relative;
bottom: 0;
}
</style>

<div class="repos--seach repos--orgtop">
<div class="ui container">
<p class="text grey">这些优秀的组织正在使用:</p>
<!-- Swiper -->
<div class="swiper-container">
<div class="swiper-wrapper">
<!--{{range .RecommendOrgs}}
<div class="swiper-slide">
<div class="ui card">
<a class="image" href="{{$.HomeLink}}/{{.User.Name}}">
<img class="ui avatar image" src="{{.User.RelAvatarLink}}" alt="{{.User.Name}}" title="{{.User.Name}}">
</a>
</div>
</div>
{{end}}-->
<div class="swiper-slide">
<div class="ui card">
<a class="image" href="https://git.openi.org.cn/OpenI">
<img src="/img/org-openi@2x-80.jpg" alt="OpenI 启智社区" title="OpenI 启智社区">
</a>
</div>
</div>
<div class="swiper-slide">
<div class="ui card">
<a class="image" href="https://git.openi.org.cn/TensorLayer">
<img src="/img/org-tensorlayer@2x-80.jpg" alt="TensorLayer" title="TensorLayer">
</a>
</div>
</div>
<div class="swiper-slide">
<div class="ui card">
<a class="image" href="https://git.openi.org.cn/PCL-Platform.Intelligence">
<img src="/img/org-platform@2x-80.jpg" alt="PCL-Platform.Intelligence" title="PCL-Platform.Intelligence">
</a>
</div>
</div>
<div class="swiper-slide">
<div class="ui card">
<a class="image" href="https://git.openi.org.cn/BAAI">
<img src="/img/org-baai@2x-80.jpg" alt="BAAI" title="BAAI">
</a>
</div>
</div>
<div class="swiper-slide">
<div class="ui card">
<a class="image" href="https://git.openi.org.cn/OpenModelZoo">
<img src="/img/org-modelzoo@2x-80.jpg" alt="OpenModelZoo" title="OpenModelZoo">
</a>
</div>
</div>
<div class="swiper-slide">
<div class="ui card">
<a class="image" href="https://git.openi.org.cn/PCL_EngineClub">
<img src="/img/org-engineclub@2x-80.jpg" alt="PCL_EngineClub" title="PCL_EngineClub">
</a>
</div>
</div>
</div>
<!-- Add Pagination -->
<div class="swiper-pagination"></div>
</div>
</div>
</div>
<!-- Initialize Swiper -->

<script>
var swiper = new Swiper('.swiper-container', {
slidesPerView: 2,
spaceBetween: 10,
autoplay: {
delay: 2500,
disableOnInteraction: false,
},
pagination: {
el: '.swiper-pagination',
clickable: true,
},
breakpoints: {
'@0.00': {
slidesPerView: 2,
spaceBetween: 10,
},
'@0.75': {
slidesPerView: 4,
spaceBetween: 20,
},
'@1.00': {
slidesPerView: 5,
spaceBetween: 30,
}
}
});
</script>

+ 39
- 1
templates/explore/repo_right.tmpl View File

@@ -1 +1,39 @@
<a href="https://openi.org.cn/html/2020/qimengxingdong_0813/450.html" target="_blank"><img class="ui mini image" src="/img/banner-qimen-4X3.jpg" style="width:100%;"></a>
<a href="https://openi.org.cn/html/2020/qimengxingdong_0813/450.html" target="_blank"><img class="ui mini image" src="/img/banner-qimen-4X3.jpg" style="width:100%;"></a>

<div class="ui secondary pointing menu">
<div class="active item">
推荐百科
</div>
</div>
<div class="ui relaxed list">
<div class="item">
<i class="sticky note outline icon"></i>
<div class="content">
<div ><a href="https://git.openi.org.cn/OpenI/aiforge/wiki">启智AI开发协同平台使用说明</a></div>
</div>
</div>
<div class="item">
<i class="sticky note outline icon"></i>
<div class="content">
<div ><a href="https://git.openi.org.cn/OpenI/Paddle/wiki">启智飞桨 Paddle 2.0 项目手册</a></div>
</div>
</div>
<div class="item">
<i class="sticky note outline icon"></i>
<div class="content">
<div ><a href="https://git.openi.org.cn/OpenI/aiforge/wiki/cloudbrain">启智社区使用云脑计算资源进行调试说明</a></div>
</div>
</div>
<div class="item">
<i class="sticky note outline icon"></i>
<div class="content">
<div ><a href="https://git.openi.org.cn/PCL-Federated.Learning.Middleware/HiStar/wiki">海星HiStar:联邦深度学习中间件帮助文档</a></div>
</div>
</div>
<div class="item">
<i class="sticky note outline icon"></i>
<div class="content">
<div ><a href="https://git.openi.org.cn/OpenI/octopus/wiki/启智章鱼">启智章鱼开源项目文档</a></div>
</div>
</div>
</div>

+ 7
- 2
templates/explore/repo_search.tmpl View File

@@ -1,12 +1,17 @@
<style>
.ui.green.button, .ui.green.buttons .button{
background-color: #5BB973;
}
</style>
<div class="repos--seach"> <div class="repos--seach">
<div class="ui container"> <div class="ui container">
<div class="ui two column centered grid"> <div class="ui two column centered grid">
<form class="mobile ten wide tablet computer column ui form ignore-dirty">
<form class="fourteen wide mobile ten wide tablet ten wide computer column ui form ignore-dirty" style="margin-top:1.2rem">
<div class="ui fluid action input"> <div class="ui fluid action input">
<input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search"}}..." autofocus> <input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search"}}..." autofocus>
<input type="hidden" name="tab" value="{{$.TabName}}"> <input type="hidden" name="tab" value="{{$.TabName}}">
<input type="hidden" name="sort" value="{{$.SortType}}"> <input type="hidden" name="sort" value="{{$.SortType}}">
<button class="ui blue button">{{.i18n.Tr "explore.search"}}</button>
<button class="ui green button">{{.i18n.Tr "explore.search"}}</button>
</div> </div>
</form> </form>
</div> </div>


+ 5
- 4
templates/explore/repos.tmpl View File

@@ -2,16 +2,17 @@
<div class="explore repositories"> <div class="explore repositories">


{{template "explore/repo_search" .}} {{template "explore/repo_search" .}}

{{template "explore/repo_orgtop" .}}
<div class="ui container"> <div class="ui container">
<div class="ui grid"> <div class="ui grid">
{{template "explore/navbar" .}}
{{template "explore/repo_left" .}}


<div class="ui sixteen wide mobile ten wide tablet ten wide computer column">
<div class="ui sixteen wide mobile twelve wide tablet ten wide computer column">
{{template "explore/repo_list" .}} {{template "explore/repo_list" .}}
{{template "base/paginate" .}} {{template "base/paginate" .}}
</div> </div>
<div class="ui sixteen wide mobile six wide tablet three wide computer column">
<div class="computer only ui three wide computer column">
{{template "explore/repo_right" .}} {{template "explore/repo_right" .}}
</div> </div>
</div> </div>


+ 11
- 2
templates/repo/cloudbrain/index.tmpl View File

@@ -2,6 +2,12 @@
{{template "base/head" .}} {{template "base/head" .}}


<style> <style>
.selectcloudbrain .active.item{
color: #0087f5 !important;
border: 1px solid #0087f5;
margin: -1px;
background: #FFF !important;
}
#deletemodel { #deletemodel {
width: 100%; width: 100%;
height: 100%; height: 100%;
@@ -210,8 +216,11 @@
</div> </div>
</div> </div>


<!-- 中间分割线 -->
<div class="ui divider"></div>
<p>使用鹏城云脑计算资源进行调试,云脑1提供CPU / GPU资源,云脑2提供Ascend NPU资源;调试使用的数据集也需要上传到对应的环境。</p>
<div class="ui blue mini menu selectcloudbrain">
<a class="active item" href="{{.RepoLink}}/cloudbrain">{{svg "octicon-server" 16}} CPU / GPU</a>
<a class="item" href="{{.RepoLink}}/modelarts">{{svg "octicon-server" 16}} Ascend NPU</a>
</div>


<!-- 中下列表展示区 --> <!-- 中下列表展示区 -->
<div class="ui grid"> <div class="ui grid">


+ 6
- 2
templates/repo/datasets/dataset_list.tmpl View File

@@ -23,9 +23,13 @@
</div> </div>


<div class="wide column one" style="{{if ne .DecompressState 1}}visibility: hidden;{{end}}"> <div class="wide column one" style="{{if ne .DecompressState 1}}visibility: hidden;{{end}}">
<a class="ui text center" href="datasets/dirs/{{.UUID}}" data-tooltip='{{$.i18n.Tr "dataset.directory"}}'>{{svg "octicon-file-directory" 16}}</a>
<a class="ui text center" href="datasets/dirs/{{.UUID}}?type={{$.Type}}" data-tooltip='{{$.i18n.Tr "dataset.directory"}}'>{{svg "octicon-file-directory" 16}}</a>
</div> </div>

{{if $.IsSigned}}
<div class="wide column one" style="{{if ne .DecompressState 1}}visibility: hidden;{{end}}">
<a class="ui text center" href="datasets/label/{{.UUID}}?type={{$.Type}}" data-tooltip='{{$.i18n.Tr "dataset.create_label_task"}}'><i class="fa fa-pencil-square-o" aria-hidden="true"></i></a>
</div>
{{end}}
{{if $.Permission.CanWrite $.UnitTypeDatasets}} {{if $.Permission.CanWrite $.UnitTypeDatasets}}
{{if $.Repository.IsPrivate}} {{if $.Repository.IsPrivate}}
<div class="two wide column"> <div class="two wide column">


+ 11
- 0
templates/repo/datasets/dirs/dir_list.tmpl View File

@@ -24,4 +24,15 @@
</tbody> </tbody>
</table> </table>


<table id="dataset-files-table" class="ui single line table">
</table>
<script src="{{StaticUrlPrefix}}/self/test.js"></script>


<script type="text/javascript">
displayDir({{$.Uuid}})
</script>


{{end}} {{end}}

+ 212
- 0
templates/repo/datasets/dirs/dir_preview.tmpl View File

@@ -0,0 +1,212 @@
{{if .Dirs}}

<style>
/* ul{
display: flex;;
position: absolute;
list-style: none;
transform: translate(-50%,-50%);
}
li{
position: relative;
padding: 20px;
color: #000;
line-height: 1;
transition: 0.2s all linear;
cursor: pointer;
}
li::before{
content: "";
position: absolute;

} */
ul,li{
list-style: none;
}
div#nav{
border: 1px solid #ccc;
}
div#nav ul{
border-bottom: 1px solid #ccc;
}
div#nav li{
position: relative;
display: inline-block;
line-height: 3em;
text-align: center;
width: 50%;
cursor: pointer;
transition: 0.2s all linear;
}
div.hide{
display: none;
}
div#nav li.active{
color: rgba(0,0,0,.85);
font-weight: 700;
opacity: 1;
border-bottom: 2px solid rgba(0,0,0,.85);
transition: 0.2s all linear;
}
/* div#nav li::before{
content: "";
position: absolute;
top: 0;
left: 100%;
width: 0;
height: 100%;
border-bottom: 2px solid #f000;
transition: 0.2s all linear;

}
.active ~ li::before{
left: 0;
}
.active::before{
width: 100%;
left: 0;
top: 0;
}
.hover::before{
width: 50%;
} */
</style>
<div id="uuid_div" style="display: none">
<input type="" value="{{$.Uuid}}" id="hide_uuidid" style="display:none;">
</div>
<div id="myCanvas_div" style="width:100%;height:100% ; position: relative;">
<!-- <div style="display:inline-block; width:6%;height: 100%; position: relative; vertical-align: middle;">
<img src="/img/left_new_new.png" onclick="clickLast()" style="margin-left: 15px" />
</div> -->

<div style="display:inline-block; width:71%; height: 100%; position: relative;border: 1px solid #ccc;border-radius: 6px;">
<!-- <div style="text-align:center">
<a>
文件名:
<span id="filename"></span>
</a>
</div> -->

<div id="win_canvas" style="width:100%;height:42em">
<canvas id="myCanvas" style="display:none;">
</canvas>
<code id="textcontent" style="display:none;overflow: auto;">这是一个测试。</code>
<div style="padding:0.2em 0;position: absolute;border-top: 1px solid #ccc;width: 100%;bottom:0;font-size: 1em;padding: 0.5em 1em;">
<div id="breadFile" class="ui small breadcrumb">
<!-- <div class="section">Home</div>
<div class="divider"> / </div>
<div class="active section">Search</div> -->
</div>
</div>


</div>

<div style="font-size: 1.5rem; opacity: 0.7; position: absolute;left: 0.5rem;top: 20rem;cursor: pointer;" onclick="clickLast()"><i class="chevron circle left icon" ></i></div>
<div style="font-size: 1.5rem; opacity: 0.7; position: absolute;right: 0.5rem;top: 20rem;cursor: pointer;" onclick="clickNext()"><i class="chevron circle right icon" ></i></div>
</div>

<!-- <div style="display:inline-block; width:6%;height: 100%; position: relative; vertical-align: middle;">
<img src="/img/right_new_new.png" onclick="clickNext()" style="margin-left: 15px"/>
</div> -->
<div id="nav" style="display:inline-block; width:25%;height: 100%; position: relative;vertical-align: top; background: #ffffff;margin-left: 20px;border-radius: 6px;">
<ul style="display: flex;padding: 0;margin: 0;">
<li id="0" class="active">文件列表</li>

<li id="1">标签列表</li>
</ul>
<div class="tabpannel">
<!-- <h4 class="ui top attached header">
文件列表
</h4> -->
<!-- <table class="ui single line table" id="filelist" style="table-layout:fixed;word-break: break-all;word-wrap: break-word;">
</table> -->
<div class="ui list" id="filelist"></div>


<div class="panel-body" id="filepanel" style='position: absolute;bottom: 0;padding: 0.9em 0;width: 100%;border-top: 1px #ccc solid;'>
<div style="width: 90%; margin: 0 auto;">
<a id="prePage" href="" style="margin-right: 0.2em;color: #000;"><i class="angle left icon"></i></a>
<span id="startIndex">0</span>-<span id="endIndex">0</span>/<span id="totalNum">0</span>
<span style="margin-left: 0.2em;">第</span><span id="displayPage1">1</span><span style="margin-right: 0.2em;">页</span>
<span>跳到</span><input type="text" id="goNum" style="width: 2em;border-radius: 4px;padding: 0 0.4em;margin: 0 0.4em;height: 1.2em;border: 1px solid;" maxlength="5" oninput="value=value.replace(/[^\d]/g,'')"><span>页</span>

<a style="margin-left: 0.4em;color: #000;" id="nextPage" href=""><i class="angle right icon"></i></a>
<!-- 第<span id="startIndex">0</span>至<span id="endIndex">0</span>条,&nbsp;共<span id="totalNum">0</span>条.&nbsp;&nbsp;
<span >
<span >
&nbsp;当前页:<span id="displayPage1">1</span>&nbsp;
</span>
<a id="nextPage" href="">下一页</a>
<span>
&nbsp;共<span id="totalPageNum"></span>页&nbsp;
</span>
</span>
<span>&nbsp;跳转至:<input type="text" id="goNum" style="width: 50px;border-radius: 6px" maxlength="5" oninput="value=value.replace(/[^\d]/g,'')"><a id="goHref" href="javascript:goPage()">&nbsp;GO</a></span> -->
</div>
</div>
</div>
<div class="hide tabpannel">
<div style="margin-top: 1em;" id="labellist">

</div>

</div>
<!-- <div class="ui pointing secondary menu">
<a class="item " data-tab="first">First</a>
<a class="item active" data-tab="second">Second</a>
</div>

<div class="ui bottom attached tab segment active" data-tab="first">
First
</div>
<div class="ui bottom attached tab segment" data-tab="second">
Second
</div>
-->

</div>
</div>
<script>
var ulObj = document.getElementById('nav').getElementsByTagName('ul')[0];
var divObj = document.getElementsByClassName('tabpannel');
var liObj = document.getElementById('nav').getElementsByTagName('li')
ulObj.onclick = function(event){
var ev = window.event || event;
var item = ev.srcElement || ev.target;

var id = item.getAttribute("id")
for (var i=0; i<divObj.length;i++){
if(i == id){
divObj[i].style.display = 'block'
liObj[i].classList.add('active')
}
else{
divObj[i].style.display = 'none'
liObj[i].classList.remove('active')
}
}
}
</script>
<script src="{{StaticUrlPrefix}}/self/dataset_preview.js"></script>
{{end}}

+ 29
- 20
templates/repo/datasets/dirs/index.tmpl View File

@@ -1,29 +1,38 @@
{{template "base/head" .}}
<div class="repository dataset dir-list view">
{{template "repo/header" .}}
<form class="ui container">
<div class="ui stackable grid {{if .Error}}hide{{end}}" id="dir-content">
<div class="row">
<div class="column sixteen wide">
<p>
{{ range $index, $item := .Path }}<a href='{{$.Link}}/?parentDir={{if gt $index 0}}{{DatasetPathJoin $.Path $index "/"}}{{else}}{{end}}'>{{ $item }}</a><span class="directory-seperator">/</span>{{ end }}
</p>
<style>
form {margin-block-end: 0;}
</style>
<div style="background:#fff">
{{template "base/head" .}}
<div class="repository dataset dir-list view">
{{template "repo/header" .}}
<div>
<form class="ui container">
<div class="ui stackable grid {{if .Error}}hide{{end}}" id="dir-content">
<div class="row">
<div class="column sixteen wide">
<div class="ui breadcrumb">
{{ range $index, $item := .Path }}<a class="section" href='{{$.Link}}/?parentDir={{if gt $index 0}}{{DatasetPathJoin $.Path $index "/"}}{{else}}{{end}}'>{{ $item }}</a><div class="divider"> / </div>{{ end }}
</div>
</div>
</div>
</div> </div>
</div>
</div>

<div class="ui grid">
<div class="row">
<div class="ui sixteen wide column">
<div class="dir list">
{{template "repo/datasets/dirs/dir_list" .}}
<div class="ui grid">
<div class="row" style="padding-top: 0.5rem;padding-bottom: 0;">
<div class="ui sixteen wide column">
<div class="dir list">
{{template "repo/datasets/dirs/dir_preview" .}}
</div>
</div>
</div> </div>
</div> </div>
</div>
</form>
</div> </div>
</form>
</div>
</div> </div>







{{template "base/footer" .}} {{template "base/footer" .}}

+ 13
- 1
templates/repo/datasets/index.tmpl View File

@@ -1,4 +1,12 @@
{{template "base/head" .}} {{template "base/head" .}}
<style>
.selectcloudbrain .active.item{
color: #0087f5 !important;
border: 1px solid #0087f5;
margin: -1px;
background: #FFF !important;
}
</style>
<div class="repository release dataset-list view"> <div class="repository release dataset-list view">
{{template "repo/header" .}} {{template "repo/header" .}}
<script> <script>
@@ -62,7 +70,11 @@
</div> </div>
</div> </div>


<div class="ui divider"></div>
<div class="ui blue mini menu selectcloudbrain">
<a class="{{if eq .Type 0}}active {{end}}item" href="{{.RepoLink}}/datasets?type=0">{{svg "octicon-server" 16}} CPU / GPU</a>
<a class="{{if eq .Type 1}}active {{end}}item" href="{{.RepoLink}}/datasets?type=1">{{svg "octicon-server" 16}} Ascend NPU</a>
</div>
<div class="ui stackable grid"> <div class="ui stackable grid">
<div class="twelve wide column"> <div class="twelve wide column">
<div class="ui sixteen wide column"> <div class="ui sixteen wide column">


+ 209
- 0
templates/repo/datasets/label/index.tmpl View File

@@ -0,0 +1,209 @@
{{template "base/head" .}}

<style>
#progress{
width: 100%;
height: 20px;
background: rgb(255, 255, 255);
}
#bar{
width: 1%;
height: 20px;
margin-top: 1px;
background: green;
}
</style>

<div class="repository dataset dir-list view">
{{template "repo/header" .}}
<input type="hidden" id="repoId" value="{{.repoId}}">
<div class="ui container">
<div class="header">
<h3 class="modal-title">人工标注任务列表</h3>
</div>
<div class="ui container">
<div class="ui container">
<table class="ui celled table" id="label_task_list"></table>

<div class="ui container" style="height: 30px;">
<div style="float:right">
显示<span id="startIndex">0</span>到<span id="endIndex">0</span>条,共<span id="totalNum">0</span>条。&nbsp;&nbsp;
<span >
<a id="prePage" href=""><b>上一页</b></a>
<span >
&nbsp;当前页:<span id="displayPage1">1</span>&nbsp;
</span>
<a id="nextPage" href=""><b>下一页</b></a>
<span>
&nbsp;共<span id="totalPageNum"></span>页&nbsp;
</span>
<span>&nbsp;跳转到:<input type="text" id="goNum" style="width: 50px;border-radius:6px" maxlength="5" oninput="value=value.replace(/[^\d]/g,'')"><a id="goHref" href="javascript:goPage()">&nbsp;GO</a></span>
</span>
</div>
</div>

<div class="ui container" style="height: 30px;">
<!-- <button type="button" onclick="setPredictTask();" class="ui blue button" style="float:left">新建自动标注结果图片标注</button> -->
<button type="button" onclick="setDataSetTask();" class="ui blue button" style="float:left">新建数据集图片标注</button>
<button type="button" onclick="setMultiTaskId();" class="ui blue button" style="float:right;margin-left:20px;">导出标注数据</button>
<button type="button" onclick="countLabel();" class="ui blue button" style="float:right;margin-left:20px;">统计所有标注数量</button>
<button type="button" onclick="delete_labeltask();" class="ui blue button" style="float:right">删除人工标注</button>
</div>


<!-- 增加新建数据集人工标注-->
<div id="labelDataModal" class="ui dataset modal">
<i class="close icon"></i>
<div class="header">
<h4 class="modal-title">新建数据集图片标注</h4>
</div>
<div class="content">
<div class="ui form">
<div class="field">
<label for="exampleInputPassword1">选择数据集对象<font color=red>*</font></label>
<select name="pre_predict_task" id="dataset_list" onchange="dataset_sele_Change(this)">
<option value="" selected="">请选择</option>
</select>
</div>

<div class="field" >
<label for="exampleInputEmail1">人工标注任务名称<font color=red>*</font></label>
<input type="text" id="datasetlabeltaskname" placeholder="标注任务名称,不超过32个字符">
</div>
<div class="field" style="display:none">
<label for="exampleInputEmail2">任务指派给</label>
<select name="任务指派给" id="assign_user">
<option value="">请选择</option>
</select>
</div>
<div class="field" >
<label for="exampleInputEmail2">模式</label>
<select name="模式" id="task_flow_type" onchange="flow_type_sele_Change(this)">
<option value="1" select="true"> 标注工作模式</option>
<!-- <option value="2"> 标注审核模式</option>
<option value="3"> 主动分类学习模式</option> -->
</select>
</div>
<div class="field" style="display:none">
<label id = "labelInfo" for="exampleInputFile">标注类别(也可以直接在标注界面上进行设置)</label>
<select name="labelpropertytask" id="labelpropertytask_dataset" >
<option value="" selected="">请选择</option>
</select>
</div>
<button type="button" onclick="submit_datasettask();">提交</button>
</div>
</div>
</div> <!-- /.box-body -->

<div id="labelModal" class="ui predict modal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button aria-hidden="true" data-dismiss="modal" class="close" type="button">×</button>
<h4 class="modal-title">新建自动标注结果人工标注</h4>
</div>
<div class="modal-body">
<div class="form-group">
<label for="exampleInputPassword1">关联的自动标注任务<font color=red>*</font></label>
<select class="form-control" name="pre_predict_task" id="pre_predict_task_for_label" onchange="sele_Change(this)">
<option value="" selected="">请选择</option>
</select>
<!-- <input type="" class="form-control" id="prepredtaskid" placeholder="预检任务"> -->
</div>
<div class="form-group" >
<label for="exampleInputEmail2">任务指派给</label>
<select class="form-control" name="任务指派给" id="label_assign_user">
<option value=""> 请选择</option>
</select>
</div>
<div class="form-group">
<label for="exampleInputEmail1">人工标注任务名称<font color=red>*</font></label>
<input type="" class="form-control" id="labeltaskname" placeholder="校验标注任务名称,不超过32个字符" maxlength="32">
</div>
<div class="form-group">
<label id = "labelInfo" for="exampleInputFile">标注类别属性,请输入符合格式Json字符串 </label>
<select class="form-control" name="labelpropertytask" id="labelpropertytask_auto">
<option value="" selected="">请选择</option>
</select>
</div>
<button type="button" onclick="submit_labeltask();">提交</button>
</div>
</div>
</div>
</div> <!-- /.box-body -->
<div id="labeltaskexport" class="ui export modal">
<i class="close icon"></i>
<div class="header">
<h4 class="modal-title">导出标注数据</h4>
</div>
<div class="content">
<div class="ui form">
<input type="" value="" id="hide_labeltaskid" style="display:none;">
<div class="field">
<label for="exampleInputPassword1">是否带图片导出<font color=red>*</font></label>
<select class="form-control" name="是否带图片导出" id="isNeedPicture" onchange="sele_export_Change(this)">
<option value="1" selected="">不带图片导出</option>
<option value="2">带图片导出</option>
<option value="3">导出所有标注抠图</option>
</select>
</div>
<div class="field">
<label for="exampleInputPassword1">选择标注导出格式<font color=red>*</font></label>
<select class="form-control" id="exportFormat">
<option value="1" selected="">COCO</option>
<option value="2">VOC</option>
</select>
</div>
<div class="field" id="maxscore_div" style="display:none;">
<label for="exampleInputEmail1">标注得分最大值(0--1.0),目标检测得分大于此值时,不导出</label>
<input type="" class="form-control" id="maxscore" placeholder="标注得分最大值(0--1.0),当目标检测得分大于此值时,不导出。" maxlength="10">
</div>
<div class="field" id="minscore_div" style="display:none;">
<label for="exampleInputEmail1">标注得分最小值(0--0.99),目标检测得分小于此值时,不导出</label>
<input type="" class="form-control" id="minscore" placeholder="标注得分最小值(0--0.99),当目标检测得分小于此值时,不导出。" maxlength="10">
</div>
<div class="field" id="progress">
<div id="bar"></div>
</div>
<div class="field"><h5 id="text-progress">0%</h3></div>
<div class="field">
<button id="predtask_id" type="button" class="btn btn-default" onclick="downloadFile();">提交</button>
</div>
</div>
</div>
</div>
</div><!-- /.box-body -->
</div>
<!-- </div> -->
</div><!-- /.box -->
</div>



<script src="/self/labelTaskPage.js"></script>

{{template "base/footer" .}}

+ 2
- 4
templates/repo/header.tmpl View File

@@ -98,9 +98,8 @@
{{end}} {{end}}


{{if .Permission.CanRead $.UnitTypeDatasets}} {{if .Permission.CanRead $.UnitTypeDatasets}}
<a class="{{if .PageIsDataset}}active{{end}} item dataset" >
<a class="{{if .PageIsDataset}}active{{end}} item" href="{{.RepoLink}}/datasets?type=0">
{{svg "octicon-inbox" 16}} {{.i18n.Tr "datasets"}} {{svg "octicon-inbox" 16}} {{.i18n.Tr "datasets"}}
<span style="display:none" class="dataset_link">{{.RepoLink}}</span>
</a> </a>
{{end}} {{end}}


@@ -141,9 +140,8 @@
{{end}} {{end}}


{{if .Permission.CanRead $.UnitTypeCloudBrain}} {{if .Permission.CanRead $.UnitTypeCloudBrain}}
<a class="{{if .PageIsCloudBrain}}active{{end}} item cloudbrain">
<a class="{{if .PageIsCloudBrain}}active{{end}} item" href="{{.RepoLink}}/cloudbrain">
{{svg "octicon-server" 16}} {{.i18n.Tr "repo.cloudbrain"}} {{svg "octicon-server" 16}} {{.i18n.Tr "repo.cloudbrain"}}
<span style="display:none" class="cloudbrain_link">{{.RepoLink}}</span>
</a> </a>
{{end}} {{end}}




+ 11
- 2
templates/repo/modelarts/index.tmpl View File

@@ -2,6 +2,12 @@
{{template "base/head" .}} {{template "base/head" .}}


<style> <style>
.selectcloudbrain .active.item{
color: #0087f5 !important;
border: 1px solid #0087f5;
margin: -1px;
background: #FFF !important;
}
#deletemodel { #deletemodel {
width: 100%; width: 100%;
height: 100%; height: 100%;
@@ -210,8 +216,11 @@
</div> </div>
</div> </div>


<!-- 中间分割线 -->
<div class="ui divider"></div>
<p>使用鹏城云脑计算资源进行调试,云脑1提供CPU / GPU资源,云脑2提供Ascend NPU资源;调试使用的数据集也需要上传到对应的环境。</p>
<div class="ui blue mini menu selectcloudbrain">
<a class="item" href="{{.RepoLink}}/cloudbrain">{{svg "octicon-server" 16}} CPU / GPU</a>
<a class="active item" href="{{.RepoLink}}/modelarts">{{svg "octicon-server" 16}} Ascend NPU</a>
</div>


<!-- 中下列表展示区 --> <!-- 中下列表展示区 -->
<div class="ui grid"> <div class="ui grid">


+ 24
- 4
templates/repo/modelarts/new.tmpl View File

@@ -112,14 +112,15 @@
<input name="job_name" id="cloudbrain_job_name" placeholder="任务名称" value="{{.job_name}}" tabindex="3" autofocus required maxlength="255"> <input name="job_name" id="cloudbrain_job_name" placeholder="任务名称" value="{{.job_name}}" tabindex="3" autofocus required maxlength="255">
</div> </div>


<div class="inline required field">
<div class="inline field">
<label>数据集</label> <label>数据集</label>
<select id="cloudbrain_dataset" class="ui search dropdown" placeholder="选择数据集" style='width:385px' name="attachment">
<input type="text" list="cloudbrain_dataset" placeholder="选择数据集" name="" id="answerInput" autofocus maxlength="36">
<datalist id="cloudbrain_dataset" class="ui search" style='width:385px' name="attachment">
{{range .attachments}} {{range .attachments}}
<option name="attachment" value="{{.UUID}}">{{.Attachment.Name}}</option> <option name="attachment" value="{{.UUID}}">{{.Attachment.Name}}</option>

{{end}} {{end}}
</select>
</datalist>
<input type="hidden" name="attachment" id="answerInput-hidden">
</div> </div>


<div class="inline required field"> <div class="inline required field">
@@ -186,4 +187,23 @@
} }
}) })
}) })
document.querySelector('input[list]').addEventListener('input',function(e){
var input = e.target,
list = input.getAttribute('list'),
options = document.querySelectorAll('#'+list+' option'),
hiddenInput = document.getElementById(input.getAttribute('id')+'-hidden'),
inputValue = input.value;
hiddenInput.value = inputValue;
for (let i=0;i<options.length;i++){
var option = options[i]
if(option.innerText===inputValue){
hiddenInput.value = option.getAttribute('data-value');
break
}
}


})
</script> </script>

+ 1
- 0
web_src/js/components/MinioUploader.vue View File

@@ -11,6 +11,7 @@
{{ file_status_text }} {{ file_status_text }}
<span class="success">{{ status }}</span> <span class="success">{{ status }}</span>
</p> </p>
<p>云脑1提供 <span class="text blue">CPU / GPU</span> 资源,云脑2提供 <span class="text blue">Ascend NPU</span> 资源;调试使用的数据集也需要上传到对应的环境。</p>
</div> </div>
</template> </template>




+ 1
- 0
web_src/js/components/ObsUploader.vue View File

@@ -8,6 +8,7 @@
{{ file_status_text }} {{ file_status_text }}
<span class="success">{{ status }}</span> <span class="success">{{ status }}</span>
</p> </p>
<p>云脑1提供 <span class="text blue">CPU / GPU</span> 资源,云脑2提供 <span class="text blue">Ascend NPU</span> 资源;调试使用的数据集也需要上传到对应的环境。</p>
</div> </div>
</template> </template>




+ 2
- 6
web_src/js/index.js View File

@@ -4113,11 +4113,7 @@ function initTopicbar() {
$.fn.form.settings.rules.validateTopic = function (_values, regExp) { $.fn.form.settings.rules.validateTopic = function (_values, regExp) {
const topics = topicDropdown.children('a.ui.label'); const topics = topicDropdown.children('a.ui.label');
const status = const status =
topics.length === 0 ||
topics
.last()
.attr('data-value')
.match(regExp);
topics.length === 0 || (topics.last().attr('data-value').match(regExp) !== null && topics.last().attr('data-value').length <= 35);
if (!status) { if (!status) {
topics topics
.last() .last()
@@ -4136,7 +4132,7 @@ function initTopicbar() {
rules: [ rules: [
{ {
type: 'validateTopic', type: 'validateTopic',
value: /^[a-z0-9][a-z0-9-]{0,35}$/,
value: /^[\u4e00-\u9fa5a-z0-9][\u4e00-\u9fa5a-z0-9-]{0,105}$/,
prompt: topicPrompts.formatPrompt prompt: topicPrompts.formatPrompt
}, },
{ {


+ 1
- 1
web_src/less/_repository.less View File

@@ -2685,7 +2685,7 @@ tbody.commit-list {
width: 1127px; width: 1127px;
} }
th .message-wrapper { th .message-wrapper {
max-width: 510px;
max-width: 400px;
} }
} }




+ 5
- 8
web_src/less/openi.less View File

@@ -168,15 +168,12 @@ footer .column{margin-bottom:0!important; padding-bottom:0!important;}
.ui.repository.list .item .ui.header .metas{ .ui.repository.list .item .ui.header .metas{
text-align: right; text-align: right;
} }
@media only screen and (max-width:768px){
.explore .repos--seach{
margin-bottom:15px;
}
.explore .navbar{
padding-top: 0px!important;
margin-top: -1.5rem!important;
}
@media only screen and (max-width:767.98px){
.explore .repository.list .ui.right.menu{
float: none;
}
} }

/*organization*/ /*organization*/
.organization-info{ .organization-info{
padding-top:15px; padding-top:15px;


Loading…
Cancel
Save