我的界面 修改昵称完成

This commit is contained in:
mmc
2026-03-04 21:21:43 +08:00
parent fcfdb2c78c
commit cb9f2aa419
12 changed files with 675 additions and 181 deletions

View 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

View File

@@ -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/update_devicename_usecase.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/domain/repositories/remote_control_repository.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());
/// 1.1.2 TcpClient:TCP客户端
sl.registerLazySingleton(() => TcpClient( sl<UserStorage>(),
getUserDeviceUseCase: sl<GetUserDeviceUseCase>(),
switchDeviceUseCase: sl<SwitchDeviceUseCase>(),));
sl.registerLazySingleton(
() => TcpClient(sl<UserStorage>(), getUserDeviceUseCase: sl<GetUserDeviceUseCase>(), switchDeviceUseCase: sl<SwitchDeviceUseCase>()),
);
/// 1.1.3 NetMessageDispatcher:消息调度器,并将 TcpClient 注入给它
sl.registerLazySingleton(() => NetMessageDispatcher(sl()));
@@ -86,11 +90,9 @@ Future<void> init() async {
sl.registerLazySingleton<ILoggerService>(() => SentryLoggerImpl());
/// 2. 数据源 (DataSource)
sl.registerLazySingleton<AuthHttpDataSource>(
() => AuthHttpDataSourceImpl(sl()),
);
sl.registerLazySingleton<AuthHttpDataSource>(() => AuthHttpDataSourceImpl(sl()));
sl.registerLazySingleton<DeviceHttpDatasource>(
() => DeviceHttpDatasourceImpl(sl(), sl<UserStorage>()), //
() => DeviceHttpDatasourceImpl(sl(), sl<UserStorage>()), //
);
/// 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>(
() => RoutePlanningRepositoryImpl(tcp: sl<TcpClient>()), //
() => RoutePlanningRepositoryImpl(tcp: sl<TcpClient>()), //
);
sl.registerLazySingleton<RoutePlanningUseCase>(
() => RoutePlanningUseCase(sl<RoutePlanningRepository>()), //
() => RoutePlanningUseCase(sl<RoutePlanningRepository>()), //
);
//工作历史
sl.registerLazySingleton<DeviceHostrityWorkRepositoryRepository>(
() => DeviceHostrityWorkRepositoryImpl(
@@ -120,9 +138,7 @@ Future<void> init() async {
);
sl.registerLazySingleton<DeviceRepository>(() => DeviceRepositoryImpl(sl()));
sl.registerLazySingleton<RemoteControlRepository>(
() => RemoteControlRepositoryImpl(sl(), sl()),
);
sl.registerLazySingleton<RemoteControlRepository>(() => RemoteControlRepositoryImpl(sl(), sl()));
/// 4. 用例 (UseCase)
sl.registerLazySingleton(() => LoginUseCase(sl()));
@@ -137,7 +153,7 @@ Future<void> init() async {
sl.registerLazySingleton<SwitchDeviceUseCase>(() => SwitchDeviceUseCase(sl()));
sl.registerLazySingleton<AuthTcpDatasource>(
() => AuthTcpDatasourceImpl(
() => AuthTcpDatasourceImpl(
sl<TcpClient>(),
sl<UserStorage>(),
getUserDeviceUseCase: sl<GetUserDeviceUseCase>(),
@@ -145,15 +161,12 @@ Future<void> init() async {
),
);
/// 5. 状态管理 (Cubit/Bloc)
sl.registerLazySingleton(() => AppUserCubit()); // AuthCubit 依赖它,必须先注册
sl.registerLazySingleton(() => GetDeviceLocationUseCase(sl()));
sl.registerLazySingleton(
() => DevicesCubit(sl(), sl(), sl(), sl(), sl(), sl(), sl(), sl(), sl(),sl(),sl(), sl()),
);
sl.registerLazySingleton(() => DevicesCubit(sl(), sl(), sl(), sl(), sl(), sl(), sl(), sl(), sl(), sl(), sl(), sl()));
sl.registerFactory(() => RemoteControlCubit(sl()));
/* // 工厂模式(留存,每次获取新实例)
/* // 工厂模式(留存,每次获取新实例)
sl.registerFactory(() => DeviceStatusBloc(sl<NetMessageDispatcher>()));
*/
//单例模式(全局共享一个实例)
@@ -161,16 +174,13 @@ Future<void> init() async {
/// . 路径生成
sl.registerLazySingleton<PathHttpDatasource>(
() => PathHttpDatasourceImpl(// 需先注册 http.Client(见下方)
() => PathHttpDatasourceImpl(
// 需先注册 http.Client(见下方)
sl<UserStorage>(),
),
);
sl.registerLazySingleton<PathRepository>(
() => PathRepositoryImpl(datasource: sl<PathHttpDatasource>()),
);
sl.registerLazySingleton<GeneratePathUseCase>(
() => GeneratePathUseCaseImpl(sl<PathRepository>()),
);
sl.registerLazySingleton<PathRepository>(() => PathRepositoryImpl(datasource: sl<PathHttpDatasource>()));
sl.registerLazySingleton<GeneratePathUseCase>(() => GeneratePathUseCaseImpl(sl<PathRepository>()));
///.路径获取和删除
sl.registerLazySingleton(() => GetWorkRecordUseCase(sl<PathRepository>()));
@@ -178,15 +188,7 @@ Future<void> init() async {
/// 6. 认证 (Auth)
// --- 关键修改点 1: AuthCubit 必须在 GoRouter 之前注册,并传入参数 ---
sl.registerLazySingleton(
() => AuthCubit(
sl<UserStorage>(),
sl<TcpClient>(),
sl<AppUserCubit>(),
sl<NetMessageDispatcher>(),
sl<AuthTcpDatasource>(),
),
);
sl.registerLazySingleton(() => AuthCubit(sl<UserStorage>(), sl<TcpClient>(), sl<AppUserCubit>(), sl<NetMessageDispatcher>(), sl<AuthTcpDatasource>()));
/// 7. 路由 (Router)
sl.registerSingleton<GoRouter>(createRouter(sl<AuthCubit>()));

View File

@@ -33,7 +33,6 @@ class UserStorageImpl implements UserStorage {
Future<void> deleteUser() async {
await _prefs.remove(_userKey);
//返回登陆页面
}
@override

View File

@@ -5,4 +5,5 @@ abstract class UserStorage {
Future<UserEntity?> getUser();
Future<void> deleteUser();
Future<bool> hasUser();
//Future<bool> updateUser();
}

View File

@@ -392,7 +392,12 @@ class _RunningStatusPageState extends State<RunningStatusPage> {
// ====================== 图表视图 ======================
Widget _buildChartContentView(DeviceStatusState state) {
if (state is! DeviceStatusUpdated) {
return const Center(child: CircularProgressIndicator());
return const Center(
child: CircularProgressIndicator(
color: Color(0xFF1677FF), // 统一使用项目主题蓝色
strokeWidth: 4, // 加粗加载圈,视觉更清晰
),
);
}
final status = state.status;
@@ -623,7 +628,12 @@ class _RunningStatusPageState extends State<RunningStatusPage> {
child: Text("数据加载失败", style: TextStyle(color: Colors.red, fontSize: 16)),
);
} else {
return const Center(child: CircularProgressIndicator());
return const Center(
child: CircularProgressIndicator(
color: Color(0xFF1677FF), // 统一使用项目主题蓝色
strokeWidth: 4, // 加粗加载圈,视觉更清晰
),
);
}
}

View 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 依赖注入)
}
}

View 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];
}

View File

@@ -3,6 +3,10 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:get_it/get_it.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/storage/user_storage.dart';
import '../../../auth/presentation/bloc/auth_cubit.dart';
@@ -24,7 +28,7 @@ class MyPage extends StatelessWidget {
if (authState is AuthAuthenticated) {
final user = authState.user;
userName = user.username ?? '未知用户';
userName = user.nickname ?? '未知用户';
userId = user.userId ?? '未知ID';
}
@@ -36,7 +40,10 @@ class MyPage extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// 顶部用户信息
UserInfoCard(userName: userName, userId: userId),
BlocProvider(
create: (context) => MyCubit(sl<MyRepository>(), sl<UpdateNameUsecase>()),
child: UserInfoCard(userName: userName, userId: userId),
),
SizedBox(height: 16),
@@ -63,24 +70,14 @@ class MyPage extends StatelessWidget {
// 添加 context 参数
return GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => WebViewPage(url: 'https://www.satabot.com/'),
),
);
Navigator.push(context, MaterialPageRoute(builder: (context) => WebViewPage(url: 'https://www.satabot.com/')));
},
child: Container(
width: double.infinity,
height: 160,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
image: DecorationImage(
image: NetworkImage(
'https://c.53326.com/d/file/lan20221010/fyhj0ibovbp.jpg',
),
fit: BoxFit.cover,
),
image: DecorationImage(image: NetworkImage('https://c.53326.com/d/file/lan20221010/fyhj0ibovbp.jpg'), fit: BoxFit.cover),
),
child: Stack(
children: [
@@ -89,23 +86,14 @@ class MyPage extends StatelessWidget {
right: 12,
child: Container(
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration(
color: Colors.black.withOpacity(0.5),
borderRadius: BorderRadius.circular(4),
),
child: Text(
'了解我们',
style: TextStyle(color: Colors.white, fontSize: 14),
),
decoration: BoxDecoration(color: Colors.black.withOpacity(0.5), borderRadius: BorderRadius.circular(4)),
child: Text('了解我们', style: TextStyle(color: Colors.white, fontSize: 14)),
),
),
Positioned(
left: 12,
bottom: 12,
child: Text(
'AI赋能农业',
style: TextStyle(color: Colors.white, fontSize: 16),
),
child: Text('AI赋能农业', style: TextStyle(color: Colors.white, fontSize: 16)),
),
],
),
@@ -115,35 +103,17 @@ class MyPage extends StatelessWidget {
Widget _buildFunctionList(BuildContext context) {
final items = [
{
'icon': Icons.play_arrow,
'title': '操作视频',
'url': 'https://www.satabot.com/Support/index.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',
},
{'icon': Icons.play_arrow, 'title': '操作视频', 'url': 'https://www.satabot.com/Support/index.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(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(color: Colors.grey.withOpacity(0.1), blurRadius: 4),
],
boxShadow: [BoxShadow(color: Colors.grey.withOpacity(0.1), blurRadius: 4)],
),
child: Column(
children: [
@@ -159,13 +129,7 @@ class MyPage extends StatelessWidget {
title: Text(item['title'] as String),
trailing: Icon(Icons.arrow_forward),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
WebViewPage(url: item['url'] as String),
),
);
Navigator.push(context, MaterialPageRoute(builder: (context) => WebViewPage(url: item['url'] as String)));
},
);
},

View File

@@ -1,17 +1,224 @@
// user_info_card.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:mobile_scanner/mobile_scanner.dart'; // 1. 导入扫码库
import 'package:get_it/get_it.dart'; // 用于获取 Cubit 实例
// 2. 导入你的 Cubit 文件,请根据实际路径调整
import 'package:maibu_satabot_v2/features/my/presentation/bloc/my_cubit.dart';
import 'package:maibu_satabot_v2/features/my/presentation/bloc/my_state.dart';
import 'package:mobile_scanner/mobile_scanner.dart';
import 'package:get_it/get_it.dart';
import '../../../auth/presentation/bloc/auth_cubit.dart';
class UserInfoCard extends StatelessWidget {
class UserInfoCard extends StatefulWidget {
final String userName;
final String 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
Widget build(BuildContext context) {
return Row(
@@ -21,97 +228,23 @@ class UserInfoCard extends StatelessWidget {
height: 48,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
image: DecorationImage(
image: NetworkImage('https://pic4.zhimg.com/v2-c34c61a90095abb8713de9d1dca7ec7b_r.jpg'),
fit: BoxFit.cover,
),
image: DecorationImage(image: NetworkImage('https://pic4.zhimg.com/v2-c34c61a90095abb8713de9d1dca7ec7b_r.jpg'), fit: BoxFit.cover),
),
),
SizedBox(width: 12),
const SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(userName, style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
Text('用户 id:$userId', style: TextStyle(fontSize: 12, color: Colors.grey)),
Text(_nicknameController.text, style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
Text('用户 id:${widget.userId}', style: const TextStyle(fontSize: 12, color: Colors.grey)),
],
),
),
IconButton(
icon: Icon(Icons.edit),
onPressed: () {},
),
Spacer(),
IconButton(
icon: Icon(Icons.add),
// 3. 绑定点击事件
onPressed: () => _handleScanAndBind(context),
),
IconButton(icon: const Icon(Icons.edit), onPressed: _openEditNicknameBottomSheet),
const Spacer(),
IconButton(icon: const Icon(Icons.add), 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),
);
}
}
}
}

View 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);
}

View 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));
}
}
}

View 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);
}