feat(person): add pages
This commit is contained in:
4
components/label/api/const.ts
Normal file
4
components/label/api/const.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export const BASE_LABEL_API =
|
||||
process.env.NEXT_PUBLIC_ENV === "production"
|
||||
? "https://label.cowarobot.com"
|
||||
: "https://label.softtest.cowarobot.com"
|
||||
49
components/label/api/daily/index.ts
Normal file
49
components/label/api/daily/index.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import httpFetch from "@/api/fetch"
|
||||
import { Daily } from "./typing"
|
||||
import { BASE_LABEL_API } from "../const"
|
||||
|
||||
export const getSelfDailyWorkList = (data: Daily.Request) => {
|
||||
return httpFetch<Daily.Response>({
|
||||
url: BASE_LABEL_API + "/api/v1/label_server/daily_work/list/self",
|
||||
method: "POST",
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
}
|
||||
export const getTeamDailyWorkList = (data: Daily.Request) => {
|
||||
return httpFetch<Daily.Response>({
|
||||
url: BASE_LABEL_API + "/api/v1/label_server/daily_work/list/team",
|
||||
method: "POST",
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
}
|
||||
|
||||
export const addDailyWorkData = (data: Daily.CreateProps) => {
|
||||
return httpFetch({
|
||||
url: BASE_LABEL_API + "/api/v1/label_server/daily_work/add",
|
||||
method: "POST",
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
}
|
||||
|
||||
export const editDailyWorkData = (data: Daily.CreateProps, id: number) => {
|
||||
return httpFetch({
|
||||
url: BASE_LABEL_API + `/api/v1/label_server/daily_work/edit/${id}`,
|
||||
method: "put",
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
}
|
||||
|
||||
export const deleteDailyWorkData = (id: number) => {
|
||||
return httpFetch({
|
||||
url: BASE_LABEL_API + `/api/v1/label_server/daily_work/delete/${id}`,
|
||||
method: "delete",
|
||||
})
|
||||
}
|
||||
|
||||
export const lockDailyWorkData = (lock_status: boolean, id: number) => {
|
||||
return httpFetch({
|
||||
url: BASE_LABEL_API + `/api/v1/label_server/daily_work/lock/${id}`,
|
||||
method: "put",
|
||||
body: JSON.stringify({ lock_status }),
|
||||
})
|
||||
}
|
||||
84
components/label/api/daily/typing.ts
Normal file
84
components/label/api/daily/typing.ts
Normal file
@@ -0,0 +1,84 @@
|
||||
export namespace Daily {
|
||||
export interface Request {
|
||||
date_end?: string
|
||||
date_start?: string
|
||||
/**
|
||||
* 0-个人日报 1-团队日报
|
||||
*/
|
||||
flag?: number
|
||||
name?: string
|
||||
order_by?: string
|
||||
page_number?: number
|
||||
page_size?: number
|
||||
[property: string]: any
|
||||
}
|
||||
|
||||
export interface Summary {
|
||||
total_work_time: number
|
||||
total_standard_size: number
|
||||
total_completed_size: number
|
||||
total_residual_size: number
|
||||
total_residual_work_time: number
|
||||
}
|
||||
|
||||
export interface Response {
|
||||
daily_work_list: DailyWorkList[]
|
||||
total_items: number
|
||||
total_pages: number
|
||||
total_summary: Summary
|
||||
[property: string]: any
|
||||
}
|
||||
|
||||
export interface DailyWorkList {
|
||||
accounting_type?: string | null
|
||||
actual_type?: string
|
||||
completed_size?: number
|
||||
date?: string
|
||||
end_time?: string
|
||||
id?: number
|
||||
leader_name?: string | null
|
||||
leader_uid?: number | null
|
||||
lock_status?: boolean
|
||||
obj_type?: number | null
|
||||
performance_accounting?: boolean | null
|
||||
project_id?: number | null
|
||||
project_name?: string | null
|
||||
rate?: number
|
||||
remarks?: string | null
|
||||
residual_pm?: boolean | null
|
||||
residual_size?: number
|
||||
residual_work_time?: number
|
||||
set_type?: string
|
||||
standard_size?: number
|
||||
start_time?: string
|
||||
uid?: number
|
||||
username?: string
|
||||
work_time?: number
|
||||
work_type?: string | null
|
||||
[property: string]: any
|
||||
}
|
||||
|
||||
export interface CreateProps {
|
||||
accounting_type?: string
|
||||
actual_type: string
|
||||
completed_size?: number
|
||||
date: string
|
||||
end_time?: string
|
||||
leader_uid?: number
|
||||
obj_type?: number
|
||||
performance_accounting?: boolean
|
||||
project_id?: number
|
||||
rate?: number
|
||||
remarks?: string
|
||||
residual_pm?: boolean
|
||||
residual_size?: number
|
||||
residual_work_time?: number
|
||||
set_type: string
|
||||
standard_size?: number
|
||||
start_time?: string
|
||||
uid: number
|
||||
work_time?: number
|
||||
work_type?: string
|
||||
[property: string]: any
|
||||
}
|
||||
}
|
||||
171
components/label/api/label/typing.ts
Normal file
171
components/label/api/label/typing.ts
Normal file
@@ -0,0 +1,171 @@
|
||||
export interface LabelResult {
|
||||
data_name: string
|
||||
image_objects?: ImageObjects
|
||||
video_objects?: {
|
||||
[key: string]: ImageObjects
|
||||
}
|
||||
pc_box_objects?: { [key: string]: any }[]
|
||||
pc_segment_objects?: { [key: string]: any }[]
|
||||
pc_vegetation_objects?: { [key: string]: any }[]
|
||||
}
|
||||
|
||||
export interface ImageObjects {
|
||||
annotations: Annotation[]
|
||||
categories: Category[]
|
||||
desc?: Desc
|
||||
image_groups: ImageGroups
|
||||
images: Images
|
||||
key_frame?: boolean
|
||||
label1_ts?: number
|
||||
label1_uid?: number
|
||||
review1_ts?: number
|
||||
review1_uid?: number
|
||||
review2_ts?: number
|
||||
review2_uid?: number
|
||||
}
|
||||
|
||||
export interface Annotation {
|
||||
bbox?: number[]
|
||||
category_id: number
|
||||
comment?: Comment[]
|
||||
create_timestamp: number
|
||||
first_modified_timestamp: number
|
||||
first_modified_uid: number
|
||||
hollow_segmentation?: Array<Array<number[]>>
|
||||
id: number
|
||||
image_id: number
|
||||
key_points?: KeyPoint[]
|
||||
last_modified_timestamp: number
|
||||
last_modified_uid: number
|
||||
line_segment?: Array<Array<number[]>>
|
||||
prelabel: boolean
|
||||
rect?: number[]
|
||||
segmentation?: Array<Array<number[]>>
|
||||
sub_attributes?: { [key: string]: any }
|
||||
uid: number
|
||||
}
|
||||
|
||||
export interface Comment {
|
||||
check_box_comments: string[]
|
||||
comment_type: number
|
||||
date: number
|
||||
scene_info: SceneInfo
|
||||
text_comments: string[]
|
||||
times: number
|
||||
turn: number
|
||||
uid: number
|
||||
}
|
||||
|
||||
export interface SceneInfo {
|
||||
phi?: number
|
||||
point_idx?: number[]
|
||||
theta?: number
|
||||
type: number
|
||||
vfov_factor?: number
|
||||
x?: number
|
||||
x_offset?: number
|
||||
y?: number
|
||||
y_offset?: number
|
||||
z?: number
|
||||
zoom?: number
|
||||
}
|
||||
|
||||
export interface KeyPoint {
|
||||
attributes?: { [key: string]: any }
|
||||
point: [number, number]
|
||||
}
|
||||
|
||||
export interface Category {
|
||||
id: number
|
||||
name: string
|
||||
supercategory: string
|
||||
}
|
||||
|
||||
export interface Desc {
|
||||
meta_operation: string[]
|
||||
other_desc: string
|
||||
}
|
||||
|
||||
export interface ImageGroups {
|
||||
// "01J4GZMQ2G8KKQVF52S6EXBGRA": string;
|
||||
}
|
||||
|
||||
export interface Images {
|
||||
file_name: string
|
||||
height: number
|
||||
id: number
|
||||
width: number
|
||||
}
|
||||
|
||||
export interface RequestLabelResult {
|
||||
label_object_size: { [key: string]: any }
|
||||
results: LabelResult[]
|
||||
task_id: number
|
||||
uid: number
|
||||
work_load: WorkLoad
|
||||
work_time: { [key: string]: any }
|
||||
}
|
||||
|
||||
export interface WorkLoad {
|
||||
comment_size: number
|
||||
dynamic_size: { [key: number]: number }
|
||||
key_frame_size: { [key: number]: number }
|
||||
object_size: { [key: number]: number }
|
||||
prelabel_modify_size: { [key: number]: number }
|
||||
question_size: { [key: number]: number }
|
||||
review_dynamic_size: { [key: number]: number }
|
||||
review_key_frame_size: { [key: number]: number }
|
||||
review_question_size: { [key: number]: number }
|
||||
review_size: number
|
||||
review_static_size: { [key: number]: number }
|
||||
static_size: { [key: number]: number }
|
||||
work_time: number
|
||||
}
|
||||
|
||||
export interface ServerResponse {
|
||||
data_list?: DataList[]
|
||||
proxy?: string
|
||||
[property: string]: any
|
||||
}
|
||||
|
||||
export interface DataList {
|
||||
data_name: string
|
||||
data_type: string
|
||||
image_data?: string
|
||||
video_data?: string
|
||||
pointcloud_data?: PointcloudDatum[]
|
||||
[property: string]: any
|
||||
}
|
||||
|
||||
export interface PointcloudDatum {
|
||||
intensity: number
|
||||
time_offset: number
|
||||
x: number
|
||||
y: number
|
||||
z: number
|
||||
[property: string]: any
|
||||
}
|
||||
|
||||
export interface AuxiliaryParams {
|
||||
project_id: number
|
||||
file_name: string
|
||||
image_hw: [number, number]
|
||||
points_and_box: Array<[number, number]>
|
||||
tags: number[]
|
||||
clear_previous_state?: boolean
|
||||
}
|
||||
|
||||
interface UserInfo {
|
||||
uid: number
|
||||
name: string
|
||||
all_projects: { [x: number]: number[] }
|
||||
collect_projects: number[]
|
||||
group_name: string
|
||||
work_status: number
|
||||
base_city: string
|
||||
}
|
||||
|
||||
export interface LoginInfo extends UserInfo {
|
||||
token: string
|
||||
refresh_token: string
|
||||
}
|
||||
198
components/label/api/project/index.ts
Normal file
198
components/label/api/project/index.ts
Normal file
@@ -0,0 +1,198 @@
|
||||
import httpFetch from "@/api/fetch"
|
||||
import { Project, ProjectDetail, ReviewUsers } from "./typing"
|
||||
import { BASE_LABEL_API } from "../const"
|
||||
|
||||
// 获取项目列表
|
||||
export const getProjectList = (data: Project.ListRequest) => {
|
||||
return httpFetch<Project.ListResponse>({
|
||||
url: BASE_LABEL_API + "/api/v1/label_server/project/list",
|
||||
method: "POST",
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
}
|
||||
|
||||
// 获取项目详情
|
||||
export const getProjectDetailById = (id: number) => {
|
||||
return httpFetch<ProjectDetail.DataProps>({
|
||||
url: BASE_LABEL_API + `/api/v1/label_server/project/detail/${id}`,
|
||||
method: "GET",
|
||||
})
|
||||
}
|
||||
|
||||
// 校验项目源数据
|
||||
export const checkLabelDataSource = (data: Project.CheckRequest) => {
|
||||
return httpFetch<Project.CheckResponse>({
|
||||
url: BASE_LABEL_API + "/api/v1/label_server/project/check_data",
|
||||
method: "POST",
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
}
|
||||
|
||||
// 创建项目
|
||||
export const projectAdd = (data: Project.CreateProps) => {
|
||||
return httpFetch({
|
||||
url: BASE_LABEL_API + "/api/v1/label_server/project/add",
|
||||
method: "POST",
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
}
|
||||
|
||||
// 审核项目
|
||||
export const projectReview = (data: Project.CreateProps) => {
|
||||
return httpFetch({
|
||||
url: BASE_LABEL_API + "/api/v1/label_server/project/review",
|
||||
method: "POST",
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
}
|
||||
|
||||
// 配置项目
|
||||
export const projectConfig = (data: Project.ConfigProps) => {
|
||||
return httpFetch({
|
||||
url: BASE_LABEL_API + "/api/v1/label_server/project/config",
|
||||
method: "POST",
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
}
|
||||
|
||||
// 编辑项目
|
||||
export const projectEditById = (data: any, id: number) => {
|
||||
return httpFetch({
|
||||
url: BASE_LABEL_API + `/api/v1/label_server/project/edit/${id}`,
|
||||
method: "POST",
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
}
|
||||
|
||||
// 审核试标项目
|
||||
export const projectPreLabelReview = (data: Project.PreLabelProps) => {
|
||||
return httpFetch({
|
||||
url: BASE_LABEL_API + "/api/v1/label_server/project/prototype_review",
|
||||
method: "POST",
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
}
|
||||
|
||||
// 提交验收
|
||||
export const projectDeliver = (data: { project_id: number }) => {
|
||||
return httpFetch({
|
||||
url: BASE_LABEL_API + "/api/v1/label_server/project/deliver",
|
||||
method: "POST",
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
}
|
||||
|
||||
// 完成项目
|
||||
export const projectAccept = (data: { project_id: number; pass: boolean }) => {
|
||||
return httpFetch({
|
||||
url: BASE_LABEL_API + "/api/v1/label_server/project/accept",
|
||||
method: "POST",
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
}
|
||||
|
||||
// 收藏项目
|
||||
export const projectCollect = (data: {
|
||||
project_id: number
|
||||
is_collect: boolean
|
||||
}) => {
|
||||
return httpFetch({
|
||||
url: BASE_LABEL_API + "/api/v1/label_server/project/collect",
|
||||
method: "POST",
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
}
|
||||
|
||||
// 获取项目抽检比例
|
||||
export const getReviewScaleList = (params: { project_id: number }) => {
|
||||
return httpFetch<any[]>({
|
||||
url: BASE_LABEL_API + "/api/v1/label_server/review_scale/list",
|
||||
method: "GET",
|
||||
data: params,
|
||||
})
|
||||
}
|
||||
|
||||
// 保存抽检比例
|
||||
export const saveUserReviewScale = (data: Project.ReviewScaleProps) => {
|
||||
return httpFetch({
|
||||
url: BASE_LABEL_API + "/api/v1/label_server/review_scale/save",
|
||||
method: "POST",
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
}
|
||||
|
||||
export const getProjectDetail = (id: number) => {
|
||||
return httpFetch<Project.DetailResponse>({
|
||||
url: BASE_LABEL_API + `/api/v1/label_server/project/detail/${id}`,
|
||||
method: "GET",
|
||||
})
|
||||
}
|
||||
|
||||
// 重新生成Embedding
|
||||
export const regenerateProjectEmbedding = (data: { project_id: number }) => {
|
||||
return httpFetch({
|
||||
url: BASE_LABEL_API + `/api/v1/label_server/project/regenerate_embedding`,
|
||||
method: "POST",
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
}
|
||||
|
||||
// 获取个人参与项目
|
||||
export const getPersonProjectDashBoard = () => {
|
||||
return httpFetch<Array<Project.PersonProjectDashboardResponseItem>>({
|
||||
url:
|
||||
BASE_LABEL_API + `/api/v1/label_server/data_statistics/personal_project`,
|
||||
method: "GET",
|
||||
})
|
||||
}
|
||||
|
||||
// 获取个人看板数据
|
||||
export const getCurrentPersonData = (params: { date: string }) => {
|
||||
return httpFetch<{
|
||||
label_data_size: number
|
||||
label_work_time: number
|
||||
review1_data_size: number
|
||||
review1_work_time: number
|
||||
review2_data_size: number
|
||||
review2_work_time: number
|
||||
}>({
|
||||
url:
|
||||
BASE_LABEL_API +
|
||||
"/api/v1/label_server/data_statistics/personal_dashboard",
|
||||
method: "GET",
|
||||
data: params,
|
||||
})
|
||||
}
|
||||
|
||||
/* ****************************** Options ****************************** */
|
||||
// 获取项目所属业务列表
|
||||
export const getProjectTypeList = () => {
|
||||
return httpFetch<string[]>({
|
||||
url: BASE_LABEL_API + "/api/v1/label_server/project/type_list",
|
||||
method: "GET",
|
||||
})
|
||||
}
|
||||
|
||||
// 获取项目管理员列表
|
||||
export const getProjectAdminList = () => {
|
||||
return httpFetch<Array<{ label: string; value: number }>>({
|
||||
url: BASE_LABEL_API + "/api/v1/label_server/project/admin_list",
|
||||
method: "GET",
|
||||
})
|
||||
}
|
||||
|
||||
// 获取项目审核员
|
||||
export const getProjectReviewers = () => {
|
||||
return httpFetch<ReviewUsers>({
|
||||
url: BASE_LABEL_API + "/api/v1/label_server/project/reviewer_map",
|
||||
method: "GET",
|
||||
})
|
||||
}
|
||||
|
||||
// 获取用户有权限的项目
|
||||
export const getSelfProjectList = () => {
|
||||
return httpFetch<Array<{ label: string; value: number }>>({
|
||||
url: BASE_LABEL_API + "/api/v1/label_server/project/self",
|
||||
method: "GET",
|
||||
})
|
||||
}
|
||||
474
components/label/api/project/typing.ts
Normal file
474
components/label/api/project/typing.ts
Normal file
@@ -0,0 +1,474 @@
|
||||
export namespace Project {
|
||||
export interface DataProps {
|
||||
key: React.Key
|
||||
id: number // 项目ID
|
||||
name: string // 项目名称
|
||||
is_collect: boolean // 是否收藏
|
||||
project_type?: string // 所属业务
|
||||
label_schema_name?: string // 标注方案
|
||||
label_schema_version?: string
|
||||
status: number // 项目状态
|
||||
labeled_scale?: number // 标注完成比例
|
||||
reviewed_scale?: number // 审核完成比例
|
||||
data_size?: number // 总数据量
|
||||
rate_speed?: number // 额定倍速
|
||||
create_user: string // 创建人
|
||||
owner: string // 项目负责人
|
||||
label_process?: string[] // 工序
|
||||
admin_user: number[] // 标注管理员id
|
||||
data_source?: string // 数据源
|
||||
remarks?: string // 备注
|
||||
// reviewer_user?: string; // 审核人
|
||||
// reviewer_comment?: string; // 审核意见
|
||||
create_at?: string // 创建时间
|
||||
update_at?: string // 更新时间
|
||||
modify?: number //0=可以发起变更,无变更 1=正在变更,无变更 2=可以发起变更,有变更 3=正在变更,有变更
|
||||
}
|
||||
|
||||
export interface CheckRequest {
|
||||
project_type: string
|
||||
nfs_path: string
|
||||
flag: number
|
||||
}
|
||||
|
||||
export interface CheckResponse {
|
||||
data_size: number
|
||||
error_code: number
|
||||
}
|
||||
|
||||
export interface CreateProps {
|
||||
admin_user: string[]
|
||||
create_user: string
|
||||
data_size: number
|
||||
data_source: string
|
||||
label_schema_name: string
|
||||
label_schema_version: string
|
||||
project_name: string
|
||||
project_type: string
|
||||
related_task?: number[]
|
||||
remarks?: string
|
||||
[property: string]: any
|
||||
}
|
||||
|
||||
export interface ReviewProps {
|
||||
pass: boolean
|
||||
project_id: number
|
||||
project_name: string
|
||||
review_comment?: string
|
||||
review_user: string
|
||||
test_proportion?: number
|
||||
}
|
||||
|
||||
export interface ListRequest {
|
||||
admin_user?: string
|
||||
create_user?: string
|
||||
end_date?: string
|
||||
page_number: number
|
||||
page_size: number
|
||||
project_id?: number
|
||||
project_name?: string
|
||||
project_type?: string
|
||||
review_user?: string
|
||||
start_date?: string
|
||||
status?: number[]
|
||||
[property: string]: any
|
||||
}
|
||||
|
||||
export interface ListResponse {
|
||||
project_list: DataProps[]
|
||||
total_pages: number
|
||||
total_items: number
|
||||
}
|
||||
|
||||
export interface LabelConfig {
|
||||
acquire_mode: number
|
||||
acquire_size: number
|
||||
avg_remind_threshold: number
|
||||
dynamic_label_speed: number
|
||||
filter_pre_label: boolean
|
||||
fix_remind_threshold: number
|
||||
label_accuracy_rate: number
|
||||
label_update_month: number
|
||||
max_size: number
|
||||
pre_label_confirm: boolean
|
||||
static_label_speed: number
|
||||
}
|
||||
|
||||
export interface Review1Config {
|
||||
acquire_mode: number
|
||||
acquire_size: number
|
||||
dynamic_review1_speed: number
|
||||
end_date?: string
|
||||
filter_label_first_sub: boolean
|
||||
filter_objs: boolean
|
||||
filter_rework: boolean
|
||||
filter_task_batch: boolean
|
||||
filter_track_user: boolean
|
||||
is_rework?: boolean
|
||||
label_first_sub_end_date?: string
|
||||
label_first_sub_start_date?: string
|
||||
max_objs?: number
|
||||
max_size: number
|
||||
min_objs?: number
|
||||
review1_accuracy_rate: number
|
||||
review1_update_month: number
|
||||
start_date?: string
|
||||
static_review1_speed: number
|
||||
track_user_list?: number[]
|
||||
}
|
||||
|
||||
export interface Review2Config {
|
||||
acquire_mode: number
|
||||
acquire_size: number
|
||||
dynamic_review2_speed: number
|
||||
end_date?: string
|
||||
filter_objs: boolean
|
||||
filter_review1_first_sub: boolean
|
||||
filter_review1_user: boolean
|
||||
filter_rework: boolean
|
||||
filter_task_batch: boolean
|
||||
filter_track_user: boolean
|
||||
is_rework?: boolean
|
||||
max_objs?: number
|
||||
max_size: number
|
||||
min_objs?: number
|
||||
review1_first_sub_end_date?: string
|
||||
review1_first_sub_start_date?: string
|
||||
review1_user_list?: number[]
|
||||
review2_update_month: number
|
||||
start_date?: string
|
||||
static_review2_speed: number
|
||||
track_user_list?: number[]
|
||||
}
|
||||
|
||||
export interface ConfigProps {
|
||||
admin_user?: number[]
|
||||
check_frame?: boolean
|
||||
check_task?: boolean
|
||||
comment_rule?: { [key: string]: any }
|
||||
default_pose?: string
|
||||
is_lock_object?: boolean
|
||||
label_config?: LabelConfig
|
||||
label_users?: number[]
|
||||
modifiable_types?: string[]
|
||||
project_id: number
|
||||
project_name?: string
|
||||
project_remark?: string
|
||||
review1_config?: Review1Config
|
||||
review1_users?: number[]
|
||||
review2_config?: Review2Config
|
||||
review2_users?: number[]
|
||||
user_grade?: { [key: string]: any }
|
||||
}
|
||||
|
||||
// 试标审核
|
||||
export interface PreLabelProps {
|
||||
id: number
|
||||
review_user: string
|
||||
action: number // 1-试标完成,2-试标通过,3-试标不通过
|
||||
detail?: string
|
||||
}
|
||||
|
||||
export interface ReviewScaleProps {
|
||||
frame_scale?: number
|
||||
grade?: string
|
||||
project_id: number
|
||||
task_scale?: number
|
||||
uids: number[]
|
||||
}
|
||||
/**
|
||||
* DetailResponse
|
||||
*/
|
||||
export interface DetailResponse {
|
||||
admin_user: string[]
|
||||
alarm_threshold: AlarmThreshold
|
||||
check_frame: boolean
|
||||
check_task: boolean
|
||||
comment_rule: CommentRule
|
||||
create_at: string
|
||||
create_user: string
|
||||
data_size: number
|
||||
default_pose: null
|
||||
id: number
|
||||
is_lock_object: boolean
|
||||
label_process: LabelProcess
|
||||
label_schema_list: LabelSchemaList[]
|
||||
label_type: number
|
||||
labeled_multiplier: LabeledMultiplier
|
||||
modifiable_types: string[]
|
||||
name: string
|
||||
project_progress: ProjectProgress
|
||||
remarks: string
|
||||
rpath: string
|
||||
status: number
|
||||
task_size: number
|
||||
user_grade: UserGrade
|
||||
}
|
||||
|
||||
export interface AlarmThreshold {
|
||||
avg_remind_threshold: number
|
||||
fix_remind_threshold: number
|
||||
}
|
||||
|
||||
export interface CommentRule {
|
||||
check_box_rules: {
|
||||
create_date: string
|
||||
create_user: string
|
||||
text: string
|
||||
}[]
|
||||
text_rules: string[]
|
||||
}
|
||||
|
||||
export interface LabelProcess {
|
||||
filter_pre_label: boolean
|
||||
filter_task_info: string[]
|
||||
pre_label_confirm: boolean
|
||||
step_detail: StepDetail[]
|
||||
}
|
||||
|
||||
export interface StepDetail {
|
||||
acquire_mode: number
|
||||
acquire_size: number
|
||||
action: number
|
||||
max_size: number
|
||||
user_list: number[]
|
||||
}
|
||||
|
||||
export interface LabelSchemaList {
|
||||
bbox_range: number[]
|
||||
bbox_size: number[]
|
||||
bbox_type: number
|
||||
category_id: number
|
||||
color: [number, number, number]
|
||||
label_class: string
|
||||
label_type: number
|
||||
radius: number
|
||||
sensor_list: string[]
|
||||
sub_attributes: string[]
|
||||
sub_attributes_describe: SubAttributesDescribe[]
|
||||
super_category: string
|
||||
}
|
||||
|
||||
export interface SubAttributesDescribe {
|
||||
chinese_name: string
|
||||
english_name: string
|
||||
isrequired: number
|
||||
optional_item: string[]
|
||||
round_id: number
|
||||
select_mode: number
|
||||
}
|
||||
|
||||
export interface LabeledMultiplier {
|
||||
dynamic_label_speed: null
|
||||
dynamic_review1_speed: null
|
||||
dynamic_review2_speed: null
|
||||
label_accuracy_rate: null
|
||||
label_update_month: null
|
||||
review1_accuracy_rate: null
|
||||
review1_update_month: null
|
||||
review2_update_month: null
|
||||
static_label_speed: null
|
||||
static_review1_speed: null
|
||||
static_review2_speed: null
|
||||
}
|
||||
|
||||
export interface ProjectProgress {
|
||||
normal_labeled_task_size: number
|
||||
normal_reviewed1_task_size: number
|
||||
normal_reviewed2_task_size: number
|
||||
rework_labeled_task_size: number
|
||||
rework_reviewed1_task_size: number
|
||||
rework_reviewed2_task_size: number
|
||||
unlabeled_task_size: number
|
||||
}
|
||||
|
||||
export interface UserGrade {
|
||||
A: {
|
||||
frame: number
|
||||
task: number
|
||||
}
|
||||
B: {
|
||||
frame: number
|
||||
task: number
|
||||
}
|
||||
C: {
|
||||
frame: number
|
||||
task: number
|
||||
}
|
||||
}
|
||||
/**
|
||||
* DetailResponse
|
||||
*/
|
||||
|
||||
export interface PersonProjectDashboardResponseItem {
|
||||
project_id: number
|
||||
project_label_type: string
|
||||
project_name: string
|
||||
project_type: string
|
||||
work_time: number
|
||||
}
|
||||
}
|
||||
|
||||
export interface ReviewUsers {
|
||||
reviewer1: string[]
|
||||
reviewer2: string[]
|
||||
reviewer3: string[]
|
||||
}
|
||||
|
||||
export namespace ProjectDetail {
|
||||
export interface DataProps {
|
||||
admin_user: number[]
|
||||
alarm_threshold: AlarmThreshold
|
||||
check_frame: boolean
|
||||
check_task: boolean
|
||||
comment_rule: CommentRule
|
||||
create_at: string
|
||||
create_user: string
|
||||
data_size: number
|
||||
default_pose: null
|
||||
id: number
|
||||
is_lock_object: boolean
|
||||
label_process: LabelProcess
|
||||
label_schema_list: LabelSchemaList[]
|
||||
label_type: number
|
||||
labeled_multiplier: LabeledMultiplier
|
||||
modifiable_types: string[]
|
||||
name: string
|
||||
project_progress: ProjectProgress
|
||||
remarks: string
|
||||
rpath: string
|
||||
status: number
|
||||
task_size: number
|
||||
user_grade: UserGrade
|
||||
[property: string]: any
|
||||
}
|
||||
|
||||
export interface AlarmThreshold {
|
||||
avg_remind_threshold: number
|
||||
fix_remind_threshold: number
|
||||
[property: string]: any
|
||||
}
|
||||
|
||||
export interface CommentRule {
|
||||
check_box_rules: string[]
|
||||
text_rules: string[]
|
||||
[property: string]: any
|
||||
}
|
||||
|
||||
export interface LabelProcess {
|
||||
filter_pre_label: boolean
|
||||
filter_task_info: FilterTaskInfo[]
|
||||
pre_label_confirm: boolean
|
||||
step_detail: StepDetail[]
|
||||
[property: string]: any
|
||||
}
|
||||
|
||||
export interface FilterTaskInfo {
|
||||
action: number
|
||||
end_date: string
|
||||
filter_label_first_sub: boolean
|
||||
filter_objs: boolean
|
||||
filter_review1_first_sub: boolean
|
||||
filter_review1_user: boolean
|
||||
filter_rework: boolean
|
||||
filter_task_batch: boolean
|
||||
filter_track_user: boolean
|
||||
is_rework: boolean
|
||||
label_first_sub_end_date: string
|
||||
label_first_sub_start_date: string
|
||||
max_objs: number
|
||||
min_objs: number
|
||||
review1_first_sub_end_date: string
|
||||
review1_first_sub_start_date: string
|
||||
review1_user_list: number[]
|
||||
start_date: string
|
||||
track_user_list: number[]
|
||||
[property: string]: any
|
||||
}
|
||||
|
||||
export interface StepDetail {
|
||||
acquire_mode: number
|
||||
acquire_size: number
|
||||
action: number
|
||||
max_size: number
|
||||
user_list: number[]
|
||||
[property: string]: any
|
||||
}
|
||||
|
||||
export interface LabelSchemaList {
|
||||
bbox_range: number[]
|
||||
bbox_size: number[]
|
||||
bbox_type: number
|
||||
category_id: number
|
||||
color: number[]
|
||||
label_class: string
|
||||
label_type: number
|
||||
radius: number
|
||||
sensor_list: string[]
|
||||
sub_attributes: string[]
|
||||
sub_attributes_describe: SubAttributesDescribe[]
|
||||
super_category: string
|
||||
[property: string]: any
|
||||
}
|
||||
|
||||
export interface SubAttributesDescribe {
|
||||
chinese_name: string
|
||||
english_name: string
|
||||
isrequired: number
|
||||
optional_item: string[]
|
||||
round_id: number
|
||||
select_mode: number
|
||||
[property: string]: any
|
||||
}
|
||||
|
||||
export interface LabeledMultiplier {
|
||||
dynamic_label_speed: number
|
||||
dynamic_review1_speed: number
|
||||
dynamic_review2_speed: number
|
||||
label_accuracy_rate: number
|
||||
label_update_month: number
|
||||
review1_accuracy_rate: number
|
||||
review1_update_month: number
|
||||
review2_update_month: number
|
||||
static_label_speed: number
|
||||
static_review1_speed: number
|
||||
static_review2_speed: number
|
||||
[property: string]: any
|
||||
}
|
||||
|
||||
export interface ProjectProgress {
|
||||
normal_labeled_task_size: number
|
||||
normal_reviewed1_task_size: number
|
||||
normal_reviewed2_task_size: number
|
||||
rework_labeled_task_size: number
|
||||
rework_reviewed1_task_size: number
|
||||
rework_reviewed2_task_size: number
|
||||
unlabeled_task_size: number
|
||||
[property: string]: any
|
||||
}
|
||||
|
||||
export interface UserGrade {
|
||||
A: A
|
||||
B: B
|
||||
C: C
|
||||
[property: string]: any
|
||||
}
|
||||
|
||||
export interface A {
|
||||
frame: number
|
||||
task: number
|
||||
[property: string]: any
|
||||
}
|
||||
|
||||
export interface B {
|
||||
frame: number
|
||||
task: number
|
||||
[property: string]: any
|
||||
}
|
||||
|
||||
export interface C {
|
||||
frame: number
|
||||
task: number
|
||||
[property: string]: any
|
||||
}
|
||||
}
|
||||
77
components/label/api/task/index.ts
Normal file
77
components/label/api/task/index.ts
Normal file
@@ -0,0 +1,77 @@
|
||||
import httpFetch from "@/api/fetch"
|
||||
import { Task } from "./typing"
|
||||
import { BASE_LABEL_API } from "../const"
|
||||
|
||||
// 获取任务列表
|
||||
export const getTaskList = (data: Task.ListRequest) => {
|
||||
return httpFetch<Task.ListResponse>({
|
||||
url: BASE_LABEL_API + "/api/v1/label_server/task/list",
|
||||
method: "POST",
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
}
|
||||
|
||||
// 领取任务
|
||||
export const taskAcquire = (data: Task.AcquireReqProps) => {
|
||||
return httpFetch<Task.ListResponse>({
|
||||
url: BASE_LABEL_API + "/api/v1/label_server/task/acquire",
|
||||
method: "POST",
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
}
|
||||
|
||||
// 调度任务
|
||||
export const taskDispatch = (data: Task.DispatchReqProps) => {
|
||||
return httpFetch({
|
||||
url: BASE_LABEL_API + "/api/v1/label_server/task/dispatch",
|
||||
method: "POST",
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
}
|
||||
|
||||
// 释放任务
|
||||
export const taskRelease = (data: Task.ReleaseReqProps) => {
|
||||
return httpFetch({
|
||||
url: BASE_LABEL_API + "/api/v1/label_server/task/release",
|
||||
method: "POST",
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
}
|
||||
|
||||
// 获取下一个任务
|
||||
export const getNextTaskId = (data: Task.NextReqProps) => {
|
||||
return httpFetch<Task.NextResProps>({
|
||||
url: BASE_LABEL_API + "/api/v1/label_server/task/next",
|
||||
method: "POST",
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
}
|
||||
|
||||
// 提交任务
|
||||
export const taskCommit = (data: Task.CommitReqProps) => {
|
||||
return httpFetch({
|
||||
url: BASE_LABEL_API + "/api/v1/label_server/task/commit",
|
||||
method: "POST",
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
}
|
||||
|
||||
// 获取任务的工作流程
|
||||
export const getTaskWorkFlow = (id: number) => {
|
||||
return httpFetch<any[]>({
|
||||
url: BASE_LABEL_API + `/api/v1/label_server/task/workflow/${id}`,
|
||||
method: "GET",
|
||||
})
|
||||
}
|
||||
|
||||
// 获取个人任务列表
|
||||
export const getUserTaskList = (params: {
|
||||
page_size: number
|
||||
page_number: number
|
||||
}) => {
|
||||
return httpFetch<Task.ResGetUserTaskList>({
|
||||
url: BASE_LABEL_API + `/api/v1/label_server/task/list_by_user`,
|
||||
method: "GET",
|
||||
data: params,
|
||||
})
|
||||
}
|
||||
179
components/label/api/task/typing.ts
Normal file
179
components/label/api/task/typing.ts
Normal file
@@ -0,0 +1,179 @@
|
||||
export namespace Task {
|
||||
export interface DataProps {
|
||||
id: number
|
||||
create_date: string
|
||||
data_type?: number
|
||||
data_name: {
|
||||
name: [string]
|
||||
related_images: []
|
||||
}[]
|
||||
project_id: number
|
||||
project_name: string
|
||||
project_uuid: string
|
||||
label_status: number
|
||||
current_uid?: number
|
||||
current_username?: string
|
||||
label_user?: number
|
||||
label_username?: string
|
||||
review_user1?: number
|
||||
review1_username?: string
|
||||
review_user2?: number
|
||||
review2_username?: string
|
||||
rejected: boolean
|
||||
work_time: {
|
||||
label_work_time: number
|
||||
first_review_work_time: number
|
||||
second_review_work_time: number
|
||||
}
|
||||
label_object_size: {
|
||||
object_size: number
|
||||
valid_size: number
|
||||
first_comment_size: number
|
||||
second_comment_size: number
|
||||
new_size: number
|
||||
prelabel_size: number
|
||||
prelabel_modify_size: number
|
||||
dynamic_size: number
|
||||
static_size: number
|
||||
review_size: number
|
||||
review_dynamic_size: number
|
||||
review_static_size: number
|
||||
key_frame_size: number
|
||||
question_size: number
|
||||
total_qa_group_size: number
|
||||
single_qa_group_size: number
|
||||
multiple_qa_group_size: number
|
||||
new_qa_group_size: number
|
||||
new_single_qa_group_size: number
|
||||
new_multiple_qa_group_size: number
|
||||
review_question_size: number
|
||||
comment_question_size: number
|
||||
}
|
||||
first_commit_label_time?: string
|
||||
first_commit_review1_time?: string
|
||||
reject_times: number
|
||||
review_rate: {
|
||||
review1_rate: number
|
||||
review2_rate: number
|
||||
}
|
||||
label_first_work_time: number
|
||||
review1_first_work_time: number
|
||||
review2_first_work_time: number
|
||||
first_reject_label_time?: string
|
||||
}
|
||||
|
||||
export interface ListRequest {
|
||||
data_type?: number
|
||||
current_uid?: number[]
|
||||
data_name?: string
|
||||
first_commit_label_time_end?: string
|
||||
first_commit_label_time_start?: string
|
||||
first_commit_review1_time_end?: string
|
||||
first_commit_review1_time_start?: string
|
||||
get_data: boolean
|
||||
id?: number[]
|
||||
label_status?: number[]
|
||||
label_user?: number[]
|
||||
order_by?: string
|
||||
page_number: number
|
||||
page_size: number
|
||||
project_id?: number[]
|
||||
rejected?: number
|
||||
review_user1?: number[]
|
||||
review_user2?: number[]
|
||||
}
|
||||
|
||||
export interface SizeProps {
|
||||
object_size: number
|
||||
valid_size: number
|
||||
first_comment_size: number
|
||||
second_comment_size: number
|
||||
new_size: number
|
||||
prelabel_size: number
|
||||
prelabel_modify_size: number
|
||||
dynamic_size: number
|
||||
static_size: number
|
||||
review_size: number
|
||||
review_dynamic_size: number
|
||||
review_static_size: number
|
||||
key_frame_size: number
|
||||
question_size: number
|
||||
total_qa_group_size: number
|
||||
single_qa_group_size: number
|
||||
multiple_qa_group_size: number
|
||||
new_qa_group_size: number
|
||||
new_single_qa_group_size: number
|
||||
new_multiple_qa_group_size: number
|
||||
review_question_size: number
|
||||
comment_question_size: number
|
||||
}
|
||||
|
||||
export interface ListResponse {
|
||||
task_list: DataProps[]
|
||||
total_items: number
|
||||
total_pages: number
|
||||
total_size: SizeProps
|
||||
}
|
||||
|
||||
export interface AcquireReqProps {
|
||||
uid: number
|
||||
project_id: number
|
||||
label_action: 1 | 2 | 3 // 1-领取标注任务 2-领取审核任务 3-领取复审任务
|
||||
}
|
||||
|
||||
export interface DispatchReqProps {
|
||||
operation_uid: number
|
||||
reject: boolean
|
||||
task_ids: number[]
|
||||
task_status_dst: number
|
||||
task_status_src: number
|
||||
uid_dst: number | null
|
||||
uid_src: number | null
|
||||
}
|
||||
|
||||
export interface ReleaseReqProps {
|
||||
operation_uid: number
|
||||
reject: boolean
|
||||
task_ids: number[]
|
||||
task_status: number
|
||||
uid: number
|
||||
}
|
||||
|
||||
export interface NextReqProps {
|
||||
project_id: number
|
||||
task_status: number
|
||||
rejected: boolean
|
||||
last_task_id: number
|
||||
}
|
||||
|
||||
export interface NextResProps {
|
||||
project_id: number
|
||||
task_id: number | null
|
||||
}
|
||||
|
||||
export interface CommitReqProps {
|
||||
task_id: number
|
||||
uid: number
|
||||
commit_action: number //1-提交标注 2-提交审核1 3-提交审核2 4-驳回 5-无法标注
|
||||
work_time: number
|
||||
comment_question_size?: number
|
||||
}
|
||||
|
||||
export interface ResGetUserTaskList {
|
||||
simple_task_list: SimpleTaskItem[]
|
||||
total_items: number
|
||||
total_pages: number
|
||||
}
|
||||
|
||||
export interface SimpleTaskItem {
|
||||
id: number
|
||||
label_status: number
|
||||
label_type: number
|
||||
label_username?: string
|
||||
project_id: number
|
||||
project_name: string
|
||||
rejected: boolean
|
||||
review1_username?: string
|
||||
review2_username?: string
|
||||
}
|
||||
}
|
||||
605
components/label/store.ts
Normal file
605
components/label/store.ts
Normal file
@@ -0,0 +1,605 @@
|
||||
import { del, get, set } from "idb-keyval"
|
||||
import superjson from "superjson"
|
||||
import { create } from "zustand"
|
||||
import { persist, PersistStorage, StorageValue } from "zustand/middleware"
|
||||
import { Comment } from "./api/label/typing"
|
||||
import { safeClone } from "./utils/clone"
|
||||
|
||||
type LabelData = Map<string, Map<string, [number, any[], any, any[]][]>>
|
||||
type LabelPathTuple = [number, any[], any, any[]]
|
||||
type LabelTime = {
|
||||
label: number
|
||||
review1: number
|
||||
review2: number
|
||||
}
|
||||
|
||||
const isPaperPointLike = (value: any) => {
|
||||
return (
|
||||
value &&
|
||||
typeof value === "object" &&
|
||||
!Array.isArray(value) &&
|
||||
typeof value.x === "number" &&
|
||||
typeof value.y === "number"
|
||||
)
|
||||
}
|
||||
|
||||
const isPaperSegmentLike = (value: any) => {
|
||||
return (
|
||||
value &&
|
||||
typeof value === "object" &&
|
||||
!Array.isArray(value) &&
|
||||
value.point &&
|
||||
isPaperPointLike(value.point)
|
||||
)
|
||||
}
|
||||
|
||||
const normalizePointCollection = (value: any): any => {
|
||||
if (Array.isArray(value)) {
|
||||
return value.map((item) => normalizePointCollection(item))
|
||||
}
|
||||
if (isPaperSegmentLike(value)) {
|
||||
return [value.point.x, value.point.y]
|
||||
}
|
||||
if (isPaperPointLike(value)) {
|
||||
return [value.x, value.y]
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
const normalizeLabelPathTuple = (path: LabelPathTuple): LabelPathTuple => {
|
||||
return [
|
||||
path[0],
|
||||
normalizePointCollection(path[1]),
|
||||
path[2],
|
||||
normalizePointCollection(path[3]),
|
||||
]
|
||||
}
|
||||
|
||||
interface LabelState {
|
||||
// pathId pathPoints detail hollowPathPoints
|
||||
label: LabelData
|
||||
labelTime: LabelTime
|
||||
labelDefaultComments: Comment[]
|
||||
setLabel: (label: LabelData) => void
|
||||
stateStack: LabelData[]
|
||||
setStateStack: (data: LabelData[]) => void
|
||||
popStateStack: () => LabelData | null
|
||||
pushStateStack: (newData: LabelData) => void
|
||||
getLabelDetailDataByKeys: (
|
||||
imageId: string,
|
||||
categoryId: string,
|
||||
id: number
|
||||
) => any
|
||||
updateLabelDetailDataByKeys: (
|
||||
imageId: string,
|
||||
categoryId: string,
|
||||
id: number,
|
||||
newDetail: any
|
||||
) => void
|
||||
addDetail: (
|
||||
imageId: string,
|
||||
categoryId: string,
|
||||
id: number,
|
||||
obj: {
|
||||
[keys: string]: any
|
||||
}
|
||||
) => void
|
||||
setLabelTime: (
|
||||
labelTime: LabelTime | ((prev: LabelTime) => LabelTime)
|
||||
) => void
|
||||
setLabelDefaultComments: (arr: Comment[]) => void
|
||||
setImage: (
|
||||
imageId: string,
|
||||
operation: Map<string, [number, any[], any, any[]][]>
|
||||
) => void
|
||||
setOperation: (
|
||||
imageId: string,
|
||||
operationId: string,
|
||||
path: [number, any[], any, any[]]
|
||||
) => void
|
||||
deleteOperation: (
|
||||
imageId: string,
|
||||
operationId: string,
|
||||
pathId: number
|
||||
) => void
|
||||
resetLabel: () => void
|
||||
}
|
||||
|
||||
interface ObjectState {
|
||||
pathStatus: {
|
||||
// key = imageId + pathId
|
||||
[key: string]: {
|
||||
["HIDE"]?: boolean
|
||||
}
|
||||
}
|
||||
selectedPath: {
|
||||
// key = imageId
|
||||
[key: string]: number[]
|
||||
}
|
||||
operationStatus: {
|
||||
// key = imageId + operationId
|
||||
[key: string]: {
|
||||
["HIDE"]?: boolean
|
||||
["INPUT"]?: string
|
||||
["COLLAPSE"]?: boolean
|
||||
}
|
||||
}
|
||||
groupStatus: {
|
||||
// key = imageId + groupId
|
||||
[key: string]: {
|
||||
["COLLAPSE"]?: boolean
|
||||
}
|
||||
}
|
||||
imageStatus: {
|
||||
// key = imageId
|
||||
[key: string]: {
|
||||
["INPUT"]?: string
|
||||
["COLLAPSE"]?: boolean
|
||||
["FILTERCOLOR"]?: {
|
||||
[key: string]: boolean
|
||||
}
|
||||
}
|
||||
}
|
||||
updatePathStatus: (
|
||||
id: string,
|
||||
statusKey: "HIDE",
|
||||
statusValue: boolean
|
||||
) => void
|
||||
updateSelectedPath: (
|
||||
id: string,
|
||||
type: "ADD" | "DELETE" | "ADDSOME",
|
||||
pathValue?: number
|
||||
) => void
|
||||
resetPathAndOperationStatus: () => void
|
||||
updateOperationStatus: (
|
||||
id: string,
|
||||
statusKey: "HIDE" | "COLLAPSE" | "INPUT",
|
||||
statusValue: string | boolean
|
||||
) => void
|
||||
updateGroupStatus: (
|
||||
id: string,
|
||||
statusKey: "COLLAPSE",
|
||||
statusValue: string | boolean
|
||||
) => void
|
||||
updateImageStatus: (
|
||||
id: string,
|
||||
statusKey: "INPUT" | "COLLAPSE" | "FILTERCOLOR",
|
||||
statusValue:
|
||||
| string
|
||||
| boolean
|
||||
| {
|
||||
[key: string]: boolean
|
||||
}
|
||||
) => void
|
||||
}
|
||||
|
||||
interface KeyEventState {
|
||||
shift: boolean
|
||||
focusInput: boolean
|
||||
setShift: (value: boolean) => void
|
||||
setFocusInput: (value: boolean) => void
|
||||
}
|
||||
|
||||
const initialLabelState = {
|
||||
label: new Map(),
|
||||
labelTime: {
|
||||
label: 0,
|
||||
review1: 0,
|
||||
review2: 0,
|
||||
},
|
||||
}
|
||||
|
||||
export const initialDetail = {
|
||||
comment: [],
|
||||
create_timestamp: 0,
|
||||
first_modified_timestamp: 0,
|
||||
first_modified_uid: 0,
|
||||
last_modified_timestamp: 0,
|
||||
last_modified_uid: 0,
|
||||
sub_attributes: {},
|
||||
prelabel: false,
|
||||
}
|
||||
|
||||
// 自定义 storage 对象
|
||||
export const storage: PersistStorage<any> = {
|
||||
getItem: async (name: string) => {
|
||||
// console.log(name, "has been retrieved");
|
||||
let str = await get(name)
|
||||
if (!str) return null
|
||||
return superjson.parse(str) || null
|
||||
},
|
||||
setItem: async (name: string, value: StorageValue<any>): Promise<void> => {
|
||||
// console.log(name, "with value", value, "has been saved");
|
||||
await set(name, superjson.stringify(value))
|
||||
},
|
||||
removeItem: async (name: string): Promise<void> => {
|
||||
console.log(name, "has been deleted")
|
||||
await del(name)
|
||||
},
|
||||
}
|
||||
|
||||
// store path data
|
||||
export const useLabelStore = create(
|
||||
persist<LabelState>(
|
||||
(storeSet) => ({
|
||||
label: initialLabelState.label,
|
||||
labelTime: initialLabelState.labelTime,
|
||||
labelDefaultComments: [],
|
||||
stateStack: [],
|
||||
setLabel: (label) =>
|
||||
storeSet((state) => {
|
||||
return {
|
||||
...state,
|
||||
label,
|
||||
}
|
||||
}),
|
||||
setStateStack: (data) =>
|
||||
storeSet((state) => {
|
||||
return {
|
||||
...state,
|
||||
stateStack: data,
|
||||
}
|
||||
}),
|
||||
popStateStack: () => {
|
||||
const arr: LabelData[] = useLabelStore.getState().stateStack
|
||||
console.log("弹出栈", arr)
|
||||
if (!arr.length) return null
|
||||
if (arr.length === 1) {
|
||||
return arr[0]
|
||||
} else {
|
||||
arr.pop()
|
||||
storeSet((state) => {
|
||||
return {
|
||||
...state,
|
||||
stateStack: arr,
|
||||
}
|
||||
})
|
||||
return arr[arr.length - 1]
|
||||
}
|
||||
},
|
||||
pushStateStack: (newData) => {
|
||||
const arr: LabelData[] = useLabelStore.getState().stateStack
|
||||
if (arr.length === 10) {
|
||||
arr.shift()
|
||||
}
|
||||
arr.push(safeClone(newData))
|
||||
console.log(arr)
|
||||
return storeSet((state) => {
|
||||
return {
|
||||
...state,
|
||||
stateStack: arr,
|
||||
}
|
||||
})
|
||||
},
|
||||
getLabelDetailDataByKeys: (
|
||||
imageId: string,
|
||||
categoryId: string,
|
||||
id: number
|
||||
) => {
|
||||
const data = useLabelStore.getState().label
|
||||
if (!data.has(imageId)) return null
|
||||
const image = data.get(imageId)
|
||||
if (!image?.has(categoryId)) return null
|
||||
const category = image.get(categoryId)
|
||||
let detail = null
|
||||
category?.map((item) => {
|
||||
if (item[0] === id) detail = item[2]
|
||||
})
|
||||
return detail
|
||||
},
|
||||
updateLabelDetailDataByKeys: (imageId, categoryId, id, newData) => {
|
||||
const labelData = useLabelStore.getState().label
|
||||
if (!labelData.has(imageId)) return
|
||||
const image = labelData.get(imageId)
|
||||
if (!image?.has(categoryId)) return
|
||||
const category = image.get(categoryId)
|
||||
category?.map((item) => {
|
||||
if (item[0] === id) item[2] = newData
|
||||
})
|
||||
},
|
||||
addDetail: (imageId, categoryId, id, obj) => {
|
||||
const labelData = useLabelStore.getState().label
|
||||
if (!labelData.has(imageId)) return
|
||||
const image = labelData.get(imageId)
|
||||
if (!image?.has(categoryId)) return
|
||||
const category = image.get(categoryId)
|
||||
category?.map((item) => {
|
||||
if (item[0] === id) item[2] = Object.assign(item[2], obj)
|
||||
})
|
||||
},
|
||||
setLabelTime: (labelTime) =>
|
||||
storeSet((state) => {
|
||||
return {
|
||||
...state,
|
||||
labelTime:
|
||||
typeof labelTime === "function"
|
||||
? labelTime(state.labelTime)
|
||||
: labelTime,
|
||||
}
|
||||
}),
|
||||
setLabelDefaultComments: (labelDefaultComments) =>
|
||||
storeSet((state) => {
|
||||
return {
|
||||
...state,
|
||||
labelDefaultComments,
|
||||
}
|
||||
}),
|
||||
setImage: (imageId, operation) =>
|
||||
storeSet((state) => {
|
||||
state.label.set(imageId, operation)
|
||||
return state
|
||||
}),
|
||||
setOperation: (imageId, operationId, path) =>
|
||||
storeSet((state) => {
|
||||
const normalizedPath = normalizeLabelPathTuple(path)
|
||||
const labelData = useLabelStore.getState().label
|
||||
if (!labelData.has(imageId)) {
|
||||
labelData.set(imageId, new Map())
|
||||
}
|
||||
if (labelData.get(imageId)?.get(operationId)?.length) {
|
||||
let result = [
|
||||
...labelData.get(imageId)?.get(operationId)!,
|
||||
normalizedPath,
|
||||
]
|
||||
.reduce((acc, curr) => {
|
||||
const key = curr[0]
|
||||
acc.set(key, curr)
|
||||
return acc
|
||||
}, new Map())
|
||||
.values()
|
||||
labelData.get(imageId)?.set(operationId, Array.from(result))
|
||||
} else {
|
||||
labelData.get(imageId)?.set(operationId, [normalizedPath])
|
||||
}
|
||||
console.log("绘制时", labelData)
|
||||
useLabelStore.getState().pushStateStack(safeClone(labelData))
|
||||
return { ...state, label: safeClone(labelData) }
|
||||
}),
|
||||
|
||||
// 删除path
|
||||
deleteOperation: (imageId, operationId, pathId) =>
|
||||
storeSet((state) => {
|
||||
if (state.label.get(imageId)?.get(operationId)?.length) {
|
||||
let result =
|
||||
state.label
|
||||
.get(imageId)
|
||||
?.get(operationId)
|
||||
?.filter((item) => item[0] !== pathId) || []
|
||||
state.label.get(imageId)?.set(operationId, result)
|
||||
}
|
||||
return state
|
||||
}),
|
||||
resetLabel: () =>
|
||||
storeSet((state) => {
|
||||
return {
|
||||
...state,
|
||||
label: initialLabelState.label,
|
||||
labelTime: initialLabelState.labelTime,
|
||||
}
|
||||
}),
|
||||
}),
|
||||
{
|
||||
name: "label-data-storage",
|
||||
storage: storage,
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
const initialObjectState = {
|
||||
pathStatus: {},
|
||||
selectedPath: {},
|
||||
operationStatus: {},
|
||||
groupStatus: {},
|
||||
imageStatus: {},
|
||||
}
|
||||
|
||||
// store object list status
|
||||
export const useObjectStore = create(
|
||||
persist<ObjectState>(
|
||||
(storeSet) => ({
|
||||
pathStatus: initialObjectState.pathStatus,
|
||||
selectedPath: initialObjectState.selectedPath,
|
||||
operationStatus: initialObjectState.operationStatus,
|
||||
groupStatus: initialObjectState.groupStatus,
|
||||
imageStatus: initialObjectState.imageStatus,
|
||||
updatePathStatus: (id: string, statusKey: "HIDE", statusValue: boolean) =>
|
||||
storeSet((state) => {
|
||||
let idStatus = state.pathStatus[id] || {}
|
||||
idStatus = Object.assign(idStatus, {
|
||||
[statusKey]: statusValue,
|
||||
})
|
||||
return {
|
||||
...state,
|
||||
pathStatus: {
|
||||
...state.pathStatus,
|
||||
[id]: idStatus,
|
||||
},
|
||||
}
|
||||
}),
|
||||
updateSelectedPath: (
|
||||
id: string,
|
||||
type: "ADD" | "DELETE" | "ADDSOME",
|
||||
pathValue?: number
|
||||
) =>
|
||||
storeSet((state) => {
|
||||
let idSelectedPath = state.selectedPath[id] || []
|
||||
if (type === "ADD") {
|
||||
if (useKeyEventStore.getState().shift) {
|
||||
idSelectedPath = pathValue
|
||||
? [...new Set([...idSelectedPath, pathValue])]
|
||||
: idSelectedPath
|
||||
} else {
|
||||
idSelectedPath = pathValue ? [pathValue] : []
|
||||
}
|
||||
} else if (type === "ADDSOME") {
|
||||
idSelectedPath = pathValue
|
||||
? [...new Set([...idSelectedPath, pathValue])]
|
||||
: idSelectedPath
|
||||
} else if (type === "DELETE") {
|
||||
idSelectedPath =
|
||||
idSelectedPath?.filter((id) => id !== pathValue) || []
|
||||
}
|
||||
return {
|
||||
...state,
|
||||
selectedPath: {
|
||||
...state.selectedPath,
|
||||
[id]: idSelectedPath,
|
||||
},
|
||||
}
|
||||
}),
|
||||
resetPathAndOperationStatus: () =>
|
||||
storeSet((state) => {
|
||||
return {
|
||||
...state,
|
||||
selectedPath: {},
|
||||
pathStatus: {},
|
||||
operationStatus: {},
|
||||
}
|
||||
}),
|
||||
updateOperationStatus: (
|
||||
id: string,
|
||||
statusKey: "HIDE" | "COLLAPSE" | "INPUT",
|
||||
statusValue: string | boolean
|
||||
) =>
|
||||
storeSet((state) => {
|
||||
let idStatus = state.operationStatus[id] || {}
|
||||
idStatus = Object.assign(idStatus, {
|
||||
[statusKey]: statusValue,
|
||||
})
|
||||
return {
|
||||
...state,
|
||||
operationStatus: {
|
||||
...state.operationStatus,
|
||||
[id]: idStatus,
|
||||
},
|
||||
}
|
||||
}),
|
||||
updateGroupStatus: (
|
||||
id: string,
|
||||
statusKey: "COLLAPSE",
|
||||
statusValue: string | boolean
|
||||
) =>
|
||||
storeSet((state) => {
|
||||
let idStatus = state.groupStatus[id] || {}
|
||||
idStatus = Object.assign(idStatus, {
|
||||
[statusKey]: statusValue,
|
||||
})
|
||||
return {
|
||||
...state,
|
||||
groupStatus: {
|
||||
...state.groupStatus,
|
||||
[id]: idStatus,
|
||||
},
|
||||
}
|
||||
}),
|
||||
updateImageStatus: (
|
||||
id: string,
|
||||
statusKey: "INPUT" | "COLLAPSE" | "FILTERCOLOR",
|
||||
statusValue:
|
||||
| string
|
||||
| boolean
|
||||
| {
|
||||
[key: string]: boolean
|
||||
}
|
||||
) =>
|
||||
storeSet((state) => {
|
||||
let idStatus = state.imageStatus[id] || {}
|
||||
idStatus = Object.assign(idStatus, {
|
||||
[statusKey]: statusValue,
|
||||
})
|
||||
return {
|
||||
...state,
|
||||
imageStatus: {
|
||||
...state.imageStatus,
|
||||
[id]: idStatus,
|
||||
},
|
||||
}
|
||||
}),
|
||||
}),
|
||||
{
|
||||
name: "object-data-storage",
|
||||
storage: storage,
|
||||
partialize: (state: ObjectState) =>
|
||||
Object.fromEntries(
|
||||
Object.entries(state).filter(
|
||||
([key]) => !["selectedPath"].includes(key)
|
||||
)
|
||||
) as any,
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
const initialKeyEventState = {
|
||||
shift: false,
|
||||
focusInput: false,
|
||||
}
|
||||
|
||||
// store keyboard and mouse status
|
||||
export const useKeyEventStore = create<KeyEventState>((set) => ({
|
||||
shift: initialKeyEventState.shift,
|
||||
setShift: (value: boolean) =>
|
||||
set((state: KeyEventState) => ({ ...state, shift: value })),
|
||||
focusInput: initialKeyEventState.focusInput,
|
||||
setFocusInput: (value: boolean) =>
|
||||
set((state: KeyEventState) => ({ ...state, focusInput: value })),
|
||||
}))
|
||||
|
||||
interface ImageState {
|
||||
images: Map<string, string>
|
||||
setImages: (value: any) => void
|
||||
}
|
||||
|
||||
interface VideoFrameState {
|
||||
videoFrames: Map<string, string[]>
|
||||
setVideoFrames: (key: string, value: string[]) => void
|
||||
removeVideoFrames: (key: string) => void
|
||||
}
|
||||
|
||||
export const useImagesStore = create(
|
||||
persist<ImageState>(
|
||||
(storeSet) => ({
|
||||
images: new Map(),
|
||||
setImages: (value: any) =>
|
||||
storeSet((state) => {
|
||||
return {
|
||||
...state,
|
||||
images: value,
|
||||
}
|
||||
}),
|
||||
}),
|
||||
{
|
||||
name: "image-data-storage",
|
||||
storage: storage,
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
export const useVideoFrameStore = create(
|
||||
persist<VideoFrameState>(
|
||||
(storeSet) => ({
|
||||
videoFrames: new Map(),
|
||||
setVideoFrames: (key: string, value: string[]) =>
|
||||
storeSet((state) => {
|
||||
const nextMap = new Map(state.videoFrames)
|
||||
nextMap.set(key, value)
|
||||
return {
|
||||
...state,
|
||||
videoFrames: nextMap,
|
||||
}
|
||||
}),
|
||||
removeVideoFrames: (key: string) =>
|
||||
storeSet((state) => {
|
||||
const nextMap = new Map(state.videoFrames)
|
||||
nextMap.delete(key)
|
||||
return {
|
||||
...state,
|
||||
videoFrames: nextMap,
|
||||
}
|
||||
}),
|
||||
}),
|
||||
{
|
||||
name: "video-frame-storage",
|
||||
storage: storage,
|
||||
}
|
||||
)
|
||||
)
|
||||
414
components/label/store/auth.ts
Normal file
414
components/label/store/auth.ts
Normal file
@@ -0,0 +1,414 @@
|
||||
import dayjs from "dayjs"
|
||||
import { create } from "zustand"
|
||||
import { persist } from "zustand/middleware"
|
||||
import { storage } from "../store"
|
||||
import { ALL_CODE } from "../utils/constants"
|
||||
|
||||
const initUserInfo = {
|
||||
user_id: null,
|
||||
user_name: null,
|
||||
user_password: null,
|
||||
detailInfo: null,
|
||||
}
|
||||
|
||||
export const usePermissionStore = create(
|
||||
persist<any>(
|
||||
(set) => ({
|
||||
user_id: null,
|
||||
user_name: null,
|
||||
user_password: null,
|
||||
detailInfo: null,
|
||||
setUserPermissionInfo: ({ user_id, user_name, detailInfo }: any) =>
|
||||
set({
|
||||
user_id,
|
||||
user_name,
|
||||
detailInfo,
|
||||
user_password: usePermissionStore.getState().user_password,
|
||||
}),
|
||||
setUserPassword: (user_password: string) =>
|
||||
set((state: any) => {
|
||||
return {
|
||||
...state,
|
||||
user_password,
|
||||
}
|
||||
}),
|
||||
logout: () => set(initUserInfo),
|
||||
}),
|
||||
{
|
||||
name: "label_permission",
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
export interface Option {
|
||||
label: string
|
||||
value: any
|
||||
}
|
||||
|
||||
interface UserStoreProps {
|
||||
userOpts: Option[]
|
||||
treeData: any[]
|
||||
adminOpts: Option[]
|
||||
needUpdate: boolean
|
||||
setUserOpts: (opts: Option[]) => any
|
||||
setTreeData: (opts: any[]) => any
|
||||
setAdminOpts: (opts: Option[]) => any
|
||||
setFlag: (f: boolean) => void
|
||||
}
|
||||
|
||||
export const useAllUserStore = create<UserStoreProps>((set) => ({
|
||||
userOpts: [],
|
||||
treeData: [],
|
||||
adminOpts: [],
|
||||
needUpdate: true,
|
||||
setUserOpts: (opts: Option[]) =>
|
||||
set((state: any) => ({ ...state, userOpts: opts })),
|
||||
setTreeData: (opts: any[]) =>
|
||||
set((state: any) => ({ ...state, treeData: opts })),
|
||||
setAdminOpts: (opts: Option[]) =>
|
||||
set((state: any) => ({ ...state, adminOpts: opts })),
|
||||
setFlag: (flag) => set((state: any) => ({ ...state, needUpdate: flag })),
|
||||
}))
|
||||
|
||||
/* ******************* Project *********************** */
|
||||
type paramsType = "all" | "collect" | "dynamic"
|
||||
export const initAllParams = {
|
||||
page_number: 1,
|
||||
page_size: 15,
|
||||
status: ALL_CODE,
|
||||
}
|
||||
export const initCollectParams = {
|
||||
page_number: 1,
|
||||
page_size: 15,
|
||||
status: ALL_CODE,
|
||||
is_collect: 1,
|
||||
}
|
||||
export const initDynamicParams = {
|
||||
page_number: 1,
|
||||
page_size: 15,
|
||||
status: ALL_CODE,
|
||||
is_dynamic: 1,
|
||||
}
|
||||
|
||||
export const useProjectStore = create((set) => ({
|
||||
allParams: initAllParams,
|
||||
allTotal: 0,
|
||||
collectParams: initCollectParams,
|
||||
collectTotal: 0,
|
||||
dynamicParams: initDynamicParams,
|
||||
dynamicTotal: 0,
|
||||
setSearchParams: (params: any, type: paramsType) =>
|
||||
set((state: any) => {
|
||||
let obj = { ...state }
|
||||
if (type === "all") {
|
||||
obj.allParams = params
|
||||
} else if (type === "collect") {
|
||||
obj.collectParams = params
|
||||
} else if (type === "dynamic") {
|
||||
obj.dynamicParams = params
|
||||
}
|
||||
return obj
|
||||
}),
|
||||
setTotal: (total: number, type: paramsType) =>
|
||||
set((state: any) => {
|
||||
let obj = { ...state }
|
||||
if (type === "all") {
|
||||
obj.allTotal = total
|
||||
} else if (type === "collect") {
|
||||
obj.collectTotal = total
|
||||
} else if (type === "dynamic") {
|
||||
obj.dynamicTotal = total
|
||||
}
|
||||
return obj
|
||||
}),
|
||||
resetParams: (type: paramsType) =>
|
||||
set((state: any) => {
|
||||
let obj = { ...state }
|
||||
if (type === "all") {
|
||||
obj.allParams = initAllParams
|
||||
} else if (type === "collect") {
|
||||
obj.collectParams = initCollectParams
|
||||
} else if (type === "dynamic") {
|
||||
obj.dynamicParams = initDynamicParams
|
||||
}
|
||||
return obj
|
||||
}),
|
||||
}))
|
||||
|
||||
/* ******************* Task *********************** */
|
||||
interface TaskStore {
|
||||
params: any
|
||||
total: number
|
||||
setParams: (params: any) => void
|
||||
resetParams: () => void
|
||||
setPagination: (page: number, size: number) => void
|
||||
setTotal: (total: number) => void
|
||||
}
|
||||
|
||||
export const initTaskParams = {
|
||||
page_number: 1,
|
||||
page_size: 20,
|
||||
}
|
||||
|
||||
export const useOwnTaskStore = create<TaskStore>((set) => ({
|
||||
params: initTaskParams,
|
||||
total: 0,
|
||||
setParams: (params: any) => set((state: any) => ({ ...state, params })),
|
||||
resetParams: () =>
|
||||
set((state: any) => ({ ...state, params: initTaskParams })),
|
||||
setPagination: (p, s) =>
|
||||
set((state: any) => ({
|
||||
...state,
|
||||
params: { ...state.params, page_number: p, page_size: s },
|
||||
})),
|
||||
setTotal: (total: number) => set((state: any) => ({ ...state, total })),
|
||||
}))
|
||||
|
||||
export const useAllTaskStore = create<TaskStore>((set) => ({
|
||||
params: initTaskParams,
|
||||
total: 0,
|
||||
setParams: (params: any) => set((state: any) => ({ ...state, params })),
|
||||
resetParams: () =>
|
||||
set((state: any) => ({ ...state, params: initTaskParams })),
|
||||
setPagination: (p, s) =>
|
||||
set((state: any) => ({
|
||||
...state,
|
||||
params: { ...state.params, page_number: p, page_size: s },
|
||||
})),
|
||||
setTotal: (total: number) => set((state: any) => ({ ...state, total })),
|
||||
}))
|
||||
|
||||
/* ******************* Scheme *********************** */
|
||||
// 处理标注方案数据结构
|
||||
const handlePlanData = (data: any) => {
|
||||
const id = data.length
|
||||
let fieldsObj: any = {}
|
||||
const list: any = []
|
||||
data.forEach((item: any, index: number) => {
|
||||
const { label_class, color, label_type, radius, sub_attributes_describe } =
|
||||
item
|
||||
const singleClass: any = {
|
||||
[`class${index}-label_class`]: label_class,
|
||||
[`class${index}-color`]: color.join("_"),
|
||||
[`class${index}-label_type`]: label_type,
|
||||
[`class${index}-radius`]: radius,
|
||||
}
|
||||
const sub_count = sub_attributes_describe.length
|
||||
const sub_attr: string[] = []
|
||||
sub_attributes_describe.forEach((subItem: any, subIndex: number) => {
|
||||
const { chinese_name, select_mode, round_id, isrequired, optional_item } =
|
||||
subItem
|
||||
sub_attr.push(`sub${subIndex}`)
|
||||
singleClass[`class${index}-sub${subIndex}-sub_attributes`] = chinese_name
|
||||
singleClass[`class${index}-sub${subIndex}-select_mode`] = select_mode
|
||||
singleClass[`class${index}-sub${subIndex}-round_id`] = round_id
|
||||
singleClass[`class${index}-sub${subIndex}-isrequired`] = isrequired
|
||||
singleClass[`class${index}-sub${subIndex}-optional_item`] = optional_item
|
||||
})
|
||||
if (sub_count === 0)
|
||||
list.push({ name: `class${index}`, sub_attr: ["sub0"], sub_count })
|
||||
else list.push({ name: `class${index}`, sub_attr, sub_count })
|
||||
fieldsObj = { ...fieldsObj, ...singleClass }
|
||||
})
|
||||
return { id, fieldsObj, list }
|
||||
}
|
||||
|
||||
// scheme Store
|
||||
export const useSchemeStore = create((set) => ({
|
||||
// 首页搜索
|
||||
searchParams: {
|
||||
current_page: 1,
|
||||
page_size: 20,
|
||||
},
|
||||
total: 0,
|
||||
setSearchParams: (params: any) =>
|
||||
set((state: any) => ({ ...state, searchParams: params })),
|
||||
setTotal: (total: number) =>
|
||||
set((state: any) => ({ ...state, total: total })),
|
||||
// 方案版本数据
|
||||
nowVersionPlan: [],
|
||||
nowVersionFormData: {},
|
||||
nowVersionFormId: 0,
|
||||
nowVersionFormLabel: [
|
||||
{ name: `class${0}`, sub_attr: ["sub0"], sub_count: 0 },
|
||||
],
|
||||
selectPlan: (obj: any, data: any) => {
|
||||
const { id, fieldsObj, list } = handlePlanData(data)
|
||||
set((state: any) => ({
|
||||
...state,
|
||||
nowVersionPlan: data,
|
||||
nowVersionFormId: id,
|
||||
nowVersionFormData: { ...fieldsObj, ...obj },
|
||||
nowVersionFormLabel: list.length
|
||||
? list
|
||||
: [{ name: `class${0}`, sub_attr: ["sub0"], sub_count: 0 }],
|
||||
}))
|
||||
},
|
||||
resetPlan: () =>
|
||||
set((state: any) => ({
|
||||
...state,
|
||||
nowVersionPlan: [],
|
||||
nowVersionFormData: {},
|
||||
nowVersionFormId: 0,
|
||||
nowVersionFormLabel: [
|
||||
{ name: `class${0}`, sub_attr: ["sub0"], sub_count: 0 },
|
||||
],
|
||||
})),
|
||||
}))
|
||||
|
||||
/* ******************* 标注页面返回跳转 *********************** */
|
||||
// 返回跳转
|
||||
export const useBackUrlStore = create(
|
||||
persist<any>(
|
||||
(set) => ({
|
||||
backUrl: null,
|
||||
backTitle: null,
|
||||
setBackProps: (url: string, title?: string) =>
|
||||
set({ backUrl: url, backTitle: title || null }),
|
||||
}),
|
||||
{
|
||||
name: "back_url",
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
/* ******************* 数据统计 *********************** */
|
||||
interface WorkLoadDataProps {
|
||||
all: any[]
|
||||
order_by_group_name: any[]
|
||||
order_by_project_name: any[]
|
||||
order_by_project_type: any[]
|
||||
order_by_user_name: any[]
|
||||
}
|
||||
type dimensionType =
|
||||
| "all"
|
||||
| "order_by_group_name"
|
||||
| "order_by_project_name"
|
||||
| "order_by_project_type"
|
||||
| "order_by_user_name"
|
||||
interface WorkloadStore {
|
||||
labelData: WorkLoadDataProps
|
||||
reviewData: WorkLoadDataProps
|
||||
review2Data: WorkLoadDataProps
|
||||
filters: {
|
||||
label: [any, any]
|
||||
review1: [any, any]
|
||||
review2: [any, any]
|
||||
}
|
||||
dimensions: {
|
||||
label: dimensionType
|
||||
review1: dimensionType
|
||||
review2: dimensionType
|
||||
}
|
||||
setLabelData: (data: WorkLoadDataProps) => void
|
||||
setReviewData: (data: WorkLoadDataProps) => void
|
||||
setReview2Data: (data: WorkLoadDataProps) => void
|
||||
setFilters: (key: "label" | "review1" | "review2", data: [any, any]) => void
|
||||
setDimensions: (
|
||||
key: "label" | "review1" | "review2",
|
||||
data: dimensionType
|
||||
) => void
|
||||
}
|
||||
|
||||
export const dimensionOpts = [
|
||||
{ label: "全部", value: "all" },
|
||||
{ label: "用户名", value: "order_by_user_name" },
|
||||
{ label: "用户组", value: "order_by_group_name" },
|
||||
{ label: "项目名称", value: "order_by_project_name" },
|
||||
{ label: "项目类型", value: "order_by_project_type" },
|
||||
]
|
||||
|
||||
export const useWorkloadStore = create(
|
||||
persist<WorkloadStore>(
|
||||
(set) => ({
|
||||
labelData: {
|
||||
all: [],
|
||||
order_by_group_name: [],
|
||||
order_by_project_name: [],
|
||||
order_by_project_type: [],
|
||||
order_by_user_name: [],
|
||||
},
|
||||
reviewData: {
|
||||
all: [],
|
||||
order_by_group_name: [],
|
||||
order_by_project_name: [],
|
||||
order_by_project_type: [],
|
||||
order_by_user_name: [],
|
||||
},
|
||||
review2Data: {
|
||||
all: [],
|
||||
order_by_group_name: [],
|
||||
order_by_project_name: [],
|
||||
order_by_project_type: [],
|
||||
order_by_user_name: [],
|
||||
},
|
||||
filters: {
|
||||
label: [dayjs().subtract(1, "day"), dayjs().subtract(1, "day")],
|
||||
review1: [dayjs().subtract(1, "day"), dayjs().subtract(1, "day")],
|
||||
review2: [dayjs().subtract(1, "day"), dayjs().subtract(1, "day")],
|
||||
},
|
||||
dimensions: {
|
||||
label: "all",
|
||||
review1: "all",
|
||||
review2: "all",
|
||||
},
|
||||
setLabelData: (data) => set((state) => ({ ...state, labelData: data })),
|
||||
setReviewData: (data) => set((state) => ({ ...state, reviewData: data })),
|
||||
setReview2Data: (data) =>
|
||||
set((state) => ({ ...state, review2Data: data })),
|
||||
setFilters: (key, data) =>
|
||||
set((state) => ({
|
||||
...state,
|
||||
filters: { ...state.filters, [key]: data },
|
||||
})),
|
||||
setDimensions: (key, data) =>
|
||||
set((state) => ({
|
||||
...state,
|
||||
dimensions: { ...state.dimensions, [key]: data },
|
||||
})),
|
||||
}),
|
||||
{
|
||||
name: "workload",
|
||||
storage: storage,
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
interface TaskDataStore {
|
||||
taskData: any[]
|
||||
filters: {
|
||||
page_size: number
|
||||
project_type?: string[]
|
||||
project_id?: number[]
|
||||
label_status?: number[]
|
||||
current_uid?: number[]
|
||||
label_user?: number[]
|
||||
review_user1?: number[]
|
||||
review_user2?: number[]
|
||||
}
|
||||
totalSize: any
|
||||
total: number | null
|
||||
setTaskData: (data: any[]) => void
|
||||
setFilters: (data: any) => void
|
||||
setTotal: (n: number) => void
|
||||
setTotalSize: (data: any) => void
|
||||
}
|
||||
|
||||
export const useTaskDataStore = create(
|
||||
persist<TaskDataStore>(
|
||||
(set) => ({
|
||||
taskData: [],
|
||||
filters: { page_size: 1000 },
|
||||
total: null,
|
||||
totalSize: {},
|
||||
setTaskData: (data) => set((state) => ({ ...state, taskData: data })),
|
||||
setFilters: (data) => set((state) => ({ ...state, filters: data })),
|
||||
setTotal: (num) => set((state) => ({ ...state, total: num })),
|
||||
setTotalSize: (data) => set((state) => ({ ...state, totalSize: data })),
|
||||
}),
|
||||
{
|
||||
name: "task-list",
|
||||
storage: storage,
|
||||
}
|
||||
)
|
||||
)
|
||||
49
components/label/utils/clone.ts
Normal file
49
components/label/utils/clone.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
const deepCloneFallback = <T>(value: T, cache = new WeakMap()): T => {
|
||||
if (value === null || typeof value !== "object") return value
|
||||
if (cache.has(value as object)) return cache.get(value as object)
|
||||
|
||||
if (value instanceof Date) return new Date(value.getTime()) as T
|
||||
if (value instanceof Map) {
|
||||
const clonedMap = new Map()
|
||||
cache.set(value as object, clonedMap)
|
||||
value.forEach((mapValue, mapKey) => {
|
||||
clonedMap.set(
|
||||
deepCloneFallback(mapKey, cache),
|
||||
deepCloneFallback(mapValue, cache)
|
||||
)
|
||||
})
|
||||
return clonedMap as T
|
||||
}
|
||||
if (value instanceof Set) {
|
||||
const clonedSet = new Set()
|
||||
cache.set(value as object, clonedSet)
|
||||
value.forEach((setValue) => {
|
||||
clonedSet.add(deepCloneFallback(setValue, cache))
|
||||
})
|
||||
return clonedSet as T
|
||||
}
|
||||
if (Array.isArray(value)) {
|
||||
const clonedArr: any[] = []
|
||||
cache.set(value as object, clonedArr)
|
||||
value.forEach((item, index) => {
|
||||
clonedArr[index] = deepCloneFallback(item, cache)
|
||||
})
|
||||
return clonedArr as T
|
||||
}
|
||||
|
||||
const clonedObj: Record<string, any> = {}
|
||||
cache.set(value as object, clonedObj)
|
||||
Object.keys(value as object).forEach((key) => {
|
||||
clonedObj[key] = deepCloneFallback((value as any)[key], cache)
|
||||
})
|
||||
return clonedObj as T
|
||||
}
|
||||
|
||||
export const safeClone = <T>(value: T): T => {
|
||||
try {
|
||||
return structuredClone(value)
|
||||
} catch (error) {
|
||||
console.warn("structuredClone failed, fallback to deep clone", error)
|
||||
return deepCloneFallback(value)
|
||||
}
|
||||
}
|
||||
248
components/label/utils/constants.ts
Normal file
248
components/label/utils/constants.ts
Normal file
@@ -0,0 +1,248 @@
|
||||
"use client"
|
||||
|
||||
export const dateFormat = "YYYY-MM-DD HH:mm:ss"
|
||||
export const weekDayText = (data: number) => {
|
||||
switch (data) {
|
||||
case 0:
|
||||
return "星期日"
|
||||
case 1:
|
||||
return "星期一"
|
||||
case 2:
|
||||
return "星期二"
|
||||
case 3:
|
||||
return "星期三"
|
||||
case 4:
|
||||
return "星期四"
|
||||
case 5:
|
||||
return "星期五"
|
||||
case 6:
|
||||
return "星期六"
|
||||
default:
|
||||
return "-"
|
||||
}
|
||||
}
|
||||
|
||||
// 标注任务工序
|
||||
export const processOpts = [
|
||||
{ label: "标注", value: "标注" },
|
||||
{ label: "审核1", value: "审核1" },
|
||||
{ label: "审核2", value: "审核2" },
|
||||
]
|
||||
|
||||
// 状态码
|
||||
export const STATUS_CODE = new Map([
|
||||
[1, "已创建"],
|
||||
[101, "已创建"], // 审核
|
||||
[102, "已创建"], // 复审
|
||||
[103, "已创建"], // 审核3
|
||||
[180, "数据同步中"],
|
||||
[190, "Embedding生成中"],
|
||||
[191, "Embedding生成失败"],
|
||||
[199, "审核失败"],
|
||||
[201, "试标阶段"], // 试标中
|
||||
[202, "试标阶段"], // 试标完成
|
||||
[203, "试标阶段"], // 试标确认
|
||||
[500, "标注中"],
|
||||
[580, "待验收"],
|
||||
[600, "已完成"],
|
||||
[700, "已终止"],
|
||||
])
|
||||
|
||||
// 状态码
|
||||
export const projectStatusOpts = [
|
||||
{ label: "试标阶段", value: "201,202,203" },
|
||||
{ label: "标注中", value: 500 },
|
||||
{ label: "待验收", value: 580 },
|
||||
{ label: "已完成", value: 600 },
|
||||
// { label: "审核失败", value: 199 },
|
||||
{ label: "已终止", value: 700 },
|
||||
]
|
||||
|
||||
export const CREATED_CODE = [1, 101, 102, 103, 190, 191, 199] // 已创建的状态码数组
|
||||
export const ALL_CODE = [201, 202, 203, 500, 580, 600, 700] // 其他的状态码数组
|
||||
export const PRELABEL_CODE = [201, 202, 203]
|
||||
export const LABEL_CODE = [500, 580]
|
||||
|
||||
export const projectLabelTypeOpts = [
|
||||
{ label: "点云框", value: 1 },
|
||||
{ label: "点云分割", value: 2 },
|
||||
{ label: "点云分类", value: 3 },
|
||||
{ label: "图片", value: 4 },
|
||||
{ label: "大语言基础", value: 5 },
|
||||
{ label: "大语言QA", value: 6 },
|
||||
{ label: "视频", value: 7 },
|
||||
]
|
||||
|
||||
// 项目列表中状态码对应值及style
|
||||
export const statusStyles = {
|
||||
1: {
|
||||
label: "已创建",
|
||||
styleText: "text-[#1874FF] bg-[#E8F0FC]",
|
||||
},
|
||||
101: {
|
||||
label: "已创建",
|
||||
styleText: "text-[#1874FF] bg-[#E8F0FC]",
|
||||
},
|
||||
102: {
|
||||
label: "已创建",
|
||||
styleText: "text-[#1874FF] bg-[#E8F0FC]",
|
||||
},
|
||||
103: {
|
||||
label: "已创建",
|
||||
styleText: "text-[#1874FF] bg-[#E8F0FC]",
|
||||
},
|
||||
190: {
|
||||
label: "Embedding生成中",
|
||||
styleText: "text-[#1874FF] bg-[#E8F0FC]",
|
||||
},
|
||||
191: {
|
||||
label: "Embedding生成失败",
|
||||
styleText: "text-[#D9333E] bg-[#FBEBEC]",
|
||||
},
|
||||
199: {
|
||||
label: "审核失败",
|
||||
styleText: "text-[#D9333E] bg-[#FBEBEC]",
|
||||
},
|
||||
201: {
|
||||
label: "试标阶段",
|
||||
styleText: "text-[#21D3ED] bg-[#EEFDFF]",
|
||||
},
|
||||
202: {
|
||||
label: "试标阶段",
|
||||
styleText: "text-[#21D3ED] bg-[#EEFDFF]",
|
||||
},
|
||||
203: {
|
||||
label: "试标阶段",
|
||||
styleText: "text-[#21D3ED] bg-[#EEFDFF]",
|
||||
},
|
||||
500: {
|
||||
label: "标注中",
|
||||
styleText: "text-[#1874FF] bg-[#E8F0FC]",
|
||||
},
|
||||
580: {
|
||||
label: "待验收",
|
||||
styleText: "text-[#FFB84D] bg-[#FEF5E7]",
|
||||
},
|
||||
600: {
|
||||
label: "已完成",
|
||||
styleText: "text-[#4FD796] bg-[#E7F9F0]",
|
||||
},
|
||||
700: {
|
||||
label: "已终止",
|
||||
styleText: "text-[#34425F] bg-[#F7F8F9]",
|
||||
},
|
||||
}
|
||||
|
||||
export const staticsColor = [
|
||||
{ "8_151_156": 1 },
|
||||
{ "9_109_217": 2 },
|
||||
{ "15_15_118": 3 },
|
||||
{ "28_27_175": 4 },
|
||||
{ "35_84_116": 5 },
|
||||
{ "45_69_235": 6 },
|
||||
{ "53_127_127": 7 },
|
||||
{ "54_124_171": 8 },
|
||||
{ "54_207_201": 9 },
|
||||
{ "56_158_13": 10 },
|
||||
{ "63_18_119": 11 },
|
||||
{ "69_151_223": 12 },
|
||||
{ "81_188_187": 13 },
|
||||
{ "83_29_171": 14 },
|
||||
{ "84_119_48": 15 },
|
||||
{ "95_33_176": 16 },
|
||||
{ "100_16_23": 17 },
|
||||
{ "113_249_251": 18 },
|
||||
{ "116_78_41": 19 },
|
||||
{ "125_179_75": 20 },
|
||||
{ "127_48_236": 21 },
|
||||
{ "127_127_54": 22 },
|
||||
{ "132_133_239": 23 },
|
||||
{ "147_210_239": 24 },
|
||||
{ "151_29_36": 25 },
|
||||
{ "155_125_62": 26 },
|
||||
{ "156_239_102": 27 },
|
||||
{ "161_98_48": 28 },
|
||||
{ "178_253_253": 29 },
|
||||
{ "188_136_242": 30 },
|
||||
{ "189_191_84": 31 },
|
||||
{ "191_49_47": 32 },
|
||||
{ "196_29_127": 33 },
|
||||
{ "202_247_138": 34 },
|
||||
{ "203_164_81": 35 },
|
||||
{ "207_19_34": 36 },
|
||||
{ "212_107_8": 37 },
|
||||
{ "212_177_6": 38 },
|
||||
{ "223_134_144": 39 },
|
||||
{ "233_157_84": 40 },
|
||||
{ "244_206_159": 41 },
|
||||
{ "252_202_0": 42 },
|
||||
{ "252_250_147": 43 },
|
||||
{ "253_247_87": 44 },
|
||||
{ "255_191_120": 45 },
|
||||
{ "255_236_61": 46 },
|
||||
]
|
||||
|
||||
export const labelTypeOpts = [
|
||||
{ label: "点云框", value: 1 },
|
||||
{ label: "点云分割", value: 2 },
|
||||
// { label: '点云分类', value: '点云分类' },
|
||||
{ label: "2D框", value: 101 },
|
||||
{ label: "多边形", value: 102 },
|
||||
{ label: "关键点", value: 103 },
|
||||
{ label: "多线段", value: 104 },
|
||||
{ label: "文本描述", value: 201 },
|
||||
]
|
||||
|
||||
export const labelTypeMap = new Map([
|
||||
[1, "点云框"],
|
||||
[2, "点云分割"],
|
||||
[101, "2D框"],
|
||||
[102, "多边形"],
|
||||
[103, "关键点"],
|
||||
[104, "多线段"],
|
||||
[201, "文本描述"],
|
||||
])
|
||||
|
||||
export const selectModeOpts = [
|
||||
{ label: "输入", value: 0 },
|
||||
{ label: "单选", value: 1 },
|
||||
{ label: "多选", value: 2 },
|
||||
]
|
||||
|
||||
export const selectModeMap = new Map([
|
||||
[0, "输入"],
|
||||
[1, "单选"],
|
||||
[2, "多选"],
|
||||
])
|
||||
|
||||
// 标注任务状态码
|
||||
export const TaskStatusEnum = new Map([
|
||||
// [0, "None"],
|
||||
[1, "待领取"],
|
||||
[2, "标注中"],
|
||||
[3, "标注完成"],
|
||||
[4, "审核中"],
|
||||
[5, "审核完成"],
|
||||
[6, "复审中"],
|
||||
[7, "复审完成"],
|
||||
[8, "无法标注"],
|
||||
])
|
||||
|
||||
export const OwnTaskStatusOpts = {
|
||||
0: "全部",
|
||||
2: "标注中",
|
||||
4: "审核中",
|
||||
6: "复审中",
|
||||
}
|
||||
|
||||
export const TaskStatusOpts = {
|
||||
0: "全部",
|
||||
1: "待领取",
|
||||
2: "标注中",
|
||||
3: "标注完成",
|
||||
4: "审核中",
|
||||
5: "审核完成",
|
||||
6: "复审中",
|
||||
7: "复审完成",
|
||||
8: "无法标注",
|
||||
}
|
||||
Reference in New Issue
Block a user