2025-03-07 23:59:53 +08:00
|
|
|
import React from 'react';
|
2025-03-22 10:13:42 +08:00
|
|
|
import { useSelector } from 'react-redux';
|
2025-03-07 23:59:53 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* 知识库表单组件
|
|
|
|
*/
|
|
|
|
const KnowledgeBaseForm = ({
|
|
|
|
formData,
|
|
|
|
formErrors,
|
|
|
|
isSubmitting,
|
|
|
|
onInputChange,
|
|
|
|
onSubmit,
|
|
|
|
onDelete,
|
2025-03-22 10:13:42 +08:00
|
|
|
onTypeChange,
|
|
|
|
isAdmin,
|
|
|
|
departments,
|
|
|
|
availableGroups,
|
2025-03-07 23:59:53 +08:00
|
|
|
}) => {
|
2025-03-22 10:13:42 +08:00
|
|
|
// 获取当前用户信息
|
|
|
|
const currentUser = useSelector((state) => state.auth.user);
|
|
|
|
|
|
|
|
// 根据用户角色确定可以设置的知识库类型
|
|
|
|
const isLeader = currentUser?.role === 'leader';
|
|
|
|
|
|
|
|
// 获取当前用户可以设置的知识库类型
|
|
|
|
const getAvailableTypes = () => {
|
|
|
|
if (isAdmin) {
|
|
|
|
return [
|
2025-03-25 09:47:30 +08:00
|
|
|
{ value: 'admin', label: '公共知识库' },
|
2025-03-29 09:36:38 +08:00
|
|
|
{ value: 'leader', label: '组长级知识库' },
|
|
|
|
{ value: 'member', label: '组内知识库' },
|
2025-03-22 10:13:42 +08:00
|
|
|
{ value: 'private', label: '私有知识库' },
|
2025-03-29 09:36:38 +08:00
|
|
|
{ value: 'secret', label: '私密知识库' },
|
2025-03-22 10:13:42 +08:00
|
|
|
];
|
|
|
|
} else if (isLeader) {
|
|
|
|
return [
|
2025-03-25 09:47:30 +08:00
|
|
|
{ value: 'admin', label: '公共知识库' },
|
2025-03-29 09:36:38 +08:00
|
|
|
{ value: 'member', label: '组内知识库' },
|
2025-03-22 10:13:42 +08:00
|
|
|
{ value: 'private', label: '私有知识库' },
|
|
|
|
];
|
|
|
|
} else {
|
2025-03-25 09:47:30 +08:00
|
|
|
return [
|
|
|
|
{ value: 'admin', label: '公共知识库' },
|
|
|
|
{ value: 'private', label: '私有知识库' },
|
|
|
|
];
|
2025-03-22 10:13:42 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
const availableTypes = getAvailableTypes();
|
|
|
|
|
|
|
|
// 检查类型是否被更改
|
|
|
|
const hasTypeChanged = formData.original_type && formData.original_type !== formData.type;
|
|
|
|
|
|
|
|
// 检查部门或组别是否被更改
|
|
|
|
const hasDepartmentOrGroupChanged =
|
|
|
|
(formData.original_department && formData.department !== formData.original_department) ||
|
|
|
|
(formData.original_group && formData.group !== formData.original_group);
|
|
|
|
|
|
|
|
// 是否显示类型更改按钮
|
|
|
|
const showTypeChangeButton = hasTypeChanged || (isAdmin && hasDepartmentOrGroupChanged);
|
2025-03-30 07:44:45 +08:00
|
|
|
|
2025-03-07 23:59:53 +08:00
|
|
|
return (
|
|
|
|
<div className='card border-0 shadow-sm'>
|
|
|
|
<div className='card-body'>
|
|
|
|
<h5 className='card-title mb-4'>知识库设置</h5>
|
|
|
|
|
|
|
|
<form onSubmit={onSubmit}>
|
|
|
|
<div className='mb-3'>
|
|
|
|
<label htmlFor='name' className='form-label'>
|
|
|
|
知识库名称 <span className='text-danger'>*</span>
|
|
|
|
</label>
|
|
|
|
<input
|
|
|
|
type='text'
|
|
|
|
className={`form-control ${formErrors.name ? 'is-invalid' : ''}`}
|
|
|
|
id='name'
|
|
|
|
name='name'
|
|
|
|
value={formData.name}
|
2025-04-03 10:26:56 +08:00
|
|
|
disabled={!formData.permissions.can_edit}
|
2025-03-07 23:59:53 +08:00
|
|
|
onChange={onInputChange}
|
|
|
|
/>
|
|
|
|
{formErrors.name && <div className='invalid-feedback'>{formErrors.name}</div>}
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div className='mb-3'>
|
|
|
|
<label htmlFor='desc' className='form-label'>
|
|
|
|
知识库描述 <span className='text-danger'>*</span>
|
|
|
|
</label>
|
|
|
|
<textarea
|
|
|
|
className={`form-control ${formErrors.desc ? 'is-invalid' : ''}`}
|
|
|
|
id='desc'
|
|
|
|
name='desc'
|
|
|
|
rows='3'
|
|
|
|
value={formData.desc}
|
2025-04-03 10:26:56 +08:00
|
|
|
disabled={!formData.permissions.can_edit}
|
2025-03-07 23:59:53 +08:00
|
|
|
onChange={onInputChange}
|
|
|
|
></textarea>
|
|
|
|
{formErrors.desc && <div className='invalid-feedback'>{formErrors.desc}</div>}
|
|
|
|
</div>
|
|
|
|
|
2025-03-22 10:13:42 +08:00
|
|
|
<div className='mb-4'>
|
|
|
|
<label className='form-label'>
|
|
|
|
知识库类型 <span className='text-danger'>*</span>
|
|
|
|
</label>
|
|
|
|
<div className='d-flex flex-column gap-2'>
|
|
|
|
{availableTypes.map((type) => (
|
|
|
|
<div className='form-check' key={type.value}>
|
|
|
|
<input
|
|
|
|
className='form-check-input'
|
|
|
|
type='radio'
|
|
|
|
name='type'
|
|
|
|
id={`type${type.value}`}
|
|
|
|
value={type.value}
|
|
|
|
checked={formData.type === type.value}
|
|
|
|
onChange={onInputChange}
|
2025-04-03 10:26:56 +08:00
|
|
|
disabled={!formData.permissions.can_edit}
|
2025-03-22 10:13:42 +08:00
|
|
|
/>
|
|
|
|
<label className='form-check-label' htmlFor={`type${type.value}`}>
|
|
|
|
{type.label}
|
|
|
|
</label>
|
|
|
|
</div>
|
|
|
|
))}
|
2025-03-07 23:59:53 +08:00
|
|
|
</div>
|
2025-03-22 10:13:42 +08:00
|
|
|
{currentUser?.role === 'member' && (
|
2025-03-25 09:47:30 +08:00
|
|
|
<small className='text-muted d-block mt-1'>您可以修改知识库类型为公共或私有。</small>
|
2025-03-22 10:13:42 +08:00
|
|
|
)}
|
|
|
|
{formErrors.type && <div className='text-danger small mt-1'>{formErrors.type}</div>}
|
2025-03-07 23:59:53 +08:00
|
|
|
</div>
|
2025-03-13 09:14:25 +08:00
|
|
|
|
2025-03-25 08:04:35 +08:00
|
|
|
{/* 仅当不是私有知识库时才显示部门选项 */}
|
2025-04-03 11:57:51 +08:00
|
|
|
{formData.type === 'member' || formData.type === 'leader' && (
|
2025-03-25 08:04:35 +08:00
|
|
|
<div className='mb-3'>
|
|
|
|
<label htmlFor='department' className='form-label'>
|
|
|
|
部门 {isAdmin && <span className='text-danger'>*</span>}
|
|
|
|
</label>
|
|
|
|
{isAdmin ? (
|
|
|
|
<>
|
|
|
|
<select
|
|
|
|
className={`form-select ${formErrors.department ? 'is-invalid' : ''}`}
|
|
|
|
id='department'
|
|
|
|
name='department'
|
|
|
|
value={formData.department || ''}
|
|
|
|
onChange={onInputChange}
|
|
|
|
disabled={isSubmitting}
|
|
|
|
>
|
|
|
|
<option value=''>请选择部门</option>
|
|
|
|
{departments.map((dept, index) => (
|
|
|
|
<option key={index} value={dept}>
|
|
|
|
{dept}
|
|
|
|
</option>
|
|
|
|
))}
|
|
|
|
</select>
|
|
|
|
{formErrors.department && (
|
|
|
|
<div className='invalid-feedback'>{formErrors.department}</div>
|
|
|
|
)}
|
|
|
|
</>
|
|
|
|
) : (
|
|
|
|
<>
|
|
|
|
<input
|
|
|
|
type='text'
|
|
|
|
className='form-control bg-light'
|
|
|
|
id='department'
|
|
|
|
name='department'
|
|
|
|
value={formData.department || ''}
|
|
|
|
readOnly
|
|
|
|
/>
|
|
|
|
</>
|
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
)}
|
2025-03-13 09:14:25 +08:00
|
|
|
|
2025-03-25 08:04:35 +08:00
|
|
|
{/* 仅当不是私有知识库时才显示组别选项 */}
|
2025-03-29 09:36:38 +08:00
|
|
|
{formData.type === 'member' && (
|
2025-03-25 08:04:35 +08:00
|
|
|
<div className='mb-3'>
|
|
|
|
<label htmlFor='group' className='form-label'>
|
|
|
|
组别 {isAdmin && <span className='text-danger'>*</span>}
|
|
|
|
</label>
|
|
|
|
{isAdmin ? (
|
|
|
|
<>
|
|
|
|
<select
|
|
|
|
className={`form-select ${formErrors.group ? 'is-invalid' : ''}`}
|
|
|
|
id='group'
|
|
|
|
name='group'
|
|
|
|
value={formData.group || ''}
|
|
|
|
onChange={onInputChange}
|
|
|
|
disabled={isSubmitting || !formData.department}
|
|
|
|
>
|
|
|
|
<option value=''>{formData.department ? '请选择组别' : '请先选择部门'}</option>
|
|
|
|
{availableGroups.map((group, index) => (
|
|
|
|
<option key={index} value={group}>
|
|
|
|
{group}
|
|
|
|
</option>
|
|
|
|
))}
|
|
|
|
</select>
|
|
|
|
{formErrors.group && <div className='invalid-feedback'>{formErrors.group}</div>}
|
|
|
|
{!formData.department && (
|
|
|
|
<small className='text-muted d-block mt-1'>请先选择部门</small>
|
|
|
|
)}
|
|
|
|
</>
|
|
|
|
) : (
|
|
|
|
<>
|
|
|
|
<input
|
|
|
|
type='text'
|
|
|
|
className='form-control bg-light'
|
|
|
|
id='group'
|
|
|
|
name='group'
|
|
|
|
value={formData.group || ''}
|
|
|
|
readOnly
|
|
|
|
/>
|
|
|
|
</>
|
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
)}
|
2025-03-13 09:14:25 +08:00
|
|
|
|
2025-03-22 10:13:42 +08:00
|
|
|
{/* 类型更改按钮 */}
|
|
|
|
{showTypeChangeButton && (
|
|
|
|
<div className='alert alert-warning d-flex align-items-center justify-content-between'>
|
|
|
|
<div>
|
|
|
|
{hasTypeChanged && (
|
|
|
|
<p className='mb-0'>
|
2025-04-03 10:26:56 +08:00
|
|
|
知识库类型更改为 <strong>{formData.type}</strong>
|
2025-03-22 10:13:42 +08:00
|
|
|
</p>
|
|
|
|
)}
|
|
|
|
{isAdmin && hasDepartmentOrGroupChanged && <p className='mb-0'>部门/组别已更改</p>}
|
|
|
|
<small>点击更新按钮单独保存这些更改</small>
|
|
|
|
</div>
|
|
|
|
<button
|
|
|
|
type='button'
|
|
|
|
className='btn btn-warning'
|
|
|
|
onClick={() => onTypeChange && onTypeChange(formData.type)}
|
|
|
|
disabled={isSubmitting || currentUser?.role === 'member'}
|
|
|
|
>
|
|
|
|
{isSubmitting ? (
|
|
|
|
<>
|
|
|
|
<span
|
|
|
|
className='spinner-border spinner-border-sm me-2'
|
|
|
|
role='status'
|
|
|
|
aria-hidden='true'
|
|
|
|
></span>
|
|
|
|
更新中...
|
|
|
|
</>
|
|
|
|
) : (
|
|
|
|
'更新知识库类型'
|
|
|
|
)}
|
|
|
|
</button>
|
|
|
|
</div>
|
|
|
|
)}
|
|
|
|
|
|
|
|
<div className='d-flex justify-content-between mt-4'>
|
2025-04-03 11:57:51 +08:00
|
|
|
<button type='submit' className='btn btn-dark' disabled={isSubmitting|| !formData.permissions.can_edit}>
|
2025-03-07 23:59:53 +08:00
|
|
|
{isSubmitting ? (
|
|
|
|
<>
|
|
|
|
<span
|
|
|
|
className='spinner-border spinner-border-sm me-2'
|
|
|
|
role='status'
|
|
|
|
aria-hidden='true'
|
|
|
|
></span>
|
|
|
|
保存中...
|
|
|
|
</>
|
|
|
|
) : (
|
|
|
|
'保存设置'
|
|
|
|
)}
|
|
|
|
</button>
|
2025-03-27 10:09:52 +08:00
|
|
|
<button
|
|
|
|
type='button'
|
2025-04-03 11:57:51 +08:00
|
|
|
className='btn btn-outline-danger'
|
2025-03-27 10:09:52 +08:00
|
|
|
onClick={onDelete}
|
2025-03-30 07:44:45 +08:00
|
|
|
// disabled='true'
|
2025-04-03 10:26:56 +08:00
|
|
|
disabled={isSubmitting || !formData.permissions.can_edit}
|
2025-03-27 10:09:52 +08:00
|
|
|
>
|
2025-03-07 23:59:53 +08:00
|
|
|
删除知识库
|
|
|
|
</button>
|
|
|
|
</div>
|
|
|
|
</form>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
export default KnowledgeBaseForm;
|