我的界面 修改昵称完成
This commit is contained in:
220
android/.kotlin/errors/errors-1772609249618.log
Normal file
220
android/.kotlin/errors/errors-1772609249618.log
Normal file
@@ -0,0 +1,220 @@
|
|||||||
|
kotlin version: 2.2.20
|
||||||
|
error message: Daemon compilation failed: null
|
||||||
|
java.lang.Exception
|
||||||
|
at org.jetbrains.kotlin.daemon.common.CompileService$CallResult$Error.get(CompileService.kt:69)
|
||||||
|
at org.jetbrains.kotlin.daemon.common.CompileService$CallResult$Error.get(CompileService.kt:65)
|
||||||
|
at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.compileWithDaemon(GradleKotlinCompilerWork.kt:240)
|
||||||
|
at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.compileWithDaemonOrFallbackImpl(GradleKotlinCompilerWork.kt:159)
|
||||||
|
at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.run(GradleKotlinCompilerWork.kt:111)
|
||||||
|
at org.jetbrains.kotlin.compilerRunner.GradleCompilerRunnerWithWorkers$GradleKotlinCompilerWorkAction.execute(GradleCompilerRunnerWithWorkers.kt:74)
|
||||||
|
at org.gradle.workers.internal.DefaultWorkerServer.execute(DefaultWorkerServer.java:63)
|
||||||
|
at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:66)
|
||||||
|
at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:62)
|
||||||
|
at org.gradle.internal.classloader.ClassLoaderUtils.executeInClassloader(ClassLoaderUtils.java:100)
|
||||||
|
at org.gradle.workers.internal.NoIsolationWorkerFactory$1.lambda$execute$0(NoIsolationWorkerFactory.java:62)
|
||||||
|
at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:44)
|
||||||
|
at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:41)
|
||||||
|
at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:210)
|
||||||
|
at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:205)
|
||||||
|
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:67)
|
||||||
|
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:60)
|
||||||
|
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:167)
|
||||||
|
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:60)
|
||||||
|
at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:54)
|
||||||
|
at org.gradle.workers.internal.AbstractWorker.executeWrappedInBuildOperation(AbstractWorker.java:41)
|
||||||
|
at org.gradle.workers.internal.NoIsolationWorkerFactory$1.execute(NoIsolationWorkerFactory.java:59)
|
||||||
|
at org.gradle.workers.internal.DefaultWorkerExecutor.lambda$submitWork$0(DefaultWorkerExecutor.java:174)
|
||||||
|
at java.base/java.util.concurrent.FutureTask.run(Unknown Source)
|
||||||
|
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runExecution(DefaultConditionalExecutionQueue.java:194)
|
||||||
|
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.access$700(DefaultConditionalExecutionQueue.java:127)
|
||||||
|
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner$1.run(DefaultConditionalExecutionQueue.java:169)
|
||||||
|
at org.gradle.internal.Factories$1.create(Factories.java:31)
|
||||||
|
at org.gradle.internal.work.DefaultWorkerLeaseService.withLocks(DefaultWorkerLeaseService.java:263)
|
||||||
|
at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:127)
|
||||||
|
at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:132)
|
||||||
|
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runBatch(DefaultConditionalExecutionQueue.java:164)
|
||||||
|
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.run(DefaultConditionalExecutionQueue.java:133)
|
||||||
|
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
|
||||||
|
at java.base/java.util.concurrent.FutureTask.run(Unknown Source)
|
||||||
|
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
|
||||||
|
at org.gradle.internal.concurrent.AbstractManagedExecutor$1.run(AbstractManagedExecutor.java:48)
|
||||||
|
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
|
||||||
|
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
|
||||||
|
at java.base/java.lang.Thread.run(Unknown Source)
|
||||||
|
Caused by: java.lang.AssertionError: java.lang.Exception: Could not close incremental caches in D:\code\FlutterApp\build\mobile_scanner\kotlin\compileDebugKotlin\cacheable\caches-jvm\jvm\kotlin: class-fq-name-to-source.tab, source-to-typealias-fq-name.tab, source-to-classes.tab, internal-name-to-source.tab
|
||||||
|
at org.jetbrains.kotlin.com.google.common.io.Closer.close(Closer.java:218)
|
||||||
|
at org.jetbrains.kotlin.incremental.IncrementalCachesManager.close(IncrementalCachesManager.kt:55)
|
||||||
|
at kotlin.io.CloseableKt.closeFinally(Closeable.kt:46)
|
||||||
|
at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileNonIncrementally(IncrementalCompilerRunner.kt:293)
|
||||||
|
at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:128)
|
||||||
|
at org.jetbrains.kotlin.daemon.CompileServiceImplBase.execIncrementalCompiler(CompileServiceImpl.kt:684)
|
||||||
|
at org.jetbrains.kotlin.daemon.CompileServiceImplBase.access$execIncrementalCompiler(CompileServiceImpl.kt:94)
|
||||||
|
at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1810)
|
||||||
|
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source)
|
||||||
|
at java.base/java.lang.reflect.Method.invoke(Unknown Source)
|
||||||
|
at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(Unknown Source)
|
||||||
|
at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source)
|
||||||
|
at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source)
|
||||||
|
at java.base/java.security.AccessController.doPrivileged(Unknown Source)
|
||||||
|
at java.rmi/sun.rmi.transport.Transport.serviceCall(Unknown Source)
|
||||||
|
at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source)
|
||||||
|
at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source)
|
||||||
|
at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(Unknown Source)
|
||||||
|
at java.base/java.security.AccessController.doPrivileged(Unknown Source)
|
||||||
|
at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source)
|
||||||
|
... 3 more
|
||||||
|
Caused by: java.lang.Exception: Could not close incremental caches in D:\code\FlutterApp\build\mobile_scanner\kotlin\compileDebugKotlin\cacheable\caches-jvm\jvm\kotlin: class-fq-name-to-source.tab, source-to-typealias-fq-name.tab, source-to-classes.tab, internal-name-to-source.tab
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.BasicMapsOwner.forEachMapSafe(BasicMapsOwner.kt:95)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.BasicMapsOwner.close(BasicMapsOwner.kt:53)
|
||||||
|
at org.jetbrains.kotlin.com.google.common.io.Closer.close(Closer.java:205)
|
||||||
|
... 22 more
|
||||||
|
Suppressed: java.lang.IllegalArgumentException: this and base files have different roots: C:\Users\15563\AppData\Local\Pub\Cache\hosted\pub.flutter-io.cn\mobile_scanner-3.5.7\android\src\main\kotlin\dev\steenbakker\mobile_scanner\BarcodeHandler.kt and D:\code\FlutterApp\android.
|
||||||
|
at kotlin.io.FilesKt__UtilsKt.toRelativeString(Utils.kt:117)
|
||||||
|
at kotlin.io.FilesKt__UtilsKt.relativeTo(Utils.kt:128)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.RelocatableFileToPathConverter.toPath(RelocatableFileToPathConverter.kt:24)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.FileDescriptor.save(FileToPathConverter.kt:33)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.FileDescriptor.save(FileToPathConverter.kt:30)
|
||||||
|
at org.jetbrains.kotlin.com.intellij.util.io.PersistentMapImpl.doPut(PersistentMapImpl.java:447)
|
||||||
|
at org.jetbrains.kotlin.com.intellij.util.io.PersistentMapImpl.put(PersistentMapImpl.java:426)
|
||||||
|
at org.jetbrains.kotlin.com.intellij.util.io.PersistentHashMap.put(PersistentHashMap.java:106)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.LazyStorage.set(LazyStorage.kt:80)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.InMemoryStorage.applyChanges(InMemoryStorage.kt:108)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.InMemoryStorage.close(InMemoryStorage.kt:136)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.PersistentStorageWrapper.close(PersistentStorage.kt:124)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.BasicMapsOwner$close$1.invoke(BasicMapsOwner.kt:53)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.BasicMapsOwner$close$1.invoke(BasicMapsOwner.kt:53)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.BasicMapsOwner.forEachMapSafe(BasicMapsOwner.kt:87)
|
||||||
|
... 24 more
|
||||||
|
Suppressed: java.lang.IllegalArgumentException: this and base files have different roots: C:\Users\15563\AppData\Local\Pub\Cache\hosted\pub.flutter-io.cn\mobile_scanner-3.5.7\android\src\main\kotlin\dev\steenbakker\mobile_scanner\MobileScannerCallbacks.kt and D:\code\FlutterApp\android.
|
||||||
|
at kotlin.io.FilesKt__UtilsKt.toRelativeString(Utils.kt:117)
|
||||||
|
at kotlin.io.FilesKt__UtilsKt.relativeTo(Utils.kt:128)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.RelocatableFileToPathConverter.toPath(RelocatableFileToPathConverter.kt:24)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.FileDescriptor.getHashCode(FileToPathConverter.kt:50)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.FileDescriptor.getHashCode(FileToPathConverter.kt:30)
|
||||||
|
at org.jetbrains.kotlin.com.intellij.util.containers.LinkedCustomHashMap.hashKey(LinkedCustomHashMap.java:109)
|
||||||
|
at org.jetbrains.kotlin.com.intellij.util.containers.LinkedCustomHashMap.remove(LinkedCustomHashMap.java:153)
|
||||||
|
at org.jetbrains.kotlin.com.intellij.util.containers.SLRUMap.remove(SLRUMap.java:89)
|
||||||
|
at org.jetbrains.kotlin.com.intellij.util.io.PersistentMapImpl.flushAppendCache(PersistentMapImpl.java:1007)
|
||||||
|
at org.jetbrains.kotlin.com.intellij.util.io.PersistentMapImpl.doPut(PersistentMapImpl.java:455)
|
||||||
|
at org.jetbrains.kotlin.com.intellij.util.io.PersistentMapImpl.put(PersistentMapImpl.java:426)
|
||||||
|
at org.jetbrains.kotlin.com.intellij.util.io.PersistentHashMap.put(PersistentHashMap.java:106)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.LazyStorage.set(LazyStorage.kt:80)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.InMemoryStorage.applyChanges(InMemoryStorage.kt:108)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.AppendableInMemoryStorage.applyChanges(InMemoryStorage.kt:179)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.InMemoryStorage.close(InMemoryStorage.kt:136)
|
||||||
|
at org.jetbrains.kotlin.incremental.AbstractIncrementalCache$SourceToTypealiasFqNameTwoWayMap.close(AbstractIncrementalCache.kt:297)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.BasicMapsOwner$close$1.invoke(BasicMapsOwner.kt:53)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.BasicMapsOwner$close$1.invoke(BasicMapsOwner.kt:53)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.BasicMapsOwner.forEachMapSafe(BasicMapsOwner.kt:87)
|
||||||
|
... 24 more
|
||||||
|
Suppressed: java.lang.IllegalArgumentException: this and base files have different roots: C:\Users\15563\AppData\Local\Pub\Cache\hosted\pub.flutter-io.cn\mobile_scanner-3.5.7\android\src\main\kotlin\dev\steenbakker\mobile_scanner\BarcodeHandler.kt and D:\code\FlutterApp\android.
|
||||||
|
at kotlin.io.FilesKt__UtilsKt.toRelativeString(Utils.kt:117)
|
||||||
|
at kotlin.io.FilesKt__UtilsKt.relativeTo(Utils.kt:128)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.RelocatableFileToPathConverter.toPath(RelocatableFileToPathConverter.kt:24)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.FileDescriptor.getHashCode(FileToPathConverter.kt:50)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.FileDescriptor.getHashCode(FileToPathConverter.kt:30)
|
||||||
|
at org.jetbrains.kotlin.com.intellij.util.containers.LinkedCustomHashMap.hashKey(LinkedCustomHashMap.java:109)
|
||||||
|
at org.jetbrains.kotlin.com.intellij.util.containers.LinkedCustomHashMap.remove(LinkedCustomHashMap.java:153)
|
||||||
|
at org.jetbrains.kotlin.com.intellij.util.containers.SLRUMap.remove(SLRUMap.java:89)
|
||||||
|
at org.jetbrains.kotlin.com.intellij.util.io.PersistentMapImpl.flushAppendCache(PersistentMapImpl.java:1007)
|
||||||
|
at org.jetbrains.kotlin.com.intellij.util.io.PersistentMapImpl.doPut(PersistentMapImpl.java:455)
|
||||||
|
at org.jetbrains.kotlin.com.intellij.util.io.PersistentMapImpl.put(PersistentMapImpl.java:426)
|
||||||
|
at org.jetbrains.kotlin.com.intellij.util.io.PersistentHashMap.put(PersistentHashMap.java:106)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.LazyStorage.set(LazyStorage.kt:80)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.InMemoryStorage.applyChanges(InMemoryStorage.kt:108)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.AppendableInMemoryStorage.applyChanges(InMemoryStorage.kt:179)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.InMemoryStorage.close(InMemoryStorage.kt:136)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.AppendableSetBasicMap.close(BasicMap.kt:157)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.BasicMapsOwner$close$1.invoke(BasicMapsOwner.kt:53)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.BasicMapsOwner$close$1.invoke(BasicMapsOwner.kt:53)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.BasicMapsOwner.forEachMapSafe(BasicMapsOwner.kt:87)
|
||||||
|
... 24 more
|
||||||
|
Suppressed: java.lang.IllegalArgumentException: this and base files have different roots: C:\Users\15563\AppData\Local\Pub\Cache\hosted\pub.flutter-io.cn\mobile_scanner-3.5.7\android\src\main\kotlin\dev\steenbakker\mobile_scanner\BarcodeHandler.kt and D:\code\FlutterApp\android.
|
||||||
|
at kotlin.io.FilesKt__UtilsKt.toRelativeString(Utils.kt:117)
|
||||||
|
at kotlin.io.FilesKt__UtilsKt.relativeTo(Utils.kt:128)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.RelocatableFileToPathConverter.toPath(RelocatableFileToPathConverter.kt:24)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.FileDescriptor.save(FileToPathConverter.kt:33)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.FileDescriptor.save(FileToPathConverter.kt:30)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.AppendableCollectionExternalizer.save(LazyStorage.kt:151)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.AppendableCollectionExternalizer.save(LazyStorage.kt:142)
|
||||||
|
at org.jetbrains.kotlin.com.intellij.util.io.PersistentMapImpl.doPut(PersistentMapImpl.java:447)
|
||||||
|
at org.jetbrains.kotlin.com.intellij.util.io.PersistentMapImpl.put(PersistentMapImpl.java:426)
|
||||||
|
at org.jetbrains.kotlin.com.intellij.util.io.PersistentHashMap.put(PersistentHashMap.java:106)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.LazyStorage.set(LazyStorage.kt:80)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.InMemoryStorage.applyChanges(InMemoryStorage.kt:108)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.AppendableInMemoryStorage.applyChanges(InMemoryStorage.kt:179)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.InMemoryStorage.close(InMemoryStorage.kt:136)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.PersistentStorageWrapper.close(PersistentStorage.kt:124)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.BasicMapsOwner$close$1.invoke(BasicMapsOwner.kt:53)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.BasicMapsOwner$close$1.invoke(BasicMapsOwner.kt:53)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.BasicMapsOwner.forEachMapSafe(BasicMapsOwner.kt:87)
|
||||||
|
... 24 more
|
||||||
|
Suppressed: java.lang.Exception: Could not close incremental caches in D:\code\FlutterApp\build\mobile_scanner\kotlin\compileDebugKotlin\cacheable\caches-jvm\lookups: id-to-file.tab, file-to-id.tab
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.BasicMapsOwner.forEachMapSafe(BasicMapsOwner.kt:95)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.BasicMapsOwner.close(BasicMapsOwner.kt:53)
|
||||||
|
at org.jetbrains.kotlin.incremental.LookupStorage.close(LookupStorage.kt:155)
|
||||||
|
... 23 more
|
||||||
|
Suppressed: java.lang.IllegalArgumentException: this and base files have different roots: C:\Users\15563\AppData\Local\Pub\Cache\hosted\pub.flutter-io.cn\mobile_scanner-3.5.7\android\src\main\kotlin\dev\steenbakker\mobile_scanner\BarcodeHandler.kt and D:\code\FlutterApp\android.
|
||||||
|
at kotlin.io.FilesKt__UtilsKt.toRelativeString(Utils.kt:117)
|
||||||
|
at kotlin.io.FilesKt__UtilsKt.relativeTo(Utils.kt:128)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.RelocatableFileToPathConverter.toPath(RelocatableFileToPathConverter.kt:24)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.LegacyFileExternalizer.save(IdToFileMap.kt:51)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.LegacyFileExternalizer.save(IdToFileMap.kt:48)
|
||||||
|
at org.jetbrains.kotlin.com.intellij.util.io.PersistentMapImpl.doPut(PersistentMapImpl.java:447)
|
||||||
|
at org.jetbrains.kotlin.com.intellij.util.io.PersistentMapImpl.put(PersistentMapImpl.java:426)
|
||||||
|
at org.jetbrains.kotlin.com.intellij.util.io.PersistentHashMap.put(PersistentHashMap.java:106)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.LazyStorage.set(LazyStorage.kt:80)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.InMemoryStorage.applyChanges(InMemoryStorage.kt:108)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.InMemoryStorage.close(InMemoryStorage.kt:136)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.PersistentStorageWrapper.close(PersistentStorage.kt:124)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.BasicMapsOwner$close$1.invoke(BasicMapsOwner.kt:53)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.BasicMapsOwner$close$1.invoke(BasicMapsOwner.kt:53)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.BasicMapsOwner.forEachMapSafe(BasicMapsOwner.kt:87)
|
||||||
|
... 25 more
|
||||||
|
Suppressed: java.lang.IllegalArgumentException: this and base files have different roots: C:\Users\15563\AppData\Local\Pub\Cache\hosted\pub.flutter-io.cn\mobile_scanner-3.5.7\android\src\main\kotlin\dev\steenbakker\mobile_scanner\BarcodeHandler.kt and D:\code\FlutterApp\android.
|
||||||
|
at kotlin.io.FilesKt__UtilsKt.toRelativeString(Utils.kt:117)
|
||||||
|
at kotlin.io.FilesKt__UtilsKt.relativeTo(Utils.kt:128)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.RelocatableFileToPathConverter.toPath(RelocatableFileToPathConverter.kt:24)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.FileDescriptor.getHashCode(FileToPathConverter.kt:50)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.FileDescriptor.getHashCode(FileToPathConverter.kt:30)
|
||||||
|
at org.jetbrains.kotlin.com.intellij.util.containers.LinkedCustomHashMap.hashKey(LinkedCustomHashMap.java:109)
|
||||||
|
at org.jetbrains.kotlin.com.intellij.util.containers.LinkedCustomHashMap.remove(LinkedCustomHashMap.java:153)
|
||||||
|
at org.jetbrains.kotlin.com.intellij.util.containers.SLRUMap.remove(SLRUMap.java:89)
|
||||||
|
at org.jetbrains.kotlin.com.intellij.util.io.PersistentMapImpl.flushAppendCache(PersistentMapImpl.java:1007)
|
||||||
|
at org.jetbrains.kotlin.com.intellij.util.io.PersistentMapImpl.doPut(PersistentMapImpl.java:455)
|
||||||
|
at org.jetbrains.kotlin.com.intellij.util.io.PersistentMapImpl.put(PersistentMapImpl.java:426)
|
||||||
|
at org.jetbrains.kotlin.com.intellij.util.io.PersistentHashMap.put(PersistentHashMap.java:106)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.LazyStorage.set(LazyStorage.kt:80)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.InMemoryStorage.applyChanges(InMemoryStorage.kt:108)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.InMemoryStorage.close(InMemoryStorage.kt:136)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.PersistentStorageWrapper.close(PersistentStorage.kt:124)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.BasicMapsOwner$close$1.invoke(BasicMapsOwner.kt:53)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.BasicMapsOwner$close$1.invoke(BasicMapsOwner.kt:53)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.BasicMapsOwner.forEachMapSafe(BasicMapsOwner.kt:87)
|
||||||
|
... 25 more
|
||||||
|
Suppressed: java.lang.Exception: Could not close incremental caches in D:\code\FlutterApp\build\mobile_scanner\kotlin\compileDebugKotlin\cacheable\caches-jvm\inputs: source-to-output.tab
|
||||||
|
... 25 more
|
||||||
|
Suppressed: java.lang.IllegalArgumentException: this and base files have different roots: C:\Users\15563\AppData\Local\Pub\Cache\hosted\pub.flutter-io.cn\mobile_scanner-3.5.7\android\src\main\kotlin\dev\steenbakker\mobile_scanner\BarcodeHandler.kt and D:\code\FlutterApp\android.
|
||||||
|
at kotlin.io.FilesKt__UtilsKt.toRelativeString(Utils.kt:117)
|
||||||
|
at kotlin.io.FilesKt__UtilsKt.relativeTo(Utils.kt:128)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.RelocatableFileToPathConverter.toPath(RelocatableFileToPathConverter.kt:24)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.FileDescriptor.getHashCode(FileToPathConverter.kt:50)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.FileDescriptor.getHashCode(FileToPathConverter.kt:30)
|
||||||
|
at org.jetbrains.kotlin.com.intellij.util.containers.LinkedCustomHashMap.hashKey(LinkedCustomHashMap.java:109)
|
||||||
|
at org.jetbrains.kotlin.com.intellij.util.containers.LinkedCustomHashMap.remove(LinkedCustomHashMap.java:153)
|
||||||
|
at org.jetbrains.kotlin.com.intellij.util.containers.SLRUMap.remove(SLRUMap.java:89)
|
||||||
|
at org.jetbrains.kotlin.com.intellij.util.io.PersistentMapImpl.flushAppendCache(PersistentMapImpl.java:1007)
|
||||||
|
at org.jetbrains.kotlin.com.intellij.util.io.PersistentMapImpl.doPut(PersistentMapImpl.java:455)
|
||||||
|
at org.jetbrains.kotlin.com.intellij.util.io.PersistentMapImpl.put(PersistentMapImpl.java:426)
|
||||||
|
at org.jetbrains.kotlin.com.intellij.util.io.PersistentHashMap.put(PersistentHashMap.java:106)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.LazyStorage.set(LazyStorage.kt:80)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.InMemoryStorage.applyChanges(InMemoryStorage.kt:108)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.AppendableInMemoryStorage.applyChanges(InMemoryStorage.kt:179)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.InMemoryStorage.close(InMemoryStorage.kt:136)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.AppendableSetBasicMap.close(BasicMap.kt:157)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.BasicMapsOwner$close$1.invoke(BasicMapsOwner.kt:53)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.BasicMapsOwner$close$1.invoke(BasicMapsOwner.kt:53)
|
||||||
|
at org.jetbrains.kotlin.incremental.storage.BasicMapsOwner.forEachMapSafe(BasicMapsOwner.kt:87)
|
||||||
|
... 24 more
|
||||||
|
|
||||||
|
|
||||||
@@ -11,6 +11,10 @@ import 'package:maibu_satabot_v2/features/devices/domain/usecases/select_work_re
|
|||||||
import 'package:maibu_satabot_v2/features/devices/domain/usecases/unbind_device_usecase.dart';
|
import 'package:maibu_satabot_v2/features/devices/domain/usecases/unbind_device_usecase.dart';
|
||||||
import 'package:maibu_satabot_v2/features/devices/domain/usecases/update_devicename_usecase.dart';
|
import 'package:maibu_satabot_v2/features/devices/domain/usecases/update_devicename_usecase.dart';
|
||||||
import 'package:maibu_satabot_v2/features/devices/presentation/bloc/devices_cubit.dart';
|
import 'package:maibu_satabot_v2/features/devices/presentation/bloc/devices_cubit.dart';
|
||||||
|
import 'package:maibu_satabot_v2/features/my/presentation/bloc/my_cubit.dart';
|
||||||
|
import 'package:maibu_satabot_v2/features/my/repository/my_repository.dart';
|
||||||
|
import 'package:maibu_satabot_v2/features/my/repository/my_repository_impl.dart';
|
||||||
|
import 'package:maibu_satabot_v2/features/my/usecases/updatename_usecase.dart';
|
||||||
import 'package:maibu_satabot_v2/features/remote_control/data/repositories/remote_control_repository_impl.dart';
|
import 'package:maibu_satabot_v2/features/remote_control/data/repositories/remote_control_repository_impl.dart';
|
||||||
import 'package:maibu_satabot_v2/features/remote_control/domain/repositories/remote_control_repository.dart';
|
import 'package:maibu_satabot_v2/features/remote_control/domain/repositories/remote_control_repository.dart';
|
||||||
import 'package:maibu_satabot_v2/features/remote_control/domain/usecase/diff_steer_usecase.dart';
|
import 'package:maibu_satabot_v2/features/remote_control/domain/usecase/diff_steer_usecase.dart';
|
||||||
@@ -64,9 +68,9 @@ Future<void> init() async {
|
|||||||
sl.registerLazySingleton<Dio>(() => DioClient.create());
|
sl.registerLazySingleton<Dio>(() => DioClient.create());
|
||||||
|
|
||||||
/// 1.1.2 TcpClient:TCP客户端
|
/// 1.1.2 TcpClient:TCP客户端
|
||||||
sl.registerLazySingleton(() => TcpClient( sl<UserStorage>(),
|
sl.registerLazySingleton(
|
||||||
getUserDeviceUseCase: sl<GetUserDeviceUseCase>(),
|
() => TcpClient(sl<UserStorage>(), getUserDeviceUseCase: sl<GetUserDeviceUseCase>(), switchDeviceUseCase: sl<SwitchDeviceUseCase>()),
|
||||||
switchDeviceUseCase: sl<SwitchDeviceUseCase>(),));
|
);
|
||||||
|
|
||||||
/// 1.1.3 NetMessageDispatcher:消息调度器,并将 TcpClient 注入给它
|
/// 1.1.3 NetMessageDispatcher:消息调度器,并将 TcpClient 注入给它
|
||||||
sl.registerLazySingleton(() => NetMessageDispatcher(sl()));
|
sl.registerLazySingleton(() => NetMessageDispatcher(sl()));
|
||||||
@@ -86,11 +90,9 @@ Future<void> init() async {
|
|||||||
sl.registerLazySingleton<ILoggerService>(() => SentryLoggerImpl());
|
sl.registerLazySingleton<ILoggerService>(() => SentryLoggerImpl());
|
||||||
|
|
||||||
/// 2. 数据源 (DataSource)
|
/// 2. 数据源 (DataSource)
|
||||||
sl.registerLazySingleton<AuthHttpDataSource>(
|
sl.registerLazySingleton<AuthHttpDataSource>(() => AuthHttpDataSourceImpl(sl()));
|
||||||
() => AuthHttpDataSourceImpl(sl()),
|
|
||||||
);
|
|
||||||
sl.registerLazySingleton<DeviceHttpDatasource>(
|
sl.registerLazySingleton<DeviceHttpDatasource>(
|
||||||
() => DeviceHttpDatasourceImpl(sl(), sl<UserStorage>()), //
|
() => DeviceHttpDatasourceImpl(sl(), sl<UserStorage>()), //
|
||||||
);
|
);
|
||||||
|
|
||||||
/// 3. 仓库 (Repository)
|
/// 3. 仓库 (Repository)
|
||||||
@@ -101,16 +103,32 @@ Future<void> init() async {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// 1. 注册 UpdateNameUsecase
|
||||||
|
sl.registerLazySingleton<UpdateNameUsecase>(
|
||||||
|
() => UpdateNameUsecase(sl<MyRepository>()), // 注入 MyRepository 实例
|
||||||
|
);
|
||||||
|
sl.registerLazySingleton<MyRepository>(
|
||||||
|
() => MyRepositoryImpl(
|
||||||
|
userStorage: sl<UserStorage>(), // 注入 UserStorage
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
// 2. 注册 MyCubit
|
||||||
|
sl.registerLazySingleton<MyCubit>(
|
||||||
|
() => MyCubit(
|
||||||
|
sl<MyRepository>(), // 注入仓库
|
||||||
|
sl<UpdateNameUsecase>(), // 注入 UseCase
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
sl.registerLazySingleton<RoutePlanningRepository>(
|
sl.registerLazySingleton<RoutePlanningRepository>(
|
||||||
() => RoutePlanningRepositoryImpl(tcp: sl<TcpClient>()), //
|
() => RoutePlanningRepositoryImpl(tcp: sl<TcpClient>()), //
|
||||||
);
|
);
|
||||||
|
|
||||||
sl.registerLazySingleton<RoutePlanningUseCase>(
|
sl.registerLazySingleton<RoutePlanningUseCase>(
|
||||||
() => RoutePlanningUseCase(sl<RoutePlanningRepository>()), //
|
() => RoutePlanningUseCase(sl<RoutePlanningRepository>()), //
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//工作历史
|
//工作历史
|
||||||
sl.registerLazySingleton<DeviceHostrityWorkRepositoryRepository>(
|
sl.registerLazySingleton<DeviceHostrityWorkRepositoryRepository>(
|
||||||
() => DeviceHostrityWorkRepositoryImpl(
|
() => DeviceHostrityWorkRepositoryImpl(
|
||||||
@@ -120,9 +138,7 @@ Future<void> init() async {
|
|||||||
);
|
);
|
||||||
|
|
||||||
sl.registerLazySingleton<DeviceRepository>(() => DeviceRepositoryImpl(sl()));
|
sl.registerLazySingleton<DeviceRepository>(() => DeviceRepositoryImpl(sl()));
|
||||||
sl.registerLazySingleton<RemoteControlRepository>(
|
sl.registerLazySingleton<RemoteControlRepository>(() => RemoteControlRepositoryImpl(sl(), sl()));
|
||||||
() => RemoteControlRepositoryImpl(sl(), sl()),
|
|
||||||
);
|
|
||||||
|
|
||||||
/// 4. 用例 (UseCase)
|
/// 4. 用例 (UseCase)
|
||||||
sl.registerLazySingleton(() => LoginUseCase(sl()));
|
sl.registerLazySingleton(() => LoginUseCase(sl()));
|
||||||
@@ -137,7 +153,7 @@ Future<void> init() async {
|
|||||||
sl.registerLazySingleton<SwitchDeviceUseCase>(() => SwitchDeviceUseCase(sl()));
|
sl.registerLazySingleton<SwitchDeviceUseCase>(() => SwitchDeviceUseCase(sl()));
|
||||||
|
|
||||||
sl.registerLazySingleton<AuthTcpDatasource>(
|
sl.registerLazySingleton<AuthTcpDatasource>(
|
||||||
() => AuthTcpDatasourceImpl(
|
() => AuthTcpDatasourceImpl(
|
||||||
sl<TcpClient>(),
|
sl<TcpClient>(),
|
||||||
sl<UserStorage>(),
|
sl<UserStorage>(),
|
||||||
getUserDeviceUseCase: sl<GetUserDeviceUseCase>(),
|
getUserDeviceUseCase: sl<GetUserDeviceUseCase>(),
|
||||||
@@ -145,15 +161,12 @@ Future<void> init() async {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
/// 5. 状态管理 (Cubit/Bloc)
|
/// 5. 状态管理 (Cubit/Bloc)
|
||||||
sl.registerLazySingleton(() => AppUserCubit()); // AuthCubit 依赖它,必须先注册
|
sl.registerLazySingleton(() => AppUserCubit()); // AuthCubit 依赖它,必须先注册
|
||||||
sl.registerLazySingleton(() => GetDeviceLocationUseCase(sl()));
|
sl.registerLazySingleton(() => GetDeviceLocationUseCase(sl()));
|
||||||
sl.registerLazySingleton(
|
sl.registerLazySingleton(() => DevicesCubit(sl(), sl(), sl(), sl(), sl(), sl(), sl(), sl(), sl(), sl(), sl(), sl()));
|
||||||
() => DevicesCubit(sl(), sl(), sl(), sl(), sl(), sl(), sl(), sl(), sl(),sl(),sl(), sl()),
|
|
||||||
);
|
|
||||||
sl.registerFactory(() => RemoteControlCubit(sl()));
|
sl.registerFactory(() => RemoteControlCubit(sl()));
|
||||||
/* // 工厂模式(留存,每次获取新实例)
|
/* // 工厂模式(留存,每次获取新实例)
|
||||||
sl.registerFactory(() => DeviceStatusBloc(sl<NetMessageDispatcher>()));
|
sl.registerFactory(() => DeviceStatusBloc(sl<NetMessageDispatcher>()));
|
||||||
*/
|
*/
|
||||||
//单例模式(全局共享一个实例)
|
//单例模式(全局共享一个实例)
|
||||||
@@ -161,16 +174,13 @@ Future<void> init() async {
|
|||||||
|
|
||||||
/// . 路径生成
|
/// . 路径生成
|
||||||
sl.registerLazySingleton<PathHttpDatasource>(
|
sl.registerLazySingleton<PathHttpDatasource>(
|
||||||
() => PathHttpDatasourceImpl(// 需先注册 http.Client(见下方)
|
() => PathHttpDatasourceImpl(
|
||||||
|
// 需先注册 http.Client(见下方)
|
||||||
sl<UserStorage>(),
|
sl<UserStorage>(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
sl.registerLazySingleton<PathRepository>(
|
sl.registerLazySingleton<PathRepository>(() => PathRepositoryImpl(datasource: sl<PathHttpDatasource>()));
|
||||||
() => PathRepositoryImpl(datasource: sl<PathHttpDatasource>()),
|
sl.registerLazySingleton<GeneratePathUseCase>(() => GeneratePathUseCaseImpl(sl<PathRepository>()));
|
||||||
);
|
|
||||||
sl.registerLazySingleton<GeneratePathUseCase>(
|
|
||||||
() => GeneratePathUseCaseImpl(sl<PathRepository>()),
|
|
||||||
);
|
|
||||||
|
|
||||||
///.路径获取和删除
|
///.路径获取和删除
|
||||||
sl.registerLazySingleton(() => GetWorkRecordUseCase(sl<PathRepository>()));
|
sl.registerLazySingleton(() => GetWorkRecordUseCase(sl<PathRepository>()));
|
||||||
@@ -178,15 +188,7 @@ Future<void> init() async {
|
|||||||
|
|
||||||
/// 6. 认证 (Auth)
|
/// 6. 认证 (Auth)
|
||||||
// --- 关键修改点 1: AuthCubit 必须在 GoRouter 之前注册,并传入参数 ---
|
// --- 关键修改点 1: AuthCubit 必须在 GoRouter 之前注册,并传入参数 ---
|
||||||
sl.registerLazySingleton(
|
sl.registerLazySingleton(() => AuthCubit(sl<UserStorage>(), sl<TcpClient>(), sl<AppUserCubit>(), sl<NetMessageDispatcher>(), sl<AuthTcpDatasource>()));
|
||||||
() => AuthCubit(
|
|
||||||
sl<UserStorage>(),
|
|
||||||
sl<TcpClient>(),
|
|
||||||
sl<AppUserCubit>(),
|
|
||||||
sl<NetMessageDispatcher>(),
|
|
||||||
sl<AuthTcpDatasource>(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
/// 7. 路由 (Router)
|
/// 7. 路由 (Router)
|
||||||
sl.registerSingleton<GoRouter>(createRouter(sl<AuthCubit>()));
|
sl.registerSingleton<GoRouter>(createRouter(sl<AuthCubit>()));
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ class UserStorageImpl implements UserStorage {
|
|||||||
Future<void> deleteUser() async {
|
Future<void> deleteUser() async {
|
||||||
await _prefs.remove(_userKey);
|
await _prefs.remove(_userKey);
|
||||||
//返回登陆页面
|
//返回登陆页面
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -5,4 +5,5 @@ abstract class UserStorage {
|
|||||||
Future<UserEntity?> getUser();
|
Future<UserEntity?> getUser();
|
||||||
Future<void> deleteUser();
|
Future<void> deleteUser();
|
||||||
Future<bool> hasUser();
|
Future<bool> hasUser();
|
||||||
|
//Future<bool> updateUser();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -392,7 +392,12 @@ class _RunningStatusPageState extends State<RunningStatusPage> {
|
|||||||
// ====================== 图表视图 ======================
|
// ====================== 图表视图 ======================
|
||||||
Widget _buildChartContentView(DeviceStatusState state) {
|
Widget _buildChartContentView(DeviceStatusState state) {
|
||||||
if (state is! DeviceStatusUpdated) {
|
if (state is! DeviceStatusUpdated) {
|
||||||
return const Center(child: CircularProgressIndicator());
|
return const Center(
|
||||||
|
child: CircularProgressIndicator(
|
||||||
|
color: Color(0xFF1677FF), // 统一使用项目主题蓝色
|
||||||
|
strokeWidth: 4, // 加粗加载圈,视觉更清晰
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
final status = state.status;
|
final status = state.status;
|
||||||
@@ -623,7 +628,12 @@ class _RunningStatusPageState extends State<RunningStatusPage> {
|
|||||||
child: Text("数据加载失败", style: TextStyle(color: Colors.red, fontSize: 16)),
|
child: Text("数据加载失败", style: TextStyle(color: Colors.red, fontSize: 16)),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return const Center(child: CircularProgressIndicator());
|
return const Center(
|
||||||
|
child: CircularProgressIndicator(
|
||||||
|
color: Color(0xFF1677FF), // 统一使用项目主题蓝色
|
||||||
|
strokeWidth: 4, // 加粗加载圈,视觉更清晰
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
48
lib/features/my/presentation/bloc/my_cubit.dart
Normal file
48
lib/features/my/presentation/bloc/my_cubit.dart
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
import 'dart:collection';
|
||||||
|
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:maibu_satabot_v2/core/di/injection.dart';
|
||||||
|
import 'package:maibu_satabot_v2/core/storage/user_storage.dart';
|
||||||
|
|
||||||
|
import 'package:maibu_satabot_v2/features/devices/domain/usecases/unbind_device_usecase.dart';
|
||||||
|
import 'package:maibu_satabot_v2/features/my/presentation/bloc/my_state.dart';
|
||||||
|
import 'package:maibu_satabot_v2/features/my/repository/my_repository.dart';
|
||||||
|
import 'package:maibu_satabot_v2/features/my/usecases/updatename_usecase.dart';
|
||||||
|
|
||||||
|
class MyCubit extends Cubit<MyState> {
|
||||||
|
// 1. 修正变量命名:小驼峰规范(_updateNameUsecase)
|
||||||
|
final UpdateNameUsecase _updateNameUsecase;
|
||||||
|
final MyRepository repository;
|
||||||
|
|
||||||
|
// 2. 构造函数参数顺序与命名对齐
|
||||||
|
MyCubit(this.repository, this._updateNameUsecase) : super(const MyState());
|
||||||
|
|
||||||
|
Future<void> updateName(String nickName) async {
|
||||||
|
emit(state.copyWith(isLoading: true, errorMessage: ''));
|
||||||
|
|
||||||
|
try {
|
||||||
|
final params = UpdateNameParams(nickName);
|
||||||
|
final result = await _updateNameUsecase(params);
|
||||||
|
print("$result 修改名称结构");
|
||||||
|
|
||||||
|
// 4. 恢复 fold 逻辑,处理 UseCase 返回结果(关键:更新 UI 状态)
|
||||||
|
result.fold((failure) => emit(state.copyWith(isLoading: false, errorMessage: failure.message ?? '修改昵称失败')), (successCode) {
|
||||||
|
print("$successCode 修改名称结构");
|
||||||
|
final isSuccess = successCode == 200;
|
||||||
|
if (isSuccess) {
|
||||||
|
emit(state.copyWith(isLoading: false, errorMessage: '', nickName: nickName));
|
||||||
|
} else {
|
||||||
|
emit(state.copyWith(isLoading: false, errorMessage: '修改昵称失败:状态码 $successCode'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
emit(state.copyWith(isLoading: false, errorMessage: '修改昵称异常:${e.toString()}'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保留解绑设备方法(如果需要)
|
||||||
|
Future<void> unbindDevice(String deviceId, String deviceName) async {
|
||||||
|
emit(state.copyWith(isLoading: true, errorMessage: ''));
|
||||||
|
// 解绑逻辑(如需保留,需补充 UnbindDeviceUsecase 依赖注入)
|
||||||
|
}
|
||||||
|
}
|
||||||
22
lib/features/my/presentation/bloc/my_state.dart
Normal file
22
lib/features/my/presentation/bloc/my_state.dart
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:maibu_satabot_v2/features/devices/domain/entities/device_entity.dart';
|
||||||
|
|
||||||
|
class MyState extends Equatable {
|
||||||
|
final bool isLoading; // 是否正在加载
|
||||||
|
final String? errorMessage; // 错误信息
|
||||||
|
final String? nickName;
|
||||||
|
|
||||||
|
const MyState({this.isLoading = false, this.errorMessage, this.nickName});
|
||||||
|
|
||||||
|
// 使用 copyWith 方便局部更新状态
|
||||||
|
MyState copyWith({bool? isLoading, String? errorMessage, String? nickName}) {
|
||||||
|
return MyState(
|
||||||
|
isLoading: isLoading ?? this.isLoading,
|
||||||
|
errorMessage: errorMessage, // 错误信息通常每次更新都要重新赋值或清空
|
||||||
|
nickName: nickName,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [isLoading, errorMessage, nickName];
|
||||||
|
}
|
||||||
@@ -3,6 +3,10 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:get_it/get_it.dart';
|
import 'package:get_it/get_it.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
|
import 'package:maibu_satabot_v2/core/di/injection.dart';
|
||||||
|
import 'package:maibu_satabot_v2/features/my/presentation/bloc/my_cubit.dart';
|
||||||
|
import 'package:maibu_satabot_v2/features/my/repository/my_repository.dart';
|
||||||
|
import 'package:maibu_satabot_v2/features/my/usecases/updatename_usecase.dart';
|
||||||
import '../../../../core/router/route_paths.dart';
|
import '../../../../core/router/route_paths.dart';
|
||||||
import '../../../../core/storage/user_storage.dart';
|
import '../../../../core/storage/user_storage.dart';
|
||||||
import '../../../auth/presentation/bloc/auth_cubit.dart';
|
import '../../../auth/presentation/bloc/auth_cubit.dart';
|
||||||
@@ -24,7 +28,7 @@ class MyPage extends StatelessWidget {
|
|||||||
|
|
||||||
if (authState is AuthAuthenticated) {
|
if (authState is AuthAuthenticated) {
|
||||||
final user = authState.user;
|
final user = authState.user;
|
||||||
userName = user.username ?? '未知用户';
|
userName = user.nickname ?? '未知用户';
|
||||||
userId = user.userId ?? '未知ID';
|
userId = user.userId ?? '未知ID';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,7 +40,10 @@ class MyPage extends StatelessWidget {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
// 顶部用户信息
|
// 顶部用户信息
|
||||||
UserInfoCard(userName: userName, userId: userId),
|
BlocProvider(
|
||||||
|
create: (context) => MyCubit(sl<MyRepository>(), sl<UpdateNameUsecase>()),
|
||||||
|
child: UserInfoCard(userName: userName, userId: userId),
|
||||||
|
),
|
||||||
|
|
||||||
SizedBox(height: 16),
|
SizedBox(height: 16),
|
||||||
|
|
||||||
@@ -63,24 +70,14 @@ class MyPage extends StatelessWidget {
|
|||||||
// 添加 context 参数
|
// 添加 context 参数
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.push(
|
Navigator.push(context, MaterialPageRoute(builder: (context) => WebViewPage(url: 'https://www.satabot.com/')));
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) => WebViewPage(url: 'https://www.satabot.com/'),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
child: Container(
|
child: Container(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
height: 160,
|
height: 160,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
image: DecorationImage(
|
image: DecorationImage(image: NetworkImage('https://c.53326.com/d/file/lan20221010/fyhj0ibovbp.jpg'), fit: BoxFit.cover),
|
||||||
image: NetworkImage(
|
|
||||||
'https://c.53326.com/d/file/lan20221010/fyhj0ibovbp.jpg',
|
|
||||||
),
|
|
||||||
fit: BoxFit.cover,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
child: Stack(
|
child: Stack(
|
||||||
children: [
|
children: [
|
||||||
@@ -89,23 +86,14 @@ class MyPage extends StatelessWidget {
|
|||||||
right: 12,
|
right: 12,
|
||||||
child: Container(
|
child: Container(
|
||||||
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(color: Colors.black.withOpacity(0.5), borderRadius: BorderRadius.circular(4)),
|
||||||
color: Colors.black.withOpacity(0.5),
|
child: Text('了解我们', style: TextStyle(color: Colors.white, fontSize: 14)),
|
||||||
borderRadius: BorderRadius.circular(4),
|
|
||||||
),
|
|
||||||
child: Text(
|
|
||||||
'了解我们',
|
|
||||||
style: TextStyle(color: Colors.white, fontSize: 14),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Positioned(
|
Positioned(
|
||||||
left: 12,
|
left: 12,
|
||||||
bottom: 12,
|
bottom: 12,
|
||||||
child: Text(
|
child: Text('AI赋能农业', style: TextStyle(color: Colors.white, fontSize: 16)),
|
||||||
'AI赋能农业',
|
|
||||||
style: TextStyle(color: Colors.white, fontSize: 16),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -115,35 +103,17 @@ class MyPage extends StatelessWidget {
|
|||||||
|
|
||||||
Widget _buildFunctionList(BuildContext context) {
|
Widget _buildFunctionList(BuildContext context) {
|
||||||
final items = [
|
final items = [
|
||||||
{
|
{'icon': Icons.play_arrow, 'title': '操作视频', 'url': 'https://www.satabot.com/Support/index.html'},
|
||||||
'icon': Icons.play_arrow,
|
{'icon': Icons.car_rental, 'title': '租赁服务', 'url': 'https://www.satabot.com/Leasing.html'},
|
||||||
'title': '操作视频',
|
{'icon': Icons.help_outline, 'title': '帮助与支持', 'url': 'https://www.satabot.com/support/index.html'},
|
||||||
'url': 'https://www.satabot.com/Support/index.html',
|
{'icon': Icons.policy, 'title': '售后政策', 'url': 'https://www.satabot.com/Aftersales-Service.html'},
|
||||||
},
|
|
||||||
{
|
|
||||||
'icon': Icons.car_rental,
|
|
||||||
'title': '租赁服务',
|
|
||||||
'url': 'https://www.satabot.com/Leasing.html',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'icon': Icons.help_outline,
|
|
||||||
'title': '帮助与支持',
|
|
||||||
'url': 'https://www.satabot.com/support/index.html',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'icon': Icons.policy,
|
|
||||||
'title': '售后政策',
|
|
||||||
'url': 'https://www.satabot.com/Aftersales-Service.html',
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
boxShadow: [
|
boxShadow: [BoxShadow(color: Colors.grey.withOpacity(0.1), blurRadius: 4)],
|
||||||
BoxShadow(color: Colors.grey.withOpacity(0.1), blurRadius: 4),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
@@ -159,13 +129,7 @@ class MyPage extends StatelessWidget {
|
|||||||
title: Text(item['title'] as String),
|
title: Text(item['title'] as String),
|
||||||
trailing: Icon(Icons.arrow_forward),
|
trailing: Icon(Icons.arrow_forward),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.push(
|
Navigator.push(context, MaterialPageRoute(builder: (context) => WebViewPage(url: item['url'] as String)));
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) =>
|
|
||||||
WebViewPage(url: item['url'] as String),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,17 +1,224 @@
|
|||||||
// user_info_card.dart
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:flutter_webrtc/flutter_webrtc.dart';
|
||||||
import 'package:maibu_satabot_v2/features/devices/presentation/bloc/devices_cubit.dart';
|
import 'package:maibu_satabot_v2/features/devices/presentation/bloc/devices_cubit.dart';
|
||||||
import 'package:mobile_scanner/mobile_scanner.dart'; // 1. 导入扫码库
|
import 'package:maibu_satabot_v2/features/my/presentation/bloc/my_cubit.dart';
|
||||||
import 'package:get_it/get_it.dart'; // 用于获取 Cubit 实例
|
import 'package:maibu_satabot_v2/features/my/presentation/bloc/my_state.dart';
|
||||||
// 2. 导入你的 Cubit 文件,请根据实际路径调整
|
import 'package:mobile_scanner/mobile_scanner.dart';
|
||||||
|
import 'package:get_it/get_it.dart';
|
||||||
import '../../../auth/presentation/bloc/auth_cubit.dart';
|
import '../../../auth/presentation/bloc/auth_cubit.dart';
|
||||||
|
|
||||||
class UserInfoCard extends StatelessWidget {
|
class UserInfoCard extends StatefulWidget {
|
||||||
final String userName;
|
final String userName;
|
||||||
final String userId;
|
final String userId;
|
||||||
|
|
||||||
const UserInfoCard({super.key, required this.userName, required this.userId});
|
const UserInfoCard({super.key, required this.userName, required this.userId});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<UserInfoCard> createState() => _UserInfoCardState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _UserInfoCardState extends State<UserInfoCard> {
|
||||||
|
late TextEditingController _nicknameController;
|
||||||
|
final GetIt _getIt = GetIt.I;
|
||||||
|
MyCubit? _myCubit; // 可空类型
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
// 优先从 BlocProvider 获取,获取失败则从 GetIt 兜底
|
||||||
|
try {
|
||||||
|
_myCubit = BlocProvider.of<MyCubit>(context);
|
||||||
|
} catch (e) {
|
||||||
|
debugPrint('从 BlocProvider 获取 MyCubit 失败:$e,尝试从 GetIt 获取');
|
||||||
|
try {
|
||||||
|
_myCubit = _getIt<MyCubit>();
|
||||||
|
} catch (e) {
|
||||||
|
debugPrint('从 GetIt 获取 MyCubit 也失败:$e');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_nicknameController = TextEditingController(text: widget.userName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_nicknameController.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 打开修改昵称的底部抽屉
|
||||||
|
void _openEditNicknameBottomSheet() {
|
||||||
|
// 修复1:先校验 _myCubit 是否为 null,避免空断言
|
||||||
|
final myCubit = _myCubit;
|
||||||
|
if (myCubit == null) {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('Cubit 初始化失败,无法修改昵称'), backgroundColor: Colors.red));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.vertical(top: Radius.circular(16))),
|
||||||
|
isScrollControlled: true,
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
constraints: BoxConstraints(maxHeight: MediaQuery.of(context).size.height * 0.8),
|
||||||
|
builder: (context) => BlocProvider.value(
|
||||||
|
// 使用非空的局部变量,无需空断言
|
||||||
|
value: myCubit,
|
||||||
|
child: BlocBuilder<MyCubit, MyState>(
|
||||||
|
builder: (context, myState) {
|
||||||
|
final cubit = context.read<MyCubit>();
|
||||||
|
|
||||||
|
return Padding(
|
||||||
|
padding: EdgeInsets.only(left: 16, right: 16, top: 20, bottom: MediaQuery.of(context).viewInsets.bottom + 80),
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(16)),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
const Text('修改昵称', style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
|
||||||
|
IconButton(padding: EdgeInsets.zero, icon: const Icon(Icons.close, size: 20), onPressed: () => Navigator.pop(context)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
const Text('新昵称', style: TextStyle(fontSize: 12, color: Colors.grey)),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
TextField(
|
||||||
|
controller: _nicknameController,
|
||||||
|
style: const TextStyle(fontSize: 16),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
border: const OutlineInputBorder(),
|
||||||
|
contentPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
|
||||||
|
),
|
||||||
|
autofocus: true,
|
||||||
|
enabled: !myState.isLoading,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
|
||||||
|
// 核心:根据 MyState 显示加载/按钮/错误提示
|
||||||
|
if (myState.isLoading)
|
||||||
|
const Center(
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
CircularProgressIndicator(color: Colors.blue),
|
||||||
|
SizedBox(height: 8),
|
||||||
|
Text("修改中...", style: TextStyle(color: Colors.grey)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
else
|
||||||
|
Column(
|
||||||
|
children: [
|
||||||
|
// 修复2:使用 ?. 和 ?? 避免空断言,安全判断错误信息
|
||||||
|
if (myState.errorMessage?.isNotEmpty ?? false)
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(bottom: 12),
|
||||||
|
child: Text(myState.errorMessage ?? "修改失败", style: const TextStyle(color: Colors.red, fontSize: 14)),
|
||||||
|
),
|
||||||
|
|
||||||
|
// 确定修改按钮
|
||||||
|
SizedBox(
|
||||||
|
width: double.infinity,
|
||||||
|
child: ElevatedButton(
|
||||||
|
onPressed: () => _submitNewNickname(context),
|
||||||
|
style: ElevatedButton.styleFrom(
|
||||||
|
backgroundColor: Colors.blue,
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 14),
|
||||||
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
|
||||||
|
),
|
||||||
|
child: const Text('确定修改', style: TextStyle(fontSize: 16, color: Colors.white)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提交新昵称的业务逻辑
|
||||||
|
Future<void> _submitNewNickname(BuildContext context) async {
|
||||||
|
final newNickname = _nicknameController.text.trim();
|
||||||
|
if (newNickname.isEmpty ) {
|
||||||
|
Navigator.pop(context);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final myCubit = _myCubit;
|
||||||
|
if (myCubit == null) {
|
||||||
|
if (context.mounted) {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('Cubit 初始化失败'), backgroundColor: Colors.red));
|
||||||
|
}
|
||||||
|
Navigator.pop(context);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 移除重复的加载弹窗(由 BlocBuilder 显示加载状态)
|
||||||
|
await myCubit.updateName(newNickname);
|
||||||
|
|
||||||
|
// 成功后由 BlocBuilder 监听状态并处理弹窗关闭和提示
|
||||||
|
if (context.mounted && myCubit.state.errorMessage!.isEmpty ?? true) {
|
||||||
|
setState(() {
|
||||||
|
_nicknameController.text = newNickname;
|
||||||
|
});
|
||||||
|
Navigator.pop(context);
|
||||||
|
// 触发 AuthCubit 重新获取用户信息
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 扫码绑定设备逻辑(保留)
|
||||||
|
Future<void> _handleScanAndBind(BuildContext context) async {
|
||||||
|
final String? qrCode = await Navigator.push<String>(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => MobileScanner(
|
||||||
|
onDetect: (capture) {
|
||||||
|
final List<Barcode> barcodes = capture.barcodes;
|
||||||
|
if (barcodes.isNotEmpty) {
|
||||||
|
final String? code = barcodes.first.rawValue;
|
||||||
|
if (code != null && code.isNotEmpty) {
|
||||||
|
Navigator.pop(context, code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (qrCode == null || qrCode.isEmpty) return;
|
||||||
|
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
barrierDismissible: false,
|
||||||
|
builder: (context) => const Center(child: CircularProgressIndicator(color: Color(0xFF1677FF), strokeWidth: 4)),
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
final devicesCubit = _getIt<DevicesCubit>();
|
||||||
|
// await devicesCubit.bindDevice(qrCode);
|
||||||
|
if (context.mounted) Navigator.pop(context);
|
||||||
|
if (context.mounted) {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('设备绑定成功!'), backgroundColor: Colors.green));
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
if (context.mounted) Navigator.pop(context);
|
||||||
|
if (context.mounted) {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('绑定失败:$e'), backgroundColor: Colors.red));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Row(
|
return Row(
|
||||||
@@ -21,97 +228,23 @@ class UserInfoCard extends StatelessWidget {
|
|||||||
height: 48,
|
height: 48,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
image: DecorationImage(
|
image: DecorationImage(image: NetworkImage('https://pic4.zhimg.com/v2-c34c61a90095abb8713de9d1dca7ec7b_r.jpg'), fit: BoxFit.cover),
|
||||||
image: NetworkImage('https://pic4.zhimg.com/v2-c34c61a90095abb8713de9d1dca7ec7b_r.jpg'),
|
|
||||||
fit: BoxFit.cover,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(width: 12),
|
const SizedBox(width: 12),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(userName, style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
|
Text(_nicknameController.text, style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
|
||||||
Text('用户 id:$userId', style: TextStyle(fontSize: 12, color: Colors.grey)),
|
Text('用户 id:${widget.userId}', style: const TextStyle(fontSize: 12, color: Colors.grey)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
IconButton(
|
IconButton(icon: const Icon(Icons.edit), onPressed: _openEditNicknameBottomSheet),
|
||||||
icon: Icon(Icons.edit),
|
const Spacer(),
|
||||||
onPressed: () {},
|
IconButton(icon: const Icon(Icons.add), onPressed: () => _handleScanAndBind(context)),
|
||||||
),
|
|
||||||
Spacer(),
|
|
||||||
IconButton(
|
|
||||||
icon: Icon(Icons.add),
|
|
||||||
// 3. 绑定点击事件
|
|
||||||
onPressed: () => _handleScanAndBind(context),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. 定义扫码与绑定逻辑
|
|
||||||
Future<void> _handleScanAndBind(BuildContext context) async {
|
|
||||||
// 跳转到扫码页面
|
|
||||||
final String? qrCode = await Navigator.push<String>(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) => MobileScanner(
|
|
||||||
onDetect: (capture) {
|
|
||||||
final List<Barcode> barcodes = capture.barcodes;
|
|
||||||
if (barcodes.isNotEmpty) {
|
|
||||||
debugPrint('识别到的数据: $barcodes');
|
|
||||||
final String? code = barcodes.first.rawValue;
|
|
||||||
if (code != null && code.isNotEmpty) {
|
|
||||||
// 识别成功,立即返回结果并关闭页面
|
|
||||||
debugPrint('扫码成功,识别到的数据: $code');
|
|
||||||
// Navigator.pop(context, code);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
// 如果用户取消或未扫到码,直接返回
|
|
||||||
if (qrCode == null || qrCode.isEmpty) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 显示加载对话框
|
|
||||||
showDialog(
|
|
||||||
context: context,
|
|
||||||
barrierDismissible: false,
|
|
||||||
builder: (context) => Center(child: CircularProgressIndicator()),
|
|
||||||
);
|
|
||||||
|
|
||||||
try {
|
|
||||||
// 5. 获取 Cubit 实例并调用绑定接口
|
|
||||||
final Cubit = GetIt.I<DevicesCubit>();
|
|
||||||
|
|
||||||
// 执行绑定逻辑
|
|
||||||
//await Cubit.bindDevice(qrCode);
|
|
||||||
|
|
||||||
// 关闭加载框
|
|
||||||
if (context.mounted) Navigator.pop(context);
|
|
||||||
|
|
||||||
// 成功提示
|
|
||||||
if (context.mounted) {
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
|
||||||
SnackBar(content: Text('设备绑定成功!'), backgroundColor: Colors.green),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
// 关闭加载框
|
|
||||||
if (context.mounted) Navigator.pop(context);
|
|
||||||
|
|
||||||
// 失败提示
|
|
||||||
if (context.mounted) {
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
|
||||||
SnackBar(content: Text('绑定失败:$e'), backgroundColor: Colors.red),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
8
lib/features/my/repository/my_repository.dart
Normal file
8
lib/features/my/repository/my_repository.dart
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
// lib/features/devices/domain/repositories/route_planning_repository.dart
|
||||||
|
import 'package:fpdart/fpdart.dart';
|
||||||
|
import 'package:maibu_satabot_v2/features/devices/domain/errors/device_failure.dart';
|
||||||
|
|
||||||
|
abstract class MyRepository {
|
||||||
|
// 抽象方法定义:参数是 String nickName,返回 Future<Either<DeviceFailure, int>>
|
||||||
|
Future<Either<DeviceFailure, int>> updateName(String nickName);
|
||||||
|
}
|
||||||
61
lib/features/my/repository/my_repository_impl.dart
Normal file
61
lib/features/my/repository/my_repository_impl.dart
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
import 'dart:math';
|
||||||
|
import 'package:fpdart/fpdart.dart';
|
||||||
|
import 'package:http/http.dart' as http;
|
||||||
|
import 'package:maibu_satabot_v2/features/my/repository/my_repository.dart';
|
||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import '../../../../core/di/injection.dart';
|
||||||
|
import '../../../../core/storage/user_storage.dart';
|
||||||
|
// 必须导入 DeviceFailure 类
|
||||||
|
import '../../../../features/devices/domain/errors/device_failure.dart';
|
||||||
|
|
||||||
|
class MyRepositoryImpl implements MyRepository {
|
||||||
|
// 可选:注入 UserStorage(如果需要获取 token 等用户信息)
|
||||||
|
final UserStorage _userStorage;
|
||||||
|
|
||||||
|
MyRepositoryImpl({UserStorage? userStorage}) : _userStorage = userStorage ?? sl<UserStorage>();
|
||||||
|
// 🔥 辅助方法:获取 Token
|
||||||
|
Future<String?> _getToken() async {
|
||||||
|
final user = await _userStorage.getUser();
|
||||||
|
return user?.token;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 核心修复:严格匹配抽象类的方法签名
|
||||||
|
@override
|
||||||
|
Future<Either<DeviceFailure, int>> updateName(String nickName) async {
|
||||||
|
final url = Uri.parse('https://serviceri.satabot.com/system/user/profile');
|
||||||
|
|
||||||
|
// 补充:从 UserStorage 获取 token(接口通常需要认证)
|
||||||
|
final token = await _getToken();
|
||||||
|
final headers = {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Authorization': 'Bearer $token', // 按需添加认证头
|
||||||
|
};
|
||||||
|
|
||||||
|
final body = jsonEncode({'nickName': nickName});
|
||||||
|
|
||||||
|
try {
|
||||||
|
final response = await http.put(url, headers: headers, body: body);
|
||||||
|
|
||||||
|
// 1. 处理成功响应(statusCode 200)
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
final data = jsonDecode(response.body) as Map<String, dynamic>;
|
||||||
|
|
||||||
|
// 根据接口返回值,返回 Either.right(成功码,比如 1 表示成功)
|
||||||
|
// 示例:假设接口返回 code=200 表示成功
|
||||||
|
final int successCode = data['code'] ?? 1;
|
||||||
|
return Right(successCode);
|
||||||
|
}
|
||||||
|
// 2. 处理失败响应(非 200 状态码)
|
||||||
|
else {
|
||||||
|
final String errorMsg = '修改昵称失败:状态码 ${response.statusCode}';
|
||||||
|
return Left(DeviceFailure.serverError(message: errorMsg));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 3. 处理网络异常
|
||||||
|
catch (e) {
|
||||||
|
final String errorMsg = '网络异常:${e.toString()}';
|
||||||
|
return Left(DeviceFailure.serverError(message: errorMsg));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
26
lib/features/my/usecases/updatename_usecase.dart
Normal file
26
lib/features/my/usecases/updatename_usecase.dart
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import 'package:fpdart/fpdart.dart';
|
||||||
|
import 'package:maibu_satabot_v2/core/domain/usecases/base_usecase.dart';
|
||||||
|
import 'package:maibu_satabot_v2/features/devices/domain/errors/device_failure.dart'; // 必须导入
|
||||||
|
import 'package:maibu_satabot_v2/features/my/repository/my_repository.dart';
|
||||||
|
|
||||||
|
// 1. 泛型严格匹配:BaseUseCase<成功类型int, 参数类型UpdateNameParams>
|
||||||
|
class UpdateNameUsecase implements BaseUseCase<int, UpdateNameParams> {
|
||||||
|
final MyRepository myRepository;
|
||||||
|
|
||||||
|
UpdateNameUsecase(this.myRepository);
|
||||||
|
|
||||||
|
// 2. 核心修复:返回值类型从 dynamic 改为 Either<DeviceFailure, int>
|
||||||
|
// 严格覆盖 BaseUseCase 的 call 方法
|
||||||
|
@override
|
||||||
|
Future<Either<DeviceFailure, int>> call(UpdateNameParams params) async {
|
||||||
|
// 3. 调用仓库方法(返回值已匹配 Either<DeviceFailure, int>)
|
||||||
|
return await myRepository.updateName(params.nickName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 参数类保持不变(不可变,语义清晰)
|
||||||
|
class UpdateNameParams {
|
||||||
|
final String nickName;
|
||||||
|
|
||||||
|
const UpdateNameParams(this.nickName);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user