mirror of
https://github.com/labring/FastGPT.git
synced 2026-02-27 01:02:22 +08:00
V4.14.5.1 dev (#6290)
* chore: cherry pick some commits from v4.14.6-dev (#6287) * fix: custom domain limitation (#6265) * fix: system secret (#6259) * fix: system secret * chore: update docs * chore: docs * fix password variable & datetime picker (#6276) * fix password variable & datetime picker * doc * chore: cherry pick some commits from v4.14.6-dev (#6287) * fix: custom domain limitation (#6265) * fix: system secret (#6259) * fix: system secret * chore: update docs * chore: docs * doc * chore: docs --------- Co-authored-by: Finley Ge <32237950+FinleyGe@users.noreply.github.com> Co-authored-by: Finley Ge <finleyge@fastgpt.io> * perf: extname computed (#6285) * perf: extname computed * chore: handle hash or query flags --------- Co-authored-by: Finley Ge <finleyge@fastgpt.io> * chore: docs (#6291) --------- Co-authored-by: heheer <heheer@sealos.io> Co-authored-by: Archer <545436317@qq.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "app",
|
||||
"version": "4.14.5",
|
||||
"version": "4.14.5.1",
|
||||
"private": false,
|
||||
"scripts": {
|
||||
"dev": "npm run build:workers && next dev",
|
||||
|
||||
@@ -66,14 +66,17 @@ const LabelAndFormRender = ({
|
||||
rules={{
|
||||
validate: (value) => {
|
||||
if (typeof value === 'number' || typeof value === 'boolean') return true;
|
||||
if (inputType === InputTypeEnum.password && props.minLength) {
|
||||
if (!value || typeof value !== 'object' || !value.value) return false;
|
||||
if (value.value.length < props.minLength) {
|
||||
if (!required) return true;
|
||||
// 密码类型特殊处理:已加密的密码格式为 { value: '', secret: 'xxx' }
|
||||
if (inputType === InputTypeEnum.password) {
|
||||
const hasValue = value && typeof value === 'object' && (value.value || value.secret);
|
||||
if (!hasValue) return false;
|
||||
// 有 minLength 要求且正在输入新值时,检查长度
|
||||
if (props.minLength && value.value && value.value.length < props.minLength) {
|
||||
return t(`common:min_length`, { minLenth: props.minLength });
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (!required) return true;
|
||||
|
||||
if (inputType === InputTypeEnum.fileSelect) {
|
||||
if (!value || !Array.isArray(value) || value.length === 0) {
|
||||
|
||||
@@ -485,7 +485,7 @@ const InputTypeConfig = ({
|
||||
setValue('timeRangeStart', date);
|
||||
}}
|
||||
popPosition="top"
|
||||
timeGranularity={timeGranularity}
|
||||
timeGranularity={timeGranularity || 'day'}
|
||||
maxDate={timeRangeEnd ? new Date(timeRangeEnd) : undefined}
|
||||
/>
|
||||
</Box>
|
||||
@@ -499,7 +499,7 @@ const InputTypeConfig = ({
|
||||
setValue('timeRangeEnd', date);
|
||||
}}
|
||||
popPosition="top"
|
||||
timeGranularity={timeGranularity}
|
||||
timeGranularity={timeGranularity || 'day'}
|
||||
minDate={timeRangeStart ? new Date(timeRangeStart) : undefined}
|
||||
/>
|
||||
</Box>
|
||||
@@ -623,7 +623,7 @@ const InputTypeConfig = ({
|
||||
setValue('defaultValue', date);
|
||||
}}
|
||||
popPosition="top"
|
||||
timeGranularity={timeGranularity}
|
||||
timeGranularity={timeGranularity || 'day'}
|
||||
minDate={timeRangeStart ? new Date(timeRangeStart) : undefined}
|
||||
maxDate={timeRangeEnd ? new Date(timeRangeEnd) : undefined}
|
||||
/>
|
||||
@@ -640,7 +640,7 @@ const InputTypeConfig = ({
|
||||
setValue('defaultValue', [date, timeRangeEndDefault]);
|
||||
}}
|
||||
popPosition="top"
|
||||
timeGranularity={timeGranularity}
|
||||
timeGranularity={timeGranularity || 'day'}
|
||||
minDate={timeRangeStart ? new Date(timeRangeStart) : undefined}
|
||||
maxDate={
|
||||
timeRangeEndDefault && timeRangeEnd
|
||||
@@ -668,7 +668,7 @@ const InputTypeConfig = ({
|
||||
setValue('defaultValue', [timeRangeStartDefault, date]);
|
||||
}}
|
||||
popPosition="top"
|
||||
timeGranularity={timeGranularity}
|
||||
timeGranularity={timeGranularity || 'day'}
|
||||
minDate={
|
||||
timeRangeStartDefault && timeRangeStart
|
||||
? new Date(
|
||||
|
||||
@@ -237,7 +237,7 @@ const Reference = ({
|
||||
borderLeftColor: 'transparent',
|
||||
borderRightColor: 'transparent',
|
||||
isDisabled: isEmptyItem,
|
||||
minW: '240px',
|
||||
w: '240px',
|
||||
_hover: {
|
||||
borderColor: 'blue.300'
|
||||
}
|
||||
|
||||
@@ -74,11 +74,11 @@ const CustomDomain = () => {
|
||||
const [editDomain, setEditDomain] = useState<CustomDomainType | undefined>(undefined);
|
||||
|
||||
// 检查用户是否有 advanced 套餐
|
||||
const isAdvancedPlan = useMemo(() => {
|
||||
const isSupportCustomDomain = useMemo(() => {
|
||||
const plan = teamPlanStatus?.standard;
|
||||
if (!plan) return false;
|
||||
|
||||
return plan.customDomain && plan.customDomain > 0;
|
||||
return !!(plan.customDomain && plan.customDomain > 0);
|
||||
}, [teamPlanStatus?.standard]);
|
||||
|
||||
return (
|
||||
@@ -100,7 +100,7 @@ const CustomDomain = () => {
|
||||
<Button
|
||||
variant="whitePrimaryOutline"
|
||||
onClick={onOpenCreateModal}
|
||||
isDisabled={!isAdvancedPlan}
|
||||
isDisabled={isSupportCustomDomain}
|
||||
>
|
||||
{t('common:Add')}
|
||||
</Button>
|
||||
@@ -185,7 +185,7 @@ const CustomDomain = () => {
|
||||
>
|
||||
<EmptyTip
|
||||
text={
|
||||
!isAdvancedPlan && (
|
||||
isSupportCustomDomain && (
|
||||
<Flex flexDir="column" alignItems="center">
|
||||
<Box>{t('account:upgrade_to_use_custom_domain')}</Box>
|
||||
<Button
|
||||
|
||||
101
projects/app/src/pages/api/admin/initv41451.ts
Normal file
101
projects/app/src/pages/api/admin/initv41451.ts
Normal file
@@ -0,0 +1,101 @@
|
||||
import { NextAPI } from '@/service/middleware/entry';
|
||||
import type { ApiRequestProps, ApiResponseType } from '@fastgpt/service/type/next';
|
||||
import { authCert } from '@fastgpt/service/support/permission/auth/common';
|
||||
import { MongoSystemTool } from '@fastgpt/service/core/plugin/tool/systemToolSchema';
|
||||
import type { AnyBulkWriteOperation } from '@fastgpt/service/common/mongo';
|
||||
import type { SystemPluginToolCollectionType } from '@fastgpt/global/core/plugin/tool/type';
|
||||
|
||||
export type ResponseType = {
|
||||
message: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* 4.14.5.1 版本数据初始化脚本
|
||||
* 1. 迁移 system tool 数据:如果工具集配置了系统密钥,则需要给其子工具都写入 InputListVal 字段
|
||||
*/
|
||||
|
||||
const migrateSystemSecret = async () => {
|
||||
// 1. find all system tools
|
||||
const tools = await MongoSystemTool.find(
|
||||
{
|
||||
pluginId: {
|
||||
$regex: /systemTool-/
|
||||
}
|
||||
},
|
||||
{
|
||||
pluginId: 1,
|
||||
inputListVal: 1
|
||||
}
|
||||
).lean();
|
||||
|
||||
// 2. 构建工具集和子工具的映射关系
|
||||
const toolSetMap = new Map<string, (typeof tools)[0]>(); // 工具集 ID -> 工具集对象
|
||||
const childToolsMap = new Map<string, typeof tools>(); // 工具集 ID -> 子工具列表
|
||||
|
||||
for (const tool of tools) {
|
||||
if (tool.pluginId.includes('/')) {
|
||||
// 这是一个子工具
|
||||
const toolSetId = tool.pluginId.split('/')[0];
|
||||
if (!childToolsMap.has(toolSetId)) {
|
||||
childToolsMap.set(toolSetId, []);
|
||||
}
|
||||
childToolsMap.get(toolSetId)!.push(tool);
|
||||
} else {
|
||||
// 这是一个工具集
|
||||
toolSetMap.set(tool.pluginId, tool);
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 构建批量更新操作
|
||||
const ops: AnyBulkWriteOperation<SystemPluginToolCollectionType>[] = [];
|
||||
|
||||
for (const [toolSetId, toolSet] of toolSetMap.entries()) {
|
||||
// 只处理配置了系统密钥的工具集
|
||||
if (toolSet.inputListVal) {
|
||||
const childTools = childToolsMap.get(toolSetId) || [];
|
||||
|
||||
// 为每个子工具添加更新操作
|
||||
for (const childTool of childTools) {
|
||||
ops.push({
|
||||
updateOne: {
|
||||
filter: {
|
||||
_id: childTool._id
|
||||
},
|
||||
update: {
|
||||
$set: {
|
||||
inputListVal: toolSet.inputListVal
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 执行批量更新
|
||||
if (ops.length > 0) {
|
||||
await MongoSystemTool.bulkWrite(ops);
|
||||
console.log(`Updated ${ops.length} child tools with system secrets`);
|
||||
}
|
||||
|
||||
return ops.length;
|
||||
};
|
||||
|
||||
/**
|
||||
* 主处理函数
|
||||
*/
|
||||
async function handler(
|
||||
req: ApiRequestProps,
|
||||
_res: ApiResponseType<ResponseType>
|
||||
): Promise<ResponseType> {
|
||||
await authCert({ req, authRoot: true });
|
||||
|
||||
// 执行系统工具密钥迁移
|
||||
const updatedCount = await migrateSystemSecret();
|
||||
|
||||
return {
|
||||
message: `Completed v4.14.6 initialization: Updated ${updatedCount} child tools with system secrets`
|
||||
};
|
||||
}
|
||||
|
||||
export default NextAPI(handler);
|
||||
@@ -68,7 +68,8 @@ async function handler(
|
||||
{ pluginId: tool.pluginId },
|
||||
{
|
||||
pluginId: tool.pluginId,
|
||||
systemKeyCost: tool.systemKeyCost
|
||||
systemKeyCost: tool.systemKeyCost,
|
||||
inputListVal: updateFields.inputListVal
|
||||
},
|
||||
{ upsert: true, session }
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user