feat: 增加库位屏幕的下拉刷新功能,优化API响应处理,改进界面样式和用户体验
This commit is contained in:
parent
4ee7e9af54
commit
c03df200ab
@ -9,7 +9,9 @@
|
|||||||
"apiEndpoints": {
|
"apiEndpoints": {
|
||||||
"getTasks": "/api/vwed-task/list",
|
"getTasks": "/api/vwed-task/list",
|
||||||
"getTaskDetail": "/api/vwed-task/{taskId}",
|
"getTaskDetail": "/api/vwed-task/{taskId}",
|
||||||
"runTask": "/api/vwed-task-edit/run"
|
"runTask": "/api/vwed-task-edit/run",
|
||||||
|
"getLocationList": "/api/vwed-operate-point/list",
|
||||||
|
"batchUpdateLocation": "/api/vwed-operate-point/batch-status"
|
||||||
},
|
},
|
||||||
"taskApiEndpoints": {
|
"taskApiEndpoints": {
|
||||||
"getTaskList": "/task",
|
"getTaskList": "/task",
|
||||||
|
@ -1,7 +1,16 @@
|
|||||||
import React, { useEffect, useState, useCallback } from 'react';
|
import React, { useEffect, useState, useCallback } from 'react';
|
||||||
import { StyleSheet, View, FlatList, Text, ActivityIndicator, Alert } from 'react-native';
|
import {
|
||||||
import { SearchBar, CheckBox, Button, useTheme, Overlay, ListItem } from '@rneui/themed';
|
StyleSheet,
|
||||||
|
View,
|
||||||
|
FlatList,
|
||||||
|
Text,
|
||||||
|
ActivityIndicator,
|
||||||
|
Alert,
|
||||||
|
RefreshControl,
|
||||||
|
} from 'react-native';
|
||||||
|
import { SearchBar, CheckBox, Button, Overlay, ListItem } from '@rneui/themed';
|
||||||
import api from '../services/api';
|
import api from '../services/api';
|
||||||
|
import { getConfig } from '../services/configService';
|
||||||
|
|
||||||
interface Location {
|
interface Location {
|
||||||
id: string;
|
id: string;
|
||||||
@ -13,20 +22,35 @@ interface Location {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const LocationScreen = () => {
|
const LocationScreen = () => {
|
||||||
const { theme } = useTheme();
|
|
||||||
const [locations, setLocations] = useState<Location[]>([]);
|
const [locations, setLocations] = useState<Location[]>([]);
|
||||||
const [search, setSearch] = useState('');
|
const [search, setSearch] = useState('');
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [selectedLocations, setSelectedLocations] = useState<string[]>([]);
|
const [selectedLocations, setSelectedLocations] = useState<string[]>([]);
|
||||||
const [isOverlayVisible, setOverlayVisible] = useState(false);
|
const [isOverlayVisible, setOverlayVisible] = useState(false);
|
||||||
|
const [isRefreshing, setIsRefreshing] = useState(false);
|
||||||
|
|
||||||
const fetchData = useCallback(async (query = '') => {
|
const fetchData = useCallback(async (query = '') => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
const response = await api.get('/api/vwed-operate-point/list', {
|
const config = await getConfig();
|
||||||
|
const endpoint =
|
||||||
|
(config?.apiEndpoints as any)?.getLocationList ||
|
||||||
|
'/api/vwed-operate-point/list';
|
||||||
|
|
||||||
|
const response = await api.get(endpoint, {
|
||||||
params: { layer_name: query },
|
params: { layer_name: query },
|
||||||
});
|
});
|
||||||
setLocations(response.storage_locations);
|
console.log('API Response:', response); // 调试日志
|
||||||
|
// API 拦截器已经处理了响应,直接使用返回的数据
|
||||||
|
const data = response as any;
|
||||||
|
if (data && data.storage_locations) {
|
||||||
|
setLocations(data.storage_locations);
|
||||||
|
} else if (Array.isArray(data)) {
|
||||||
|
setLocations(data);
|
||||||
|
} else {
|
||||||
|
console.warn('Unexpected response format:', data);
|
||||||
|
setLocations([]);
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
Alert.alert('错误', '加载库位列表失败。');
|
Alert.alert('错误', '加载库位列表失败。');
|
||||||
@ -43,9 +67,20 @@ const LocationScreen = () => {
|
|||||||
fetchData(search);
|
fetchData(search);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleRefresh = useCallback(async () => {
|
||||||
|
setIsRefreshing(true);
|
||||||
|
try {
|
||||||
|
await fetchData(search);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('刷新失败:', error);
|
||||||
|
} finally {
|
||||||
|
setIsRefreshing(false);
|
||||||
|
}
|
||||||
|
}, [fetchData, search]);
|
||||||
|
|
||||||
const toggleSelection = (id: string) => {
|
const toggleSelection = (id: string) => {
|
||||||
setSelectedLocations(prev =>
|
setSelectedLocations(prev =>
|
||||||
prev.includes(id) ? prev.filter(item => item !== id) : [...prev, id]
|
prev.includes(id) ? prev.filter(item => item !== id) : [...prev, id],
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -56,12 +91,19 @@ const LocationScreen = () => {
|
|||||||
}
|
}
|
||||||
setOverlayVisible(false);
|
setOverlayVisible(false);
|
||||||
try {
|
try {
|
||||||
const response = await api.put('/api/vwed-operate-point/batch-status', {
|
const config = await getConfig();
|
||||||
|
const endpoint =
|
||||||
|
(config?.apiEndpoints as any)?.batchUpdateLocation ||
|
||||||
|
'/api/vwed-operate-point/batch-status';
|
||||||
|
|
||||||
|
const response = await api.put(endpoint, {
|
||||||
layer_names: selectedLocations,
|
layer_names: selectedLocations,
|
||||||
action: action,
|
action: action,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { success_count, failed_count, results } = response;
|
console.log('Batch Update Response:', response); // 调试日志
|
||||||
|
// API 拦截器已经处理了响应,直接使用返回的数据
|
||||||
|
const { success_count, failed_count, results } = response as any;
|
||||||
let message = `批量操作完成:\n成功 ${success_count} 个, 失败 ${failed_count} 个。\n\n`;
|
let message = `批量操作完成:\n成功 ${success_count} 个, 失败 ${failed_count} 个。\n\n`;
|
||||||
if (failed_count > 0) {
|
if (failed_count > 0) {
|
||||||
message += '失败详情:\n';
|
message += '失败详情:\n';
|
||||||
@ -75,7 +117,7 @@ const LocationScreen = () => {
|
|||||||
|
|
||||||
fetchData(search);
|
fetchData(search);
|
||||||
setSelectedLocations([]);
|
setSelectedLocations([]);
|
||||||
} catch (error) {
|
} catch (error: any) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
Alert.alert('错误', `批量操作失败: ${error.message}`);
|
Alert.alert('错误', `批量操作失败: ${error.message}`);
|
||||||
}
|
}
|
||||||
@ -91,72 +133,137 @@ const LocationScreen = () => {
|
|||||||
];
|
];
|
||||||
|
|
||||||
const renderItem = ({ item }: { item: Location }) => (
|
const renderItem = ({ item }: { item: Location }) => (
|
||||||
<View style={[styles.itemContainer, { backgroundColor: theme.colors.background }]}>
|
<View style={styles.itemContainer}>
|
||||||
<CheckBox
|
<CheckBox
|
||||||
checked={selectedLocations.includes(item.id)}
|
checked={selectedLocations.includes(item.id)}
|
||||||
onPress={() => toggleSelection(item.id)}
|
onPress={() => toggleSelection(item.id)}
|
||||||
containerStyle={{ backgroundColor: 'transparent' }}
|
containerStyle={styles.checkboxContainer}
|
||||||
|
checkedColor="#4CAF50"
|
||||||
|
uncheckedColor="#666"
|
||||||
/>
|
/>
|
||||||
<Text style={[styles.itemText, { color: theme.colors.black }]}>{item.layer_name}</Text>
|
<Text style={styles.itemText}>{item.layer_name}</Text>
|
||||||
<Text style={[styles.itemText, { color: item.is_occupied ? 'red' : 'green' }]}>{item.is_occupied ? '是' : '否'}</Text>
|
<Text
|
||||||
<Text style={[styles.itemText, { color: item.is_locked ? 'red' : 'green' }]}>{item.is_locked ? '是' : '否'}</Text>
|
style={[
|
||||||
<Text style={[styles.itemText, { color: item.is_empty_tray ? 'orange' : 'green' }]}>{item.is_empty_tray ? '是' : '否'}</Text>
|
styles.itemText,
|
||||||
<Text style={[styles.itemText, { color: item.is_disabled ? 'red' : 'green' }]}>{item.is_disabled ? '是' : '否'}</Text>
|
{ color: item.is_occupied ? '#F44336' : '#4CAF50' },
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
{item.is_occupied ? '是' : '否'}
|
||||||
|
</Text>
|
||||||
|
<Text
|
||||||
|
style={[
|
||||||
|
styles.itemText,
|
||||||
|
{ color: item.is_locked ? '#F44336' : '#4CAF50' },
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
{item.is_locked ? '是' : '否'}
|
||||||
|
</Text>
|
||||||
|
<Text
|
||||||
|
style={[
|
||||||
|
styles.itemText,
|
||||||
|
{ color: item.is_empty_tray ? '#FF9800' : '#4CAF50' },
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
{item.is_empty_tray ? '是' : '否'}
|
||||||
|
</Text>
|
||||||
|
<Text
|
||||||
|
style={[
|
||||||
|
styles.itemText,
|
||||||
|
{ color: item.is_disabled ? '#F44336' : '#4CAF50' },
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
{item.is_disabled ? '是' : '否'}
|
||||||
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return (
|
return (
|
||||||
<View style={styles.loader}>
|
<View style={styles.loader}>
|
||||||
<ActivityIndicator size="large" color={theme.colors.primary} />
|
<ActivityIndicator size="large" color="#4CAF50" />
|
||||||
|
<Text style={styles.loadingText}>加载中...</Text>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={[styles.container, { backgroundColor: theme.colors.grey5 }]}>
|
<View style={styles.container}>
|
||||||
<View style={styles.searchContainer}>
|
<View style={styles.searchContainer}>
|
||||||
<SearchBar
|
<SearchBar
|
||||||
placeholder="搜索库位..."
|
placeholder="搜索库位..."
|
||||||
onChangeText={setSearch}
|
onChangeText={setSearch}
|
||||||
value={search}
|
value={search}
|
||||||
containerStyle={styles.searchBarContainer}
|
containerStyle={styles.searchBarContainer}
|
||||||
inputContainerStyle={{ backgroundColor: theme.colors.grey4 }}
|
inputContainerStyle={styles.searchInputContainer}
|
||||||
/>
|
inputStyle={styles.searchInput}
|
||||||
<Button title="搜索" onPress={handleSearch} buttonStyle={styles.searchButton} />
|
placeholderTextColor="#999"
|
||||||
</View>
|
searchIcon={{ color: '#999' }}
|
||||||
|
clearIcon={{ color: '#999' }}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
title="搜索"
|
||||||
|
onPress={handleSearch}
|
||||||
|
buttonStyle={styles.searchButton}
|
||||||
|
titleStyle={styles.searchButtonText}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
title="批量操作"
|
title="批量操作"
|
||||||
onPress={() => setOverlayVisible(true)}
|
onPress={() => setOverlayVisible(true)}
|
||||||
containerStyle={styles.batchButtonContainer}
|
containerStyle={styles.batchButtonContainer}
|
||||||
buttonStyle={{ backgroundColor: theme.colors.primary }}
|
buttonStyle={styles.batchButton}
|
||||||
|
titleStyle={styles.batchButtonText}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Overlay isVisible={isOverlayVisible} onBackdropPress={() => setOverlayVisible(false)}>
|
<Overlay
|
||||||
<View>
|
isVisible={isOverlayVisible}
|
||||||
|
onBackdropPress={() => setOverlayVisible(false)}
|
||||||
|
overlayStyle={styles.overlay}
|
||||||
|
>
|
||||||
|
<View style={styles.overlayContainer}>
|
||||||
|
<Text style={styles.overlayTitle}>选择操作</Text>
|
||||||
{actions.map((item, index) => (
|
{actions.map((item, index) => (
|
||||||
<ListItem key={index} onPress={() => handleBatchUpdate(item.action)} bottomDivider>
|
<ListItem
|
||||||
|
key={index}
|
||||||
|
onPress={() => handleBatchUpdate(item.action)}
|
||||||
|
bottomDivider
|
||||||
|
containerStyle={styles.listItemContainer}
|
||||||
|
>
|
||||||
<ListItem.Content>
|
<ListItem.Content>
|
||||||
<ListItem.Title>{item.title}</ListItem.Title>
|
<ListItem.Title style={styles.listItemTitle}>
|
||||||
|
{item.title}
|
||||||
|
</ListItem.Title>
|
||||||
</ListItem.Content>
|
</ListItem.Content>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
))}
|
))}
|
||||||
</View>
|
</View>
|
||||||
</Overlay>
|
</Overlay>
|
||||||
|
|
||||||
<View style={[styles.headerContainer, { backgroundColor: theme.colors.grey4 }]}>
|
<View style={styles.headerContainer}>
|
||||||
<Text style={[styles.headerText, { color: theme.colors.black }]}>库位名称</Text>
|
<Text style={styles.headerText}>库位名称</Text>
|
||||||
<Text style={[styles.headerText, { color: theme.colors.black }]}>是否占用</Text>
|
<Text style={styles.headerText}>是否占用</Text>
|
||||||
<Text style={[styles.headerText, { color: theme.colors.black }]}>是否锁定</Text>
|
<Text style={styles.headerText}>是否锁定</Text>
|
||||||
<Text style={[styles.headerText, { color: theme.colors.black }]}>空托盘</Text>
|
<Text style={styles.headerText}>空托盘</Text>
|
||||||
<Text style={[styles.headerText, { color: theme.colors.black }]}>是否禁用</Text>
|
<Text style={styles.headerText}>是否禁用</Text>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<FlatList
|
<FlatList
|
||||||
data={locations}
|
data={locations}
|
||||||
renderItem={renderItem}
|
renderItem={renderItem}
|
||||||
keyExtractor={(item) => item.id}
|
keyExtractor={item => item.id}
|
||||||
ItemSeparatorComponent={() => <View style={styles.separator} />}
|
ItemSeparatorComponent={() => <View style={styles.separator} />}
|
||||||
|
refreshControl={
|
||||||
|
<RefreshControl
|
||||||
|
refreshing={isRefreshing}
|
||||||
|
onRefresh={handleRefresh}
|
||||||
|
colors={['#4CAF50']}
|
||||||
|
tintColor="#4CAF50"
|
||||||
|
title="下拉刷新"
|
||||||
|
titleColor="#999"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
showsVerticalScrollIndicator={false}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
@ -165,54 +272,131 @@ const LocationScreen = () => {
|
|||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
|
backgroundColor: '#1a1a1a',
|
||||||
},
|
},
|
||||||
loader: {
|
loader: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
|
backgroundColor: '#1a1a1a',
|
||||||
|
},
|
||||||
|
loadingText: {
|
||||||
|
color: '#999',
|
||||||
|
marginTop: 10,
|
||||||
|
fontSize: 16,
|
||||||
},
|
},
|
||||||
searchContainer: {
|
searchContainer: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
|
backgroundColor: '#2a2a2a',
|
||||||
|
paddingHorizontal: 10,
|
||||||
|
paddingVertical: 5,
|
||||||
},
|
},
|
||||||
searchBarContainer: {
|
searchBarContainer: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
backgroundColor: 'transparent',
|
backgroundColor: 'transparent',
|
||||||
borderTopWidth: 0,
|
borderTopWidth: 0,
|
||||||
borderBottomWidth: 0,
|
borderBottomWidth: 0,
|
||||||
|
paddingHorizontal: 0,
|
||||||
|
},
|
||||||
|
searchInputContainer: {
|
||||||
|
backgroundColor: '#333',
|
||||||
|
borderRadius: 8,
|
||||||
|
},
|
||||||
|
searchInput: {
|
||||||
|
color: '#fff',
|
||||||
|
fontSize: 16,
|
||||||
},
|
},
|
||||||
searchButton: {
|
searchButton: {
|
||||||
marginRight: 10,
|
backgroundColor: '#4CAF50',
|
||||||
|
borderRadius: 8,
|
||||||
|
paddingHorizontal: 20,
|
||||||
|
paddingVertical: 12,
|
||||||
|
marginLeft: 10,
|
||||||
|
},
|
||||||
|
searchButtonText: {
|
||||||
|
color: '#fff',
|
||||||
|
fontWeight: 'bold',
|
||||||
},
|
},
|
||||||
batchButtonContainer: {
|
batchButtonContainer: {
|
||||||
margin: 10,
|
margin: 15,
|
||||||
|
},
|
||||||
|
batchButton: {
|
||||||
|
backgroundColor: '#2196F3',
|
||||||
|
borderRadius: 8,
|
||||||
|
paddingVertical: 12,
|
||||||
|
},
|
||||||
|
batchButtonText: {
|
||||||
|
color: '#fff',
|
||||||
|
fontWeight: 'bold',
|
||||||
|
fontSize: 16,
|
||||||
|
},
|
||||||
|
overlay: {
|
||||||
|
backgroundColor: '#2a2a2a',
|
||||||
|
borderRadius: 12,
|
||||||
|
padding: 0,
|
||||||
|
},
|
||||||
|
overlayContainer: {
|
||||||
|
minWidth: 250,
|
||||||
|
paddingVertical: 10,
|
||||||
|
},
|
||||||
|
overlayTitle: {
|
||||||
|
color: '#fff',
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
textAlign: 'center',
|
||||||
|
paddingVertical: 15,
|
||||||
|
borderBottomWidth: 1,
|
||||||
|
borderBottomColor: '#444',
|
||||||
|
},
|
||||||
|
listItemContainer: {
|
||||||
|
backgroundColor: 'transparent',
|
||||||
|
paddingVertical: 15,
|
||||||
|
paddingHorizontal: 20,
|
||||||
|
borderBottomColor: '#444',
|
||||||
|
},
|
||||||
|
listItemTitle: {
|
||||||
|
fontSize: 16,
|
||||||
|
textAlign: 'center',
|
||||||
|
color: '#fff',
|
||||||
},
|
},
|
||||||
itemContainer: {
|
itemContainer: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
paddingVertical: 8,
|
paddingVertical: 12,
|
||||||
paddingHorizontal: 10,
|
paddingHorizontal: 10,
|
||||||
|
backgroundColor: '#2a2a2a',
|
||||||
|
},
|
||||||
|
checkboxContainer: {
|
||||||
|
backgroundColor: 'transparent',
|
||||||
|
borderWidth: 0,
|
||||||
|
padding: 0,
|
||||||
|
marginLeft: 0,
|
||||||
|
marginRight: 5,
|
||||||
},
|
},
|
||||||
itemText: {
|
itemText: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
|
color: '#fff',
|
||||||
},
|
},
|
||||||
headerContainer: {
|
headerContainer: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
padding: 12,
|
padding: 12,
|
||||||
|
backgroundColor: '#333',
|
||||||
borderBottomWidth: 1,
|
borderBottomWidth: 1,
|
||||||
borderBottomColor: '#ccc',
|
borderBottomColor: '#444',
|
||||||
},
|
},
|
||||||
headerText: {
|
headerText: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
fontWeight: 'bold',
|
fontWeight: 'bold',
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
|
color: '#fff',
|
||||||
},
|
},
|
||||||
separator: {
|
separator: {
|
||||||
height: 1,
|
height: 1,
|
||||||
backgroundColor: '#e0e0e0',
|
backgroundColor: '#333',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@ export default function SettingsScreen() {
|
|||||||
const [settings, setSettings] = useState<AppSettings>({
|
const [settings, setSettings] = useState<AppSettings>({
|
||||||
configFileName: '',
|
configFileName: '',
|
||||||
serverUrl: '',
|
serverUrl: '',
|
||||||
|
taskServerUrl: '',
|
||||||
});
|
});
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [configStatus, setConfigStatus] = useState<string>('未加载');
|
const [configStatus, setConfigStatus] = useState<string>('未加载');
|
||||||
@ -251,14 +252,29 @@ export default function SettingsScreen() {
|
|||||||
<Text style={styles.sectionTitle}>服务器设置</Text>
|
<Text style={styles.sectionTitle}>服务器设置</Text>
|
||||||
|
|
||||||
<View style={styles.inputGroup}>
|
<View style={styles.inputGroup}>
|
||||||
<Text style={styles.label}>服务器地址:</Text>
|
<Text style={styles.label}>库位管理服务器地址:</Text>
|
||||||
<TextInput
|
<TextInput
|
||||||
style={styles.textInput}
|
style={styles.textInput}
|
||||||
value={settings.serverUrl}
|
value={settings.serverUrl}
|
||||||
onChangeText={text =>
|
onChangeText={text =>
|
||||||
setSettings(prev => ({ ...prev, serverUrl: text }))
|
setSettings(prev => ({ ...prev, serverUrl: text }))
|
||||||
}
|
}
|
||||||
placeholder="http://localhost:3000/api"
|
placeholder="http://192.168.189.206:8000"
|
||||||
|
placeholderTextColor="#999"
|
||||||
|
autoCapitalize="none"
|
||||||
|
keyboardType="url"
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={styles.inputGroup}>
|
||||||
|
<Text style={styles.label}>任务管理服务器地址:</Text>
|
||||||
|
<TextInput
|
||||||
|
style={styles.textInput}
|
||||||
|
value={settings.taskServerUrl}
|
||||||
|
onChangeText={text =>
|
||||||
|
setSettings(prev => ({ ...prev, taskServerUrl: text }))
|
||||||
|
}
|
||||||
|
placeholder="http://192.168.189.206:8080/jeecg-boot"
|
||||||
placeholderTextColor="#999"
|
placeholderTextColor="#999"
|
||||||
autoCapitalize="none"
|
autoCapitalize="none"
|
||||||
keyboardType="url"
|
keyboardType="url"
|
||||||
@ -308,7 +324,7 @@ export default function SettingsScreen() {
|
|||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
backgroundColor: '#f5f5f5',
|
backgroundColor: '#1a1a1a',
|
||||||
},
|
},
|
||||||
content: {
|
content: {
|
||||||
padding: 20,
|
padding: 20,
|
||||||
@ -318,10 +334,10 @@ const styles = StyleSheet.create({
|
|||||||
fontWeight: 'bold',
|
fontWeight: 'bold',
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
marginBottom: 30,
|
marginBottom: 30,
|
||||||
color: '#333',
|
color: '#fff',
|
||||||
},
|
},
|
||||||
section: {
|
section: {
|
||||||
backgroundColor: 'white',
|
backgroundColor: '#2a2a2a',
|
||||||
borderRadius: 10,
|
borderRadius: 10,
|
||||||
padding: 20,
|
padding: 20,
|
||||||
marginBottom: 20,
|
marginBottom: 20,
|
||||||
@ -330,7 +346,7 @@ const styles = StyleSheet.create({
|
|||||||
width: 0,
|
width: 0,
|
||||||
height: 2,
|
height: 2,
|
||||||
},
|
},
|
||||||
shadowOpacity: 0.1,
|
shadowOpacity: 0.3,
|
||||||
shadowRadius: 3.84,
|
shadowRadius: 3.84,
|
||||||
elevation: 5,
|
elevation: 5,
|
||||||
},
|
},
|
||||||
@ -338,7 +354,7 @@ const styles = StyleSheet.create({
|
|||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
fontWeight: 'bold',
|
fontWeight: 'bold',
|
||||||
marginBottom: 15,
|
marginBottom: 15,
|
||||||
color: '#333',
|
color: '#fff',
|
||||||
},
|
},
|
||||||
inputGroup: {
|
inputGroup: {
|
||||||
marginBottom: 15,
|
marginBottom: 15,
|
||||||
@ -346,7 +362,7 @@ const styles = StyleSheet.create({
|
|||||||
label: {
|
label: {
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
marginBottom: 8,
|
marginBottom: 8,
|
||||||
color: '#333',
|
color: '#fff',
|
||||||
fontWeight: '500',
|
fontWeight: '500',
|
||||||
},
|
},
|
||||||
inputRow: {
|
inputRow: {
|
||||||
@ -356,16 +372,17 @@ const styles = StyleSheet.create({
|
|||||||
textInput: {
|
textInput: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
borderWidth: 1,
|
borderWidth: 1,
|
||||||
borderColor: '#ddd',
|
borderColor: '#444',
|
||||||
borderRadius: 8,
|
borderRadius: 8,
|
||||||
padding: 12,
|
padding: 12,
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
backgroundColor: '#fafafa',
|
backgroundColor: '#333',
|
||||||
|
color: '#fff',
|
||||||
},
|
},
|
||||||
extension: {
|
extension: {
|
||||||
marginLeft: 8,
|
marginLeft: 8,
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
color: '#666',
|
color: '#999',
|
||||||
fontWeight: '500',
|
fontWeight: '500',
|
||||||
},
|
},
|
||||||
statusRow: {
|
statusRow: {
|
||||||
@ -375,12 +392,12 @@ const styles = StyleSheet.create({
|
|||||||
},
|
},
|
||||||
statusLabel: {
|
statusLabel: {
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
color: '#333',
|
color: '#fff',
|
||||||
fontWeight: '500',
|
fontWeight: '500',
|
||||||
},
|
},
|
||||||
statusText: {
|
statusText: {
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
color: '#007AFF',
|
color: '#4CAF50',
|
||||||
marginLeft: 8,
|
marginLeft: 8,
|
||||||
},
|
},
|
||||||
button: {
|
button: {
|
||||||
@ -418,7 +435,7 @@ const styles = StyleSheet.create({
|
|||||||
marginTop: 10,
|
marginTop: 10,
|
||||||
},
|
},
|
||||||
infoSection: {
|
infoSection: {
|
||||||
backgroundColor: 'white',
|
backgroundColor: '#2a2a2a',
|
||||||
borderRadius: 10,
|
borderRadius: 10,
|
||||||
padding: 20,
|
padding: 20,
|
||||||
marginBottom: 20,
|
marginBottom: 20,
|
||||||
@ -427,12 +444,12 @@ const styles = StyleSheet.create({
|
|||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
fontWeight: 'bold',
|
fontWeight: 'bold',
|
||||||
marginBottom: 15,
|
marginBottom: 15,
|
||||||
color: '#333',
|
color: '#fff',
|
||||||
},
|
},
|
||||||
infoText: {
|
infoText: {
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
lineHeight: 20,
|
lineHeight: 20,
|
||||||
color: '#666',
|
color: '#999',
|
||||||
marginBottom: 5,
|
marginBottom: 5,
|
||||||
},
|
},
|
||||||
loadingOverlay: {
|
loadingOverlay: {
|
||||||
@ -441,7 +458,7 @@ const styles = StyleSheet.create({
|
|||||||
left: 0,
|
left: 0,
|
||||||
right: 0,
|
right: 0,
|
||||||
bottom: 0,
|
bottom: 0,
|
||||||
backgroundColor: 'rgba(255, 255, 255, 0.8)',
|
backgroundColor: 'rgba(26, 26, 26, 0.8)',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
zIndex: 1,
|
zIndex: 1,
|
||||||
@ -449,7 +466,7 @@ const styles = StyleSheet.create({
|
|||||||
loadingText: {
|
loadingText: {
|
||||||
marginTop: 10,
|
marginTop: 10,
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
color: '#007AFF',
|
color: '#4CAF50',
|
||||||
},
|
},
|
||||||
clearButton: {
|
clearButton: {
|
||||||
backgroundColor: '#FF3B30',
|
backgroundColor: '#FF3B30',
|
||||||
|
@ -11,7 +11,18 @@ api.interceptors.request.use(
|
|||||||
async config => {
|
async config => {
|
||||||
const appConfig = await getConfig();
|
const appConfig = await getConfig();
|
||||||
const settings = await getSettings();
|
const settings = await getSettings();
|
||||||
const serverUrl = settings.serverUrl || appConfig?.serverUrl;
|
|
||||||
|
// 优先使用设置中的服务器地址,然后是配置文件中的地址
|
||||||
|
let serverUrl = '';
|
||||||
|
|
||||||
|
// 根据请求的URL判断使用哪个服务器地址
|
||||||
|
if (config.url?.includes('/task')) {
|
||||||
|
// 任务管理相关的API使用taskServerUrl
|
||||||
|
serverUrl = settings.taskServerUrl || appConfig?.taskServerUrl || '';
|
||||||
|
} else {
|
||||||
|
// 其他API使用普通的serverUrl(库位管理等)
|
||||||
|
serverUrl = settings.serverUrl || appConfig?.serverUrl || '';
|
||||||
|
}
|
||||||
|
|
||||||
if (!serverUrl) {
|
if (!serverUrl) {
|
||||||
const error = new Error('服务器地址未配置');
|
const error = new Error('服务器地址未配置');
|
||||||
|
@ -8,6 +8,7 @@ const CONFIG_CACHE_KEY = 'cached_config';
|
|||||||
const DEFAULT_SETTINGS: AppSettings = {
|
const DEFAULT_SETTINGS: AppSettings = {
|
||||||
configFileName: 'config.json',
|
configFileName: 'config.json',
|
||||||
serverUrl: '',
|
serverUrl: '',
|
||||||
|
taskServerUrl: '',
|
||||||
};
|
};
|
||||||
|
|
||||||
// 获取设置
|
// 获取设置
|
||||||
|
@ -28,4 +28,5 @@ export interface AppConfig {
|
|||||||
export interface AppSettings {
|
export interface AppSettings {
|
||||||
configFileName: string;
|
configFileName: string;
|
||||||
serverUrl: string;
|
serverUrl: string;
|
||||||
|
taskServerUrl?: string; // 任务管理服务器地址
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user