Commit 352655d5 by xmh

<feature> 子任务添加方向

<feature> 公司添加状态
<feature> 低质提取
<feature> 导出添加条件和导出内容
<feature> 非管理员和内部质检员无法看到关闭了的 pack
<feature> 内部质检员可以看到所有公司
<refactor> 菜单重构
1 parent 8f0a6d20
-- 数据仓库表,用来配置数据仓库的使用方式,例如网络硬盘,云存储,本地存储等等 -- 数据仓库表,用来配置数据仓库的使用方式,例如网络硬盘,云存储,本地存储等等
create table if not exists d_storage ( create table if not exists d_storage
"id" serial8 primary key, (
"unid" character varying(36) not null DEFAULT uuid_generate_v1(), "id" serial8 primary key,
"create_time" TIMESTAMP NOT NULL DEFAULT now(), "unid" character varying(36) not null DEFAULT uuid_generate_v1(),
"create_user" int8, "create_time" TIMESTAMP NOT NULL DEFAULT now(),
"create_user" int8,
"name" character varying(64) not null,
"type" int4 not null, "name" character varying(64) not null,
"path" character varying(512) not null "type" int4 not null,
"path" character varying(512) not null
); );
comment on table d_storage is '数据仓库表'; comment on table d_storage is '数据仓库表';
comment on column "d_storage"."name" is '数据仓库名称'; comment on column "d_storage"."name" is '数据仓库名称';
comment on column "d_storage"."type" is '数据仓库类型'; comment on column "d_storage"."type" is '数据仓库类型';
comment on column "d_storage"."path" is '路径或使用方式,配合类型使用'; comment on column "d_storage"."path" is '路径或使用方式,配合类型使用';
create index if not exists "d_storage_unid_idx" on "d_storage" using btree("unid"); create index if not exists "d_storage_unid_idx" on "d_storage" using btree ("unid");
-- 图包表,一个图包包含多张图片 -- 图包表,一个图包包含多张图片
create table if not exists d_pack ( create table if not exists d_pack
"id" serial8 primary key, (
"unid" character varying(36) not null DEFAULT uuid_generate_v1(), "id" serial8 primary key,
"create_time" TIMESTAMP NOT NULL DEFAULT now(), "unid" character varying(36) not null DEFAULT uuid_generate_v1(),
"create_user" int8, "create_time" TIMESTAMP NOT NULL DEFAULT now(),
"create_user" int8,
"storage_id" int8 not null,
"task_id" int8, "storage_id" int8 not null,
"name" character varying(64) not null, "task_id" int8,
"type" int4 not null, "name" character varying(64) not null,
"status" int4 not null default 0 "type" int4 not null,
"status" int4 not null default 0
); );
comment on table "d_pack" is '图包表'; comment on table "d_pack" is '图包表';
comment on column "d_pack"."storage_id" is '对应数据仓库id'; comment on column "d_pack"."storage_id" is '对应数据仓库id';
...@@ -35,67 +37,71 @@ comment on column "d_pack"."name" is '图包名称'; ...@@ -35,67 +37,71 @@ comment on column "d_pack"."name" is '图包名称';
comment on column "d_pack"."status" is '图包状态'; comment on column "d_pack"."status" is '图包状态';
comment on column "d_pack"."type" is '图包类型'; comment on column "d_pack"."type" is '图包类型';
comment on column "d_pack"."task_id" is '关联的任务'; comment on column "d_pack"."task_id" is '关联的任务';
create index if not exists "d_pack_unid_idx" on "d_pack" using btree("unid"); create index if not exists "d_pack_unid_idx" on "d_pack" using btree ("unid");
create index if not exists "d_pack_storage_id_idx" on "d_pack" using btree("storage_id"); create index if not exists "d_pack_storage_id_idx" on "d_pack" using btree ("storage_id");
-- 图片表,图片路径为 /d_pack.unid/d_pic.name -- 图片表,图片路径为 /d_pack.unid/d_pic.name
create table if not exists d_pic ( create table if not exists d_pic
"id" serial8 primary key, (
"unid" character varying(36) not null DEFAULT uuid_generate_v1(), "id" serial8 primary key,
"create_time" TIMESTAMP NOT NULL DEFAULT now(), "unid" character varying(36) not null DEFAULT uuid_generate_v1(),
"create_time" TIMESTAMP NOT NULL DEFAULT now(),
"name" character varying(128) not null,
"storage_id" int8 not null, "name" character varying(128) not null,
"pack_id" int8 not null, "storage_id" int8 not null,
"status" int4 not null default 0 "pack_id" int8 not null,
"status" int4 not null default 0
); );
comment on table "d_pic" is '图片表'; comment on table "d_pic" is '图片表';
comment on column "d_pic"."name" is '图片名称'; comment on column "d_pic"."name" is '图片名称';
comment on column "d_pic"."storage_id" is '对应数据仓库id'; comment on column "d_pic"."storage_id" is '对应数据仓库id';
comment on column "d_pic"."pack_id" is '对应图片包id'; comment on column "d_pic"."pack_id" is '对应图片包id';
comment on column "d_pic"."status" is '状态'; comment on column "d_pic"."status" is '状态';
create index if not exists "d_pic_unid_idx" on "d_pic" using btree("unid"); create index if not exists "d_pic_unid_idx" on "d_pic" using btree ("unid");
create index if not exists "d_pic_storage_id_idx" on "d_pic" using btree("storage_id"); create index if not exists "d_pic_storage_id_idx" on "d_pic" using btree ("storage_id");
create index if not exists "d_pic_pack_id_idx" on "d_pic" using btree("pack_id"); create index if not exists "d_pic_pack_id_idx" on "d_pic" using btree ("pack_id");
-- 字典表 -- 字典表
create table if not exists s_dict ( create table if not exists s_dict
"id" serial8 primary key, (
"unid" character varying(36) not null DEFAULT uuid_generate_v1(), "id" serial8 primary key,
"create_time" TIMESTAMP NOT NULL DEFAULT now(), "unid" character varying(36) not null DEFAULT uuid_generate_v1(),
"create_user" int8, "create_time" TIMESTAMP NOT NULL DEFAULT now(),
"create_user" int8,
"key" character varying(36) not null,
"value" int4 not null, "key" character varying(36) not null,
"description" character varying(128) "value" int4 not null,
"description" character varying(128)
); );
comment on table "s_dict" is '字典表'; comment on table "s_dict" is '字典表';
comment on column "s_dict"."key" is '关键字'; comment on column "s_dict"."key" is '关键字';
comment on column "s_dict"."value" is '值'; comment on column "s_dict"."value" is '值';
comment on column "s_dict"."description" is '描述'; comment on column "s_dict"."description" is '描述';
create index if not exists "s_dict_unid_idx" on "s_dict" using btree("unid"); create index if not exists "s_dict_unid_idx" on "s_dict" using btree ("unid");
create index if not exists "s_dict_key_idx" on "s_dict" using btree("key"); create index if not exists "s_dict_key_idx" on "s_dict" using btree ("key");
alter table s_dict add constraint s_dict_key_value_unique unique(key,value); alter table s_dict
add constraint s_dict_key_value_unique unique (key, value);
-- 任务表,任务表可以包含多个图片包 -- 任务表,任务表可以包含多个图片包
create table if not exists d_task ( create table if not exists d_task
"id" serial8 primary key, (
"unid" character varying(36) not null DEFAULT uuid_generate_v1(), "id" serial8 primary key,
"create_time" TIMESTAMP NOT NULL DEFAULT now(), "unid" character varying(36) not null DEFAULT uuid_generate_v1(),
"create_user" int8, "create_time" TIMESTAMP NOT NULL DEFAULT now(),
"create_user" int8,
"name" character varying(64) not null,
"type" int4 not null, "name" character varying(64) not null,
"label_type" int4 not null, "type" int4 not null,
"account_id" int8 not null, "label_type" int4 not null,
"contractor_manager_id" int8, "account_id" int8 not null,
"manager_id" int8, "contractor_manager_id" int8,
"assign_time" timestamp, "manager_id" int8,
"finish_time" timestamp, "assign_time" timestamp,
"in_inspector_id" int8 not null, "finish_time" timestamp,
"description" character varying(1024), "in_inspector_id" int8 not null,
"status" int4 not null default 0 "description" character varying(1024),
"status" int4 not null default 0
); );
comment on table "d_task" is '任务/项目表'; comment on table "d_task" is '任务/项目表';
comment on column "d_task"."name" is '任务名称'; comment on column "d_task"."name" is '任务名称';
...@@ -109,33 +115,34 @@ comment on column "d_task"."description" is '任务描述'; ...@@ -109,33 +115,34 @@ comment on column "d_task"."description" is '任务描述';
comment on column "d_task"."status" is '任务状态'; comment on column "d_task"."status" is '任务状态';
comment on column "d_task"."assign_time" is '任务分配时间'; comment on column "d_task"."assign_time" is '任务分配时间';
comment on column "d_task"."finish_time" is '任务完成时间'; comment on column "d_task"."finish_time" is '任务完成时间';
create index if not exists "d_task_unid_idx" on "d_task" using btree("unid"); create index if not exists "d_task_unid_idx" on "d_task" using btree ("unid");
create index if not exists "d_task_account_id_idx" on "d_task" using btree("account_id"); create index if not exists "d_task_account_id_idx" on "d_task" using btree ("account_id");
create index if not exists "d_task_contractor_manager_id_idx" on "d_task" using btree("contractor_manager_id"); create index if not exists "d_task_contractor_manager_id_idx" on "d_task" using btree ("contractor_manager_id");
create index if not exists "d_task_manager_id_idx" on "d_task" using btree("manager_id"); create index if not exists "d_task_manager_id_idx" on "d_task" using btree ("manager_id");
create index if not exists "d_task_assign_time_idx" on "d_task" using btree("assign_time"); create index if not exists "d_task_assign_time_idx" on "d_task" using btree ("assign_time");
create index if not exists "d_task_finish_time_idx" on "d_task" using btree("finish_time"); create index if not exists "d_task_finish_time_idx" on "d_task" using btree ("finish_time");
-- 子任务表 -- 子任务表
create table if not exists d_sub_task ( create table if not exists d_sub_task
"id" serial8 primary key, (
"unid" character varying(36) not null DEFAULT uuid_generate_v1(), "id" serial8 primary key,
"create_time" TIMESTAMP NOT NULL DEFAULT now(), "unid" character varying(36) not null DEFAULT uuid_generate_v1(),
"create_user" int8, "create_time" TIMESTAMP NOT NULL DEFAULT now(),
"create_user" int8,
"pic_id" int8 not null,
"pack_id" int8 not null, "pic_id" int8 not null,
"task_id" int8 not null, "pack_id" int8 not null,
"in_inspector_id" int8, "task_id" int8 not null,
"out_inspector_id" int8, "in_inspector_id" int8,
"annotator_id" int8, "out_inspector_id" int8,
"annotate_time" timestamp, "annotator_id" int8,
"label_result" character varying(1024), "annotate_time" timestamp,
"in_status" int4 not null default 1, "label_result" character varying(1024),
"out_status" int4 not null default 1, "in_status" int4 not null default 1,
"status" int4 not null default 1, "out_status" int4 not null default 1,
"direction" int4, "status" int4 not null default 1,
"person_unid" varchar(36) "direction" int4,
"person_unid" varchar(36)
); );
comment on table "d_sub_task" is '子任务表'; comment on table "d_sub_task" is '子任务表';
comment on column "d_sub_task"."pic_id" is '对应图片id'; comment on column "d_sub_task"."pic_id" is '对应图片id';
...@@ -149,30 +156,31 @@ comment on column "d_sub_task"."out_status" is '外部质检状态'; ...@@ -149,30 +156,31 @@ comment on column "d_sub_task"."out_status" is '外部质检状态';
comment on column "d_sub_task"."status" is '子任务状态'; comment on column "d_sub_task"."status" is '子任务状态';
comment on column "d_sub_task"."direction" is '方向'; comment on column "d_sub_task"."direction" is '方向';
comment on column "d_sub_task"."person_unid" is '人员Unid,reid标注中用来表示同一个人'; comment on column "d_sub_task"."person_unid" is '人员Unid,reid标注中用来表示同一个人';
create index if not exists "d_sub_task_unid_idx" on "d_sub_task" using btree("unid"); create index if not exists "d_sub_task_unid_idx" on "d_sub_task" using btree ("unid");
create index if not exists "d_sub_task_pack_id_idx" on "d_sub_task" using btree("pack_id"); create index if not exists "d_sub_task_pack_id_idx" on "d_sub_task" using btree ("pack_id");
create index if not exists "d_sub_task_pack_id_person_unid_status_idx" on "d_sub_task" using btree("pic_id","person_unid","status"); create index if not exists "d_sub_task_pack_id_person_unid_status_idx" on "d_sub_task" using btree ("pic_id", "person_unid", "status");
create index if not exists "d_sub_task_task_id_idx" on "d_sub_task" using btree("task_id"); create index if not exists "d_sub_task_task_id_idx" on "d_sub_task" using btree ("task_id");
create index if not exists "d_sub_task_in_inspector_id_idx" on "d_sub_task" using btree("in_inspector_id"); create index if not exists "d_sub_task_in_inspector_id_idx" on "d_sub_task" using btree ("in_inspector_id");
create index if not exists "d_sub_task_out_inspector_id_idx" on "d_sub_task" using btree("out_inspector_id"); create index if not exists "d_sub_task_out_inspector_id_idx" on "d_sub_task" using btree ("out_inspector_id");
create index if not exists "d_sub_task_annotator_id_idx" on "d_sub_task" using btree("annotator_id"); create index if not exists "d_sub_task_annotator_id_idx" on "d_sub_task" using btree ("annotator_id");
create index if not exists "d_sub_task_person_unid_status_idx" on "d_sub_task" using btree("person_unid","status"); create index if not exists "d_sub_task_person_unid_status_idx" on "d_sub_task" using btree ("person_unid", "status");
-- 用户表 -- 用户表
create table if not exists s_user ( create table if not exists s_user
"id" serial8 primary key, (
"unid" character varying(36) not null DEFAULT uuid_generate_v1(), "id" serial8 primary key,
"create_time" TIMESTAMP NOT NULL DEFAULT now(), "unid" character varying(36) not null DEFAULT uuid_generate_v1(),
"create_user" int8, "create_time" TIMESTAMP NOT NULL DEFAULT now(),
"create_user" int8,
"username" character varying(20) not null,
"password" character varying(20) not null, "username" character varying(20) not null,
"type" int4 not null default -1, "password" character varying(20) not null,
"name" character varying(20), "type" int4 not null default -1,
"mail" character varying(64), "name" character varying(20),
"tel" character varying(20), "mail" character varying(64),
"account_id" int8, "tel" character varying(20),
"last_login_time" TIMESTAMP "account_id" int8,
"last_login_time" TIMESTAMP
); );
comment on table "s_user" is '用户表'; comment on table "s_user" is '用户表';
comment on column "s_user"."username" is '用户名'; comment on column "s_user"."username" is '用户名';
...@@ -183,22 +191,24 @@ comment on column "s_user"."mail" is '邮箱'; ...@@ -183,22 +191,24 @@ comment on column "s_user"."mail" is '邮箱';
comment on column "s_user"."tel" is '电话'; comment on column "s_user"."tel" is '电话';
comment on column "s_user"."account_id" is '所属账户/公司'; comment on column "s_user"."account_id" is '所属账户/公司';
comment on column "s_user"."last_login_time" is '最后登录时间'; comment on column "s_user"."last_login_time" is '最后登录时间';
alter table s_user add constraint s_user_username_unique unique(username); alter table s_user
create index if not exists "s_user_unid_idx" on "s_user" using btree("unid"); add constraint s_user_username_unique unique (username);
create index if not exists "s_user_username_idx" on "s_user" using btree("username"); create index if not exists "s_user_unid_idx" on "s_user" using btree ("unid");
create index if not exists "s_user_account_id_idx" on "s_user" using btree("account_id"); create index if not exists "s_user_username_idx" on "s_user" using btree ("username");
create index if not exists "s_user_account_id_idx" on "s_user" using btree ("account_id");
-- 账户/公司表 -- 账户/公司表
create table if not exists s_account ( create table if not exists s_account
"id" serial8 primary key, (
"unid" character varying(36) not null DEFAULT uuid_generate_v1(), "id" serial8 primary key,
"create_time" TIMESTAMP NOT NULL DEFAULT now(), "unid" character varying(36) not null DEFAULT uuid_generate_v1(),
"create_user" int8, "create_time" TIMESTAMP NOT NULL DEFAULT now(),
"create_user" int8,
"name" character varying(128) not null,
"manager_id" int8, "name" character varying(128) not null,
"description" character varying(128), "manager_id" int8,
"status" int4 not null default 1 "description" character varying(128),
"status" int4 not null default 1
); );
comment on table "s_account" is '账户/公司表'; comment on table "s_account" is '账户/公司表';
comment on column "s_account"."name" is '账户/公司名称'; comment on column "s_account"."name" is '账户/公司名称';
...@@ -207,89 +217,52 @@ comment on column "s_account"."description" is '描述'; ...@@ -207,89 +217,52 @@ comment on column "s_account"."description" is '描述';
-- 图包-标签表 -- 图包-标签表
create table if not exists r_pack_tag ( create table if not exists r_pack_tag
"id" serial8 primary key, (
"create_time" TIMESTAMP NOT NULL DEFAULT now(), "id" serial8 primary key,
"create_time" TIMESTAMP NOT NULL DEFAULT now(),
"pack_id" int8 not null,
"tag" int4 not null "pack_id" int8 not null,
"tag" int4 not null
); );
comment on table "r_pack_tag" is '图包标签关联表'; comment on table "r_pack_tag" is '图包标签关联表';
comment on column "r_pack_tag"."pack_id" is '图包id'; comment on column "r_pack_tag"."pack_id" is '图包id';
comment on column "r_pack_tag"."tag" is '标签值'; comment on column "r_pack_tag"."tag" is '标签值';
create index if not exists "r_pack_tag_pack_id_idx" on "r_pack_tag" using btree("pack_id"); create index if not exists "r_pack_tag_pack_id_idx" on "r_pack_tag" using btree ("pack_id");
create index if not exists "r_pack_tag_tag_idx" on "r_pack_tag" using btree("tag"); create index if not exists "r_pack_tag_tag_idx" on "r_pack_tag" using btree ("tag");
-- 日志表 -- 日志表
CREATE TABLE IF NOT EXISTS s_log ( CREATE TABLE IF NOT EXISTS s_log
"id" serial8 PRIMARY KEY, (
"create_time" TIMESTAMP NOT NULL DEFAULT now( ), "id" serial8 PRIMARY KEY,
"create_time" TIMESTAMP NOT NULL DEFAULT now(),
"operate_user" int8 NOT NULL,
"operate_date" DATE NOT NULL DEFAULT now( ), "operate_user" int8 NOT NULL,
"operate_type" int4, "operate_date" DATE NOT NULL DEFAULT now(),
"operate" VARCHAR ( 1024 ) "operate_type" int4,
"operate" VARCHAR(1024)
); );
comment on table "s_log" is '日志表'; comment on table "s_log" is '日志表';
comment on column "s_log"."operate_user" is '用户'; comment on column "s_log"."operate_user" is '用户';
comment on column "s_log"."operate_date" is '日期'; comment on column "s_log"."operate_date" is '日期';
comment on column "s_log"."operate_type" is '操作代码'; comment on column "s_log"."operate_type" is '操作代码';
comment on column "s_log"."operate" is '具体操作'; comment on column "s_log"."operate" is '具体操作';
create index if not exists "s_log_date_user_idx" on "s_log" using btree("operate_date","operate_user"); create index if not exists "s_log_date_user_idx" on "s_log" using btree ("operate_date", "operate_user");
create index if not exists "s_log_user_idx" on "s_log" using btree("operate_user"); create index if not exists "s_log_user_idx" on "s_log" using btree ("operate_user");
-- 初始数据
insert into s_user(username,password,type,name,account_id) values ('vion','viontech',0,'超级管理员',1);
insert into s_account(name,manager_id,description) values ('vion',1,'vion');
insert into s_dict(key,value,description) values ('userType',0,'超级管理员');
insert into s_dict(key,value,description) values ('userType',1,'项目经理');
insert into s_dict(key,value,description) values ('userType',2,'内部质检员');
insert into s_dict(key,value,description) values ('userType',3,'外部管理员');
insert into s_dict(key,value,description) values ('userType',4,'外部质检员');
insert into s_dict(key,value,description) values ('userType',5,'外部标注员');
insert into s_dict(key,value,description) values ('userType',6,'兼职标注员');
insert into s_dict(key,value,description) values ('packStatus',1,'待完成');
insert into s_dict(key,value,description) values ('packStatus',2,'审核中');
insert into s_dict(key,value,description) values ('packStatus',3,'审核驳回');
insert into s_dict(key,value,description) values ('packStatus',4,'审核通过');
insert into s_dict(key,value,description) values ('reidOperateType',1,'REID合并图片');
insert into s_dict(key,value,description) values ('reidOperateType',2,'REID合并人');
insert into s_dict(key,value,description) values ('reidOperateType',3,'REID合并图片到人');
insert into s_dict(key,value,description) values ('reidOperateType',4,'REID删除');
insert into s_dict(key,value,description) values ('reidOperateType',5,'REID完成标注');
-- 外键,正式环境不执行
alter table s_user add FOREIGN KEY ("account_id") REFERENCES "public"."s_account" ("id");
alter table d_sub_task add FOREIGN KEY ("task_id") REFERENCES "public"."d_task" ("id");
alter table d_sub_task add FOREIGN KEY ("pic_id") REFERENCES "public"."d_pic" ("id");
alter table d_task add FOREIGN KEY ("account_id") REFERENCES "public"."s_account" ("id");
alter table d_pic add FOREIGN KEY ("storage_id") REFERENCES "public"."d_storage" ("id");
alter table d_pic add FOREIGN KEY ("pack_id") REFERENCES "public"."d_pack" ("id");
alter table d_pack add FOREIGN KEY ("storage_id") REFERENCES "public"."d_storage" ("id");
alter table d_pack add FOREIGN KEY ("task_id") REFERENCES "public"."d_task" ("id");
alter table r_pack_tag add FOREIGN KEY ("pack_id") REFERENCES "public"."d_pack" ("id");
-- 禁止用户表 -- 禁止用户表
create table if not exists s_forbidden_user ( create table if not exists s_forbidden_user
"id" serial8, (
"user_id" varchar(64) DEFAULT NULL, "id" serial8,
"status" int2 DEFAULT NULL, "user_id" varchar(64) DEFAULT NULL,
"deleted" int2 DEFAULT NULL, "status" int2 DEFAULT NULL,
"name" varchar(32) DEFAULT NULL, "deleted" int2 DEFAULT NULL,
"remark" varchar(64) DEFAULT NULL, "name" varchar(32) DEFAULT NULL,
"url" varchar(32) DEFAULT NULL, "remark" varchar(64) DEFAULT NULL,
"create_time" timestamp DEFAULT NULL, "url" varchar(32) DEFAULT NULL,
"update_time" timestamp DEFAULT NULL, "create_time" timestamp DEFAULT NULL,
CONSTRAINT "s_forbidden_user_pkey" PRIMARY KEY ("id") "update_time" timestamp DEFAULT NULL,
CONSTRAINT "s_forbidden_user_pkey" PRIMARY KEY ("id")
); );
COMMENT ON COLUMN "public"."s_forbidden_user"."id" IS 'id'; COMMENT ON COLUMN "public"."s_forbidden_user"."id" IS 'id';
COMMENT ON COLUMN "public"."s_forbidden_user"."user_id" IS '用户id'; COMMENT ON COLUMN "public"."s_forbidden_user"."user_id" IS '用户id';
...@@ -301,4 +274,73 @@ COMMENT ON COLUMN "public"."s_forbidden_user"."url" IS '请求接口'; ...@@ -301,4 +274,73 @@ COMMENT ON COLUMN "public"."s_forbidden_user"."url" IS '请求接口';
COMMENT ON COLUMN "public"."s_forbidden_user"."create_time" IS '创建时间'; COMMENT ON COLUMN "public"."s_forbidden_user"."create_time" IS '创建时间';
COMMENT ON COLUMN "public"."s_forbidden_user"."update_time" IS '修改时间'; COMMENT ON COLUMN "public"."s_forbidden_user"."update_time" IS '修改时间';
COMMENT ON TABLE "public"."s_forbidden_user" IS '禁止用户表'; COMMENT ON TABLE "public"."s_forbidden_user" IS '禁止用户表';
create index if not exists "indx_user_id" on "s_forbidden_user" using btree("user_id"); create index if not exists "indx_user_id" on "s_forbidden_user" using btree ("user_id");
-- 初始数据
insert into s_user(username, password, type, name, account_id)
values ('vion', 'viontech', 0, '超级管理员', 1);
insert into s_account(name, manager_id, description)
values ('vion', 1, 'vion');
insert into s_dict(key, value, description)
values ('userType', 0, '超级管理员');
insert into s_dict(key, value, description)
values ('userType', 1, '项目经理');
insert into s_dict(key, value, description)
values ('userType', 2, '内部质检员');
insert into s_dict(key, value, description)
values ('userType', 3, '外部管理员');
insert into s_dict(key, value, description)
values ('userType', 4, '外部质检员');
insert into s_dict(key, value, description)
values ('userType', 5, '外部标注员');
insert into s_dict(key, value, description)
values ('userType', 6, '兼职标注员');
insert into s_dict(key, value, description)
values ('packStatus', 1, '待完成');
insert into s_dict(key, value, description)
values ('packStatus', 2, '审核中');
insert into s_dict(key, value, description)
values ('packStatus', 3, '审核驳回');
insert into s_dict(key, value, description)
values ('packStatus', 4, '审核通过');
insert into s_dict(key, value, description)
values ('reidOperateType', 1, 'REID合并图片');
insert into s_dict(key, value, description)
values ('reidOperateType', 2, 'REID合并人');
insert into s_dict(key, value, description)
values ('reidOperateType', 3, 'REID合并图片到人');
insert into s_dict(key, value, description)
values ('reidOperateType', 4, 'REID删除');
insert into s_dict(key, value, description)
values ('reidOperateType', 5, 'REID完成标注');
-- 外键,正式环境不执行
alter table s_user
add FOREIGN KEY ("account_id") REFERENCES "public"."s_account" ("id");
alter table d_sub_task
add FOREIGN KEY ("task_id") REFERENCES "public"."d_task" ("id");
alter table d_sub_task
add FOREIGN KEY ("pic_id") REFERENCES "public"."d_pic" ("id");
alter table d_task
add FOREIGN KEY ("account_id") REFERENCES "public"."s_account" ("id");
alter table d_pic
add FOREIGN KEY ("storage_id") REFERENCES "public"."d_storage" ("id");
alter table d_pic
add FOREIGN KEY ("pack_id") REFERENCES "public"."d_pack" ("id");
alter table d_pack
add FOREIGN KEY ("storage_id") REFERENCES "public"."d_storage" ("id");
alter table d_pack
add FOREIGN KEY ("task_id") REFERENCES "public"."d_task" ("id");
alter table r_pack_tag
add FOREIGN KEY ("pack_id") REFERENCES "public"."d_pack" ("id");
...@@ -22,10 +22,11 @@ public class AccountController extends AccountBaseController { ...@@ -22,10 +22,11 @@ public class AccountController extends AccountBaseController {
protected BaseExample getExample(AccountVo accountVo, int type) { protected BaseExample getExample(AccountVo accountVo, int type) {
User currentUser = userService.getCurrentUser(); User currentUser = userService.getCurrentUser();
Long accountId = currentUser.getAccountId(); Long accountId = currentUser.getAccountId();
if (!currentUser.getType().equals(0)) { // 类型为管理员和内部质检员 可以查看所有公司
if (!currentUser.getType().equals(0) && !currentUser.getType().equals(2)) {
accountVo.setId(accountId); accountVo.setId(accountId);
} }
AccountExample accountExample = (AccountExample)super.getExample(accountVo,type); AccountExample accountExample = (AccountExample) super.getExample(accountVo, type);
return accountExample; return accountExample;
} }
} }
\ No newline at end of file \ No newline at end of file
...@@ -36,9 +36,9 @@ public class PackController extends PackBaseController { ...@@ -36,9 +36,9 @@ public class PackController extends PackBaseController {
User currentUser = userService.getCurrentUser(); User currentUser = userService.getCurrentUser();
// 类型为管理员和内部质检员 可以查看所有的 pack // 类型为管理员和内部质检员 可以查看所有的 pack
if (!currentUser.getType().equals(0) && !currentUser.getType().equals(2)) { if (!currentUser.getType().equals(0) && !currentUser.getType().equals(2)) {
packExample.andTaskCriteria().andAccountIdEqualTo(currentUser.getAccountId()); packExample.andTaskCriteria().andAccountIdEqualTo(currentUser.getAccountId())
.andStatusNotEqualTo(0);
} }
return packExample; return packExample;
} }
......
...@@ -9,10 +9,10 @@ import com.viontech.keliu.util.DateUtil; ...@@ -9,10 +9,10 @@ import com.viontech.keliu.util.DateUtil;
import com.viontech.keliu.util.JsonMessageUtil; import com.viontech.keliu.util.JsonMessageUtil;
import com.viontech.label.platform.mapper.LogMapper; import com.viontech.label.platform.mapper.LogMapper;
import com.viontech.label.platform.mapper.SubTaskMapper; import com.viontech.label.platform.mapper.SubTaskMapper;
import com.viontech.label.platform.model.SubTask; import com.viontech.label.platform.model.*;
import com.viontech.label.platform.model.SubTaskExample; import com.viontech.label.platform.service.adapter.PackService;
import com.viontech.label.platform.model.User;
import com.viontech.label.platform.service.adapter.SubTaskService; import com.viontech.label.platform.service.adapter.SubTaskService;
import com.viontech.label.platform.service.adapter.TaskService;
import com.viontech.label.platform.service.main.ReidService; import com.viontech.label.platform.service.main.ReidService;
import com.viontech.label.platform.vo.LogVo; import com.viontech.label.platform.vo.LogVo;
import com.viontech.label.platform.vo.ReidUploadData; import com.viontech.label.platform.vo.ReidUploadData;
...@@ -26,6 +26,7 @@ import javax.servlet.http.HttpServletResponse; ...@@ -26,6 +26,7 @@ import javax.servlet.http.HttpServletResponse;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.*; import java.util.*;
import java.util.stream.Collectors;
/** /**
* . * .
...@@ -42,6 +43,10 @@ public class ReidController { ...@@ -42,6 +43,10 @@ public class ReidController {
private ReidService reidService; private ReidService reidService;
@Resource @Resource
private SubTaskService subTaskService; private SubTaskService subTaskService;
@Resource
private PackService packservice;
@Resource
private TaskService taskService;
@PostMapping("/upload") @PostMapping("/upload")
...@@ -166,6 +171,17 @@ public class ReidController { ...@@ -166,6 +171,17 @@ public class ReidController {
return JsonMessageUtil.getSuccessJsonMsg("success"); return JsonMessageUtil.getSuccessJsonMsg("success");
} }
@GetMapping("/mergeAndLowQuality")
public Object mergeAndLowQuality(@RequestParam(required = false, defaultValue = "") String[] personUnidArr, @RequestParam(required = false, defaultValue = "") Long[] subTaskIdArr,
@RequestParam Long packId, @RequestParam String currentPerson) {
try {
reidService.mergeAndLowQuality(personUnidArr, subTaskIdArr, packId, currentPerson);
} catch (Exception e) {
return JsonMessageUtil.getErrorJsonMsg(e.getMessage());
}
return JsonMessageUtil.getSuccessJsonMsg("success");
}
/** /**
* 标记某个人已经被清理干净了 * 标记某个人已经被清理干净了
...@@ -253,13 +269,36 @@ public class ReidController { ...@@ -253,13 +269,36 @@ public class ReidController {
} }
@GetMapping("export") @GetMapping("export")
public void exportLabelResult(@RequestParam Long packId, @RequestParam Date start, @RequestParam Date end, HttpServletResponse response) throws IOException { public void exportLabelResult(@RequestParam(required = false) Long packId, @RequestParam(required = false) Long accountId, @RequestParam(required = false) Long taskId,
@RequestParam Date start, @RequestParam Date end, HttpServletResponse response) throws IOException {
StpUtil.checkRole("super"); StpUtil.checkRole("super");
List<Pack> packs = getPacks(accountId, taskId, packId);
List<Long> packIds = packs.stream().map(Pack::getId).collect(Collectors.toList());
if (packIds.size() == 0) {
return;
}
List<Long> taskIds = packs.stream().map(Pack::getTaskId).collect(Collectors.toList());
TaskExample taskExample = new TaskExample();
taskExample.createColumns();
taskExample.createAccountColumns();
taskExample.createCriteria().andIdIn(taskIds);
List<Task> tasks = taskService.selectByExample(taskExample);
Map<Long, Task> taskMap = tasks.stream().collect(Collectors.toMap(Task::getId, x -> x, (a, b) -> a));
Account account = tasks.get(0).getAccount();
LogMapper mapper = (LogMapper) reidService.getLogService().getMapper(); LogMapper mapper = (LogMapper) reidService.getLogService().getMapper();
List<LogVo> logs = mapper.exportLogByDateAndPack(packId, start, end); List<LogVo> logs = mapper.exportLogByDateAndPack(packIds, start, end);
for (LogVo log : logs) {
log.setTaskName(taskMap.get(log.getTaskId()).getName());
log.setAccountName(account.getName());
}
HashSet<String> includeColumn = new HashSet<>(); HashSet<String> includeColumn = new HashSet<>();
includeColumn.add("accountName");
includeColumn.add("taskName");
includeColumn.add("username"); includeColumn.add("username");
includeColumn.add("name");
includeColumn.add("personUnid"); includeColumn.add("personUnid");
includeColumn.add("picNum"); includeColumn.add("picNum");
includeColumn.add("finishTime"); includeColumn.add("finishTime");
...@@ -269,6 +308,25 @@ public class ReidController { ...@@ -269,6 +308,25 @@ public class ReidController {
EasyExcel.write(response.getOutputStream(), LogVo.class).includeColumnFiledNames(includeColumn).sheet().doWrite(logs); EasyExcel.write(response.getOutputStream(), LogVo.class).includeColumnFiledNames(includeColumn).sheet().doWrite(logs);
} }
private List<Pack> getPacks(Long accountId, Long taskId, Long packId) {
if (packId != null) {
return Collections.singletonList(packservice.selectByPrimaryKey(packId));
}
PackExample packExample = new PackExample();
TaskExample.Criteria criteria = packExample.andTaskCriteria();
if (taskId != null) {
criteria.andIdEqualTo(taskId);
} else if (accountId != null) {
criteria.andAccountIdEqualTo(accountId);
} else {
return Collections.emptyList();
}
return packservice.selectByExample(packExample);
}
/**
* 特征池重建
*/
@GetMapping("reconstruction") @GetMapping("reconstruction")
public Object featurePoolReconstruction(@RequestParam Long packId) { public Object featurePoolReconstruction(@RequestParam Long packId) {
reidService.reConstruction(packId); reidService.reConstruction(packId);
......
...@@ -7,6 +7,7 @@ import com.viontech.keliu.util.JsonMessageUtil.JsonMessage; ...@@ -7,6 +7,7 @@ import com.viontech.keliu.util.JsonMessageUtil.JsonMessage;
import com.viontech.label.platform.base.BaseExample; import com.viontech.label.platform.base.BaseExample;
import com.viontech.label.platform.config.VionConfig; import com.viontech.label.platform.config.VionConfig;
import com.viontech.label.platform.controller.base.UserBaseController; import com.viontech.label.platform.controller.base.UserBaseController;
import com.viontech.label.platform.model.Account;
import com.viontech.label.platform.model.User; import com.viontech.label.platform.model.User;
import com.viontech.label.platform.model.UserExample; import com.viontech.label.platform.model.UserExample;
import com.viontech.label.platform.vo.UserVo; import com.viontech.label.platform.vo.UserVo;
...@@ -47,10 +48,16 @@ public class UserController extends UserBaseController { ...@@ -47,10 +48,16 @@ public class UserController extends UserBaseController {
String username = loginUser.getUsername(); String username = loginUser.getUsername();
String password = loginUser.getPassword(); String password = loginUser.getPassword();
UserExample userExample = new UserExample(); UserExample userExample = new UserExample();
userExample.createAccountColumns();
userExample.createColumns();
userExample.createCriteria().andUsernameEqualTo(username); userExample.createCriteria().andUsernameEqualTo(username);
List<User> users = getService().selectByExample(userExample); List<User> users = getService().selectByExample(userExample);
if (users.size() > 0) { if (users.size() > 0) {
User user = users.get(0); User user = users.get(0);
Account account = user.getAccount();
if (account.getStatus() == 0) {
throw new RuntimeException("账户无法使用");
}
String passwordInDb = user.getPassword(); String passwordInDb = user.getPassword();
user.setPassword(null); user.setPassword(null);
if (password.equals(passwordInDb)) { if (password.equals(passwordInDb)) {
...@@ -74,6 +81,12 @@ public class UserController extends UserBaseController { ...@@ -74,6 +81,12 @@ public class UserController extends UserBaseController {
} }
} }
@GetMapping("/logout")
public Object logout() {
StpUtil.logout();
return JsonMessageUtil.getSuccessJsonMsg();
}
@RequestMapping(value = "", method = RequestMethod.POST) @RequestMapping(value = "", method = RequestMethod.POST)
@ResponseBody @ResponseBody
@Override @Override
......
...@@ -33,6 +33,9 @@ public interface LogMapper extends BaseMapper { ...@@ -33,6 +33,9 @@ public interface LogMapper extends BaseMapper {
int updateByPrimaryKey(Log record); int updateByPrimaryKey(Log record);
@Select("select \"max\"(s_user.name) as username ,\"max\"(annotate_time) as finishTime ,person_unid as personUnid,count(*) as picNum from d_sub_task left join s_user on d_sub_task.annotator_id=s_user.id where pack_id=#{packId} and status=3 and annotate_time BETWEEN #{start} and #{end} group by person_unid ") @Select("<script> select \"max\"(s_user.username) as username,\"max\"(s_user.name) as name ,\"max\"(annotate_time) as finishTime ,person_unid as personUnid,count(*) as picNum, task_id as taskId " +
List<LogVo> exportLogByDateAndPack(Long packId, Date start, Date end); "from d_sub_task left join s_user on d_sub_task.annotator_id=s_user.id where pack_id in " +
" <foreach item='item' collection='packId' open='(' separator=',' close=')'> #{item ,jdbcType=NUMERIC} </foreach>" +
" and status=3 and annotate_time BETWEEN #{start} and #{end} group by task_id,person_unid </script>")
List<LogVo> exportLogByDateAndPack(List<Long> packId, Date start, Date end);
} }
\ No newline at end of file \ No newline at end of file
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
<result column="account_name" property="account.name" /> <result column="account_name" property="account.name" />
<result column="account_manager_id" property="account.managerId" /> <result column="account_manager_id" property="account.managerId" />
<result column="account_description" property="account.description" /> <result column="account_description" property="account.description" />
<result column="account_status" property="account.status" />
</resultMap> </resultMap>
<sql id="Left_Join_List" > <sql id="Left_Join_List" >
<foreach collection="leftJoinTableSet" item="leftJoinTable" > <foreach collection="leftJoinTableSet" item="leftJoinTable" >
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
<result column="account_name" property="account.name" /> <result column="account_name" property="account.name" />
<result column="account_manager_id" property="account.managerId" /> <result column="account_manager_id" property="account.managerId" />
<result column="account_description" property="account.description" /> <result column="account_description" property="account.description" />
<result column="account_status" property="account.status" />
</resultMap> </resultMap>
<sql id="Left_Join_List" > <sql id="Left_Join_List" >
<foreach collection="leftJoinTableSet" item="leftJoinTable" > <foreach collection="leftJoinTableSet" item="leftJoinTable" >
......
...@@ -328,6 +328,12 @@ public class ReidService { ...@@ -328,6 +328,12 @@ public class ReidService {
/** /**
* 按规则合并,并跟新为todo 状态 * 按规则合并,并跟新为todo 状态
* <ul>
* <li>一个 personUnid 多个 subTaskId -> mergeTo</li>
* <li>一个 personUnid 没有 subTaskId -> update</li>
* <li>没有 personUnid 多个 subTaskId -> mergeAsNewPerson</li>
* <li>多个 personUnid 没有 subTaskId -> mergePerson</li>
* </ul>
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void mergeAndTodo(String[] personUnidArr, Long[] subTaskIdArr, Long packId, String currentPerson) throws Exception { public void mergeAndTodo(String[] personUnidArr, Long[] subTaskIdArr, Long packId, String currentPerson) throws Exception {
...@@ -380,6 +386,67 @@ public class ReidService { ...@@ -380,6 +386,67 @@ public class ReidService {
} }
/** /**
* 低质量合并
* <ul>
* <li>一个 personUnid 多个 subTaskId -> mergeTo</li>
* <li>一个 personUnid 没有 subTaskId -> update</li>
* <li>没有 personUnid 多个 subTaskId -> mergeAsNewPerson</li>
* <li>多个 personUnid 没有 subTaskId -> mergePerson</li>
* </ul>
*/
public void mergeAndLowQuality(String[] personUnidArr, Long[] subTaskIdArr, Long packId, String currentPerson) throws Exception {
log.info("mergeAndLowQuality:[{}]-[{}]-[{}]-[{}]", Arrays.toString(personUnidArr), Arrays.toString(subTaskIdArr), packId, currentPerson);
// int i = ArrayUtils.indexOf(personUnidArr, currentPerson);
// if (i != -1) {
// personUnidArr = ArrayUtils.remove(personUnidArr, i);
// }
String type = "";
if (personUnidArr.length > 1 && subTaskIdArr.length > 1) {
throw new RuntimeException("参数不正确");
}
if (personUnidArr.length == 1) {
if (subTaskIdArr.length > 0) {
type = "mergeTo";
} else {
type = "update";
}
} else if (personUnidArr.length == 0 && subTaskIdArr.length > 0) {
type = "mergeAsNewPerson";
} else if (personUnidArr.length > 1 && subTaskIdArr.length == 0) {
type = "mergePerson";
}
String personUnid;
switch (type) {
case "mergeTo":
personUnid = mergeTo(subTaskIdArr, personUnidArr[0], currentPerson, packId);
break;
case "mergeAsNewPerson":
personUnid = mergeAsNewPerson(subTaskIdArr, packId);
break;
case "mergePerson":
personUnid = mergePerson(personUnidArr, currentPerson, packId);
break;
case "update":
personUnid = personUnidArr[0];
break;
default:
throw new RuntimeException("未知原因");
}
SubTaskExample subTaskExample = new SubTaskExample();
subTaskExample.createCriteria().andPersonUnidEqualTo(personUnid).andPackIdEqualTo(packId);
SubTask subTask = new SubTask();
subTask.setStatus(SubTaskStatus.LOW_QUALITY.val);
subTaskService.updateByExampleSelective(subTask, subTaskExample);
String reidPoolName = Constants.getReidPoolName(packId);
CompletableFuture<AlgResult> feature = matchClient.EASY_PERSON_API.deletePerson(reidPoolName, Collections.singletonList(personUnid));
feature.get(20, TimeUnit.SECONDS);
}
/**
* 标记人为纯净的(修改人对应的所有的图片状态) * 标记人为纯净的(修改人对应的所有的图片状态)
*/ */
public void finishLabeling(String personUnid, Long packId) { public void finishLabeling(String personUnid, Long packId) {
...@@ -579,7 +646,7 @@ public class ReidService { ...@@ -579,7 +646,7 @@ public class ReidService {
SubTask subTask = new SubTask(); SubTask subTask = new SubTask();
subTask.setStatus(SubTaskStatus.LABELING.val); subTask.setStatus(SubTaskStatus.LABELING.val);
subTask.setAnnotatorId(StpUtil.getLoginIdAsLong()); // subTask.setAnnotatorId(StpUtil.getLoginIdAsLong());
SubTaskExample subTaskExample = new SubTaskExample(); SubTaskExample subTaskExample = new SubTaskExample();
subTaskExample.createCriteria().andPersonUnidEqualTo(personUnid).andPackIdEqualTo(packId); subTaskExample.createCriteria().andPersonUnidEqualTo(personUnid).andPackIdEqualTo(packId);
...@@ -588,7 +655,7 @@ public class ReidService { ...@@ -588,7 +655,7 @@ public class ReidService {
if (subTasks.size() > 0) { if (subTasks.size() > 0) {
Integer status = subTasks.get(0).getStatus(); Integer status = subTasks.get(0).getStatus();
if (status.equals(SubTaskStatus.FINISH_LABELING.val) || status.equals(SubTaskStatus.recycled.val)) { if (status.equals(SubTaskStatus.FINISH_LABELING.val) || status.equals(SubTaskStatus.recycled.val) || status.equals(SubTaskStatus.LOW_QUALITY.val)) {
return true; return true;
} }
} }
...@@ -799,6 +866,9 @@ public class ReidService { ...@@ -799,6 +866,9 @@ public class ReidService {
return tempFile; return tempFile;
} }
/**
* 特征池重建
*/
public void reConstruction(Long packId) { public void reConstruction(Long packId) {
SubTaskExample subTaskExample = new SubTaskExample(); SubTaskExample subTaskExample = new SubTaskExample();
subTaskExample.createCriteria().andPackIdEqualTo(packId); subTaskExample.createCriteria().andPackIdEqualTo(packId);
...@@ -817,6 +887,12 @@ public class ReidService { ...@@ -817,6 +887,12 @@ public class ReidService {
for (Map.Entry<String, List<SubTask>> entry : collect.entrySet()) { for (Map.Entry<String, List<SubTask>> entry : collect.entrySet()) {
String personUnid = entry.getKey(); String personUnid = entry.getKey();
List<SubTask> value = entry.getValue(); List<SubTask> value = entry.getValue();
Integer status = value.get(0).getStatus();
// 低质量和已回收的不加到特征池里
if (status == SubTaskStatus.LOW_QUALITY.val || status == SubTaskStatus.recycled.val) {
continue;
}
ArrayList<Person> people = new ArrayList<>(); ArrayList<Person> people = new ArrayList<>();
for (SubTask item : value) { for (SubTask item : value) {
......
...@@ -8,14 +8,21 @@ import java.util.Date; ...@@ -8,14 +8,21 @@ import java.util.Date;
public class LogVo extends LogVoBase { public class LogVo extends LogVoBase {
@ExcelProperty("账号") @ExcelProperty("公司名称")
private String accountName;
@ExcelProperty("项目名称")
private String taskName;
@ExcelProperty("标注员账号")
private String username; private String username;
@ExcelProperty("标注员姓名")
private String name;
@ExcelProperty("文件夹ID") @ExcelProperty("文件夹ID")
private String personUnid; private String personUnid;
@ExcelProperty("图片数量") @ExcelProperty("图片数量")
private Integer picNum; private Integer picNum;
@ExcelProperty("完成标注时间") @ExcelProperty("完成标注时间")
private Date finishTime; private Date finishTime;
private Long taskId;
public LogVo() { public LogVo() {
...@@ -61,4 +68,40 @@ public class LogVo extends LogVoBase { ...@@ -61,4 +68,40 @@ public class LogVo extends LogVoBase {
this.picNum = picNum; this.picNum = picNum;
return this; return this;
} }
public String getAccountName() {
return accountName;
}
public LogVo setAccountName(String accountName) {
this.accountName = accountName;
return this;
}
public String getTaskName() {
return taskName;
}
public LogVo setTaskName(String taskName) {
this.taskName = taskName;
return this;
}
public String getName() {
return name;
}
public LogVo setName(String name) {
this.name = name;
return this;
}
public Long getTaskId() {
return taskId;
}
public LogVo setTaskId(Long taskId) {
this.taskId = taskId;
return this;
}
} }
\ No newline at end of file \ No newline at end of file
...@@ -2,7 +2,7 @@ server: ...@@ -2,7 +2,7 @@ server:
port: 12100 port: 12100
spring: spring:
profiles: profiles:
active: dev active: pro
sa-token: sa-token:
token-name: token token-name: token
activity-timeout: 36000 activity-timeout: 36000
...@@ -22,46 +22,36 @@ pagehelper: ...@@ -22,46 +22,36 @@ pagehelper:
params: count=countByExample params: count=countByExample
vion: vion:
menu-map: menu-map:
# 超级管理员
0: 0:
label: label:
- "标注" - "标注"
- "提交质检"
- "标注工作薄" - "标注工作薄"
inspection:
- "质检审核"
project: project:
- "项目管理" - "项目管理"
management: management:
- "外包公司" - "外包公司"
- "用户管理" - "用户管理"
1: # 内部质检员
2:
label: label:
- "标注" - "标注"
- "提交质检" # 外部管理员(公司管理员)
- "标注工作薄"
inspection:
- "质检审核"
project:
- "项目管理"
management:
- "外包公司"
- "用户管理"
2:
inspection:
- "质检审核"
3: 3:
label: label:
- "标注" - "标注"
- "提交质检"
- "标注工作薄" - "标注工作薄"
management: management:
- "用户管理" - "用户管理"
# 外部质检员(公司质检员)
4: 4:
inspection: label:
- "质检审核" - "标注"
# 外部标注员(公司标注员)
5: 5:
label: label:
- "标注" - "标注"
# 兼职标注员
6: 6:
label: label:
- "标注" - "标注"
\ No newline at end of file \ No newline at end of file
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!