1.添加移动端用户的检测工具类,移动端用户只能访问对话页面。

2.评查点列表添加文档属性类型字段。
3.优化dify的对话侧边栏的显示效果。
4.评查点规则添加使用文档属性类型的输入框。添加多实体开关的操作开关。
This commit is contained in:
2025-12-30 18:35:48 +08:00
parent d2aba899cc
commit 66d2f7cef4
18 changed files with 552 additions and 56 deletions
+135 -12
View File
@@ -1,7 +1,7 @@
import React, { useState, useEffect } from 'react';
import type { EvaluationPoint } from '~/models/evaluation_points';
import type { EvaluationPointGroup } from '~/models/evaluation_point_groups';
import { getRulesList, getRuleTypes, type RuleType } from '~/api/evaluation_points/rules';
import { getRulesList, getRuleTypes, getAttributeTypes, type RuleType, type AttributeTypeOption } from '~/api/evaluation_points/rules';
interface BasicInfoProps {
onChange?: (data: Record<string, unknown>) => void;
@@ -101,6 +101,11 @@ export function BasicInfo({
const [filteredRuleTypes, setFilteredRuleTypes] = useState<RuleType[]>([]);
const [ruleTypesLoading, setRuleTypesLoading] = useState(false);
// 适用文档属性类型相关状态
const [attributeTypeOptions, setAttributeTypeOptions] = useState<AttributeTypeOption[]>([]);
const [attributeTypesLoading, setAttributeTypesLoading] = useState(false);
const [isCustomAttributeType, setIsCustomAttributeType] = useState(false); // 是否为自定义输入模式
// 从 Session Storage 获取 documentTypeIds 并调用 API 获取评查点类型
useEffect(() => {
const fetchRuleTypes = async () => {
@@ -140,6 +145,43 @@ export function BasicInfo({
fetchRuleTypes();
}, [frontendJWT]);
// 获取适用文档属性类型选项
useEffect(() => {
const fetchAttributeTypes = async () => {
try {
setAttributeTypesLoading(true);
const response = await getAttributeTypes(frontendJWT);
if (response.data) {
setAttributeTypeOptions(response.data);
} else {
// 使用默认选项
setAttributeTypeOptions([{ code: 'ALL', label: '通用' }]);
}
} catch (error) {
console.error('获取适用属性类型失败:', error);
setAttributeTypeOptions([{ code: 'ALL', label: '通用' }]);
} finally {
setAttributeTypesLoading(false);
}
};
fetchAttributeTypes();
}, [frontendJWT]);
// 检查初始数据中的 document_attribute_type 是否为自定义值
useEffect(() => {
if (formData.document_attribute_type) {
const isInOptions = attributeTypeOptions.some(
opt => opt.code === formData.document_attribute_type
);
// 如果当前值不在选项列表中,则切换到自定义模式
if (!isInOptions && attributeTypeOptions.length > 0) {
setIsCustomAttributeType(true);
}
}
}, [formData.document_attribute_type, attributeTypeOptions]);
// 根据选择的评查点类型筛选可用的规则组
const filteredRuleGroups = evaluationPointGroups.filter(group =>
formData.evaluation_point_groups_pid &&
@@ -268,6 +310,14 @@ export function BasicInfo({
newData.evaluation_point_groups_id = null; // 清空规则组选择
}
break;
case 'document-attribute-type':
// 处理适用文档属性类型选择(下拉框模式)
newData.document_attribute_type = value || 'ALL';
break;
case 'document-attribute-type-custom':
// 处理适用文档属性类型输入(自定义模式)
newData.document_attribute_type = value;
break;
}
setFormData(newData);
@@ -320,18 +370,19 @@ export function BasicInfo({
}
}, [formData.references_laws?.articles]);
// 检查是否需要自动展开描述区域
// 检查是否需要自动展开描述区域(仅在初始数据加载时执行一次)
useEffect(() => {
// 如果描述或法律依据相关字段有值,则自动展开
// 如果初始数据中描述或法律依据相关字段有值,则自动展开
if (
formData.description ||
formData.references_laws?.name ||
(formData.references_laws?.articles && formData.references_laws.articles.length > 0) ||
formData.references_laws?.content
initialData?.description ||
initialData?.references_laws?.name ||
(initialData?.references_laws?.articles && initialData.references_laws.articles.length > 0) ||
initialData?.references_laws?.content
) {
setIsDescExpanded(true);
}
}, [formData]);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
// 注释掉自动选择规则组的逻辑,避免无限循环
// 原因:此 useEffect 依赖 onChange 和 filteredRuleGroups,每次渲染都可能触发
@@ -461,8 +512,8 @@ export function BasicInfo({
</div>
<div>
<label className="form-label" htmlFor="is-enabled"></label>
<select
id="is-enabled"
<select
id="is-enabled"
className="form-select"
value={formData.is_enabled ? 'true' : 'false'}
onChange={handleInputChange}
@@ -472,11 +523,83 @@ export function BasicInfo({
</select>
<div className="form-tip"></div>
</div>
<div>
<label className="form-label" htmlFor="document-attribute-type">
</label>
<div className="flex items-center gap-2">
{isCustomAttributeType ? (
// 自定义输入模式
<input
type="text"
id="document-attribute-type-custom"
className="form-input flex-1"
placeholder="请输入自定义属性类型"
value={formData.document_attribute_type || ''}
onChange={handleInputChange}
/>
) : (
// 下拉选择模式
<select
id="document-attribute-type"
className="form-select flex-1"
value={formData.document_attribute_type || 'ALL'}
onChange={handleInputChange}
disabled={attributeTypesLoading}
>
{attributeTypesLoading ? (
<option value="">...</option>
) : (
attributeTypeOptions.map(option => (
<option key={option.code} value={option.code}>
{option.label}
</option>
))
)}
</select>
)}
<button
type="button"
className={`px-3 py-2 text-sm rounded border transition-colors ${
isCustomAttributeType
? 'bg-[#00684a] text-white border-[#00684a] hover:bg-[#005a3f]'
: 'bg-white text-gray-600 border-gray-300 hover:border-[#00684a] hover:text-[#00684a]'
}`}
onClick={() => {
setIsCustomAttributeType(!isCustomAttributeType);
// 切换到自定义模式时,如果当前值是预设值,清空它让用户输入
// 切换回下拉模式时,如果当前值不在选项中,设置为默认值 ALL
if (!isCustomAttributeType) {
// 切换到自定义模式
} else {
// 切换回下拉模式
const currentValue = formData.document_attribute_type;
const isInOptions = attributeTypeOptions.some(opt => opt.code === currentValue);
if (!isInOptions) {
const newData = { ...formData, document_attribute_type: 'ALL' };
setFormData(newData);
if (onChange) {
onChange(newData);
}
}
}
}}
title={isCustomAttributeType ? '切换到下拉选择' : '切换到自定义输入'}
>
<i className={`ri-${isCustomAttributeType ? 'list-check' : 'edit-line'}`}></i>
</button>
</div>
<div className="form-tip">
{isCustomAttributeType
? '输入自定义的文档属性类型,点击右侧按钮可切换回下拉选择'
: '选择评查点适用的文档属性类型,点击右侧按钮可自定义输入'}
</div>
</div>
</div>
<div className="mt-8">
<div
className={`flex justify-between items-center cursor-pointer ${isDescExpanded ? 'expanded' : ''}`}
className={`flex items-center cursor-pointer ${isDescExpanded ? 'expanded' : ''}`}
onClick={handleToggleDescription}
onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
@@ -487,7 +610,7 @@ export function BasicInfo({
role="button"
>
<label className="form-label mb-0" htmlFor="description-section"></label>
<i className={`ri-arrow-${isDescExpanded ? 'up' : 'down'}-s-line text-lg expand-icon`}></i>
<i className={`${isDescExpanded ? 'ri-arrow-drop-up-line' : 'ri-arrow-drop-down-line'} text-lg expand-icon ml-2`}></i>
</div>
<div className={`mt-2 ${isDescExpanded ? '' : 'hidden'}`} id="description-section">