From 6aff5dd0c85250b9a8a473b76e122c4d70b4fe4e Mon Sep 17 00:00:00 2001 From: xudan Date: Wed, 23 Jul 2025 11:35:09 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=9B=B4=E6=96=B0=E4=BB=BB=E5=8A=A1?= =?UTF-8?q?=E8=A1=A8=E5=8D=95=E5=92=8C=E4=BB=BB=E5=8A=A1=E5=88=97=E8=A1=A8?= =?UTF-8?q?=E7=BB=84=E4=BB=B6=E4=BB=A5=E6=94=AF=E6=8C=81=E5=8A=A8=E6=80=81?= =?UTF-8?q?=E5=8F=82=E6=95=B0=E9=85=8D=E7=BD=AE=EF=BC=8C=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?axios=E4=BE=9D=E8=B5=96=EF=BC=8C=E4=BF=AE=E6=94=B9=E6=9C=8D?= =?UTF-8?q?=E5=8A=A1=E5=99=A8URL=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CLAUDE.md | 2 + config.json | 2 +- package-lock.json | 95 ++++++++++-- package.json | 1 + src/components/TaskCard.tsx | 27 ++-- src/components/TaskForm.tsx | 271 ++++++--------------------------- src/context/TasksContext.tsx | 163 ++++++++++++++------ src/screens/TaskEditScreen.tsx | 19 +-- src/screens/TaskListScreen.tsx | 15 +- src/services/configService.ts | 1 - src/types/task.ts | 30 +++- 11 files changed, 309 insertions(+), 317 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 6554b0f..fdd0bf3 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -25,3 +25,5 @@ This is a React Native application for task management. - **Types**: TypeScript types, like the `Task` type, are defined in the `src/types` directory. The root component of the application is `App.tsx`, which sets up the `ThemeProvider`, `TasksProvider`, and `NavigationContainer`. + +# 请你检查 读取文件后,是否发送请求给 AI 大模型了 diff --git a/config.json b/config.json index 6ee3b53..3454c8e 100644 --- a/config.json +++ b/config.json @@ -705,5 +705,5 @@ } } ], - "serverUrl": "http://localhost:3000/api" + "serverUrl": "http://192.168.189.206:8000" } diff --git a/package-lock.json b/package-lock.json index ee99a32..3d38cf6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ "@react-navigation/stack": "^7.4.2", "@rneui/base": "^4.0.0-rc.8", "@rneui/themed": "^4.0.0-rc.8", + "axios": "^1.10.0", "react": "19.1.0", "react-native": "0.80.1", "react-native-gesture-handler": "^2.27.1", @@ -4381,6 +4382,12 @@ "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", "license": "MIT" }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, "node_modules/available-typed-arrays": { "version": "1.0.7", "resolved": "https://registry.npmmirror.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", @@ -4397,6 +4404,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/axios": { + "version": "1.10.0", + "resolved": "https://registry.npmmirror.com/axios/-/axios-1.10.0.tgz", + "integrity": "sha512-/1xYAC4MP/HEG+3duIhFr4ZQXR4sQXOIe+o6sdqzeykGLx6Upp/1p8MHqhINOvGeP7xyNHe7tsiJByc4SSVUxw==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/babel-jest": { "version": "29.7.0", "resolved": "https://registry.npmmirror.com/babel-jest/-/babel-jest-29.7.0.tgz", @@ -4775,7 +4793,6 @@ "version": "1.0.2", "resolved": "https://registry.npmmirror.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", - "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -5094,6 +5111,18 @@ "dev": true, "license": "MIT" }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/command-exists": { "version": "1.2.9", "resolved": "https://registry.npmmirror.com/command-exists/-/command-exists-1.2.9.tgz", @@ -5473,6 +5502,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmmirror.com/depd/-/depd-2.0.0.tgz", @@ -5542,7 +5580,6 @@ "version": "1.0.1", "resolved": "https://registry.npmmirror.com/dunder-proto/-/dunder-proto-1.0.1.tgz", "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", - "dev": true, "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.1", @@ -5721,7 +5758,6 @@ "version": "1.0.1", "resolved": "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.1.tgz", "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -5731,7 +5767,6 @@ "version": "1.3.0", "resolved": "https://registry.npmmirror.com/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -5769,7 +5804,6 @@ "version": "1.1.1", "resolved": "https://registry.npmmirror.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz", "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", - "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0" @@ -5782,7 +5816,6 @@ "version": "2.1.0", "resolved": "https://registry.npmmirror.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", - "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -6717,6 +6750,26 @@ "integrity": "sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw==", "license": "MIT" }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/for-each": { "version": "0.3.5", "resolved": "https://registry.npmmirror.com/for-each/-/for-each-0.3.5.tgz", @@ -6733,6 +6786,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/form-data": { + "version": "4.0.4", + "resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fresh": { "version": "0.5.2", "resolved": "https://registry.npmmirror.com/fresh/-/fresh-0.5.2.tgz", @@ -6781,7 +6850,6 @@ "version": "1.1.2", "resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -6840,7 +6908,6 @@ "version": "1.3.0", "resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz", "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", - "dev": true, "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.2", @@ -6874,7 +6941,6 @@ "version": "1.0.1", "resolved": "https://registry.npmmirror.com/get-proto/-/get-proto-1.0.1.tgz", "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", - "dev": true, "license": "MIT", "dependencies": { "dunder-proto": "^1.0.1", @@ -7029,7 +7095,6 @@ "version": "1.2.0", "resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.2.0.tgz", "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -7106,7 +7171,6 @@ "version": "1.1.0", "resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.1.0.tgz", "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -7119,7 +7183,6 @@ "version": "1.0.2", "resolved": "https://registry.npmmirror.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz", "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "dev": true, "license": "MIT", "dependencies": { "has-symbols": "^1.0.3" @@ -7135,7 +7198,6 @@ "version": "2.0.2", "resolved": "https://registry.npmmirror.com/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, "license": "MIT", "dependencies": { "function-bind": "^1.1.2" @@ -9368,7 +9430,6 @@ "version": "1.1.0", "resolved": "https://registry.npmmirror.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz", "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -10624,6 +10685,12 @@ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", "license": "MIT" }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmmirror.com/punycode/-/punycode-2.3.1.tgz", diff --git a/package.json b/package.json index d1dc4b4..4d49da3 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "@react-navigation/stack": "^7.4.2", "@rneui/base": "^4.0.0-rc.8", "@rneui/themed": "^4.0.0-rc.8", + "axios": "^1.10.0", "react": "19.1.0", "react-native": "0.80.1", "react-native-gesture-handler": "^2.27.1", diff --git a/src/components/TaskCard.tsx b/src/components/TaskCard.tsx index 52a9b12..295056c 100644 --- a/src/components/TaskCard.tsx +++ b/src/components/TaskCard.tsx @@ -1,41 +1,42 @@ import React from 'react'; import { StyleSheet, TouchableOpacity, Dimensions } from 'react-native'; import { Card, Chip } from '@rneui/themed'; -import { Task, TaskStatus } from '../types/task'; +import { Task } from '../types/task'; interface TaskCardProps { task: Task; - onPress: (task: Task) => void; + onPress: (id: string) => void; } -const statusColors: Record = { - IDLE: 'grey', - RUNNING: 'blue', - COMPLETED: 'green', - ERROR: 'red', +const statusMap: { [key: number]: { text: string; color: string } } = { + 0: { text: 'IDLE', color: 'grey' }, + 1: { text: 'RUNNING', color: 'blue' }, + 2: { text: 'COMPLETED', color: 'green' }, + 3: { text: 'ERROR', color: 'red' }, }; const { width } = Dimensions.get('window'); const cardWidth = (width - 32) / 2; // 减去padding,除以2得到每个卡片的宽度 const TaskCard: React.FC = ({ task, onPress }) => { + const statusInfo = statusMap[task.status] || statusMap[0]; return ( - onPress(task)} style={styles.touchable}> + onPress(task.id)} style={styles.touchable}> - {task.name} + {task.label} diff --git a/src/components/TaskForm.tsx b/src/components/TaskForm.tsx index d787fdf..58567fb 100644 --- a/src/components/TaskForm.tsx +++ b/src/components/TaskForm.tsx @@ -1,7 +1,13 @@ import React, { useState, useRef, useEffect } from 'react'; -import { StyleSheet, ScrollView, TouchableOpacity, View } from 'react-native'; +import { + StyleSheet, + ScrollView, + TouchableOpacity, + View, + Text, +} from 'react-native'; import { Input, BottomSheet, ListItem, Button } from '@rneui/themed'; -import { Task, RobotAction } from '../types/task'; +import { Task, RobotAction, InputParam } from '../types/task'; import { useTasks } from '../context/TasksContext'; interface TaskFormProps { @@ -16,151 +22,24 @@ const TaskForm: React.FC = ({ task, onTaskChange }) => { const [currentItems, setCurrentItems] = useState< { label: string; value: string }[] >([]); - const [isQrInputFocused, setIsQrInputFocused] = useState(true); - // 创建隐藏的二维码扫描输入框的ref - const qrScanInputRef = useRef(null); - - // 用于防止循环更新的标志 - const isUpdatingFromQrRef = useRef(false); - const isUpdatingFromFormRef = useRef(false); - - // 组件挂载时自动聚焦到隐藏的扫描输入框 useEffect(() => { - const timer = setTimeout(() => { - if (qrScanInputRef.current) { - qrScanInputRef.current.focus(); - } - }, 100); - - return () => clearTimeout(timer); - }, []); - - // 解析二维码信息对象字面量格式 - const parseQrCodeInfo = (infoString: string): Partial => { - const result: Partial = {}; - - try { - // 移除花括号和换行符,准备解析 - let cleanString = infoString.trim(); - if (cleanString.startsWith('{')) { - cleanString = cleanString.substring(1); - } - if (cleanString.endsWith('}')) { - cleanString = cleanString.substring(0, cleanString.length - 1); - } - - // 按逗号分割各个属性 - const items = cleanString.split(','); - - for (const item of items) { - const trimmedItem = item.trim(); - if (!trimmedItem) continue; - - // 解析 "key: value" 格式 - const colonIndex = trimmedItem.indexOf(':'); - if (colonIndex === -1) continue; - - const key = trimmedItem.substring(0, colonIndex).trim(); - const value = trimmedItem.substring(colonIndex + 1).trim(); - - // 映射字段名 - switch (key) { - case 'startLocation': - result.startLocation = value; - break; - case 'endLocation': - result.endLocation = value; - break; - case 'waypoint': - result.waypoint = value; - break; - case 'robotAction': - result.robotAction = value as RobotAction; - break; - case 'payload': - result.payload = value; - break; - case 'locationBay': - result.locationBay = value; - break; - } - } - } catch (error) { - // 解析失败时不报错,返回空对象 - console.log('解析二维码信息失败:', error); - } - - return result; - }; - - // 处理二维码扫描输入,更新表单字段 - const handleQrCodeScan = (scanData: string) => { - if (isUpdatingFromFormRef.current || !scanData.trim()) return; - - isUpdatingFromQrRef.current = true; - const parsedParams = parseQrCodeInfo(scanData); - - const updatedTask = { - ...task, - parameters: { - ...task.parameters, - ...parsedParams, - }, - }; - - onTaskChange(updatedTask); - - // 清空扫描输入框 - if (qrScanInputRef.current) { - qrScanInputRef.current.clear(); - } - - // 重置标志 - setTimeout(() => { - isUpdatingFromQrRef.current = false; - }, 0); - }; - - // 重新扫描按钮点击处理 - const handleRescan = () => { - if (qrScanInputRef.current) { - qrScanInputRef.current.focus(); - } - }; - - // 处理其他输入框获得焦点 - const handleOtherInputFocus = () => { - setIsQrInputFocused(false); - }; - - // 处理二维码输入框焦点事件 - const handleQrInputFocus = () => { - setIsQrInputFocused(true); - }; - - const handleQrInputBlur = () => { - setIsQrInputFocused(false); - }; + console.log('TaskForm task prop updated:', task); + }, [task]); const handleParamChange = (field: string, value: string | RobotAction) => { - if (isUpdatingFromQrRef.current) return; - - isUpdatingFromFormRef.current = true; - + const currentParam = task.parameters[field] || {}; const updatedTask = { ...task, parameters: { ...task.parameters, - [field]: value, + [field]: { + ...currentParam, + value: value, + }, }, }; onTaskChange(updatedTask); - - // 重置标志 - setTimeout(() => { - isUpdatingFromFormRef.current = false; - }, 0); }; const openBottomSheet = ( @@ -188,83 +67,48 @@ const TaskForm: React.FC = ({ task, onTaskChange }) => { ); + const renderFormInput = (param: InputParam) => { + const parameter = task.parameters?.[param.name]; + const value = parameter?.value || param.defaultValue; + + switch (param.type) { + case 'String': + case 'STRING': // + return ( + handleParamChange(param.name, text)} + placeholder={param.remark} + /> + ); + default: + return ( + handleParamChange(param.name, text)} + placeholder={param.remark} + /> + ); + } + }; + return ( - {/* 隐藏的二维码扫描输入框 */} - - - {/* 扫描二维码按钮 */} - -