feat: 完成设备置顶、重命名、分享功能迭代

本次提交包含以下核心更新:
1. 新增设备置顶功能,支持将设备在列表中优先展示
2. 实现设备重命名、分享、取消共享功能
3. 优化首页设备列表滑动交互,重构设备项UI菜单逻辑
4. 新增is_top设备字段并完善设备列表排序逻辑
5. 调整部分UI布局与服务器接口地址
6. 补充多语言文案与新增提示文本
7. 修复绑定设备错误提示适配逻辑
This commit is contained in:
“虞渠成” 2026-08-19 17:08:15 +08:00
parent 3a335e60a2
commit f0a6f0f764
36 changed files with 3348 additions and 601 deletions

View File

@ -336,8 +336,8 @@
},
{
"key": "100068",
"zh": "蓝牙连接失败",
"en": "Bluetooth connection failed"
"zh": "设备绑定失败",
"en": "Device binding failed"
},
{
"key": "100069",
@ -347,7 +347,7 @@
{
"key": "100070",
"zh": "该设备已绑定至其他账号,无法重复绑定",
"en": "This device is already linked to another account and cannot be re-linked."
"en": "This device is already bound to another account and cannot be re-bound."
},
{
"key": "100071",
@ -1623,6 +1623,36 @@
"key": "100325",
"zh": "请将手指放置于设备指纹识别区域",
"en": "Place your finger on the device fingerprint sensor"
},
{
"key": "100326",
"zh": "重命名",
"en": "Rename"
},
{
"key": "100327",
"zh": "分享",
"en": "Share"
},
{
"key": "100328",
"zh": "删除",
"en": "Delete"
},
{
"key": "100329",
"zh": "置顶",
"en": "Pin"
},
{
"key": "100330",
"zh": "取消置顶",
"en": "Unpin"
},
{
"key": "100331",
"zh": "设备未录入",
"en": "Device not enrolled"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 257 B

View File

@ -0,0 +1,127 @@
fileFormatVersion: 2
guid: 926e9eea4b7bd4749bf80e2d44578723
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 0
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@ -451,7 +451,7 @@ RectTransform:
m_AnchorMin: {x: 0, y: 1}
m_AnchorMax: {x: 0, y: 1}
m_AnchoredPosition: {x: 30, y: -194.7}
m_SizeDelta: {x: 300, y: 30}
m_SizeDelta: {x: 700, y: 30}
m_Pivot: {x: 0, y: 0.5}
--- !u!222 &8340398492869491780
CanvasRenderer:

View File

@ -2714,7 +2714,7 @@ RectTransform:
m_AnchorMin: {x: 0, y: 1}
m_AnchorMax: {x: 0, y: 1}
m_AnchoredPosition: {x: 30, y: -195}
m_SizeDelta: {x: 300, y: 30}
m_SizeDelta: {x: 700, y: 30}
m_Pivot: {x: 0, y: 0.5}
--- !u!222 &7645982901015283803
CanvasRenderer:

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -0,0 +1,127 @@
fileFormatVersion: 2
guid: 65753048ee69962498a0ffb76fa39d7d
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 0
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 672 B

View File

@ -0,0 +1,127 @@
fileFormatVersion: 2
guid: ad79445c7db4fdd4d9621bbc5cf9a673
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 0
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: ac5f6bcc90dd5e44197b25b564cdc1ca
guid: 9cb90b79666a1f4439e7dc9b3d32ef6f
TextureImporter:
internalIDToNameTable: []
externalObjects: {}

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: d0b671cff2ca7f148a5a7211d1cbcc41
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 956 B

View File

@ -0,0 +1,127 @@
fileFormatVersion: 2
guid: 1197402f56a50ba4c8dba1099ddd7ad5
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 0
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 862 B

View File

@ -0,0 +1,127 @@
fileFormatVersion: 2
guid: 427ab269b614d734b9a13b33e6f99c7d
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 0
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 641 B

View File

@ -0,0 +1,127 @@
fileFormatVersion: 2
guid: c67a76187877d574697fc512a9347d1e
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 0
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 702 B

View File

@ -0,0 +1,127 @@
fileFormatVersion: 2
guid: 11b6abc19a2f2dc48b3d52f80c984460
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 0
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 460 B

View File

@ -0,0 +1,127 @@
fileFormatVersion: 2
guid: fa1d0be7a6f44ea4aaca6a7a47b98cd6
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 0
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@ -4352,7 +4352,7 @@ MonoBehaviour:
m_Left: 0
m_Right: 0
m_Top: 0
m_Bottom: 0
m_Bottom: 50
m_ChildAlignment: 1
m_Spacing: 35
m_ChildForceExpandWidth: 1

View File

@ -484,7 +484,7 @@ MonoBehaviour:
serverBaseUrls:
- https://nextreal.cn/photon-matrix-api
- https://api.photonmatrixlab.com
serverBaseUrl: https://api.photonmatrixlab.com
serverBaseUrl: https://nextreal.cn/photon-matrix-api
enableServerBackdoor: 1
backdoorTapCount: 15
backdoorTapInterval: 1
@ -529,6 +529,7 @@ MonoBehaviour:
owner_name:
owner_username:
share_time:
is_top: 0
OwnedDevices: []
SharedDevices: []
isOwner: 0

View File

@ -281,6 +281,7 @@ namespace Kill.Managers
public string owner_name;
public string owner_username;
public string share_time;
public bool is_top;
}
#endregion

View File

@ -711,7 +711,12 @@ public class ConnectDevicePageCtrl : MonoBehaviour
onError: (code,message) =>
{
Debug.Log($"绑定设备失败:{code},{message}");
errorTip = "100070";
if(code==404)
{
errorTip="100331";
}
else
errorTip = "100070";
ShowErrorPage();
}
);

View File

@ -23,17 +23,20 @@ namespace Kill.UI.Pages
private string currentName;
private Action<string> onConfirmCallback;
private int type = 0;//0设备重命名 1用户名重命名
private string deviceMac;// 待重命名设备的蓝牙MAC为空时取当前选中设备
/// <summary>
/// 初始化页面
/// </summary>
/// <param name="deviceName">当前名称</param>
/// <param name="onConfirm">确认回调,返回名称</param>
/// <param name="type">类型 0 重命名设备 1 用户名重命名</param>
public void Init(string name, Action<string> onConfirm, int type = 0)
/// <param name="deviceMac">设备蓝牙MAC重命名非选中设备时传入</param>
public void Init(string name, Action<string> onConfirm, int type = 0, string deviceMac = null)
{
currentName = name;
onConfirmCallback = onConfirm;
this.type = type;
this.deviceMac = deviceMac;
// 初始化输入框
if (nameInput != null)
@ -94,7 +97,9 @@ namespace Kill.UI.Pages
{
device_name = newName,
user_id = DataManager.Instance.userInfo.id,
device_sn = DataManager.Instance.selectedDevice.ble_mac
device_sn = string.IsNullOrEmpty(deviceMac)
? DataManager.Instance.selectedDevice.ble_mac
: deviceMac
};
// 发送PUT请求

View File

@ -15,6 +15,20 @@ namespace Kill.UI.Pages
public Button shareButton;
public ScanQRcode scanQRcode;
public Button backButton;
/// <summary>待分享设备的蓝牙MAC为空时取当前选中设备</summary>
private string deviceMac;
/// <summary>关闭页面时的回调(用于恢复上层页面的返回事件)</summary>
private Action onCloseAction;
/// <summary>
/// 初始化
/// </summary>
/// <param name="deviceMac">设备蓝牙MAC分享非选中设备时传入</param>
/// <param name="onClose">关闭页面回调</param>
public void Init(string deviceMac = null, Action onClose = null)
{
this.deviceMac = deviceMac;
this.onCloseAction = onClose;
}
void Start()
{
UIManager.Instance.RegisterBackAction(Back);
@ -39,8 +53,23 @@ namespace Kill.UI.Pages
}
public void Back()
{
UIManager.Instance.RegisterBackAction(GetComponentInParent<DeviceInfoPage>().Back);
if (onCloseAction != null)
{
// 恢复上层页面的返回事件
UIManager.Instance.RegisterBackAction(onCloseAction);
}
else
{
var infoPage = GetComponentInParent<DeviceInfoPage>();
if (infoPage != null)
{
UIManager.Instance.RegisterBackAction(infoPage.Back);
}
else
{
UIManager.Instance.ClearBackAction();
}
}
Destroy(gameObject);
}
public async Task Share()
@ -56,7 +85,9 @@ namespace Kill.UI.Pages
var requestData = new ShareDeviceRequest
{
device_sn = DataManager.Instance.selectedDevice.ble_mac,
device_sn = string.IsNullOrEmpty(deviceMac)
? DataManager.Instance.selectedDevice.ble_mac
: deviceMac,
target_user_id = targetUserId,
owner_id = DataManager.Instance.userInfo.id
};

View File

@ -1,5 +1,6 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Kill.Managers;
using UnityEngine;
using UnityEngine.UI;
@ -1002,6 +1003,9 @@ namespace Kill.UI.Pages
device.ble_mac = device.device_sn;
}
}
// 每种类型(自有/共享)的置顶设备排在第一个
OwnedDevices = OwnedDevices.OrderByDescending(d => d.is_top).ToList();
SharedDevices = SharedDevices.OrderByDescending(d => d.is_top).ToList();
Debug.Log($"[HomePageCtrl] 获取设备列表成功: 自有设备={OwnedDevices.Count}, 共享设备={SharedDevices.Count}");
DataManager.Instance.userInfo.device_count = OwnedDevices.Count + SharedDevices.Count;

View File

@ -1,3 +1,4 @@
using System.Collections.Generic;
using DG.Tweening;
using Kill.Managers;
using UnityEngine;
@ -8,21 +9,28 @@ namespace Kill.UI.Pages
{
/// <summary>
/// 首页设备列表项 - 显示单个设备信息
/// 支持左滑手势:左滑时菜单向左滑出并显示高斯模糊覆盖层
/// 滑动超过菜单宽度1/3松手则完整展开否则缩回并隐藏模糊层
/// 支持左滑手势:左滑时内容元素向左滑出,露出右侧菜单
/// 滑动超过菜单宽度1/3松手则完整展开否则缩回
/// </summary>
public class HomePageDeviceItem : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{
public Text deviceNameText;
/// <summary>
/// 置顶标识
/// </summary>
public GameObject topIcon;
public GameObject selectedIndicator;
/// <summary>菜单子物体锚点位于item最右侧左滑时向左滑出</summary>
/// <summary>菜单子物体锚点位于item最右侧内容左移后露出</summary>
public RectTransform menuRect;
/// <summary>高斯模糊覆盖层(子物体,覆盖其他内容),菜单出现时显示,缩回时隐藏</summary>
public GameObject blurOverlay;
// 当前设备信息
public DeviceInfo deviceInfo;
/// <summary>
/// 菜单按钮数组 0重命名 1分享 2删除 3置顶 4取消置顶
/// 最多显示3个按钮 拥有的设备显示分享 被分享的设备显示删除
/// 根据置顶状态显示置顶/取消置顶按钮
/// </summary>
public Button[] menuButtons;
/// <summary>当前展开菜单的item全局仅允许一个菜单展开</summary>
private static HomePageDeviceItem openItem;
@ -34,13 +42,31 @@ namespace Kill.UI.Pages
private Vector3 menuInitPos;
private Tweener tweener;
private Button button;
private bool menuListenersBound;
/// <summary>除菜单外的内容子物体</summary>
private readonly List<RectTransform> contentRects = new List<RectTransform>();
/// <summary>各内容子物体的初始位置</summary>
private readonly List<Vector2> contentInitPositions = new List<Vector2>();
void Awake()
{
button = GetComponent<Button>();
// 点击item主体关闭其他item展开的菜单同时收起自己的
if (button != null)
button.onClick.AddListener(OnItemClicked);
InitSwipe();
}
/// <summary>
/// item主体点击全局仅保留一个菜单点击任意item时关闭其他item的展开菜单
/// </summary>
private void OnItemClicked()
{
if (openItem != null && openItem != this)
openItem.CloseMenu();
CloseMenu();
}
void OnDisable()
{
// 防止拖拽中被禁用且未恢复的情况
@ -54,14 +80,43 @@ namespace Kill.UI.Pages
openItem = null;
}
public void InitDeviceItem(DeviceInfo device)
public void InitDeviceItem(DeviceInfo device, bool isOwner)
{
deviceInfo = device;
deviceNameText.text = device.device_name;
selectedIndicator.SetActive(false);
if (topIcon != null) topIcon.SetActive(device.is_top);
SetupMenuButtons(isOwner);
BindMenuButtonClose();
InitSwipe();
}
/// <summary>
/// 根据设备归属和置顶状态显示/隐藏菜单按钮
/// 0重命名 1分享 2删除 3置顶 4取消置顶
/// 拥有者:重命名+分享+置顶/取消置顶;被分享者:删除+置顶/取消置顶
/// </summary>
private void SetupMenuButtons(bool isOwner)
{
if (menuButtons == null || menuButtons.Length < 5) return;
menuButtons[0].gameObject.SetActive(true); // 重命名仅拥有者
menuButtons[1].gameObject.SetActive(isOwner); // 分享仅拥有者
menuButtons[2].gameObject.SetActive(!isOwner); // 删除(移除共享)仅被分享者
menuButtons[3].gameObject.SetActive(!deviceInfo.is_top); // 置顶:未置顶时显示
menuButtons[4].gameObject.SetActive(deviceInfo.is_top); // 取消置顶:已置顶时显示
}
/// <summary>
/// 点击菜单内任意按钮时自动收起菜单
/// </summary>
private void BindMenuButtonClose()
{
if (menuListenersBound || menuRect == null) return;
menuListenersBound = true;
foreach (var b in menuRect.GetComponentsInChildren<Button>(true))
b.onClick.AddListener(CloseMenu);
}
public void SetSelectedState(bool isSelected)
{
// 设置选中状态
@ -69,18 +124,29 @@ namespace Kill.UI.Pages
}
/// <summary>
/// 初始化滑动数据:记录菜单初始位置、菜单宽度,重置为收起状态
/// 初始化滑动数据:收集内容子物体、记录初始位置,重置为收起状态
/// </summary>
private void InitSwipe()
{
tweener?.Kill();
if (menuRect == null) return;
// 先复位已记录的内容再重新收集兼容item复用
ApplyOffset(0);
contentRects.Clear();
contentInitPositions.Clear();
foreach (Transform child in transform)
{
if (child == menuRect) continue;
RectTransform rt = child as RectTransform;
if (rt == null) continue;
contentRects.Add(rt);
contentInitPositions.Add(rt.anchoredPosition);
}
menuWidth = menuRect.sizeDelta.x;
menuInitPos = menuRect.anchoredPosition3D;
isMenuOpen = false;
currentOffset = 0;
ApplyMenuOffset(0);
if (blurOverlay != null) blurOverlay.SetActive(false);
ApplyOffset(0);
}
public void OnBeginDrag(PointerEventData eventData)
@ -92,11 +158,9 @@ namespace Kill.UI.Pages
if (openItem != null && openItem != this)
openItem.CloseMenu();
isDragging = true;
// 菜单开始出现,显示高斯模糊覆盖层
if (blurOverlay != null) blurOverlay.SetActive(true);
currentOffset = isMenuOpen ? -menuWidth : 0;
dragStartOffset = currentOffset;
ApplyMenuOffset(currentOffset);
ApplyOffset(currentOffset);
}
public void OnDrag(PointerEventData eventData)
@ -105,7 +169,7 @@ namespace Kill.UI.Pages
// 累加位移并限制在 [-菜单宽度, 0],只允许左滑露出菜单
currentOffset += eventData.delta.x;
currentOffset = Mathf.Clamp(currentOffset, -menuWidth, 0);
ApplyMenuOffset(currentOffset);
ApplyOffset(currentOffset);
}
public void OnEndDrag(PointerEventData eventData)
@ -136,13 +200,19 @@ namespace Kill.UI.Pages
}
/// <summary>
/// 将菜单平移到指定偏移
/// 将内容子物体和菜单一起平移到指定偏移(内容左移、菜单从屏幕外滑入露出)
/// </summary>
private void ApplyMenuOffset(float offset)
private void ApplyOffset(float offset)
{
Vector3 pos = menuInitPos;
pos.x += offset;
menuRect.anchoredPosition3D = pos;
for (int i = 0; i < contentRects.Count; i++)
{
Vector2 pos = contentInitPositions[i];
pos.x += offset;
contentRects[i].anchoredPosition = pos;
}
Vector3 menuPos = menuInitPos;
menuPos.x += offset;
menuRect.anchoredPosition3D = menuPos;
}
/// <summary>
@ -164,12 +234,10 @@ namespace Kill.UI.Pages
openItem = null;
}
isMenuOpen = open;
if (!isMenuOpen && blurOverlay != null)
blurOverlay.SetActive(false); // 菜单缩回时隐藏模糊层
tweener = DOTween.To(() => currentOffset, v =>
{
currentOffset = v;
ApplyMenuOffset(v);
ApplyOffset(v);
}, target, 0.25f).SetEase(Ease.OutCubic);
}
}

View File

@ -1,6 +1,12 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
using Kill.Managers;
using Kill.Network;
using Kill.UI.Components;
using Kill.Bluetooth;
using Kill.Core;
using UnityEngine;
using UnityEngine.UI;
namespace Kill.UI.Pages
@ -17,9 +23,14 @@ namespace Kill.UI.Pages
public DeviceInfo lastSelectedDevice;
public DeviceInfo selectedDevice;
public Text selectedDeviceName;
public GameObject renamePagePrefab;
public ShareDevicePage shareDevicePagePrefab;
/// <summary>当前已打开的重命名页实例(防连点重入)</summary>
private RenamePage currentRenamePage;
/// <summary>当前已打开的分享页实例(防连点重入)</summary>
private ShareDevicePage currentShareDevicePage;
public void InitDeviceList(List<DeviceInfo> ownedDevices, List<DeviceInfo> sharedDevices, DeviceInfo selectedDevice)
{
selectedDeviceName.text=selectedDevice.device_name;
typeStr[0]=LanguageManager.Instance.GetLanguage(typeKey[0]);
typeStr[1]=LanguageManager.Instance.GetLanguage(typeKey[1]);
lastSelectedDevice = selectedDevice;
@ -61,7 +72,8 @@ namespace Kill.UI.Pages
var deviceItem = Instantiate(devicePrefab, deviceParent);
deviceItem.SetActive(true);
deviceItem.GetComponent<HomePageDeviceItem>().InitDeviceItem(device);
deviceItem.GetComponent<HomePageDeviceItem>().InitDeviceItem(device,true);
BindMenuButtons(deviceItem.GetComponent<HomePageDeviceItem>());
deviceList.Add(deviceItem);
deviceItem.gameObject.SetActive(true);
deviceItem.GetComponent<Button>().onClick.AddListener(() =>
@ -85,7 +97,8 @@ namespace Kill.UI.Pages
}
var deviceItem = Instantiate(devicePrefab, deviceParent);
deviceItem.SetActive(true);
deviceItem.GetComponent<HomePageDeviceItem>().InitDeviceItem(device);
deviceItem.GetComponent<HomePageDeviceItem>().InitDeviceItem(device,false);
BindMenuButtons(deviceItem.GetComponent<HomePageDeviceItem>());
deviceList.Add(deviceItem);
deviceItem.gameObject.SetActive(true);
deviceItem.GetComponent<Button>().onClick.AddListener(() =>
@ -93,22 +106,68 @@ namespace Kill.UI.Pages
OnClickDeviceItem(deviceItem);
});
}
// 解析最终选中的设备:优先保持原选中;原选中设备不存在时,默认选中置顶设备;无置顶则选第一个设备
DeviceInfo effectiveSelected = null;
if (selectedDevice != null)
{
foreach (var deviceItem in deviceList)
{
if (deviceItem.GetComponent<HomePageDeviceItem>().deviceInfo.ble_mac == selectedDevice.ble_mac)
{
deviceItem.GetComponent<HomePageDeviceItem>().SetSelectedState(true);
effectiveSelected = selectedDevice;
break;
}
}
}
if (effectiveSelected == null)
{
foreach (var deviceItem in deviceList)
{
if (deviceItem.GetComponent<HomePageDeviceItem>().deviceInfo.is_top)
{
effectiveSelected = deviceItem.GetComponent<HomePageDeviceItem>().deviceInfo;
break;
}
}
}
if (effectiveSelected == null && deviceList.Count > 0)
{
effectiveSelected = deviceList[0].GetComponent<HomePageDeviceItem>().deviceInfo;
}
if (effectiveSelected != null)
{
// 选中设备发生回退(原选中不存在或无选中)时,同步选中信息并持久化
if (selectedDevice == null || selectedDevice.ble_mac != effectiveSelected.ble_mac)
{
lastSelectedDevice = effectiveSelected;
DataManager.Instance.selectedDevice = effectiveSelected;
DataManager.Instance.SavaSelectedDeviceMac(effectiveSelected.ble_mac);
var ctrl = HomePageCtrl.Instance;
if (ctrl != null)
{
ctrl.selectedDevice = effectiveSelected;
if (ctrl.selectDeviceButton != null)
ctrl.selectDeviceButton.GetComponentInChildren<Text>().text = effectiveSelected.device_name;
}
}
this.selectedDevice = effectiveSelected;
selectedDeviceName.text = effectiveSelected.device_name;
foreach (var deviceItem in deviceList)
{
bool isSelected = deviceItem.GetComponent<HomePageDeviceItem>().deviceInfo.ble_mac == effectiveSelected.ble_mac;
deviceItem.GetComponent<HomePageDeviceItem>().SetSelectedState(isSelected);
if (isSelected)
{
Debug.Log("选中设备:" + deviceItem.GetComponent<HomePageDeviceItem>().deviceInfo.ble_mac);
}
else
{
deviceItem.GetComponent<HomePageDeviceItem>().SetSelectedState(false);
}
}
}
else
{
selectedDeviceName.text = "";
}
}
public void OnClickDeviceItem(GameObject deviceItem)
@ -124,8 +183,125 @@ namespace Kill.UI.Pages
{
UIManager.Instance.OpenPage(UIManager.PageName.connectDevicePage);
}
/// <summary>
/// 绑定菜单按钮事件0=重命名 1=分享 2=删除 3=置顶 4=取消置顶)
/// </summary>
private void BindMenuButtons(HomePageDeviceItem item)
{
if (item.menuButtons == null || item.menuButtons.Length < 5) return;
item.menuButtons[0].onClick.AddListener(() => OpenRenamePage(item));
item.menuButtons[1].onClick.AddListener(() => OpenShareDevicePage(item));
item.menuButtons[2].onClick.AddListener(() => CancelShareBySharedUser(item.deviceInfo.ble_mac));
item.menuButtons[3].onClick.AddListener(() => ToggleTop(item, true));
item.menuButtons[4].onClick.AddListener(() => ToggleTop(item, false));
}
/// <summary>
/// 打开设备分享页面
/// </summary>
public void OpenShareDevicePage(HomePageDeviceItem item)
{
// 防连点:页面已打开时忽略重复触发
if (shareDevicePagePrefab == null || item == null || item.deviceInfo == null) return;
if (currentShareDevicePage != null) return;
currentShareDevicePage = Instantiate(shareDevicePagePrefab, transform).GetComponent<ShareDevicePage>();
currentShareDevicePage.gameObject.SetActive(true);
// 关闭分享页时恢复设备列表页的返回事件
currentShareDevicePage.Init(item.deviceInfo.ble_mac, () => UIManager.Instance.RegisterBackAction(ClosePage));
}
/// <summary>
/// 打开设备重命名页面
/// </summary>
public void OpenRenamePage(HomePageDeviceItem item)
{
// 防连点:页面已打开时忽略重复触发
if (renamePagePrefab == null || item == null || item.deviceInfo == null) return;
if (currentRenamePage != null) return;
currentRenamePage = Instantiate(renamePagePrefab, transform).GetComponent<RenamePage>();
currentRenamePage.gameObject.SetActive(true);
currentRenamePage.Init(item.deviceInfo.device_name, (newName) => CloseRenamePage(item, newName), 0, item.deviceInfo.ble_mac);
}
/// <summary>
/// 重命名成功回调更新本地名称并刷新UI
/// </summary>
public void CloseRenamePage(HomePageDeviceItem item, string newName)
{
currentRenamePage = null;
if (item == null || item.deviceInfo == null) return;
item.deviceInfo.device_name = newName;
if (item.deviceNameText != null) item.deviceNameText.text = newName;
// 重命名的是当前选中设备时,同步选中信息
if (selectedDevice != null && selectedDevice.ble_mac == item.deviceInfo.ble_mac)
{
selectedDevice.device_name = newName;
if (selectedDeviceName != null) selectedDeviceName.text = newName;
if (DataManager.Instance.selectedDevice != null &&
DataManager.Instance.selectedDevice.ble_mac == item.deviceInfo.ble_mac)
{
DataManager.Instance.selectedDevice.device_name = newName;
}
}
}
/// <summary>
/// 置顶/取消置顶:调用 /api/v1/device/top成功后重新获取设备列表并刷新
/// 每种类型仅一个置顶设备,冲突置顶由后端自动处理
/// </summary>
public async void ToggleTop(HomePageDeviceItem item, bool isTop)
{
if (item == null || item.deviceInfo == null) return;
string mac = item.deviceInfo.ble_mac;
if (string.IsNullOrEmpty(mac))
{
Debug.LogError("[HomePageDevicePage] 置顶失败: 设备MAC为空");
return;
}
LoadingUI.Show();
try
{
var requestData = new { ble_mac = mac, is_top = isTop };
var response = await NetworkCtrl.Instance.Put<NoDataResponse>("/api/v1/device/top", requestData);
LoadingUI.Hide();
ResponseCodeHandler.HandleResponse(response,
onSuccess: async (data) =>
{
// 后端会自动处理同类型冲突置顶,重新获取设备列表刷新
var ctrl = HomePageCtrl.Instance;
if (ctrl == null) return;
await ctrl.FetchDeviceList();
ctrl.selectDevicePage.GetComponent<HomePageDevicePage>()
.InitDeviceList(ctrl.OwnedDevices, ctrl.SharedDevices, ctrl.selectedDevice);
});
}
catch (Exception ex)
{
LoadingUI.Hide();
Debug.LogError($"[HomePageDevicePage] 置顶设置异常: {ex.Message}");
}
}
public void ClosePage()
{
// 设备可能在列表页被重命名,关闭时刷新主页显示的当前设备名
if (selectedDevice != null)
{
var ctrl = HomePageCtrl.Instance;
if (ctrl != null && ctrl.selectedDevice != null &&
ctrl.selectedDevice.ble_mac == selectedDevice.ble_mac)
{
ctrl.selectedDevice.device_name = selectedDevice.device_name;
if (ctrl.selectDeviceButton != null)
ctrl.selectDeviceButton.GetComponentInChildren<Text>().text = selectedDevice.device_name;
}
if (DataManager.Instance.selectedDevice != null &&
DataManager.Instance.selectedDevice.ble_mac == selectedDevice.ble_mac)
{
DataManager.Instance.selectedDevice.device_name = selectedDevice.device_name;
}
}
if(lastSelectedDevice==selectedDevice)
{
gameObject.SetActive(false);
@ -136,5 +312,85 @@ namespace Kill.UI.Pages
UIManager.Instance.OpenPage(UIManager.PageName.homePage,null,true);
}
}
string cancelShareDeviceMac="";
public WindowTipCtrl cancelShareTip;
public void CancelShareBySharedUser(string mac)
{
cancelShareDeviceMac=mac;
cancelShareTip.Init(()=>CancelShareAsyncBySharedUser(),()=>{
cancelShareTip.gameObject.SetActive(false);
});
cancelShareTip.gameObject.SetActive(true);
}
public async Task CancelShareAsyncBySharedUser()
{
cancelShareTip.gameObject.SetActive(false);
string targetUserId = DataManager.Instance.userInfo.id;
// 调用后端接口共享设备
LoadingUI.Show();
var requestData = new ShareDeviceRequest
{
device_sn = cancelShareDeviceMac,
target_user_id = targetUserId,
owner_id = "-1"
};
try
{
var response = await NetworkCtrl.Instance.Post<NoDataResponse>("/api/v1/device/unshare", requestData);
ResponseCodeHandler.HandleResponse(response,
onSuccess: (data) =>
{
Debug.Log("取消设备共享成功");
ToastUI.Show("100206");
if (BluetoothManager.Instance.IsConnected)
{
BLECommunicationManager.Instance.UnregisterUser(targetUserId, (unregisterSuccess) =>
{
Loom.QueueOnMainThread(() =>
{
if (unregisterSuccess.IsSuccess)
{
BluetoothManager.Instance.Disconnect();
StartCoroutine(BackToHomePage());
}
else
{
Debug.LogError("取消设备共享成功,但蓝牙用户注销失败");
StartCoroutine(BackToHomePage());
}
});
});
}
else
{
StartCoroutine(BackToHomePage());
}
},
onError: (code, msg) =>
{
Debug.LogError($"取消设备共享失败: {code} - {msg}");
LoadingUI.Hide();
ToastUI.ShowText(code.ToString());
}
);
}
catch (Exception ex)
{
LoadingUI.Hide();
Debug.LogError("取消设备共享失败: " + ex.Message);
}
}
public IEnumerator BackToHomePage()
{
LoadingUI.Show();
yield return new WaitForSeconds(2);
LoadingUI.ForceHide();
UIManager.Instance.OpenMainPage(UIManager.PageName.homePage);
}
}
}