feat(web): add per-document author_only toggle in project settings
Show a single author picker when兼任 is enabled, respect the system capability flag, and surface author_only docs in activation preview. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -29,11 +29,12 @@ import {
|
||||
} from '../../lib/projectSettingsMode';
|
||||
import {
|
||||
canToggleHumanApproval,
|
||||
classifyClientDuty,
|
||||
clientDutyIssues,
|
||||
formatDutyIssues,
|
||||
locateDutyIssue,
|
||||
needsThreeMembersForDuties,
|
||||
resolveClientDocTaskDuty,
|
||||
toggleAuthorOnly,
|
||||
toggleHumanApproval,
|
||||
} from '../../lib/projectSettingsDuties';
|
||||
import { ACTIVATION_UNMANAGED_FREEZE_HINT } from '../../lib/blockedGovernanceCopy';
|
||||
@@ -502,7 +503,13 @@ export const ProjectSettingsModal: React.FC<ProjectSettingsModalProps> = ({
|
||||
<div key={st.stage_key} style={{ border: '1px solid var(--border)', borderRadius: '8px', padding: '12px' }}>
|
||||
<div style={{ fontWeight: 600, marginBottom: '8px' }}>{st.stage_name || st.stage_key}</div>
|
||||
{st.doc_tasks.map((dt, ti) => {
|
||||
const managed = classifyClientDuty(dt.duties) !== 'none' || requireApprovalKeys.includes(dt.task_key);
|
||||
const resolved = resolveClientDocTaskDuty(dt);
|
||||
const managed =
|
||||
resolved.mode !== 'none' ||
|
||||
dt.duty_policy === 'author_only' ||
|
||||
requireApprovalKeys.includes(dt.task_key);
|
||||
const authorOnly = dt.duty_policy === 'author_only';
|
||||
const authorOnlyAllowed = Boolean(settings?.author_only_policy?.allowed);
|
||||
const inline = locateDutyIssue(dutyIssues, dt.task_key);
|
||||
return (
|
||||
<div key={dt.task_key} style={{ marginBottom: '10px', fontSize: '12px' }}>
|
||||
@@ -530,7 +537,63 @@ export const ProjectSettingsModal: React.FC<ProjectSettingsModalProps> = ({
|
||||
纳入人工审批
|
||||
</label>
|
||||
)}
|
||||
{dt.enabled && managed && (
|
||||
<label
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '6px',
|
||||
marginBottom: '6px',
|
||||
opacity: authorOnlyAllowed || authorOnly ? 1 : 0.7,
|
||||
}}
|
||||
title={
|
||||
authorOnlyAllowed
|
||||
? undefined
|
||||
: settings?.author_only_policy?.blocked_reason ||
|
||||
'系统管理员尚未开启「允许编制人兼任审核、批准」'
|
||||
}
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={authorOnly}
|
||||
disabled={!authorOnlyAllowed && !authorOnly}
|
||||
onChange={(e) => updateDocTask(si, ti, toggleAuthorOnly(dt, e.target.checked))}
|
||||
/>
|
||||
由编制人兼任审核、批准
|
||||
{!authorOnlyAllowed && (
|
||||
<span style={{ color: 'var(--text-muted)', fontSize: '11px' }}>
|
||||
(总开关未开启)
|
||||
</span>
|
||||
)}
|
||||
</label>
|
||||
)}
|
||||
{dt.enabled && (managed || !dt.approval_configurable) && (
|
||||
authorOnly ? (
|
||||
<div style={{ display: 'grid', gridTemplateColumns: '1fr', gap: '6px' }}>
|
||||
<select
|
||||
value={dt.duties.author_user_id || ''}
|
||||
onChange={(e) =>
|
||||
updateDocTask(si, ti, {
|
||||
duties: { author_user_id: Number(e.target.value) || undefined },
|
||||
duty_policy: 'author_only',
|
||||
})
|
||||
}
|
||||
style={{ fontSize: '11px', padding: '4px' }}
|
||||
>
|
||||
<option value="">编制人(兼任审核与批准)</option>
|
||||
{members.map((m) => (
|
||||
<option key={m.userId} value={m.userId}>
|
||||
{m.name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
{dt.duties.author_user_id ? (
|
||||
<div style={{ color: 'var(--text-muted)', fontSize: '11px' }}>
|
||||
审核、批准:同编制人(自动承担)
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
) : (
|
||||
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: '6px' }}>
|
||||
{(['author', 'reviewer', 'approver'] as const).map((role) => (
|
||||
<select
|
||||
@@ -555,6 +618,7 @@ export const ProjectSettingsModal: React.FC<ProjectSettingsModalProps> = ({
|
||||
</select>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
)}
|
||||
{inline?.message && (
|
||||
<div style={{ color: 'var(--danger-700)', marginTop: '4px' }}>{inline.message}</div>
|
||||
@@ -587,6 +651,16 @@ export const ProjectSettingsModal: React.FC<ProjectSettingsModalProps> = ({
|
||||
纳入人工审批:{preview.summary.governed_doc_tasks ?? preview.summary.enabled_doc_tasks} · 不纳入:{preview.summary.unmanaged_doc_tasks ?? 0}
|
||||
</div>
|
||||
<div>职责指派:{preview.summary.assigned_duties} 项</div>
|
||||
{(preview.summary.author_only_doc_tasks ?? 0) > 0 && (
|
||||
<div>
|
||||
兼任审批:{preview.summary.author_only_doc_tasks} 份
|
||||
{(preview.summary.author_only_documents || []).length > 0
|
||||
? `(${(preview.summary.author_only_documents || [])
|
||||
.map((doc) => doc.title || doc.task_key)
|
||||
.join('、')})`
|
||||
: ''}
|
||||
</div>
|
||||
)}
|
||||
{(preview.summary.unmanaged_documents || []).length > 0 && (
|
||||
<div>
|
||||
例外文档:{(preview.summary.unmanaged_documents || []).map((doc) => doc.title || doc.task_key).join('、')}
|
||||
|
||||
Reference in New Issue
Block a user