useOptions.ts
7.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
import { ref, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import optionsApi, { type Option, type OptionsData, type FieldPathNode } from '../services/options'
// 缓存的下拉数据
const cachedOptions = ref<OptionsData | null>(null)
const isLoading = ref(false)
const currentLang = ref('')
const manufacturerOptions = ref<Option[]>([])
/**
* @author zzy
* @description 字段路径选项缓存(按来源类型存储)
*/
const fieldPathOptionsCache = ref<Record<number, Option[]>>({})
/**
* 下拉选项管理 composable
* 统一管理所有下拉数据,支持多语言
* @author zzy
*/
export function useOptions() {
const { locale } = useI18n()
// 语言映射
const getLangParam = () => {
const lang = locale.value
if (lang === 'cn') return 'zh-cn'
if (lang === 'gb') return 'en'
return 'zh-cn'
}
// 加载所有下拉选项
const loadOptions = async (force = false) => {
const lang = getLangParam()
if (!force && cachedOptions.value && currentLang.value === lang) {
return cachedOptions.value
}
if (isLoading.value) return cachedOptions.value
try {
isLoading.value = true
const res: any = await optionsApi.getAll(lang)
const data = (res && (res.Data ?? res.data)) || res
cachedOptions.value = data
currentLang.value = lang
return data
} catch (err) {
console.error('加载下拉选项失败', err)
return null
} finally {
isLoading.value = false
}
}
// 监听语言变化,自动重新加载
watch(locale, () => {
loadOptions(true)
})
// 转换为 VaSelect 格式 { text, value }
const toSelectOptions = (options: Option[] | undefined) => {
if (!options) return []
return options.map(opt => ({ text: opt.label, value: opt.value }))
}
// 加载制造商选项(从独立接口获取)
const loadManufacturerOptions = async () => {
if (manufacturerOptions.value.length > 0) {
return manufacturerOptions.value
}
try {
const res: any = await optionsApi.getManufacturers()
const data = (res && (res.Data ?? res.data)) || res || []
// 后端返回格式: { value, text, code } -> 转换为 { label, value }
manufacturerOptions.value = data.map((item: any) => ({
label: item.text || item.value,
value: item.value
}))
return manufacturerOptions.value
} catch (err) {
console.error('加载制造商选项失败', err)
return []
}
}
// 获取制造商选项
const getManufacturerOptions = () => {
if (manufacturerOptions.value.length === 0) {
loadManufacturerOptions()
}
return toSelectOptions(manufacturerOptions.value)
}
/**
* @author zzy
* @description 扁平化字段路径树为选项列表
* 使用 path 作为 label,以便显示完整路径(如 Robot.Status 而不是 Status)
*/
const flattenFieldPathTree = (nodes: FieldPathNode[], parentPath = ''): Option[] => {
const options: Option[] = []
for (const node of nodes) {
const currentPath = parentPath ? `${parentPath}.${node.name}` : node.name
options.push({
value: node.path || currentPath,
label: node.path || node.displayName || node.name
})
if (node.children && node.children.length > 0) {
options.push(...flattenFieldPathTree(node.children, currentPath))
}
}
return options
}
/**
* @author zzy
* @description 加载字段路径选项(按来源类型)
*/
const loadFieldPathOptions = async (sourceType: number) => {
if (fieldPathOptionsCache.value[sourceType]) {
return fieldPathOptionsCache.value[sourceType]
}
try {
const lang = getLangParam()
const res: any = await optionsApi.getFieldPathTree(sourceType, lang)
const nodes = res?.nodes || res?.Nodes || []
fieldPathOptionsCache.value[sourceType] = flattenFieldPathTree(nodes)
return fieldPathOptionsCache.value[sourceType]
} catch (err) {
console.error('加载字段路径选项失败', err)
return []
}
}
/**
* @author zzy
* @description 获取字段路径选项
*/
const getFieldPathOptions = (sourceType: number) => {
if (!fieldPathOptionsCache.value[sourceType]) {
loadFieldPathOptions(sourceType)
}
return toSelectOptions(fieldPathOptionsCache.value[sourceType])
}
// 获取各类下拉选项
const getRobotTypeOptions = () => toSelectOptions(cachedOptions.value?.robotType)
const getMovementTypeOptions = () => toSelectOptions(cachedOptions.value?.movementType)
const getRobotStatusOptions = () => toSelectOptions(cachedOptions.value?.robotStatus)
const getOnlineStatusOptions = () => toSelectOptions(cachedOptions.value?.onlineStatus)
const getOperatingModeOptions = () => toSelectOptions(cachedOptions.value?.operatingMode)
const getProtocolTypeOptions = () => toSelectOptions(cachedOptions.value?.protocolType)
const getMapTypeOptions = () => toSelectOptions(cachedOptions.value?.mapType)
const getMapNodeTypeOptions = () => toSelectOptions(cachedOptions.value?.mapNodeType)
const getMapResourceTypeOptions = () => toSelectOptions(cachedOptions.value?.mapResourceType)
const getActionCategoryOptions = () => toSelectOptions(cachedOptions.value?.actionCategory)
const getActionBlockTypeOptions = () => toSelectOptions(cachedOptions.value?.actionBlockType)
const getExecutionScopeOptions = () => toSelectOptions(cachedOptions.value?.executionScope)
const getParameterValueTypeOptions = () => toSelectOptions(cachedOptions.value?.parameterValueType)
const getParameterSourceTypeOptions = () => toSelectOptions(cachedOptions.value?.parameterSourceType)
const getTaskTypeOptions = () => toSelectOptions(cachedOptions.value?.taskType)
const getTaskStatusOptions = () => toSelectOptions(cachedOptions.value?.taskStatus)
const getTaskStepTypeOptions = () => toSelectOptions(cachedOptions.value?.taskStepType)
const getStepPropertyTypeOptions = () => toSelectOptions(cachedOptions.value?.stepPropertyType)
const getAfterActionTypeOptions = () => toSelectOptions(cachedOptions.value?.afterActionType)
const getNodeValueTypeOptions = () => toSelectOptions(cachedOptions.value?.nodeValueType)
const getShelfTypeOptions = () => toSelectOptions(cachedOptions.value?.shelfType)
const getLocationTypeOptions = () => toSelectOptions(cachedOptions.value?.LocationType)
// 根据值获取标签
const getLabelByValue = (options: Option[] | undefined, value: any) => {
if (!options || value === undefined || value === null) return ''
const opt = options.find(o => o.value === value || String(o.value) === String(value))
return opt?.label || String(value)
}
return {
cachedOptions,
isLoading,
loadOptions,
toSelectOptions,
getLabelByValue,
// 机器人
getRobotTypeOptions,
getMovementTypeOptions,
getRobotStatusOptions,
getOnlineStatusOptions,
getOperatingModeOptions,
getProtocolTypeOptions,
// 制造商
getManufacturerOptions,
loadManufacturerOptions,
// 地图
getMapTypeOptions,
getMapNodeTypeOptions,
getMapResourceTypeOptions,
// 动作
getActionCategoryOptions,
getActionBlockTypeOptions,
getExecutionScopeOptions,
getParameterValueTypeOptions,
getParameterSourceTypeOptions,
// 任务
getTaskTypeOptions,
getTaskStatusOptions,
getTaskStepTypeOptions,
getStepPropertyTypeOptions,
getAfterActionTypeOptions,
getNodeValueTypeOptions,
// 储位类型
getShelfTypeOptions,
getLocationTypeOptions,
// 字段路径
loadFieldPathOptions,
getFieldPathOptions
}
}