Browse Source

Merge branch 'V20220328' of git.openi.org.cn:OpenI/aiforge into cb-train

tags/v1.22.3.2^2
lewis 3 years ago
parent
commit
e0aadf0132
31 changed files with 4167 additions and 160 deletions
  1. +0
    -70
      custom/public/css/git.openi.css
  2. +22
    -2
      models/cloudbrain.go
  3. +186
    -0
      models/dbsql/dataset_foreigntable_for_es.sql
  4. +215
    -0
      models/dbsql/issue_foreigntable_for_es.sql
  5. +532
    -0
      models/dbsql/repo_foreigntable_for_es.sql
  6. +308
    -0
      models/dbsql/user_foreigntable_for_es.sql
  7. +1
    -0
      models/models.go
  8. +2
    -1
      models/repo.go
  9. +7
    -3
      models/repo_list.go
  10. +83
    -0
      models/search_record.go
  11. +2
    -1
      modules/setting/setting.go
  12. +12
    -0
      options/locale/locale_en-US.ini
  13. +12
    -0
      options/locale/locale_zh-CN.ini
  14. +1281
    -0
      public/home/search.js
  15. +3
    -3
      public/self/dataset_preview.js
  16. +3
    -12
      routers/api/v1/repo/cloudbrain.go
  17. +2
    -0
      routers/init.go
  18. +27
    -34
      routers/repo/cloudbrain.go
  19. +3
    -0
      routers/routes/routes.go
  20. +1190
    -0
      routers/search.go
  21. +4
    -4
      templates/base/head_navbar.tmpl
  22. +4
    -4
      templates/base/head_navbar_fluid.tmpl
  23. +4
    -4
      templates/base/head_navbar_pro.tmpl
  24. +95
    -0
      templates/explore/search_new.tmpl
  25. +14
    -2
      templates/repo/cloudbrain/benchmark/show.tmpl
  26. +10
    -2
      templates/repo/cloudbrain/show.tmpl
  27. +16
    -14
      templates/repo/cloudbrain/trainjob/new.tmpl
  28. +1
    -1
      templates/repo/editor/upload.tmpl
  29. +7
    -1
      templates/repo/modelarts/inferencejob/show.tmpl
  30. +12
    -2
      templates/repo/modelarts/trainjob/show.tmpl
  31. +109
    -0
      web_src/less/openi.less

+ 0
- 70
custom/public/css/git.openi.css View File

@@ -44,12 +44,6 @@
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
.ui.label{
font-weight: normal;
}
.active {
color: #0366D6 !important;
}

.opacity5{ opacity:0.5;}
.radius15{ border-radius:1.5rem !important; }
@@ -287,70 +281,6 @@
position: relative;
}

/**seach**/
/**搜索导航条适配窄屏**/
.seachnav{
overflow-x: auto;
overflow-y: hidden;
scrollbar-width: none; /* firefox */
-ms-overflow-style: none; /* IE 10+ */
}
.seachnav::-webkit-scrollbar {
display: none; /* Chrome Safari */
}
.ui.green.button, .ui.green.buttons .button{
background-color: #5BB973;
}
.seach .repos--seach{
padding-bottom: 0;
border-bottom: none;
}
.seach .ui.secondary.pointing.menu{
border-bottom: none;
}
.seach .ui.secondary.pointing.menu .item > i{
margin-right: 5px;
}
.seach .ui.secondary.pointing.menu .active.item{
border-bottom-width: 2px;
margin: 0 0 -1px;
}
.seach .ui.menu .active.item>.label {
background: #1684FC;
color: #FFF;
}
.seach .ui.menu .item>.label:not(.active.item>.label) {
background: #e8e8e8;
color: rgba(0,0,0,.6);
}

.highlight{
color: red;
}
.ui.list .list>.item>img.image+.content, .ui.list>.item>img.image+.content {
width: calc(100% - 3.0em);
margin-left: 0;
}

.seach .ui.list .list>.item .header, .seach .ui.list>.item .header{
margin-bottom: 0.5em;
font-size: 1.4rem !important;
font-weight: normal;
}
.seach .time, .seach .time a{
font-size: 12px;
color: grey;
}

.seach .list .item.members .ui.avatar.image {
width: 3.2em;
height: 3.2em;
}
.ui.list .list>.item.members>img.image+.content, .ui.list>.item.members>img.image+.content {
width: calc(100% - 4.0em);
margin-left: 0;
}

@media only screen and (max-width: 767px) {
.am-mt-30{ margin-top: 1.5rem !important;}
.ui.secondary.hometop.segment{


+ 22
- 2
models/cloudbrain.go View File

@@ -170,7 +170,9 @@ func (task *Cloudbrain) ComputeAndSetDuration() {
if task.StartTime == 0 {
d = 0
} else if task.EndTime == 0 {
d = time.Now().Unix() - task.StartTime.AsTime().Unix()
if !task.IsTerminal() {
d = time.Now().Unix() - task.StartTime.AsTime().Unix()
}
} else {
d = task.EndTime.AsTime().Unix() - task.StartTime.AsTime().Unix()
}
@@ -182,6 +184,11 @@ func (task *Cloudbrain) ComputeAndSetDuration() {
task.TrainJobDuration = ConvertDurationToStr(d)
}

func (task *Cloudbrain) IsTerminal() bool {
status := task.Status
return status == string(ModelArtsTrainJobCompleted) || status == string(ModelArtsTrainJobFailed) || status == string(ModelArtsTrainJobKilled) || status == string(ModelArtsStopped) || status == string(JobStopped) || status == string(JobFailed) || status == string(JobSucceeded)
}

func ConvertDurationToStr(duration int64) string {
if duration == 0 {
return DURATION_STR_ZERO
@@ -201,6 +208,19 @@ func IsCloudBrainOneDebugJobTerminal(status string) bool {
return status == string(JobStopped) || status == string(JobFailed) || status == string(JobSucceeded)
}

func ParseAndSetDurationFromCloudBrainOne(result JobResultPayload, task *Cloudbrain) {
isActivated := result.JobStatus.CreatedTime > 0
if task.StartTime == 0 && isActivated {
task.StartTime = timeutil.TimeStamp(result.JobStatus.CreatedTime / 1000)
}
if task.EndTime == 0 && IsCloudBrainOneDebugJobTerminal(task.Status) && isActivated {
if result.JobStatus.CompletedTime > 0 {
task.EndTime = timeutil.TimeStamp(result.JobStatus.CompletedTime / 1000)
}
}
task.ComputeAndSetDuration()
}

type CloudbrainInfo struct {
Cloudbrain `xorm:"extends"`
User `xorm:"extends"`
@@ -368,7 +388,7 @@ type JobResultPayload struct {
AppProgress string `json:"appProgress"`
AppTrackingURL string `json:"appTrackingUrl"`
AppLaunchedTime int64 `json:"appLaunchedTime"`
AppCompletedTime interface{} `json:"appCompletedTime"`
AppCompletedTime int64 `json:"appCompletedTime"`
AppExitCode int `json:"appExitCode"`
AppExitDiagnostics string `json:"appExitDiagnostics"`
AppExitType interface{} `json:"appExitType"`


+ 186
- 0
models/dbsql/dataset_foreigntable_for_es.sql View File

@@ -0,0 +1,186 @@
DROP FOREIGN TABLE public.dataset_es;
CREATE FOREIGN TABLE public.dataset_es
(
id bigint NOT NULL,
title character varying(255),
status integer,
category character varying(255),
description text,
download_times bigint,
license character varying(255),
task character varying(255),
release_id bigint,
user_id bigint,
repo_id bigint,
created_unix bigint,
updated_unix bigint,
file_name text,
file_desc text
)SERVER multicorn_es
OPTIONS
(
host '192.168.207.94',
port '9200',
index 'dataset-es-index',
rowid_column 'id',
default_sort '_id'
)
;
DELETE FROM public.dataset_es;
INSERT INTO public.dataset_es(
id,
title,
status,
category,
description,
download_times,
license, task,
release_id,
user_id,
repo_id,
created_unix,
updated_unix,
file_name,
file_desc
)
SELECT
b.id,
b.title,
b.status,
b.category,
b.description,
b.download_times,
b.license,
b.task,
b.release_id,
b.user_id,
b.repo_id,
b.created_unix,
b.updated_unix,
(select array_to_string(array_agg(name order by created_unix desc),'-#,#-') from public.attachment a where a.dataset_id=b.id and a.is_private=false),
(select array_to_string(array_agg(description order by created_unix desc),'-#,#-') from public.attachment a where a.dataset_id=b.id and a.is_private=false)
FROM public.dataset b,public.repository c where b.repo_id=c.id and c.is_private=false;


DROP TRIGGER IF EXISTS es_insert_dataset on public.dataset;

CREATE OR REPLACE FUNCTION public.insert_dataset_data() RETURNS trigger AS
$def$
DECLARE
privateValue boolean=false;
BEGIN
select into privateValue is_private from public.repository where id=NEW.repo_id;
if not privateValue then
INSERT INTO public.dataset_es(
id,
title,
status,
category,
description,
download_times,
license,
task,
release_id,
user_id,
repo_id,
created_unix,
updated_unix)
VALUES (
NEW.id,
NEW.title,
NEW.status,
NEW.category,
NEW.description,
NEW.download_times,
NEW.license,
NEW.task,
NEW.release_id,
NEW.user_id,
NEW.repo_id,
NEW.created_unix,
NEW.updated_unix
);
end if;
RETURN NEW;
END;
$def$
LANGUAGE plpgsql;



CREATE TRIGGER es_insert_dataset
AFTER INSERT ON public.dataset
FOR EACH ROW EXECUTE PROCEDURE insert_dataset_data();

ALTER TABLE public.dataset ENABLE ALWAYS TRIGGER es_insert_dataset;


DROP TRIGGER IF EXISTS es_udpate_dataset_file_name on public.attachment;

CREATE OR REPLACE FUNCTION public.udpate_dataset_file_name() RETURNS trigger AS
$def$
BEGIN
if (TG_OP = 'UPDATE') then
update public.dataset_es SET file_desc=(select array_to_string(array_agg(description order by created_unix desc),'-#,#-') from public.attachment where dataset_id=NEW.dataset_id and is_private=false) where id=NEW.dataset_id;
elsif (TG_OP = 'INSERT') then
update public.dataset_es SET file_name=(select array_to_string(array_agg(name order by created_unix desc),'-#,#-') from public.attachment where dataset_id=NEW.dataset_id and is_private=false) where id=NEW.dataset_id;
elsif (TG_OP = 'DELETE') then
update public.dataset_es SET file_name=(select array_to_string(array_agg(name order by created_unix desc),'-#,#-') from public.attachment where dataset_id=OLD.dataset_id and is_private=false) where id=OLD.dataset_id;
update public.dataset_es SET file_desc=(select array_to_string(array_agg(description order by created_unix desc),'-#,#-') from public.attachment where dataset_id=OLD.dataset_id and is_private=false) where id=OLD.dataset_id;
end if;
return NEW;
END;
$def$
LANGUAGE plpgsql;


CREATE TRIGGER es_udpate_dataset_file_name
AFTER INSERT OR UPDATE OR DELETE ON public.attachment
FOR EACH ROW EXECUTE PROCEDURE udpate_dataset_file_name();

ALTER TABLE public.attachment ENABLE ALWAYS TRIGGER es_udpate_dataset_file_name;

DROP TRIGGER IF EXISTS es_update_dataset on public.dataset;

CREATE OR REPLACE FUNCTION public.update_dataset() RETURNS trigger AS
$def$
BEGIN
UPDATE public.dataset_es
SET description=NEW.description,
title=NEW.title,
category=NEW.category,
task=NEW.task,
download_times=NEW.download_times,
updated_unix=NEW.updated_unix,
file_name=(select array_to_string(array_agg(name order by created_unix desc),'-#,#-') from public.attachment where dataset_id=NEW.id and is_private=false),
file_desc=(select array_to_string(array_agg(description order by created_unix desc),'-#,#-') from public.attachment where dataset_id=NEW.id and is_private=false)
where id=NEW.id;
return new;
END
$def$
LANGUAGE plpgsql;

CREATE TRIGGER es_update_dataset
AFTER UPDATE ON public.dataset
FOR EACH ROW EXECUTE PROCEDURE update_dataset();

ALTER TABLE public.dataset ENABLE ALWAYS TRIGGER es_update_dataset;

DROP TRIGGER IF EXISTS es_delete_dataset on public.dataset;

CREATE OR REPLACE FUNCTION public.delete_dataset() RETURNS trigger AS
$def$
declare
BEGIN
DELETE FROM public.dataset_es where id=OLD.id;
return new;
END
$def$
LANGUAGE plpgsql;


CREATE TRIGGER es_delete_dataset
AFTER DELETE ON public.dataset
FOR EACH ROW EXECUTE PROCEDURE delete_dataset();

ALTER TABLE public.dataset ENABLE ALWAYS TRIGGER es_delete_dataset;

+ 215
- 0
models/dbsql/issue_foreigntable_for_es.sql View File

@@ -0,0 +1,215 @@
DROP FOREIGN TABLE public.issue_es;
CREATE FOREIGN TABLE public.issue_es
(
id bigint NOT NULL,
repo_id bigint,
index bigint,
poster_id bigint,
original_author character varying(255),
original_author_id bigint,
name character varying(255) ,
content text,
comment text,
milestone_id bigint,
priority integer,
is_closed boolean,
is_pull boolean,
pr_id bigint,
num_comments integer,
ref character varying(255),
deadline_unix bigint,
created_unix bigint,
updated_unix bigint,
closed_unix bigint,
is_locked boolean NOT NULL,
amount bigint,
is_transformed boolean NOT NULL
)SERVER multicorn_es
OPTIONS
(
host '192.168.207.94',
port '9200',
index 'issue-es-index',
rowid_column 'id',
default_sort '_id'
)
;

delete from public.issue_es;
INSERT INTO public.issue_es(
id,
repo_id,
index,
poster_id,
original_author,
original_author_id,
name,
content,
milestone_id,
priority,
is_closed,
is_pull,
num_comments,
ref,
deadline_unix,
created_unix,
updated_unix,
closed_unix,
is_locked,
amount,
is_transformed,comment,pr_id)
SELECT
b.id,
b.repo_id,
b.index,
b.poster_id,
b.original_author,
b.original_author_id,
b.name,
b.content,
b.milestone_id,
b.priority,
b.is_closed,
b.is_pull,
b.num_comments,
b.ref,
b.deadline_unix,
b.created_unix,
b.updated_unix,
b.closed_unix,
b.is_locked,
b.amount,
b.is_transformed,
(select array_to_string(array_agg(content order by created_unix desc),',') from public.comment a where a.issue_id=b.id),
(select id from public.pull_request d where b.id=d.issue_id and b.is_pull=true)
FROM public.issue b,public.repository c where b.repo_id=c.id and c.is_private=false;


CREATE OR REPLACE FUNCTION public.insert_issue_data() RETURNS trigger AS
$def$
DECLARE
privateValue boolean=false;
BEGIN
select into privateValue is_private from public.repository where id=NEW.repo_id;
if not privateValue then
INSERT INTO public.issue_es(
id,
repo_id,
index,
poster_id,
original_author,
original_author_id,
name,
content,
milestone_id,
priority,
is_closed,
is_pull,
num_comments,
ref,
deadline_unix,
created_unix,
updated_unix,
closed_unix,
is_locked,
amount,
is_transformed)
VALUES (
NEW.id,
NEW.repo_id,
NEW.index,
NEW.poster_id,
NEW.original_author,
NEW.original_author_id,
NEW.name,
NEW.content,
NEW.milestone_id,
NEW.priority,
NEW.is_closed,
NEW.is_pull,
NEW.num_comments,
NEW.ref,
NEW.deadline_unix,
NEW.created_unix,
NEW.updated_unix,
NEW.closed_unix,
NEW.is_locked,
NEW.amount,
NEW.is_transformed
);
end if;
RETURN NEW;
END;
$def$
LANGUAGE plpgsql;

DROP TRIGGER IF EXISTS es_insert_issue on public.issue;

CREATE TRIGGER es_insert_issue
AFTER INSERT ON public.issue
FOR EACH ROW EXECUTE PROCEDURE insert_issue_data();

ALTER TABLE public.issue ENABLE ALWAYS TRIGGER es_insert_issue;

CREATE OR REPLACE FUNCTION public.udpate_issue_comment() RETURNS trigger AS
$def$
BEGIN
if (TG_OP = 'DELETE') then
update public.issue_es SET comment=(select array_to_string(array_agg(content order by created_unix desc),',') from public.comment where issue_id=OLD.issue_id) where id=OLD.issue_id;
elsif (TG_OP = 'UPDATE') then
update public.issue_es SET comment=(select array_to_string(array_agg(content order by created_unix desc),',') from public.comment where issue_id=NEW.issue_id) where id=NEW.issue_id;
end if;
return null;
END;
$def$
LANGUAGE plpgsql;

DROP TRIGGER IF EXISTS es_udpate_issue_comment on public.comment;
CREATE TRIGGER es_udpate_issue_comment
AFTER DELETE OR UPDATE ON public.comment
FOR EACH ROW EXECUTE PROCEDURE udpate_issue_comment();

ALTER TABLE public.comment ENABLE ALWAYS TRIGGER es_udpate_issue_comment;


CREATE OR REPLACE FUNCTION public.update_issue() RETURNS trigger AS
$def$
declare
BEGIN
UPDATE public.issue_es
SET content=NEW.content,
name=NEW.name,
is_closed=NEW.is_closed,
num_comments=NEW.num_comments,
comment=(select array_to_string(array_agg(content order by created_unix desc),',') from public.comment where issue_id=NEW.id)
where id=NEW.id;
return new;
END
$def$
LANGUAGE plpgsql;

DROP TRIGGER IF EXISTS es_update_issue on public.issue;

CREATE TRIGGER es_update_issue
AFTER UPDATE ON public.issue
FOR EACH ROW EXECUTE PROCEDURE update_issue();

ALTER TABLE public.issue ENABLE ALWAYS TRIGGER es_update_issue;

CREATE OR REPLACE FUNCTION public.delete_issue() RETURNS trigger AS
$def$
declare
BEGIN
DELETE FROM public.issue_es where id=OLD.id;
return new;
END
$def$
LANGUAGE plpgsql;

DROP TRIGGER IF EXISTS es_delete_issue on public.issue;
CREATE TRIGGER es_delete_issue
AFTER DELETE ON public.issue
FOR EACH ROW EXECUTE PROCEDURE delete_issue();

ALTER TABLE public.issue ENABLE ALWAYS TRIGGER es_delete_issue;

+ 532
- 0
models/dbsql/repo_foreigntable_for_es.sql View File

@@ -0,0 +1,532 @@
-- 要处理项目从私有变为公有,并且从公有变成私有的情况
DROP FOREIGN table if exists public.repository_es;
CREATE FOREIGN TABLE public.repository_es (
id bigint NOT NULL,
owner_id bigint,
owner_name character varying(255),
lower_name character varying(255) NOT NULL,
name character varying(255) NOT NULL,
description text,
website character varying(2048),
original_service_type integer,
original_url character varying(2048),
default_branch character varying(255),
num_watches integer,
num_stars integer,
num_forks integer,
num_issues integer,
num_closed_issues integer,
num_pulls integer,
num_closed_pulls integer,
num_milestones integer DEFAULT 0 NOT NULL,
num_closed_milestones integer DEFAULT 0 NOT NULL,
is_private boolean,
is_empty boolean,
is_archived boolean,
is_mirror boolean,
status integer DEFAULT 0 NOT NULL,
is_fork boolean DEFAULT false NOT NULL,
fork_id bigint,
is_template boolean DEFAULT false NOT NULL,
template_id bigint,
size bigint DEFAULT 0 NOT NULL,
is_fsck_enabled boolean DEFAULT true NOT NULL,
close_issues_via_commit_in_any_branch boolean DEFAULT false NOT NULL,
topics text,
avatar character varying(64),
created_unix bigint,
updated_unix bigint,
contract_address character varying(255),
block_chain_status integer DEFAULT 0 NOT NULL,
balance character varying(255) DEFAULT '0'::character varying NOT NULL,
clone_cnt bigint DEFAULT 0 NOT NULL,
license character varying(100),
download_cnt bigint DEFAULT 0 NOT NULL,
num_commit bigint DEFAULT 0 NOT NULL,
git_clone_cnt bigint DEFAULT 0 NOT NULL,
creator_id bigint NOT NULL DEFAULT 0,
repo_type integer NOT NULL DEFAULT 0,
lang character varying(2048),
alias character varying(255),
lower_alias character varying(255)
) SERVER multicorn_es
OPTIONS
(
host '192.168.207.94',
port '9200',
index 'repository-es-index',
rowid_column 'id',
default_sort '_id'
)
;
delete from public.repository_es;
INSERT INTO public.repository_es (id,
owner_id,
owner_name,
lower_name,
name,
description,
website,
original_service_type,
original_url,
default_branch,
num_watches,
num_stars,
num_forks,
num_issues,
num_closed_issues,
num_pulls,
num_closed_pulls,
num_milestones,
num_closed_milestones,
is_private,
is_empty,
is_archived,
is_mirror,
status,
is_fork,
fork_id,
is_template,
template_id,
size,
is_fsck_enabled,
close_issues_via_commit_in_any_branch,
topics,
avatar,
created_unix,
updated_unix,
contract_address,
block_chain_status,
balance,
clone_cnt,
num_commit,
git_clone_cnt,
creator_id,
repo_type,
lang,
alias,
lower_alias
)
SELECT
id,
owner_id,
owner_name,
lower_name,
name,
description,
website,
original_service_type,
original_url,
default_branch,
num_watches,
num_stars,
num_forks,
num_issues,
num_closed_issues,
num_pulls,
num_closed_pulls,
num_milestones,
num_closed_milestones,
is_private,
is_empty,
is_archived,
is_mirror,
status,
is_fork,
fork_id,
is_template,
template_id,
size,
is_fsck_enabled,
close_issues_via_commit_in_any_branch,
topics,
avatar,
created_unix,
updated_unix,
contract_address,
block_chain_status,
balance,
clone_cnt,
num_commit,
git_clone_cnt,
creator_id,
repo_type,
(select array_to_string(array_agg(language order by percentage desc),',') from public.language_stat a where a.repo_id=b.id),
alias,
lower_alias
FROM public.repository b where b.is_private=false;

DROP TRIGGER IF EXISTS es_insert_repository on public.repository;

CREATE OR REPLACE FUNCTION public.insert_repository_data() RETURNS trigger AS
$def$
BEGIN
if not NEW.is_private then
INSERT INTO public.repository_es (id,
owner_id,
owner_name,
lower_name,
name,
description,
website,
original_service_type,
original_url,
default_branch,
num_watches,
num_stars,
num_forks,
num_issues,
num_closed_issues,
num_pulls,
num_closed_pulls,
num_milestones,
num_closed_milestones,
is_private,
is_empty,
is_archived,
is_mirror,
status,
is_fork,
fork_id,
is_template,
template_id,
size,
is_fsck_enabled,
close_issues_via_commit_in_any_branch,
topics,
avatar,
created_unix,
updated_unix,
contract_address,
block_chain_status,
balance,
clone_cnt,
num_commit,
git_clone_cnt,
creator_id,
repo_type,
alias,
lower_alias) VALUES
(NEW.id,
NEW.owner_id,
NEW.owner_name,
NEW.lower_name,
NEW.name,
NEW.description,
NEW.website,
NEW.original_service_type,
NEW.original_url,
NEW.default_branch,
NEW.num_watches,
NEW.num_stars,
NEW.num_forks,
NEW.num_issues,
NEW.num_closed_issues,
NEW.num_pulls,
NEW.num_closed_pulls,
NEW.num_milestones,
NEW.num_closed_milestones,
NEW.is_private,
NEW.is_empty,
NEW.is_archived,
NEW.is_mirror,
NEW.status,
NEW.is_fork,
NEW.fork_id,
NEW.is_template,
NEW.template_id,
NEW.size,
NEW.is_fsck_enabled,
NEW.close_issues_via_commit_in_any_branch,
NEW.topics,
NEW.avatar,
NEW.created_unix,
NEW.updated_unix,
NEW.contract_address,
NEW.block_chain_status,
NEW.balance,
NEW.clone_cnt,
NEW.num_commit,
NEW.git_clone_cnt,
NEW.creator_id,
NEW.repo_type,
NEW.alias,
NEW.lower_alias);
end if;
RETURN NEW;
END;
$def$
LANGUAGE plpgsql;


CREATE TRIGGER es_insert_repository
AFTER INSERT ON public.repository
FOR EACH ROW EXECUTE PROCEDURE insert_repository_data();

ALTER TABLE public.repository ENABLE ALWAYS TRIGGER es_insert_repository;

DROP TRIGGER IF EXISTS es_update_repository on public.repository;

CREATE OR REPLACE FUNCTION public.update_repository() RETURNS trigger AS
$def$
BEGIN
if OLD.is_private != NEW.is_private then
if OLD.is_private and not NEW.is_private then
--insert
INSERT INTO public.repository_es (id,
owner_id,
owner_name,
lower_name,
name,
description,
website,
original_service_type,
original_url,
default_branch,
num_watches,
num_stars,
num_forks,
num_issues,
num_closed_issues,
num_pulls,
num_closed_pulls,
num_milestones,
num_closed_milestones,
is_private,
is_empty,
is_archived,
is_mirror,
status,
is_fork,
fork_id,
is_template,
template_id,
size,
is_fsck_enabled,
close_issues_via_commit_in_any_branch,
topics,
avatar,
created_unix,
updated_unix,
contract_address,
block_chain_status,
balance,
clone_cnt,
num_commit,
git_clone_cnt,
creator_id,
repo_type,
lang,
alias,
lower_alias)
SELECT
id,
owner_id,
owner_name,
lower_name,
name,
description,
website,
original_service_type,
original_url,
default_branch,
num_watches,
num_stars,
num_forks,
num_issues,
num_closed_issues,
num_pulls,
num_closed_pulls,
num_milestones,
num_closed_milestones,
is_private,
is_empty,
is_archived,
is_mirror,
status,
is_fork,
fork_id,
is_template,
template_id,
size,
is_fsck_enabled,
close_issues_via_commit_in_any_branch,
topics,
avatar,
created_unix,
updated_unix,
contract_address,
block_chain_status,
balance,
clone_cnt,
num_commit,
git_clone_cnt,
creator_id,
repo_type,
(select array_to_string(array_agg(language order by percentage desc),',') from public.language_stat a where a.repo_id=b.id),
alias,
lower_alias
FROM public.repository b where b.id=NEW.id;
INSERT INTO public.dataset_es(
id,
title,
status,
category,
description,
download_times,
license, task,
release_id,
user_id,
repo_id,
created_unix,
updated_unix,file_name)
SELECT
b.id,
b.title,
b.status,
b.category,
b.description,
b.download_times,
b.license,
b.task,
b.release_id,
b.user_id,
b.repo_id,
b.created_unix,
b.updated_unix,(select array_to_string(array_agg(name order by created_unix desc),',') from public.attachment a where a.dataset_id=b.id and a.is_private=false)
FROM public.dataset b where b.repo_id=NEW.id;

INSERT INTO public.issue_es(
id,
repo_id,
index,
poster_id,
original_author,
original_author_id,
name,
content,
milestone_id,
priority,
is_closed,
is_pull,
num_comments,
ref,
deadline_unix,
created_unix,
updated_unix,
closed_unix,
is_locked,
amount,
is_transformed,comment,pr_id)
SELECT
b.id,
b.repo_id,
b.index,
b.poster_id,
b.original_author,
b.original_author_id,
b.name,
b.content,
b.milestone_id,
b.priority,
b.is_closed,
b.is_pull,
b.num_comments,
b.ref,
b.deadline_unix,
b.created_unix,
b.updated_unix,
b.closed_unix,
b.is_locked,
b.amount,
b.is_transformed,
(select array_to_string(array_agg(content order by created_unix desc),',') from public.comment a where a.issue_id=b.id),
(select id from public.pull_request d where d.issue_id=b.id)
FROM public.issue b where b.repo_id=NEW.id;
end if;

if not OLD.is_private and NEW.is_private then
delete from public.issue_es where repo_id=NEW.id;
delete from public.dataset_es where repo_id=NEW.id;
delete from public.repository_es where id=NEW.id;
end if;

end if;

if not NEW.is_private then
raise notice 'update repo,the updated_unix is %',NEW.updated_unix;
update public.repository_es SET description=NEW.description,
name=NEW.name,
lower_name=NEW.lower_name,
owner_name=NEW.owner_name,
website=NEW.website,
updated_unix=NEW.updated_unix,
num_watches=NEW.num_watches,
num_stars=NEW.num_stars,
num_forks=NEW.num_forks,
topics=NEW.topics,
alias = NEW.alias,
lower_alias = NEW.lower_alias,
avatar=NEW.avatar
where id=NEW.id;
end if;
return new;
END
$def$
LANGUAGE plpgsql;

CREATE TRIGGER es_update_repository
AFTER UPDATE ON public.repository
FOR EACH ROW EXECUTE PROCEDURE update_repository();

ALTER TABLE public.repository ENABLE ALWAYS TRIGGER es_update_repository;


DROP TRIGGER IF EXISTS es_delete_repository on public.repository;

CREATE OR REPLACE FUNCTION public.delete_repository() RETURNS trigger AS
$def$
declare
BEGIN
delete from public.issue_es where repo_id=OLD.id;
delete from public.dataset_es where repo_id=OLD.id;
DELETE FROM public.repository_es where id=OLD.id;
return new;
END
$def$
LANGUAGE plpgsql;


CREATE TRIGGER es_delete_repository
AFTER DELETE ON public.repository
FOR EACH ROW EXECUTE PROCEDURE delete_repository();

ALTER TABLE public.repository ENABLE ALWAYS TRIGGER es_delete_repository;



DROP TRIGGER IF EXISTS es_udpate_repository_lang on public.language_stat;

CREATE OR REPLACE FUNCTION public.udpate_repository_lang() RETURNS trigger AS
$def$
BEGIN
if (TG_OP = 'UPDATE') then
update public.repository_es SET lang=(select array_to_string(array_agg(language order by percentage desc),',') from public.language_stat where repo_id=NEW.repo_id) where id=NEW.repo_id;
elsif (TG_OP = 'INSERT') then
update public.repository_es SET lang=(select array_to_string(array_agg(language order by percentage desc),',') from public.language_stat where repo_id=NEW.repo_id) where id=NEW.repo_id;
elsif (TG_OP = 'DELETE') then
if exists(select 1 from public.repository where id=OLD.repo_id) then
update public.repository_es SET lang=(select array_to_string(array_agg(language order by percentage desc),',') from public.language_stat where repo_id=OLD.repo_id) where id=OLD.repo_id;
end if;
end if;
return null;
END;
$def$
LANGUAGE plpgsql;

CREATE TRIGGER es_udpate_repository_lang
AFTER INSERT OR UPDATE OR DELETE ON public.language_stat
FOR EACH ROW EXECUTE PROCEDURE udpate_repository_lang();

ALTER TABLE public.language_stat ENABLE ALWAYS TRIGGER es_udpate_repository_lang;

+ 308
- 0
models/dbsql/user_foreigntable_for_es.sql View File

@@ -0,0 +1,308 @@
DROP FOREIGN table if exists public.user_es;
CREATE FOREIGN TABLE public.user_es
(
id bigint NOT NULL ,
lower_name character varying(255) NULL,
name character varying(255) NULL,
full_name character varying(255),
email character varying(255),
keep_email_private boolean,
email_notifications_preference character varying(20) ,
passwd character varying(255) ,
passwd_hash_algo character varying(255) ,
must_change_password boolean NOT NULL DEFAULT false,
login_type integer,
login_source bigint NOT NULL DEFAULT 0,
login_name character varying(255) ,
type integer,
location character varying(255),
website character varying(255),
rands character varying(10),
salt character varying(10),
language character varying(5),
description character varying(255),
created_unix bigint,
updated_unix bigint,
last_login_unix bigint,
last_repo_visibility boolean,
max_repo_creation integer,
is_active boolean,
is_admin boolean,
is_restricted boolean NOT NULL DEFAULT false,
allow_git_hook boolean,
allow_import_local boolean,
allow_create_organization boolean DEFAULT true,
prohibit_login boolean NOT NULL DEFAULT false,
avatar character varying(2048) ,
avatar_email character varying(255),
use_custom_avatar boolean,
num_followers integer,
num_following integer NOT NULL DEFAULT 0,
num_stars integer,
num_repos integer,
num_teams integer,
num_members integer,
visibility integer NOT NULL DEFAULT 0,
repo_admin_change_team_access boolean NOT NULL DEFAULT false,
diff_view_style character varying(255),
theme character varying(255),
token character varying(1024) ,
public_key character varying(255),
private_key character varying(255),
is_operator boolean NOT NULL DEFAULT false,
num_dataset_stars integer NOT NULL DEFAULT 0
) SERVER multicorn_es
OPTIONS
(
host '192.168.207.94',
port '9200',
index 'user-es-index',
rowid_column 'id',
default_sort '_id'
)
;
delete from public.user_es;
INSERT INTO public.user_es(
id,
lower_name,
name,
full_name,
email,
keep_email_private,
email_notifications_preference,
must_change_password,
login_type,
login_source,
login_name,
type,
location,
website,
rands,
language,
description,
created_unix,
updated_unix,
last_login_unix,
last_repo_visibility,
max_repo_creation,
is_active,
is_restricted,
allow_git_hook,
allow_import_local,
allow_create_organization,
prohibit_login,
avatar,
avatar_email,
use_custom_avatar,
num_followers,
num_following,
num_stars,
num_repos,
num_teams,
num_members,
visibility,
repo_admin_change_team_access,
diff_view_style,
theme,
is_operator,
num_dataset_stars)
SELECT
id,
lower_name,
name,
full_name,
email,
keep_email_private,
email_notifications_preference,
must_change_password,
login_type,
login_source,
login_name,
type,
location,
website,
rands,
language,
description,
created_unix,
updated_unix,
last_login_unix,
last_repo_visibility,
max_repo_creation,
is_active,
is_restricted,
allow_git_hook,
allow_import_local,
allow_create_organization,
prohibit_login,
avatar,
avatar_email,
use_custom_avatar,
num_followers,
num_following,
num_stars,
num_repos,
num_teams,
num_members,
visibility,
repo_admin_change_team_access,
diff_view_style,
theme,
is_operator,
num_dataset_stars
FROM public.user;

DROP TRIGGER IF EXISTS es_insert_user on public.user;

CREATE OR REPLACE FUNCTION public.insert_user_data() RETURNS trigger AS
$def$
BEGIN
INSERT INTO public."user_es"(
id,
lower_name,
name,
full_name,
email,
keep_email_private,
email_notifications_preference,
must_change_password,
login_type,
login_source,
login_name,
type,
location,
website,
rands,
language,
description,
created_unix,
updated_unix,
last_login_unix,
last_repo_visibility,
max_repo_creation,
is_active,
is_restricted,
allow_git_hook,
allow_import_local,
allow_create_organization,
prohibit_login,
avatar,
avatar_email,
use_custom_avatar,
num_followers,
num_following,
num_stars,
num_repos,
num_teams,
num_members,
visibility,
repo_admin_change_team_access,
diff_view_style,
theme,
is_operator,
num_dataset_stars)
VALUES (
NEW.id,
NEW.lower_name,
NEW.name,
NEW.full_name,
NEW.email,
NEW.keep_email_private,
NEW.email_notifications_preference,
NEW.must_change_password,
NEW.login_type,
NEW.login_source,
NEW.login_name,
NEW.type,
NEW.location,
NEW.website,
NEW.rands,
NEW.language,
NEW.description,
NEW.created_unix,
NEW.updated_unix,
NEW.last_login_unix,
NEW.last_repo_visibility,
NEW.max_repo_creation,
NEW.is_active,
NEW.is_restricted,
NEW.allow_git_hook,
NEW.allow_import_local,
NEW.allow_create_organization,
NEW.prohibit_login,
NEW.avatar,
NEW.avatar_email,
NEW.use_custom_avatar,
NEW.num_followers,
NEW.num_following,
NEW.num_stars,
NEW.num_repos,
NEW.num_teams,
NEW.num_members,
NEW.visibility,
NEW.repo_admin_change_team_access,
NEW.diff_view_style,
NEW.theme,
NEW.is_operator,
NEW.num_dataset_stars
);

RETURN NEW;
END;
$def$
LANGUAGE plpgsql;



CREATE TRIGGER es_insert_user
AFTER INSERT ON public.user
FOR EACH ROW EXECUTE PROCEDURE insert_user_data();

ALTER TABLE public.user ENABLE ALWAYS TRIGGER es_insert_user;

DROP TRIGGER IF EXISTS es_update_user on public.user;

CREATE OR REPLACE FUNCTION public.update_user() RETURNS trigger AS
$def$
BEGIN
UPDATE public.user_es
SET description=NEW.description,
name=NEW.name,
full_name=NEW.full_name,
location=NEW.location,
website=NEW.website,
email=NEW.email,
num_dataset_stars=NEW.num_dataset_stars,
updated_unix=NEW.updated_unix
where id=NEW.id;
return new;
END
$def$
LANGUAGE plpgsql;



CREATE TRIGGER es_update_user
AFTER UPDATE ON public.user
FOR EACH ROW EXECUTE PROCEDURE update_user();

ALTER TABLE public.user ENABLE ALWAYS TRIGGER es_update_user;

DROP TRIGGER IF EXISTS es_delete_user on public.user;

CREATE OR REPLACE FUNCTION public.delete_user() RETURNS trigger AS
$def$
declare
BEGIN
DELETE FROM public.user_es where id=OLD.id;
return new;
END
$def$
LANGUAGE plpgsql;


CREATE TRIGGER es_delete_user
AFTER DELETE ON public.user
FOR EACH ROW EXECUTE PROCEDURE delete_user();
ALTER TABLE public.user ENABLE ALWAYS TRIGGER es_delete_user;

+ 1
- 0
models/models.go View File

@@ -138,6 +138,7 @@ func init() {
new(OfficialTag),
new(OfficialTagRepos),
new(WechatBindLog),
new(SearchRecord),
)

tablesStatistic = append(tablesStatistic,


+ 2
- 1
models/repo.go View File

@@ -6,13 +6,14 @@
package models

import (
"code.gitea.io/gitea/modules/git"
"context"
"crypto/md5"
"errors"
"fmt"
"html/template"
"math/rand"

"code.gitea.io/gitea/modules/git"
"xorm.io/xorm"

"code.gitea.io/gitea/modules/blockchain"


+ 7
- 3
models/repo_list.go View File

@@ -190,7 +190,8 @@ type SearchRepoOptions struct {
// None -> include all repos
// True -> include just courses
// False -> include just no courses
Course util.OptionalBool
Course util.OptionalBool
OnlySearchPrivate bool
}

//SearchOrderBy is used to sort the result
@@ -219,12 +220,15 @@ const (
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"
SearchOrderByWatches SearchOrderBy = "num_watches DESC"
)

// SearchRepositoryCondition creates a query condition according search repository options
func SearchRepositoryCondition(opts *SearchRepoOptions) builder.Cond {
var cond = builder.NewCond()

if opts.OnlySearchPrivate {
cond = cond.And(builder.Eq{"is_private": true})
}
if opts.Private {
if opts.Actor != nil && !opts.Actor.IsAdmin && opts.Actor.ID != opts.OwnerID {
// OK we're in the context of a User
@@ -337,7 +341,7 @@ func SearchRepositoryCondition(opts *SearchRepoOptions) builder.Cond {
if !opts.TopicOnly {
var likes = builder.NewCond()
for _, v := range strings.Split(opts.Keyword, ",") {
likes = likes.Or(builder.Like{"lower_name", strings.ToLower(v)})
likes = likes.Or(builder.Like{"lower_alias", strings.ToLower(v)})
likes = likes.Or(builder.Like{"alias", v})
if opts.IncludeDescription {
likes = likes.Or(builder.Like{"LOWER(description)", strings.ToLower(v)})


+ 83
- 0
models/search_record.go View File

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

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

type SearchRecord struct {
ID int64 `xorm:"pk autoincr"`
//user
Keyword string `xorm:"NOT NULL"`
//
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
}

func SaveSearchKeywordToDb(keyword string) error {
record := &SearchRecord{
Keyword: keyword,
}
sess := x.NewSession()
defer sess.Close()
_, err := sess.Insert(record)
if err != nil {
log.Info("insert error." + err.Error())
return err
}
return nil
}

func setIssueQueryCondition(sess *xorm.Session, Keyword string, isPull bool, userId int64) {
sess.And("issue.poster_id=?", userId)
sess.And("issue.is_pull=?", isPull)
sess.And("(issue.name like '%" + Keyword + "%' or issue.content like '%" + Keyword + "%')")
sess.Join("INNER", "repository", "issue.repo_id = repository.id").And("repository.is_private = ?", true)
}

func SearchPrivateIssueOrPr(Page int, PageSize int, Keyword string, isPull bool, userId int64) ([]*Issue, int64, error) {
sess := x.NewSession()
defer sess.Close()
setIssueQueryCondition(sess, Keyword, isPull, userId)
count, err := sess.Count(new(Issue))
if err != nil {
return nil, 0, err
}

setIssueQueryCondition(sess, Keyword, isPull, userId)
sess.Desc("issue.created_unix")
sess.Limit(PageSize, (Page-1)*PageSize)
issues := make([]*Issue, 0)
if err := sess.Find(&issues); err != nil {
return nil, 0, err
} else {
return issues, count, nil
}
}

func setDataSetQueryCondition(sess *xorm.Session, Keyword string, userId int64) {
sess.And("dataset.user_id=?", userId)
sess.And("(dataset.title like '%" + Keyword + "%' or dataset.description like '%" + Keyword + "%')")
sess.Join("INNER", "repository", "dataset.repo_id = repository.id").And("repository.is_private = ?", true)
}

func SearchDatasetBySQL(Page int, PageSize int, Keyword string, userId int64) ([]*Dataset, int64, error) {
sess := x.NewSession()
defer sess.Close()
setDataSetQueryCondition(sess, Keyword, userId)
count, err := sess.Count(new(Dataset))
if err != nil {
return nil, 0, err
}

setDataSetQueryCondition(sess, Keyword, userId)
sess.Desc("dataset.created_unix")
sess.Limit(PageSize, (Page-1)*PageSize)
datasets := make([]*Dataset, 0)
if err := sess.Find(&datasets); err != nil {
return nil, 0, err
} else {
return datasets, count, nil
}

}

+ 2
- 1
modules/setting/setting.go View File

@@ -437,7 +437,7 @@ var (

//home page
RecommentRepoAddr string
ESSearchURL string
//notice config
UserNameOfNoticeRepo string
RepoNameOfNoticeRepo string
@@ -1267,6 +1267,7 @@ func NewContext() {

sec = Cfg.Section("homepage")
RecommentRepoAddr = sec.Key("Address").MustString("https://git.openi.org.cn/OpenIOSSG/promote/raw/branch/master/")
ESSearchURL = sec.Key("ESSearchURL").MustString("http://192.168.207.94:9200")

sec = Cfg.Section("notice")
UserNameOfNoticeRepo = sec.Key("USER_NAME").MustString("OpenIOSSG")


+ 12
- 0
options/locale/locale_en-US.ini View File

@@ -254,6 +254,18 @@ page_dev_yunlao_desc3=Developers can freely choose the corresponding computing r
page_dev_yunlao_desc4=If your model requires more computing resources, you can also apply for it separately.
page_dev_yunlao_apply=Apply Separately

search=Search
search_repo=Repository
search_dataset=DataSet
search_issue=Issue
search_pr=Pull Request
search_user=User
search_org=Organization
search_finded=Find
search_related=related
search_maybe=maybe
search_ge=

[explore]
repos = Repositories
select_repos = Select the project


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

@@ -256,6 +256,18 @@ page_dev_yunlao_desc3=开发者可以根据使用需求,自由选择相应计
page_dev_yunlao_desc4=如果您的模型需要更多的计算资源,也可以单独申请
page_dev_yunlao_apply=单独申请

search=搜索
search_repo=项目
search_dataset=数据集
search_issue=任务
search_pr=合并请求
search_user=用户
search_org=组织
search_finded=找到
search_related=相关
search_maybe=约为
search_ge=个

[explore]
repos=项目
select_repos=精选项目


+ 1281
- 0
public/home/search.js
File diff suppressed because it is too large
View File


+ 3
- 3
public/self/dataset_preview.js View File

@@ -620,10 +620,10 @@ function showfilelist(){
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])
//console.log(labeltastresult[i])
if(labeltastresult[i].pic_image_field.length > 70){
var tmpIndex = labeltastresult[i].pic_image_field.indexOf("/",70);
console.log(tmpIndex)
//console.log(tmpIndex)
if(tmpIndex != -1){
fname = labeltastresult[i].pic_image_field.substring(tmpIndex + 1);
fname = fname.substring(fname.indexOf('/')+1);
@@ -679,7 +679,7 @@ function breadFiles(){
fname_full_path = tableData[fileindex].pic_image_field.substring(tmp_index + 1);
}
var fname_path = fname_full_path.split('/')
console.log(fname_path)
//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'


+ 3
- 12
routers/api/v1/repo/cloudbrain.go View File

@@ -17,7 +17,6 @@ import (
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/storage"
"code.gitea.io/gitea/modules/timeutil"
routerRepo "code.gitea.io/gitea/routers/repo"
)

@@ -74,24 +73,16 @@ func GetCloudbrainTask(ctx *context.APIContext) {
}

job.Status = result.JobStatus.State
taskRoles := result.TaskRoles
taskRes, _ := models.ConvertToTaskPod(taskRoles[cloudbrain.SubTaskName].(map[string]interface{}))
if result.JobStatus.State != string(models.JobWaiting) && result.JobStatus.State != string(models.JobFailed) {
taskRoles := result.TaskRoles
taskRes, _ := models.ConvertToTaskPod(taskRoles[cloudbrain.SubTaskName].(map[string]interface{}))

job.ContainerIp = taskRes.TaskStatuses[0].ContainerIP
job.ContainerID = taskRes.TaskStatuses[0].ContainerID
job.Status = taskRes.TaskStatuses[0].State

if job.StartTime == 0 && !taskRes.TaskStatuses[0].StartAt.IsZero() {
job.StartTime = timeutil.TimeStamp(taskRes.TaskStatuses[0].StartAt.Unix())
}
}

if result.JobStatus.State != string(models.JobWaiting) {
if job.EndTime == 0 && models.IsCloudBrainOneDebugJobTerminal(job.Status) {
job.EndTime = timeutil.TimeStampNow()
}
job.ComputeAndSetDuration()
models.ParseAndSetDurationFromCloudBrainOne(result, job)
err = models.UpdateJob(job)
if err != nil {
log.Error("UpdateJob failed:", err)


+ 2
- 0
routers/init.go View File

@@ -71,6 +71,8 @@ func NewServices() {
log.Info("decompression.NewContext() succeed.")
labelmsg.Init()
log.Info("labelmsg.Init() succeed.")
InitESClient()
log.Info("ES Client succeed.")
}

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


+ 27
- 34
routers/repo/cloudbrain.go View File

@@ -435,9 +435,7 @@ func cloudBrainShow(ctx *context.Context, tpName base.TplName, jobType models.Jo
task.Status = taskRes.TaskStatuses[0].State
task.ContainerID = taskRes.TaskStatuses[0].ContainerID
task.ContainerIp = taskRes.TaskStatuses[0].ContainerIP
if task.StartTime == 0 && !taskRes.TaskStatuses[0].StartAt.IsZero() {
task.StartTime = timeutil.TimeStamp(taskRes.TaskStatuses[0].StartAt.Unix())
}
models.ParseAndSetDurationFromCloudBrainOne(jobRes, task)
err = models.UpdateJob(task)
if err != nil {
ctx.Data["error"] = err.Error()
@@ -1048,14 +1046,7 @@ func SyncCloudbrainStatus() {
taskRes, _ := models.ConvertToTaskPod(taskRoles[cloudbrain.SubTaskName].(map[string]interface{}))
task.Status = taskRes.TaskStatuses[0].State
if task.Status != string(models.JobWaiting) {
task.Duration = time.Now().Unix() - taskRes.TaskStatuses[0].StartAt.Unix()
if task.StartTime == 0 && !taskRes.TaskStatuses[0].StartAt.IsZero() {
task.StartTime = timeutil.TimeStamp(taskRes.TaskStatuses[0].StartAt.Unix())
}
if task.EndTime == 0 && models.IsCloudBrainOneDebugJobTerminal(task.Status) {
task.EndTime = timeutil.TimeStampNow()
}
task.ComputeAndSetDuration()
models.ParseAndSetDurationFromCloudBrainOne(jobRes, task)
err = models.UpdateJob(task)
if err != nil {
log.Error("UpdateJob(%s) failed:%v", task.JobName, err)
@@ -1111,7 +1102,7 @@ func SyncCloudbrainStatus() {
continue
}
}
} else if task.JobType == string(models.JobTypeTrain) {
} else if task.JobType == string(models.JobTypeTrain) || task.JobType == string(models.JobTypeInference) {
result, err := modelarts.GetTrainJob(task.JobID, strconv.FormatInt(task.VersionID, 10))
if err != nil {
log.Error("GetTrainJob(%s) failed:%v", task.JobName, err)
@@ -1152,6 +1143,7 @@ func SyncCloudbrainStatus() {
func HandleTaskWithNoDuration(ctx *context.Context) {
log.Info("HandleTaskWithNoDuration start")
count := 0
start := time.Now().Unix()
for {
cloudBrains, err := models.GetStoppedJobWithNoDurationJob()
if err != nil {
@@ -1168,13 +1160,19 @@ func HandleTaskWithNoDuration(ctx *context.Context) {
log.Info("HandleTaskWithNoTrainJobDuration:task less than 100")
break
}
if time.Now().Unix()-start > 600 {
log.Info("HandleTaskWithNoDuration : time out")
ctx.JSON(200, fmt.Sprintf("task stop for time out,count=%d", count))
return
}
}
log.Info("HandleTaskWithNoTrainJobDuration:count=%d", count)
ctx.JSON(200, "success")
ctx.JSON(200, fmt.Sprintf("success,count=%d", count))
}

func handleNoDurationTask(cloudBrains []*models.Cloudbrain) {
for _, task := range cloudBrains {
time.Sleep(time.Millisecond * 100)
log.Info("Handle job ,%+v", task)
if task.Type == models.TypeCloudBrainOne {
result, err := cloudbrain.GetJob(task.JobID)
@@ -1201,18 +1199,17 @@ func handleNoDurationTask(cloudBrains []*models.Cloudbrain) {
continue
}
task.Status = taskRes.TaskStatuses[0].State
startTime := taskRes.TaskStatuses[0].StartAt.Unix()
endTime := taskRes.TaskStatuses[0].FinishedAt.Unix()
log.Info("task startTime = %v endTime= %v ,jobId=%d", startTime, endTime, task.ID)
if startTime > 0 {
task.StartTime = timeutil.TimeStamp(startTime)
} else {
task.StartTime = task.CreatedUnix
}
if endTime > 0 {
task.EndTime = timeutil.TimeStamp(endTime)
log.Info("task startTime = %v endTime= %v ,jobId=%d", jobRes.JobStatus.StartTime, jobRes.JobStatus.EndTime, task.ID)
if jobRes.JobStatus.CreatedTime > 0 {
task.StartTime = timeutil.TimeStamp(jobRes.JobStatus.CreatedTime / 1000)
if jobRes.JobStatus.CompletedTime > 0 {
task.EndTime = timeutil.TimeStamp(jobRes.JobStatus.CompletedTime / 1000)
} else {
task.EndTime = task.UpdatedUnix
}
} else {
task.EndTime = task.UpdatedUnix
task.StartTime = 0
task.EndTime = 0
}

if task.EndTime < task.StartTime {
@@ -1221,7 +1218,8 @@ func handleNoDurationTask(cloudBrains []*models.Cloudbrain) {
task.StartTime = task.EndTime
task.EndTime = st
}
task.ComputeAndSetDuration()
task.Duration = task.EndTime.AsTime().Unix() - task.StartTime.AsTime().Unix()
task.TrainJobDuration = models.ConvertDurationToStr(task.Duration)
err = models.UpdateJob(task)
if err != nil {
log.Error("UpdateJob(%s) failed:%v", task.JobName, err)
@@ -1233,13 +1231,7 @@ func handleNoDurationTask(cloudBrains []*models.Cloudbrain) {
result, err := modelarts.GetNotebook2(task.JobID)
if err != nil {
log.Error("GetJob(%s) failed:%v", task.JobName, err)
task.StartTime = task.CreatedUnix
task.EndTime = task.UpdatedUnix
task.ComputeAndSetDuration()
err = models.UpdateJob(task)
if err != nil {
log.Error("UpdateJob(%s) failed:%v", task.JobName, err)
}
updateDefaultDuration(task)
continue
}

@@ -1248,7 +1240,7 @@ func handleNoDurationTask(cloudBrains []*models.Cloudbrain) {
startTime := result.Lease.CreateTime
duration := result.Lease.Duration / 1000
if startTime > 0 {
task.StartTime = timeutil.TimeStamp(startTime)
task.StartTime = timeutil.TimeStamp(startTime / 1000)
task.EndTime = task.StartTime.Add(duration)
}
task.ComputeAndSetDuration()
@@ -1258,10 +1250,11 @@ func handleNoDurationTask(cloudBrains []*models.Cloudbrain) {
continue
}
}
} else if task.JobType == string(models.JobTypeTrain) {
} else if task.JobType == string(models.JobTypeTrain) || task.JobType == string(models.JobTypeInference) {
result, err := modelarts.GetTrainJob(task.JobID, strconv.FormatInt(task.VersionID, 10))
if err != nil {
log.Error("GetTrainJob(%s) failed:%v", task.JobName, err)
updateDefaultDuration(task)
continue
}



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

@@ -323,6 +323,9 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Get("/action/notification", routers.ActionNotification)
m.Get("/recommend/org", routers.RecommendOrgFromPromote)
m.Get("/recommend/repo", routers.RecommendRepoFromPromote)
m.Post("/all/search/", routers.Search)
m.Get("/all/search/", routers.EmptySearch)
m.Get("/all/dosearch/", routers.SearchApi)
m.Get("/home/term", routers.HomeTerm)
m.Group("/explore", func() {
m.Get("", func(ctx *context.Context) {


+ 1190
- 0
routers/search.go
File diff suppressed because it is too large
View File


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

@@ -95,9 +95,9 @@

{{if .IsSigned}}
<div class="right stackable menu">
<form class="fourteen wide mobile ten wide tablet ten wide computer column ui form ignore-dirty" style="margin:auto" action="/explore/repos">
<form id="searchForm" class="fourteen wide mobile ten wide tablet ten wide computer column ui form ignore-dirty" style="margin:auto" action="/all/search/" method="post">
<div class="ui fluid action input" style="background:#363840 ;border-radius: 5px;width: 200px;height:30px;border: #888888 solid 1px;">
<input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search_pro"}}..."
<input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search"}}..."
style="transition: background-color 5000s ease-in-out 0s;-webkit-text-fill-color:#888888;background:#363840 ;color:#888888;border: none;outline: none;">
<input type="hidden" name="tab" value="{{$.TabName}}">
<input type="hidden" name="sort" value="hot">
@@ -199,9 +199,9 @@
<!--a class="item" target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io">{{.i18n.Tr "help"}}</a-->
<div class="right stackable menu">
<form class="fourteen wide mobile ten wide tablet ten wide computer column ui form ignore-dirty" style="margin:auto" action="/explore/repos">
<form id="searchForm" class="fourteen wide mobile ten wide tablet ten wide computer column ui form ignore-dirty" style="margin:auto" action="/all/search/" method="post">
<div class="ui fluid action input" style="background:#363840 ;border-radius: 5px;width: 200px;height:30px;border: #888888 solid 1px;">
<input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search_pro"}}..."
<input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search"}}..."
style="transition: background-color 5000s ease-in-out 0s;-webkit-text-fill-color:#888888;background:#363840 ;color:#888888;border: none;outline: none;">
<input type="hidden" name="tab" value="{{$.TabName}}">
<input type="hidden" name="sort" value="hot">


+ 4
- 4
templates/base/head_navbar_fluid.tmpl View File

@@ -93,9 +93,9 @@

{{if .IsSigned}}
<div class="right stackable menu">
<form class="fourteen wide mobile ten wide tablet ten wide computer column ui form ignore-dirty" style="margin:auto" action="/explore/repos">
<form id="searchForm" class="fourteen wide mobile ten wide tablet ten wide computer column ui form ignore-dirty" style="margin:auto" action="/all/search/" method="post">
<div class="ui fluid action input" style="background:#363840 ;border-radius: 5px;width: 200px;height:30px;border: #888888 solid 1px;">
<input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search_pro"}}..."
<input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search"}}..."
style="transition: background-color 5000s ease-in-out 0s;-webkit-text-fill-color:#888888;background:#363840 ;color:#888888;border: none;outline: none;">
<input type="hidden" name="tab" value="{{$.TabName}}">
<input type="hidden" name="sort" value="{{$.SortType}}">
@@ -196,9 +196,9 @@

<!--a class="item" target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io">{{.i18n.Tr "help"}}</a-->
<div class="right stackable menu">
<form class="fourteen wide mobile ten wide tablet ten wide computer column ui form ignore-dirty" style="margin:auto" action="/explore/repos">
<form id="searchForm" class="fourteen wide mobile ten wide tablet ten wide computer column ui form ignore-dirty" style="margin:auto" action="/all/search/" method="post">
<div class="ui fluid action input" style="background:#363840 ;border-radius: 5px;width: 200px;height:30px;border: #888888 solid 1px;">
<input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search_pro"}}..."
<input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search"}}..."
style="transition: background-color 5000s ease-in-out 0s;-webkit-text-fill-color:#888888;background:#363840 ;color:#888888;border: none;outline: none;">
<input type="hidden" name="tab" value="{{$.TabName}}">
<input type="hidden" name="sort" value="{{$.SortType}}">


+ 4
- 4
templates/base/head_navbar_pro.tmpl View File

@@ -96,9 +96,9 @@

{{if .IsSigned}}
<div class="right stackable menu">
<form class="fourteen wide mobile ten wide tablet ten wide computer column ui form ignore-dirty" style="margin:auto" action="/explore/repos">
<form id="searchForm" class="fourteen wide mobile ten wide tablet ten wide computer column ui form ignore-dirty" style="margin:auto" action="/all/search/" method="post">
<div class="ui fluid action input" style="background:#363840 ;border-radius: 5px;width: 200px;height:30px;border: #888888 solid 1px;">
<input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search_pro"}}..."
<input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search"}}..."
style="transition: background-color 5000s ease-in-out 0s;-webkit-text-fill-color:#888888;background:#363840 ;color:#888888;border: none;outline: none;">
<input type="hidden" name="tab" value="{{$.TabName}}">
<input type="hidden" name="sort" value="{{$.SortType}}">
@@ -199,9 +199,9 @@

<!--a class="item" target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io">{{.i18n.Tr "help"}}</a-->
<div class="right stackable menu">
<form class="fourteen wide mobile ten wide tablet ten wide computer column ui form ignore-dirty" style="margin:auto" action="/explore/repos">
<form id="searchForm" class="fourteen wide mobile ten wide tablet ten wide computer column ui form ignore-dirty" style="margin:auto" action="/all/search/" method="post">
<div class="ui fluid action input" style="background:#363840 ;border-radius: 5px;width: 200px;height:30px;border: #888888 solid 1px;">
<input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search_pro"}}..."
<input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search"}}..."
style="transition: background-color 5000s ease-in-out 0s;-webkit-text-fill-color:#888888;background:#363840 ;color:#888888;border: none;outline: none;">
<input type="hidden" name="tab" value="{{$.TabName}}">
<input type="hidden" name="sort" value="{{$.SortType}}">


+ 95
- 0
templates/explore/search_new.tmpl View File

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

<div class="explore seach">
<div class="repos--seach">
<div class="ui container">
<div id="search_div" class="ui two column centered grid">
<div class="fourteen wide mobile ten wide tablet ten wide computer column ui form ignore-dirty" style="margin-top:1.2rem;margin-bottom: 1.2rem;">
<div class="ui fluid action input">
<input name="q" id="keyword_input" value="{{.Keyword}}" placeholder="{{.i18n.Tr "home.search"}}..." autofocus="">
<input type="hidden" name="topic" value="">
<input type="hidden" name="tab" value="">
<input type="hidden" name="sort" value="hot">
<button class="ui green button" onclick="search()">{{.i18n.Tr "home.search"}}</button>
</div>
</div>
</div>
<div id="search_label_div" style="display:none">
</div>
</div>

<div class="ui container seachnav">
<div class="ui secondary pointing menu">
<a id="repo_item" class="item" href="javascript:searchItem(1,10);">
{{.i18n.Tr "home.search_repo"}}
<span class="ui circular mini label" id="repo_total"></span>
</a>
<a id="dataset_item" class="item" href="javascript:searchItem(5,50);">
{{.i18n.Tr "home.search_dataset"}}
<span class="ui circular mini label" id="dataset_total"></span>
</a>
<a id="issue_item" class="item" href="javascript:searchItem(2,20);">
{{.i18n.Tr "home.search_issue"}}
<span class="ui circular mini label" id="issue_total"></span>
</a>
<a id="pr_item" class="item" href="javascript:searchItem(6,60);">
{{.i18n.Tr "home.search_pr"}}
<span class="ui circular mini label" id="pr_total"></span>
</a>
<a id="user_item" class="item" href="javascript:searchItem(3,30);">
{{.i18n.Tr "home.search_user"}}
<span class="ui circular mini label" id="user_total"></span>
</a>
<a id="org_item" class="item" href="javascript:searchItem(4,40);">
{{.i18n.Tr "home.search_org"}} <span class="ui circular mini label" id="org_total"></span>
</a>
</div>
</div>
</div>

<div class="ui container">
<span id="find_id">{{.i18n.Tr "home.search_finded"}}</span><span id="find_title"></span>
<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" id="sort_type">
</div>
</div>

</div>
<div class="ui divider" style="margin-top: 1.25rem;"></div>

<div class="ui very relaxed divided list" id="child_search_item">

</div><!--seach list end-->
<div class="center page buttons" style="margin: 0px auto 15px">
<div class="ui borderless mini pagination menu" id="page_menu">
</div>
</div>
<div id="tipmsg"></div>
</div>

</div>
<script src="/self/js/jquery.min.js" type="text/javascript"></script>
<script src="/home/search.js?v={{MD5 AppVer}}" type="text/javascript"></script>
<div class="am-mt-30"></div>


{{template "base/footer" .}}

+ 14
- 2
templates/repo/cloudbrain/benchmark/show.tmpl View File

@@ -196,7 +196,13 @@ td, th {
<span class="accordion-panel-title-content">
<span>
<div class="ac-display-inblock title_text acc-margin-bottom">
<span class="cti-mgRight-sm">{{TimeSinceUnix1 .CreatedUnix}}</span>
<span class="cti-mgRight-sm">
{{if not (eq .StartTime 0)}}
<td>{{TimeSinceUnix1 .StartTime}}</td>
{{else}}
<td>{{TimeSinceUnix1 .CreatedUnix}}<td>
{{end}}
</span>

<span class="cti-mgRight-sm">{{$.i18n.Tr "repo.modelarts.status"}}:
<span id="{{.VersionName}}-status-span"><i id="icon" style="vertical-align: middle;" class="{{.Status}}"></i><span id="text" style="margin-left: 0.4em;font-size: 12px;">{{.Status}}</span></span>
@@ -252,7 +258,13 @@ td, th {

<td class="ti-text-form-content">
<div class="text-span text-span-w">
<span style="font-size: 12px;" class="">{{TimeSinceUnix1 .CreatedUnix}}</span>
<span style="font-size: 12px;" class="">
{{if not (eq .StartTime 0)}}
{{TimeSinceUnix1 .StartTime}}
{{else}}
{{TimeSinceUnix1 .CreatedUnix}}
{{end}}
</span>
</div>
</td>
</tr>


+ 10
- 2
templates/repo/cloudbrain/show.tmpl View File

@@ -74,11 +74,19 @@
</tr>
<tr>
<td> 开始时间 </td>
<td>{{.JobStatus.StartTime}}</td>
{{if not (eq $.task.StartTime 0)}}
<td>{{TimeSinceUnix1 $.task.StartTime}}</td>
{{else}}
<td>无<td>
{{end}}
</tr>
<tr>
<td> 结束时间 </td>
<td>{{.JobStatus.EndTime}}</td>
{{if not (eq $.task.EndTime 0)}}
<td>{{TimeSinceUnix1 $.task.EndTime}}</td>
{{else}}
<td>无<td>
{{end}}
</tr>
<tr>
<td> ExitCode </td>


+ 16
- 14
templates/repo/cloudbrain/trainjob/new.tmpl View File

@@ -195,20 +195,22 @@
<span id="add_run_para" style="margin-left: 0.5rem;cursor:pointer;color: rgba(3, 102, 214, 100);font-size: 14px;line-height: 26px;font-family: SourceHanSansSC-medium;"><i class="plus square outline icon"></i>{{.i18n.Tr "repo.modelarts.train_job.add_run_parameter"}}</span>
<input id="store_run_para" type="hidden" name="run_para_list">
<div class="dynamic field" style="margin-top: 1rem;">
{{if ne 0 (len .params)}}
{{range $k ,$v := .params}}
<div class="two fields width85" id="para{{$k}}">
<div class="field">
<input type="text" name="shipping_first-name" value={{$v.Label}} required>
</div>
<div class="field">
<input type="text" name="shipping_last-name" value={{$v.Value}} required>
</div>
<span>
<i class="trash icon"></i>
</span>
{{if .params}}
{{if ne 0 (len .params)}}
{{range $k ,$v := .params}}
<div class="two fields width85" id="para{{$k}}">
<div class="field">
<input type="text" name="shipping_first-name" value={{$v.Label}} required>
</div>
<div class="field">
<input type="text" name="shipping_last-name" value={{$v.Value}} required>
</div>
<span>
<i class="trash icon"></i>
</span>

</div>
</div>
{{end}}
{{end}}
{{end}}
</div>
@@ -386,7 +388,7 @@
identifier : 'display_job_name',
rules: [
{
type: 'regExp[/^[a-zA-Z0-9-_]{1,64}[^-]$/]',
type: 'regExp[/^[a-zA-Z0-9-_]{1,64}[a-zA-Z0-9_]$/]',
}
]
},


+ 1
- 1
templates/repo/editor/upload.tmpl View File

@@ -27,7 +27,7 @@
</div>
<div class="field">
<div class="files"></div>
<div class="ui dropzone" id="dropzone" data-upload-url="{{.RepoLink}}/upload-file" data-remove-url="{{.RepoLink}}/upload-remove" data-csrf="{{.CsrfToken}}" data-accepts="{{.UploadAllowedTypes}}" data-max-file="{{.UploadMaxFiles}}" data-max-size="{{.UploadMaxSize}}" data-default-message="{{.i18n.Tr "dropzone.default_message"}}asdsadsad" data-invalid-input-type="{{.i18n.Tr "dropzone.invalid_input_type"}}" data-file-too-big="{{.i18n.Tr "dropzone.file_too_big"}}" data-remove-file="{{.i18n.Tr "dropzone.remove_file"}}"></div>
<div class="ui dropzone" id="dropzone" data-upload-url="{{.RepoLink}}/upload-file" data-remove-url="{{.RepoLink}}/upload-remove" data-csrf="{{.CsrfToken}}" data-accepts="{{.UploadAllowedTypes}}" data-max-file="{{.UploadMaxFiles}}" data-max-size="{{.UploadMaxSize}}" data-default-message="{{.i18n.Tr "dropzone.default_message"}}" data-invalid-input-type="{{.i18n.Tr "dropzone.invalid_input_type"}}" data-file-too-big="{{.i18n.Tr "dropzone.file_too_big"}}" data-remove-file="{{.i18n.Tr "dropzone.remove_file"}}"></div>
</div>
{{template "repo/editor/commit_form" .}}
</form>


+ 7
- 1
templates/repo/modelarts/inferencejob/show.tmpl View File

@@ -232,7 +232,13 @@ td, th {

<td class="ti-text-form-content">
<div class="text-span text-span-w">
<span style="font-size: 12px;" class="">{{TimeSinceUnix1 .CreatedUnix}}</span>
<span style="font-size: 12px;" class="">
{{if not (eq .StartTime 0)}}
{{TimeSinceUnix1 .StartTime}}
{{else}}
{{TimeSinceUnix1 .CreatedUnix}}
{{end}}
</span>
</div>
</td>
</tr>


+ 12
- 2
templates/repo/modelarts/trainjob/show.tmpl View File

@@ -223,7 +223,12 @@ td, th {
</div>
<div class="ac-display-inblock title_text acc-margin-bottom">

<span class="cti-mgRight-sm">{{TimeSinceUnix1 .Cloudbrain.CreatedUnix}}</span>
<span class="cti-mgRight-sm">
{{if not (eq .Cloudbrain.StartTime 0)}}
{{TimeSinceUnix1 .Cloudbrain.StartTime}}
{{else}}
{{TimeSinceUnix1 .Cloudbrain.CreatedUnix}}
{{end}}</span>
<span class="cti-mgRight-sm"> {{$.i18n.Tr "repo.modelarts.current_version"}}:{{.VersionName}}</span>
<span class="cti-mgRight-sm"> {{$.i18n.Tr "repo.modelarts.parent_version"}}:{{.PreVersionName}}</span>
<span class="cti-mgRight-sm">{{$.i18n.Tr "repo.modelarts.status"}}:
@@ -293,7 +298,12 @@ td, th {

<td class="ti-text-form-content">
<div class="text-span text-span-w">
<span style="font-size: 12px;" class="">{{TimeSinceUnix1 .Cloudbrain.CreatedUnix}}</span>
<span style="font-size: 12px;" class="">
{{if not (eq .Cloudbrain.StartTime 0)}}
{{TimeSinceUnix1 .Cloudbrain.StartTime}}
{{else}}
{{TimeSinceUnix1 .Cloudbrain.CreatedUnix}}
{{end}}</span>
</div>
</td>
</tr>


+ 109
- 0
web_src/less/openi.less View File

@@ -628,6 +628,32 @@ display: block;
.a_margin{
margin: 0px !important;
}

/*pages*/
.ui.borderless.pagination {border:none}
.ui.pagination.menu .item {
min-width: 32px;
text-align: center;
height: 32px;
border-radius: .28571429rem;
margin: 0 5px;
background-color: #F2F2F2;
}
.ui.pagination.menu>.item:first-child, .ui.pagination.menu .item:last-child {
background-color: #FFF !important;
}
.ui.ui.menu .item.disabled{
background-color: #F2F2F2;
}
.ui.pagination.menu .active.item {
background-color: #3291F8;
color: #FFF;
}
.ui.pagination.menu .item>.input {
margin: 0em .5em;
width: 3em;
height: 32px;
}
@media only screen and (max-width: 767px) {
.following.bar #navbar .brand{
padding-top: 6px;
@@ -783,4 +809,87 @@ display: block;
border: none !important;
color: #0366d6 !important;
box-shadow: -15px 0px 10px #fff;
}

/**seach**/
/**搜索导航条适配窄屏**/
.seachnav{
overflow-x: auto;
overflow-y: hidden;
scrollbar-width: none; /* firefox */
-ms-overflow-style: none; /* IE 10+ */
}
.seachnav::-webkit-scrollbar {
display: none; /* Chrome Safari */
}
.ui.green.button, .ui.green.buttons .button{
background-color: #5BB973;
}
.seach .repos--seach{
padding-bottom: 0;
border-bottom: none;
}
.seach .ui.secondary.pointing.menu{
border-bottom: none;
}
.seach .ui.secondary.pointing.menu .item > i{
margin-right: 5px;
}
.seach .ui.secondary.pointing.menu .active.item{
border-bottom-width: 2px;
margin: 0 0 -1px;
}
.seach .ui.menu .active.item>.label {
background: #1684FC;
color: #FFF;
}
.seach .ui.menu .item>.label:not(.active.item>.label) {
background: #e8e8e8;
color: rgba(0,0,0,.6);
}
.highlight{
color: red;
}
.ui.list .list>.item>img.image+.content, .ui.list>.item>img.image+.content {
width: calc(100% - 4.0em);
margin-left: 0;
}
.seach .ui.list .list>.item .header, .seach .ui.list>.item .header{
margin-bottom: 0.5em;
font-size: 1.4rem !important;
font-weight: normal;
}
.seach .time, .seach .time a{
font-size: 12px;
color: grey;
}
.seach .list .item.members .ui.avatar.image {
width: 3.2em;
height: 3.2em;
}
.ui.list .list>.item.members>img.image+.content, .ui.list>.item.members>img.image+.content {
width: calc(100% - 4.0em);
margin-left: 0;
}

.searchlabel{
color: rgba(16, 16, 16, 100);
font-size: 24px;
text-align: left;
font-family: SourceHanSansSC-medium;
}

.hiddenSearch{
margin: auto;
display: none;
}

#tipmsg {
display: none;
z-index: 9999;
width:150;
height: 80;
}

Loading…
Cancel
Save