新增应用样式 agent 工具
This commit is contained in:
@@ -0,0 +1,150 @@
|
||||
import type { StyleConfig, DefaultLayerStyleId } from "@components/olmap/core/Controls/styleEditorTypes";
|
||||
|
||||
export type ApplyLayerStyleActionPayload = {
|
||||
layerId: DefaultLayerStyleId;
|
||||
resetToDefault: boolean;
|
||||
styleConfig?: Partial<StyleConfig>;
|
||||
};
|
||||
|
||||
export const APPLY_LAYER_STYLE_TOOL = "apply_layer_style";
|
||||
|
||||
const LAYER_LABELS: Record<DefaultLayerStyleId, string> = {
|
||||
junctions: "节点",
|
||||
pipes: "管道",
|
||||
};
|
||||
|
||||
const asString = (value: unknown): string | undefined =>
|
||||
typeof value === "string" && value.trim() ? value.trim() : undefined;
|
||||
|
||||
const asNumber = (value: unknown): number | undefined =>
|
||||
typeof value === "number" && Number.isFinite(value)
|
||||
? value
|
||||
: typeof value === "string" && value.trim() && Number.isFinite(Number(value))
|
||||
? Number(value)
|
||||
: undefined;
|
||||
|
||||
const asBoolean = (value: unknown): boolean | undefined =>
|
||||
typeof value === "boolean"
|
||||
? value
|
||||
: typeof value === "string"
|
||||
? value === "true"
|
||||
? true
|
||||
: value === "false"
|
||||
? false
|
||||
: undefined
|
||||
: undefined;
|
||||
|
||||
const asNumberArray = (value: unknown): number[] | undefined =>
|
||||
Array.isArray(value)
|
||||
? value
|
||||
.map((item) => asNumber(item))
|
||||
.filter((item): item is number => item !== undefined)
|
||||
: undefined;
|
||||
|
||||
const asStringArray = (value: unknown): string[] | undefined =>
|
||||
Array.isArray(value)
|
||||
? value
|
||||
.map((item) => asString(item))
|
||||
.filter((item): item is string => item !== undefined)
|
||||
: undefined;
|
||||
|
||||
export const normalizeStyleLayerId = (value: unknown): DefaultLayerStyleId | null => {
|
||||
const normalized = asString(value)?.toLowerCase();
|
||||
if (normalized === "junctions" || normalized === "pipes") {
|
||||
return normalized;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
export const getStyleLayerLabel = (layerId: DefaultLayerStyleId): string =>
|
||||
LAYER_LABELS[layerId];
|
||||
|
||||
export const parseApplyLayerStylePayload = (
|
||||
params: Record<string, unknown>,
|
||||
): ApplyLayerStyleActionPayload | null => {
|
||||
const layerId = normalizeStyleLayerId(params.layer_id ?? params.layerId);
|
||||
if (!layerId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const resetToDefault = Boolean(
|
||||
asBoolean(params.reset_to_default ?? params.resetToDefault),
|
||||
);
|
||||
const rawStyleConfig =
|
||||
params.style_config && typeof params.style_config === "object"
|
||||
? (params.style_config as Record<string, unknown>)
|
||||
: params.styleConfig && typeof params.styleConfig === "object"
|
||||
? (params.styleConfig as Record<string, unknown>)
|
||||
: null;
|
||||
|
||||
const styleConfig: Partial<StyleConfig> | undefined = rawStyleConfig
|
||||
? {
|
||||
property: asString(rawStyleConfig.property),
|
||||
classificationMethod: asString(
|
||||
rawStyleConfig.classification_method ?? rawStyleConfig.classificationMethod,
|
||||
),
|
||||
segments: asNumber(rawStyleConfig.segments),
|
||||
minSize: asNumber(rawStyleConfig.min_size ?? rawStyleConfig.minSize),
|
||||
maxSize: asNumber(rawStyleConfig.max_size ?? rawStyleConfig.maxSize),
|
||||
minStrokeWidth: asNumber(
|
||||
rawStyleConfig.min_stroke_width ?? rawStyleConfig.minStrokeWidth,
|
||||
),
|
||||
maxStrokeWidth: asNumber(
|
||||
rawStyleConfig.max_stroke_width ?? rawStyleConfig.maxStrokeWidth,
|
||||
),
|
||||
fixedStrokeWidth: asNumber(
|
||||
rawStyleConfig.fixed_stroke_width ?? rawStyleConfig.fixedStrokeWidth,
|
||||
),
|
||||
colorType: asString(rawStyleConfig.color_type ?? rawStyleConfig.colorType),
|
||||
singlePaletteIndex: asNumber(
|
||||
rawStyleConfig.single_palette_index ?? rawStyleConfig.singlePaletteIndex,
|
||||
),
|
||||
gradientPaletteIndex: asNumber(
|
||||
rawStyleConfig.gradient_palette_index ?? rawStyleConfig.gradientPaletteIndex,
|
||||
),
|
||||
rainbowPaletteIndex: asNumber(
|
||||
rawStyleConfig.rainbow_palette_index ?? rawStyleConfig.rainbowPaletteIndex,
|
||||
),
|
||||
showLabels: asBoolean(rawStyleConfig.show_labels ?? rawStyleConfig.showLabels),
|
||||
showId: asBoolean(rawStyleConfig.show_id ?? rawStyleConfig.showId),
|
||||
opacity: asNumber(rawStyleConfig.opacity),
|
||||
adjustWidthByProperty: asBoolean(
|
||||
rawStyleConfig.adjust_width_by_property ??
|
||||
rawStyleConfig.adjustWidthByProperty,
|
||||
),
|
||||
customBreaks: asNumberArray(
|
||||
rawStyleConfig.custom_breaks ?? rawStyleConfig.customBreaks,
|
||||
),
|
||||
customColors: asStringArray(
|
||||
rawStyleConfig.custom_colors ?? rawStyleConfig.customColors,
|
||||
),
|
||||
}
|
||||
: undefined;
|
||||
|
||||
const hasStyleOverrides =
|
||||
styleConfig &&
|
||||
Object.values(styleConfig).some((value) =>
|
||||
Array.isArray(value) ? value.length > 0 : value !== undefined,
|
||||
);
|
||||
|
||||
if (!resetToDefault && !hasStyleOverrides) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
layerId,
|
||||
resetToDefault,
|
||||
styleConfig: hasStyleOverrides ? styleConfig : undefined,
|
||||
};
|
||||
};
|
||||
|
||||
export const describeApplyLayerStyle = (
|
||||
payload: ApplyLayerStyleActionPayload,
|
||||
): string => {
|
||||
const layerLabel = getStyleLayerLabel(payload.layerId);
|
||||
if (payload.resetToDefault) {
|
||||
return `${layerLabel} · 重置默认样式`;
|
||||
}
|
||||
const property = payload.styleConfig?.property;
|
||||
return property ? `${layerLabel} · ${property}` : `${layerLabel} · 应用样式`;
|
||||
};
|
||||
Reference in New Issue
Block a user