Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
P
project_manager_xy
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
David Yang
project_manager_xy
Commits
c1615014
Commit
c1615014
authored
Jul 14, 2026
by
David Yang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: 部分字段改成选项,优化 ui
parent
12c2303f
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
62 additions
and
125 deletions
+62
-125
Login.jsx
src/pages/Login.jsx
+2
-2
Layout.jsx
src/pages/project_manager_xy/Layout.jsx
+1
-4
ProjectBookingWorkspace.jsx
src/pages/project_manager_xy/ProjectBookingWorkspace.jsx
+0
-0
project-management.business-flow.md
...es/project_manager_xy/project-management.business-flow.md
+13
-14
projectTaskService.js
src/pages/project_manager_xy/projectTaskService.js
+18
-0
index.jsx
src/pages/project_manager_xy/resource-stat/index.jsx
+3
-95
subjectsDefinition.md
src/services/subjectsDefinition.md
+24
-9
Site.jsx
src/wrapper/Site.jsx
+1
-1
No files found.
src/pages/Login.jsx
View file @
c1615014
...
@@ -26,7 +26,7 @@ export default function LoginPage() {
...
@@ -26,7 +26,7 @@ export default function LoginPage() {
const
redirect
=
searchParams
.
get
(
'redirect'
)
||
'/'
;
const
redirect
=
searchParams
.
get
(
'redirect'
)
||
'/'
;
const
siteTitle
=
site
?.
title
||
site
?.
name
||
'
项目管理系统
'
;
const
siteTitle
=
site
?.
title
||
site
?.
name
||
'
部门任务管理
'
;
const
siteSubtitle
=
const
siteSubtitle
=
site
?.
subtitle
||
'项目下发、成员协作、甘特排期与个人日历统一协同'
;
site
?.
subtitle
||
'项目下发、成员协作、甘特排期与个人日历统一协同'
;
...
@@ -141,7 +141,7 @@ export default function LoginPage() {
...
@@ -141,7 +141,7 @@ export default function LoginPage() {
Sign In
Sign In
</
p
>
</
p
>
<
h2
className=
"mt-3 text-3xl font-semibold text-slate-900"
>
<
h2
className=
"mt-3 text-3xl font-semibold text-slate-900"
>
登录
项目管理系统
登录
部门任务管理
</
h2
>
</
h2
>
<
p
className=
"mt-3 text-sm leading-6 text-slate-500"
>
<
p
className=
"mt-3 text-sm leading-6 text-slate-500"
>
参考 `streams-admin` 登录页改造,已接入验证码校验流程。
参考 `streams-admin` 登录页改造,已接入验证码校验流程。
...
...
src/pages/project_manager_xy/Layout.jsx
View file @
c1615014
...
@@ -14,7 +14,7 @@ import clsx from 'clsx';
...
@@ -14,7 +14,7 @@ import clsx from 'clsx';
import
{
useContext
,
useEffect
,
useMemo
,
useState
}
from
'react'
;
import
{
useContext
,
useEffect
,
useMemo
,
useState
}
from
'react'
;
import
{
Link
,
Outlet
,
useLocation
}
from
'umi'
;
import
{
Link
,
Outlet
,
useLocation
}
from
'umi'
;
const
APP_NAME
=
'
项目管理系统
'
;
const
APP_NAME
=
'
部门任务管理
'
;
const
menuGroups
=
[
const
menuGroups
=
[
{
{
...
@@ -272,9 +272,6 @@ export default function ProjectManagerLayout() {
...
@@ -272,9 +272,6 @@ export default function ProjectManagerLayout() {
<
h1
className=
"truncate text-sm font-semibold tracking-[0.02em] text-white/95"
>
<
h1
className=
"truncate text-sm font-semibold tracking-[0.02em] text-white/95"
>
{
APP_NAME
}
{
APP_NAME
}
</
h1
>
</
h1
>
<
div
className=
"mt-1 text-xs text-zinc-400"
>
项目资源管理工作台
</
div
>
</
div
>
</
div
>
{
applicationSwitcherButton
}
{
applicationSwitcherButton
}
</>
</>
...
...
src/pages/project_manager_xy/ProjectBookingWorkspace.jsx
View file @
c1615014
This diff is collapsed.
Click to expand it.
src/pages/project_manager_xy/project-management.business-flow.md
View file @
c1615014
...
@@ -35,12 +35,12 @@
...
@@ -35,12 +35,12 @@
关键字段:
关键字段:
-
`project_name`
:项目名称
-
`project_name`
:项目名称
-
`big_category`
:大类
-
`big_category`
:大类
,选择项为部门管理、纪检工作、审计工作
-
`project`
:项目归属或项目分类补充字段
-
`project`
:项目归属或项目分类补充字段
-
`project_owner`
:项目负责人,直接关联系统用户,多值
-
`project_owner`
:项目负责人,直接关联系统用户,多值
-
`project_collaborator`
:项目协作人,直接关联系统用户,多值
-
`project_collaborator`
:项目协作人,直接关联系统用户,多值
-
`task_source`
:任务来源
-
`task_source`
:任务来源
,选择项由 Subject 字段配置
`settings.options`
提供
-
`task_nature`
:任务性质
-
`task_nature`
:任务性质
,选择项由 Subject 字段配置
`settings.options`
提供
-
`occurrence_frequency`
:发生频率
-
`occurrence_frequency`
:发生频率
-
`planned_start_date`
/
`planned_end_date`
:计划时间
-
`planned_start_date`
/
`planned_end_date`
:计划时间
-
`actual_start_date`
/
`actual_finish_date`
:实际时间
-
`actual_start_date`
/
`actual_finish_date`
:实际时间
...
@@ -59,7 +59,7 @@
...
@@ -59,7 +59,7 @@
1.
领导创建一条
`pm_project_task`
1.
领导创建一条
`pm_project_task`
2.
填写项目名称、计划开始日期、计划结束日期
2.
填写项目名称、计划开始日期、计划结束日期
3.
按需要
补充大类、项目、任务来源、任务性质、发生频率
3.
按需要
选择大类、任务来源、任务性质、发生频率,并补充项目
4.
按需勾选是否属于年度审计计划
`is_annual_audit_plan`
4.
按需勾选是否属于年度审计计划
`is_annual_audit_plan`
5.
选择一个或多个项目负责人
`project_owner`
5.
选择一个或多个项目负责人
`project_owner`
6.
选择一个或多个项目协作人
`project_collaborator`
6.
选择一个或多个项目协作人
`project_collaborator`
...
@@ -128,28 +128,25 @@
...
@@ -128,28 +128,25 @@
-
结果状态分布柱状图
-
结果状态分布柱状图
-
进度区间分布柱状图
-
进度区间分布柱状图
-
成员负载 Top N 横向柱状图
-
成员负载 Top N 横向柱状图
-
维度概览区保留列表化统计:
-
“维度概览”区块当前意义不明确,资源统计看板暂不展示该模块;发生频率、大类、任务来源等维度待统计口径明确后再补充为独立图表或筛选项
-
发生频率
-
大类
-
任务来源
-
风险清单区展示:
-
风险清单区展示:
-
即将到期项目
-
即将到期项目
-
超时项目清单
-
超时项目清单
-
风险清单区位于成员负载明细下方,采用独立全宽区块展示,避免作为右侧纵列造成页面左右高度失衡
-
建议补充统计维度:
-
建议补充统计维度:
-
项目状态分布
-
项目状态分布
-
结果状态分布(按时间规则实时派生)
-
结果状态分布(按时间规则实时派生)
-
发生频率分布
-
大类分布
-
任务来源分布
-
负责人/协作人负载分布
-
负责人/协作人负载分布
-
即将到期项目
-
即将到期项目
-
超时项目清单
-
超时项目清单
-
统计口径以
`pm_project_task.metadata`
的当前字段为准,优先展示:
-
统计口径以
`pm_project_task.metadata`
的当前字段为准,优先展示:
-
`project_status`
-
`project_status`
-
`occurrence_frequency`
-
`completion_percent`
-
`big_category`
-
`project_owner`
-
`task_source`
-
`project_collaborator`
-
`planned_end_date`
-
`actual_finish_date`
### 5.1 甘特图
### 5.1 甘特图
...
@@ -229,6 +226,8 @@ const result = await queryUsers(0, 20, {
...
@@ -229,6 +226,8 @@ const result = await queryUsers(0, 20, {
## 6.3 Excel 批量导入口径
## 6.3 Excel 批量导入口径
-
Excel 模板采用业务列头:
`大类`
、
`项目`
、
`是否属于年度审计计划`
、
`发生频率`
、
`任务名称`
、
`任务来源`
、
`任务性质`
、
`计划启动时间`
、
`计划完成时间`
、
`时间进度`
、
`任务进度`
、
`任务状态`
、
`主办人`
、
`协办人1`
-
Excel 模板采用业务列头:
`大类`
、
`项目`
、
`是否属于年度审计计划`
、
`发生频率`
、
`任务名称`
、
`任务来源`
、
`任务性质`
、
`计划启动时间`
、
`计划完成时间`
、
`时间进度`
、
`任务进度`
、
`任务状态`
、
`主办人`
、
`协办人1`
-
`大类`
导入到
`metadata.big_category`
,当前仅支持
`部门管理`
、
`纪检工作`
、
`审计工作`
-
`任务来源`
/
`任务性质`
导入到
`metadata.task_source`
/
`metadata.task_nature`
,应填写对应 Subject 字段
`settings.options`
中配置的存储值
-
`任务名称`
导入到
`metadata.project_name`
-
`任务名称`
导入到
`metadata.project_name`
-
`是否属于年度审计计划`
导入到
`metadata.is_annual_audit_plan`
,支持
`是/否`
、
`true/false`
、
`1/0`
-
`是否属于年度审计计划`
导入到
`metadata.is_annual_audit_plan`
,支持
`是/否`
、
`true/false`
、
`1/0`
-
`主办人`
导入到
`metadata.project_owner`
,
`协办人1`
导入到
`metadata.project_collaborator`
;支持填写系统用户
`display_name`
或
`username`
,前端会先按
`username/display_name`
的
`$regex`
条件调用
`queryUsers`
查询,并最终保存为用户
`_id`
数组
-
`主办人`
导入到
`metadata.project_owner`
,
`协办人1`
导入到
`metadata.project_collaborator`
;支持填写系统用户
`display_name`
或
`username`
,前端会先按
`username/display_name`
的
`$regex`
条件调用
`queryUsers`
查询,并最终保存为用户
`_id`
数组
...
...
src/pages/project_manager_xy/projectTaskService.js
View file @
c1615014
...
@@ -28,6 +28,12 @@ export const OCCURRENCE_FREQUENCY_OPTIONS = [
...
@@ -28,6 +28,12 @@ export const OCCURRENCE_FREQUENCY_OPTIONS = [
{
label
:
'低'
,
value
:
'1'
},
{
label
:
'低'
,
value
:
'1'
},
];
];
export
const
BIG_CATEGORY_OPTIONS
=
[
{
label
:
'部门管理'
,
value
:
'部门管理'
},
{
label
:
'纪检工作'
,
value
:
'纪检工作'
},
{
label
:
'审计工作'
,
value
:
'审计工作'
},
];
export
const
PRIORITY_OPTIONS
=
[
export
const
PRIORITY_OPTIONS
=
[
{
label
:
'高'
,
value
:
'high'
},
{
label
:
'高'
,
value
:
'high'
},
{
label
:
'中'
,
value
:
'medium'
},
{
label
:
'中'
,
value
:
'medium'
},
...
@@ -331,11 +337,20 @@ function extractSubjectField(subject, fieldName) {
...
@@ -331,11 +337,20 @@ function extractSubjectField(subject, fieldName) {
export
async
function
loadProjectTaskFieldOptions
()
{
export
async
function
loadProjectTaskFieldOptions
()
{
try
{
try
{
const
subject
=
await
loadSubject
(
PROJECT_TASK_SUBJECT
);
const
subject
=
await
loadSubject
(
PROJECT_TASK_SUBJECT
);
const
bigCategoryField
=
extractSubjectField
(
subject
,
'big_category'
);
const
taskSourceField
=
extractSubjectField
(
subject
,
'task_source'
);
const
taskNatureField
=
extractSubjectField
(
subject
,
'task_nature'
);
const
projectStatusField
=
extractSubjectField
(
subject
,
'project_status'
);
const
projectStatusField
=
extractSubjectField
(
subject
,
'project_status'
);
const
priorityField
=
extractSubjectField
(
subject
,
'priority'
);
const
priorityField
=
extractSubjectField
(
subject
,
'priority'
);
const
occurrenceFrequencyField
=
extractSubjectField
(
subject
,
'occurrence_frequency'
);
const
occurrenceFrequencyField
=
extractSubjectField
(
subject
,
'occurrence_frequency'
);
return
{
return
{
bigCategoryOptions
:
normalizeSelectOptions
(
bigCategoryField
?.
settings
?.
options
).
length
>
0
?
normalizeSelectOptions
(
bigCategoryField
?.
settings
?.
options
)
:
BIG_CATEGORY_OPTIONS
,
taskSourceOptions
:
normalizeSelectOptions
(
taskSourceField
?.
settings
?.
options
),
taskNatureOptions
:
normalizeSelectOptions
(
taskNatureField
?.
settings
?.
options
),
projectStatusOptions
:
projectStatusOptions
:
normalizeSelectOptions
(
projectStatusField
?.
settings
?.
options
).
length
>
0
normalizeSelectOptions
(
projectStatusField
?.
settings
?.
options
).
length
>
0
?
normalizeSelectOptions
(
projectStatusField
?.
settings
?.
options
)
?
normalizeSelectOptions
(
projectStatusField
?.
settings
?.
options
)
...
@@ -348,6 +363,9 @@ export async function loadProjectTaskFieldOptions() {
...
@@ -348,6 +363,9 @@ export async function loadProjectTaskFieldOptions() {
};
};
}
catch
(
error
)
{
}
catch
(
error
)
{
return
{
return
{
bigCategoryOptions
:
BIG_CATEGORY_OPTIONS
,
taskSourceOptions
:
[],
taskNatureOptions
:
[],
projectStatusOptions
:
PROJECT_STATUS_OPTIONS
,
projectStatusOptions
:
PROJECT_STATUS_OPTIONS
,
priorityOptions
:
[],
priorityOptions
:
[],
occurrenceFrequencyOptions
:
OCCURRENCE_FREQUENCY_OPTIONS
,
occurrenceFrequencyOptions
:
OCCURRENCE_FREQUENCY_OPTIONS
,
...
...
src/pages/project_manager_xy/resource-stat/index.jsx
View file @
c1615014
...
@@ -4,7 +4,6 @@ import { useContext, useEffect, useMemo, useState } from 'react';
...
@@ -4,7 +4,6 @@ import { useContext, useEffect, useMemo, useState } from 'react';
import
ReactECharts
from
'echarts-for-react'
;
import
ReactECharts
from
'echarts-for-react'
;
import
{
import
{
formatDateLabel
,
formatDateLabel
,
OCCURRENCE_FREQUENCY_LABEL_MAP
,
PROJECT_STATUS_LABEL_MAP
,
PROJECT_STATUS_LABEL_MAP
,
RESULT_STATUS_LABEL_MAP
,
RESULT_STATUS_LABEL_MAP
,
}
from
'../projectTaskService'
;
}
from
'../projectTaskService'
;
...
@@ -297,28 +296,6 @@ function ChartPanel({ title, description, option, hasData }) {
...
@@ -297,28 +296,6 @@ function ChartPanel({ title, description, option, hasData }) {
);
);
}
}
function
DimensionList
({
items
,
emptyText
})
{
if
(
items
.
length
===
0
)
{
return
<
div
className=
"text-sm text-zinc-400"
>
{
emptyText
}
</
div
>;
}
return
(
<
div
className=
"space-y-3"
>
{
items
.
map
((
item
)
=>
(
<
div
key=
{
item
.
key
}
className=
"rounded-2xl border border-zinc-200 bg-zinc-50 px-4 py-4"
>
<
div
className=
"flex items-center justify-between gap-4"
>
<
div
className=
"min-w-0 text-sm font-medium text-zinc-800"
>
{
item
.
label
}
</
div
>
<
div
className=
"shrink-0 text-lg font-semibold text-zinc-950"
>
{
item
.
count
}
</
div
>
</
div
>
</
div
>
))
}
</
div
>
);
}
export
default
function
ResourceStatPage
({
currentUsername
=
''
})
{
export
default
function
ResourceStatPage
({
currentUsername
=
''
})
{
const
userInfo
=
useContext
(
UserContext
);
const
userInfo
=
useContext
(
UserContext
);
const
effectiveCurrentUsername
=
currentUsername
||
userInfo
?.
username
||
userInfo
?.
_id
||
''
;
const
effectiveCurrentUsername
=
currentUsername
||
userInfo
?.
username
||
userInfo
?.
_id
||
''
;
...
@@ -400,48 +377,6 @@ export default function ResourceStatPage({ currentUsername = '' }) {
...
@@ -400,48 +377,6 @@ export default function ResourceStatPage({ currentUsername = '' }) {
}))
}))
.
sort
((
left
,
right
)
=>
right
.
count
-
left
.
count
);
.
sort
((
left
,
right
)
=>
right
.
count
-
left
.
count
);
const
frequencyGroups
=
Object
.
entries
(
tasks
.
reduce
((
accumulator
,
task
)
=>
{
const
key
=
task
.
occurrenceFrequency
||
'unset'
;
accumulator
[
key
]
=
(
accumulator
[
key
]
||
0
)
+
1
;
return
accumulator
;
},
{}),
)
.
map
(([
key
,
count
])
=>
({
key
,
label
:
key
===
'unset'
?
'未设置'
:
OCCURRENCE_FREQUENCY_LABEL_MAP
[
key
]
||
key
,
count
,
}))
.
sort
((
left
,
right
)
=>
right
.
count
-
left
.
count
);
const
categoryGroups
=
Object
.
entries
(
tasks
.
reduce
((
accumulator
,
task
)
=>
{
const
key
=
task
.
bigCategory
||
'unset'
;
accumulator
[
key
]
=
(
accumulator
[
key
]
||
0
)
+
1
;
return
accumulator
;
},
{}),
)
.
map
(([
key
,
count
])
=>
({
key
,
label
:
key
===
'unset'
?
'未设置'
:
key
,
count
,
}))
.
sort
((
left
,
right
)
=>
right
.
count
-
left
.
count
);
const
taskSourceGroups
=
Object
.
entries
(
tasks
.
reduce
((
accumulator
,
task
)
=>
{
const
key
=
task
.
taskSource
||
'unset'
;
accumulator
[
key
]
=
(
accumulator
[
key
]
||
0
)
+
1
;
return
accumulator
;
},
{}),
)
.
map
(([
key
,
count
])
=>
({
key
,
label
:
key
===
'unset'
?
'未设置'
:
key
,
count
,
}))
.
sort
((
left
,
right
)
=>
right
.
count
-
left
.
count
);
const
progressBuckets
=
PROGRESS_BUCKETS
.
map
((
bucket
)
=>
({
const
progressBuckets
=
PROGRESS_BUCKETS
.
map
((
bucket
)
=>
({
...
bucket
,
...
bucket
,
count
:
tasks
.
filter
((
task
)
=>
{
count
:
tasks
.
filter
((
task
)
=>
{
...
@@ -495,9 +430,6 @@ export default function ResourceStatPage({ currentUsername = '' }) {
...
@@ -495,9 +430,6 @@ export default function ResourceStatPage({ currentUsername = '' }) {
currentUserTaskCount
,
currentUserTaskCount
,
statusGroups
,
statusGroups
,
resultStatusGroups
,
resultStatusGroups
,
frequencyGroups
,
categoryGroups
,
taskSourceGroups
,
progressBuckets
,
progressBuckets
,
memberLoad
,
memberLoad
,
upcoming
,
upcoming
,
...
@@ -635,7 +567,7 @@ export default function ResourceStatPage({ currentUsername = '' }) {
...
@@ -635,7 +567,7 @@ export default function ResourceStatPage({ currentUsername = '' }) {
/>
/>
</
div
>
</
div
>
<
div
className=
"grid gap-6 xl:grid-cols-
[1fr_1fr_0.9fr]
"
>
<
div
className=
"grid gap-6 xl:grid-cols-
2
"
>
<
ChartPanel
<
ChartPanel
title=
"进度区间分布"
title=
"进度区间分布"
description=
"按 `completion_percent` 分桶,快速查看项目推进层级。"
description=
"按 `completion_percent` 分桶,快速查看项目推进层级。"
...
@@ -648,29 +580,8 @@ export default function ResourceStatPage({ currentUsername = '' }) {
...
@@ -648,29 +580,8 @@ export default function ResourceStatPage({ currentUsername = '' }) {
option=
{
memberLoadOption
}
option=
{
memberLoadOption
}
hasData=
{
dashboard
.
memberLoad
.
length
>
0
}
hasData=
{
dashboard
.
memberLoad
.
length
>
0
}
/>
/>
<
SectionCard
title=
"维度概览"
description=
"保留发生频率、大类、任务来源三类核心统计维度。"
bodyClassName=
"space-y-5"
>
<
div
>
<
div
className=
"mb-3 text-sm font-medium text-zinc-500"
>
发生频率
</
div
>
<
DimensionList
items=
{
dashboard
.
frequencyGroups
.
slice
(
0
,
3
)
}
emptyText=
"暂无发生频率统计数据"
/>
</
div
>
<
div
>
<
div
className=
"mb-3 text-sm font-medium text-zinc-500"
>
大类
</
div
>
<
DimensionList
items=
{
dashboard
.
categoryGroups
.
slice
(
0
,
3
)
}
emptyText=
"暂无大类统计数据"
/>
</
div
>
</
div
>
<
div
>
<
div
className=
"mb-3 text-sm font-medium text-zinc-500"
>
任务来源
</
div
>
<
DimensionList
items=
{
dashboard
.
taskSourceGroups
.
slice
(
0
,
3
)
}
emptyText=
"暂无任务来源统计数据"
/>
</
div
>
</
SectionCard
>
</
div
>
<
div
className=
"grid gap-6 xl:grid-cols-[1.1fr_0.9fr]"
>
<
SectionCard
<
SectionCard
title=
"成员负载明细"
title=
"成员负载明细"
description=
"展示每位成员的关联项目、进行中项目和超时项目数量。"
description=
"展示每位成员的关联项目、进行中项目和超时项目数量。"
...
@@ -705,12 +616,11 @@ export default function ResourceStatPage({ currentUsername = '' }) {
...
@@ -705,12 +616,11 @@ export default function ResourceStatPage({ currentUsername = '' }) {
</
div
>
</
div
>
</
SectionCard
>
</
SectionCard
>
<
div
className=
"space-y-6"
>
<
SectionCard
<
SectionCard
title=
"即将到期"
title=
"即将到期"
description=
"按计划完成日期升序展示,便于提前提醒负责人。"
description=
"按计划完成日期升序展示,便于提前提醒负责人。"
>
>
<
div
className=
"space-y
-3"
>
<
div
className=
"grid gap-3 md:grid-cols-2 xl:grid-cols
-3"
>
{
dashboard
.
upcoming
.
length
>
0
?
(
{
dashboard
.
upcoming
.
length
>
0
?
(
dashboard
.
upcoming
.
map
((
task
)
=>
(
dashboard
.
upcoming
.
map
((
task
)
=>
(
<
div
<
div
...
@@ -734,7 +644,7 @@ export default function ResourceStatPage({ currentUsername = '' }) {
...
@@ -734,7 +644,7 @@ export default function ResourceStatPage({ currentUsername = '' }) {
title=
"超时清单"
title=
"超时清单"
description=
"按超时天数倒序展示,帮助工作台聚焦风险项目。"
description=
"按超时天数倒序展示,帮助工作台聚焦风险项目。"
>
>
<
div
className=
"space-y
-3"
>
<
div
className=
"grid gap-3 md:grid-cols-2 xl:grid-cols
-3"
>
{
dashboard
.
overdueList
.
length
>
0
?
(
{
dashboard
.
overdueList
.
length
>
0
?
(
dashboard
.
overdueList
.
map
((
task
)
=>
(
dashboard
.
overdueList
.
map
((
task
)
=>
(
<
div
<
div
...
@@ -754,7 +664,5 @@ export default function ResourceStatPage({ currentUsername = '' }) {
...
@@ -754,7 +664,5 @@ export default function ResourceStatPage({ currentUsername = '' }) {
</
div
>
</
div
>
</
SectionCard
>
</
SectionCard
>
</
div
>
</
div
>
</
div
>
</
div
>
);
);
}
}
src/services/subjectsDefinition.md
View file @
c1615014
...
@@ -89,12 +89,12 @@ type Record = {
...
@@ -89,12 +89,12 @@ type Record = {
| 字段标签 | 字段别名 | 字段类型 | 是否主键 | 是否多值 | 是否必填 |
| 字段标签 | 字段别名 | 字段类型 | 是否主键 | 是否多值 | 是否必填 |
| --- | --- | --- | --- | --- | --- |
| --- | --- | --- | --- | --- | --- |
| 项目名称 |
`project_name`
| text | 否 | 否 | 是 |
| 项目名称 |
`project_name`
| text | 否 | 否 | 是 |
| 大类 |
`big_category`
|
tex
t | 否 | 否 | 否 |
| 大类 |
`big_category`
|
selec
t | 否 | 否 | 否 |
| 项目 |
`project`
| text | 否 | 否 | 否 |
| 项目 |
`project`
| text | 否 | 否 | 否 |
| 项目负责人 |
`project_owner`
| user | 否 | 是 | 否 |
| 项目负责人 |
`project_owner`
| user | 否 | 是 | 否 |
| 项目协作人 |
`project_collaborator`
| user | 否 | 是 | 否 |
| 项目协作人 |
`project_collaborator`
| user | 否 | 是 | 否 |
| 任务来源 |
`task_source`
|
tex
t | 否 | 否 | 否 |
| 任务来源 |
`task_source`
|
selec
t | 否 | 否 | 否 |
| 任务性质 |
`task_nature`
|
tex
t | 否 | 否 | 否 |
| 任务性质 |
`task_nature`
|
selec
t | 否 | 否 | 否 |
| 发生频率 |
`occurrence_frequency`
| select | 否 | 否 | 否 |
| 发生频率 |
`occurrence_frequency`
| select | 否 | 否 | 否 |
| 计划开始日期 |
`planned_start_date`
| date | 否 | 否 | 是 |
| 计划开始日期 |
`planned_start_date`
| date | 否 | 否 | 是 |
| 计划结束日期 |
`planned_end_date`
| date | 否 | 否 | 是 |
| 计划结束日期 |
`planned_end_date`
| date | 否 | 否 | 是 |
...
@@ -109,7 +109,22 @@ type Record = {
...
@@ -109,7 +109,22 @@ type Record = {
| 周进度记录 |
`weekly_updates`
| object | 否 | 否 | 否 |
| 周进度记录 |
`weekly_updates`
| object | 否 | 否 | 否 |
| 是否属于年度审计计划 |
`is_annual_audit_plan`
| boolean | 否 | 否 | 否 |
| 是否属于年度审计计划 |
`is_annual_audit_plan`
| boolean | 否 | 否 | 否 |
### 3.1.1 `project_status` 选项
### 3.1.1 `big_category` 选项
| 显示值 | 存储值 |
| --- | --- |
| 部门管理 |
`部门管理`
|
| 纪检工作 |
`纪检工作`
|
| 审计工作 |
`审计工作`
|
### 3.1.2 `task_source` / `task_nature` 配置说明
-
`task_source`
与
`task_nature`
为
`select`
类型
-
选项必须由 Subject 字段配置中的
`settings.options`
提供
-
前端表单只读取配置项生成下拉,不在代码中硬编码选项
-
Excel 导入时应填写对应选项的存储值
### 3.1.3 `project_status` 选项
| 显示值 | 存储值 |
| 显示值 | 存储值 |
| --- | --- |
| --- | --- |
...
@@ -119,7 +134,7 @@ type Record = {
...
@@ -119,7 +134,7 @@ type Record = {
| 受阻 |
`blocked`
|
| 受阻 |
`blocked`
|
| 已取消 |
`cancelled`
|
| 已取消 |
`cancelled`
|
### 3.1.
2
`occurrence_frequency` 选项
### 3.1.
4
`occurrence_frequency` 选项
| 显示值 | 存储值 |
| 显示值 | 存储值 |
| --- | --- |
| --- | --- |
...
@@ -127,13 +142,13 @@ type Record = {
...
@@ -127,13 +142,13 @@ type Record = {
| 中 |
`2`
|
| 中 |
`2`
|
| 低 |
`1`
|
| 低 |
`1`
|
### 3.1.
3
`priority` 配置说明
### 3.1.
5
`priority` 配置说明
-
当前最新结构中,
`priority`
为
`select`
类型
-
当前最新结构中,
`priority`
为
`select`
类型
-
但字段定义内暂未提供
`settings.options`
-
但字段定义内暂未提供
`settings.options`
-
前端生成表单时不得硬编码选项,需等对象配置或接口返回的
`settings.options`
-
前端生成表单时不得硬编码选项,需等对象配置或接口返回的
`settings.options`
### 3.1.
4
`weekly_updates` 子结构建议
### 3.1.
6
`weekly_updates` 子结构建议
`weekly_updates`
当前字段类型为
`object`
。如业务上继续沿用“周进度记录集合”方案,建议对象内维护
`items`
数组,每项至少包含以下字段:
`weekly_updates`
当前字段类型为
`object`
。如业务上继续沿用“周进度记录集合”方案,建议对象内维护
`items`
数组,每项至少包含以下字段:
...
@@ -155,12 +170,12 @@ type Record = {
...
@@ -155,12 +170,12 @@ type Record = {
-
列表页或项目详情只展示最近一条摘要,不直接暴露底层 JSON
-
列表页或项目详情只展示最近一条摘要,不直接暴露底层 JSON
-
若后端最终确认
`weekly_updates`
直接存数组,可再将本节从“对象内
`items`
数组”调整为“字段直接存数组”
-
若后端最终确认
`weekly_updates`
直接存数组,可再将本节从“对象内
`items`
数组”调整为“字段直接存数组”
### 3.1.
5
metadata 示例
### 3.1.
7
metadata 示例
```
json
```
json
{
{
"project_name"
:
"某客户 2026 年专项项目"
,
"project_name"
:
"某客户 2026 年专项项目"
,
"big_category"
:
"审计"
,
"big_category"
:
"审计
工作
"
,
"project"
:
"2026 年专项项目"
,
"project"
:
"2026 年专项项目"
,
"project_owner"
:
[
"project_owner"
:
[
"69b12a47e92b1de77c94a9f6"
"69b12a47e92b1de77c94a9f6"
...
...
src/wrapper/Site.jsx
View file @
c1615014
...
@@ -42,7 +42,7 @@ export default function SiteWrapper() {
...
@@ -42,7 +42,7 @@ export default function SiteWrapper() {
setLoadError
(
error
?.
message
||
'加载站点配置失败'
);
setLoadError
(
error
?.
message
||
'加载站点配置失败'
);
setSiteInfo
({
setSiteInfo
({
name
:
'
项目管理系统
'
,
name
:
'
部门任务管理
'
,
});
});
}
finally
{
}
finally
{
if
(
!
cancelled
)
{
if
(
!
cancelled
)
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment