scanFitWatch.vue 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685
  1. <template>
  2. <view class="container" :style="{ paddingTop: statusBarHeight + 'px' }">
  3. <!-- 背景装饰 -->
  4. <view class="bg-gradient"></view>
  5. <!-- 搜索列表页面 -->
  6. <view class="scan-section">
  7. <!-- 正在搜索设备 UI -->
  8. <view class="searching-box">
  9. <image class="search-icon" src="/static/images/pages_watch/icons/smartwatch_img.png" mode="aspectFit"></image>
  10. <view class="search-text-content">
  11. <view class="search-title">正在搜索设备...</view>
  12. <view class="search-subtitle">{{ currentSubtitle }}</view>
  13. </view>
  14. </view>
  15. <view class="header">
  16. <view class="title">搜索到{{ deviceList.length }}个设备</view>
  17. <view class="subtitle">请选择要连接的设备</view>
  18. </view>
  19. <view class="tips">
  20. 提示:手表“设置”-“系统信息”中,查看“Mac地址”,匹配下列设备名称。
  21. </view>
  22. <scroll-view scroll-y class="device-list">
  23. <view v-for="(item, index) in deviceList" :key="index" class="device-card">
  24. <image class="device-icon" src="/static/images/pages_watch/icons/smartwatch_img.png" mode="aspectFit"></image>
  25. <view class="device-info">
  26. <view class="device-name">{{ item.mac || '未知设备' }}</view>
  27. <view class="device-signal" v-show="item.alreadyConnected">
  28. 状态:{{connectionText(connectionState) }}
  29. </view>
  30. <view class="device-signal" v-show="!item.alreadyConnected">信号:{{ item.rssi }}</view>
  31. </view>
  32. <view class="connect-btn" @tap="startConnect(item)">{{ item.alreadyConnected ? '绑定' : '连接' }}</view>
  33. </view>
  34. </scroll-view>
  35. </view>
  36. <!-- 连接中弹窗 -->
  37. <u-popup :show="isConnecting" mode="bottom" round="24" :safeAreaInsetBottom="true" @close="closePopup">
  38. <view class="connecting-popup-content">
  39. <view class="popup-handle"></view>
  40. <view class="connecting-card">
  41. <image class="device-icon-small" src="/static/images/pages_watch/icons/smartwatch_img.png" mode="aspectFit"></image>
  42. <view>
  43. <view class="device-name-small">{{ connectingDevice ? connectingDevice.name : '未知设备' }}</view>
  44. <view class="device-name-small">{{ connectingDevice ? connectingDevice.mac : '' }}</view>
  45. </view>
  46. </view>
  47. <view class="status-header">
  48. <view class="status-title">{{ statusTitle }}</view>
  49. <view class="status-subtitle">{{ statusSubtitle }}</view>
  50. </view>
  51. <view class="watch-display">
  52. <image class="watch-large" src="/static/images/pages_watch/images/watch_img.png" mode="aspectFit"></image>
  53. </view>
  54. <view class="connect-tips">
  55. <view class="tip-title">提示:</view>
  56. <view class="tip-item">1、请同意设备的蓝牙配对请求;</view>
  57. <view class="tip-item">2、请同意设备的接收消息通知请求(设备上可能会有确认弹窗)。</view>
  58. </view>
  59. </view>
  60. </u-popup>
  61. </view>
  62. </template>
  63. <script>
  64. import {
  65. getWatchUserInfo,
  66. editMyfamily
  67. } from "@/api/pages_watch/user.js";
  68. import {
  69. editXHSDevice,
  70. } from "@/api/pages_watch/device.js"
  71. // 引入原生插件
  72. const fitCloudWatch = uni.requireNativePlugin('fitCloudWatch');
  73. export default {
  74. data() {
  75. return {
  76. statusBarHeight: 0,
  77. isConnecting: false,
  78. isScanning: false,
  79. deviceList: [],
  80. connectingDevice: null,
  81. currentSubtitle: '请确认设备在旁边',
  82. subtitleTimer: null,
  83. connectionState: 'DISCONNECTED', // CONNECTED, DISCONNECTED, CONNECTING
  84. fitCloudWatchUser: {},
  85. isFamily: false,
  86. selectUser: 0,
  87. xhsDeviceList: [],
  88. deviceType: 2, // 2新表
  89. statusTitle: '设备正在连接中...',
  90. statusSubtitle: '请勿离开本应用及本页面',
  91. retryCount: 0,
  92. maxRetries: 3
  93. }
  94. },
  95. computed: {
  96. connectionText() {
  97. const map = {
  98. 'CONNECTED': '已连接',
  99. 'DISCONNECTED': '未连接',
  100. 'CONNECTING': '连接中...'
  101. };
  102. return (item) => {
  103. return map[item];
  104. }
  105. }
  106. },
  107. onLoad(option) {
  108. this.selectUser = Number(option.selectUser || 0)
  109. this.isFamily = option.selectUser != '0';
  110. const sys = uni.getSystemInfoSync();
  111. this.statusBarHeight = sys.statusBarHeight || 0;
  112. this.startSubtitleRotation();
  113. this.getUser();
  114. },
  115. onShow() {
  116. this.registerGlobalEvents();
  117. this.checkCurrentConnectionState();
  118. },
  119. onHide() {
  120. this.stopScan();
  121. this.removeGlobalEvents();
  122. },
  123. onUnload() {
  124. this.stopScan();
  125. this.removeGlobalEvents();
  126. if (this.subtitleTimer) {
  127. clearInterval(this.subtitleTimer);
  128. }
  129. },
  130. methods: {
  131. getUser() {
  132. getWatchUserInfo({
  133. isFamily: false
  134. }).then(res => {
  135. if (res.code == 200) {
  136. this.fitCloudWatchUser = res.user;
  137. if (this.isFamily) {
  138. const otherDevice = this.fitCloudWatchUser.otherDevice ? JSON.parse(this.fitCloudWatchUser.otherDevice) : [];
  139. const index = this.selectUser - 1;
  140. const currentMemberDeviceStr = otherDevice[index]?.newXhsDeviceId || '';
  141. this.xhsDeviceList = currentMemberDeviceStr ? currentMemberDeviceStr.split(',').map(id => ({ newXhsDeviceId: id })) : [];
  142. } else {
  143. const deviceIds = this.fitCloudWatchUser.newXhsDeviceId ? this.fitCloudWatchUser.newXhsDeviceId.split(',') : [];
  144. this.xhsDeviceList = deviceIds.map(id => ({ newXhsDeviceId: id }));
  145. }
  146. }
  147. })
  148. },
  149. // 检查当前连接状态
  150. checkCurrentConnectionState() {
  151. this.deviceList = [];
  152. if (!fitCloudWatch) {
  153. this.startScan();
  154. return;
  155. }
  156. fitCloudWatch.getConnectionState({}, (res) => {
  157. console.log('当前连接状态:', res);
  158. if (res.state === 'CONNECTED' && res.mac) {
  159. this.connectionState = 'CONNECTED';
  160. const mac = res.mac;
  161. // 检查是否已经在 xhsDeviceList 中
  162. const isBound = this.xhsDeviceList.some(item => item.newXhsDeviceId === mac);
  163. if (!isBound) {
  164. // 如果没绑定,加入 deviceList 供用户点击“绑定”
  165. const connectedDevice = {
  166. mac: mac,
  167. name: res.name || '已连接设备',
  168. rssi: '--',
  169. alreadyConnected: true,
  170. connectionState: res.state
  171. };
  172. // 避免重复添加
  173. const index = this.deviceList.findIndex(item => item.mac === mac);
  174. if (index === -1) {
  175. this.deviceList.push(connectedDevice);
  176. } else {
  177. this.$set(this.deviceList, index, { ...this.deviceList[index], alreadyConnected: true });
  178. }
  179. }
  180. }
  181. // 无论是否已连接,都开启扫描以发现新设备
  182. this.startScan();
  183. });
  184. },
  185. registerGlobalEvents() {
  186. this.removeGlobalEvents();
  187. plus.globalEvent.addEventListener('onFitCloudDeviceFound', this.onDeviceFound);
  188. plus.globalEvent.addEventListener('onFitCloudConnectionStateChanged', this.onConnectionStateChanged);
  189. plus.globalEvent.addEventListener('onFitCloudConnectionError', this.onConnectionError);
  190. },
  191. removeGlobalEvents() {
  192. plus.globalEvent.removeEventListener('onFitCloudDeviceFound', this.onDeviceFound);
  193. plus.globalEvent.removeEventListener('onFitCloudConnectionStateChanged', this.onConnectionStateChanged);
  194. plus.globalEvent.removeEventListener('onFitCloudConnectionError', this.onConnectionError);
  195. },
  196. onDeviceFound(device) {
  197. console.log('onDeviceFound==:', device);
  198. const index = this.deviceList.findIndex(item => item.mac === device.mac);
  199. if (index === -1) {
  200. this.deviceList.push({ ...device, alreadyConnected: false });
  201. } else {
  202. // 如果原本是 alreadyConnected 的,保留这个状态
  203. const existing = this.deviceList[index];
  204. this.$set(this.deviceList, index, { ...device, alreadyConnected: existing.alreadyConnected || false });
  205. }
  206. },
  207. onConnectionStateChanged(res) {
  208. console.log('连接状态改变:', res);
  209. this.connectionState = res.state;
  210. if (res.state === 'CONNECTED') {
  211. this.retryCount = 0;
  212. this.statusTitle = '连接成功,正在绑定中...';
  213. this.statusSubtitle = '请耐心等待绑定结果';
  214. const mac = res.mac || (this.connectingDevice ? this.connectingDevice.mac : '');
  215. if (mac) {
  216. if(this.isConnecting) {
  217. // 弹窗打开才连接成功才自动绑定
  218. this.bindDevice(mac);
  219. } else {
  220. // 检查是否已经在 xhsDeviceList 中
  221. const isBound = this.xhsDeviceList.some(item => item.newXhsDeviceId === mac);
  222. if (!isBound) {
  223. // 如果没绑定,加入 deviceList 供用户点击“绑定”
  224. const connectedDevice = {
  225. mac: mac,
  226. name: res.name || '已连接设备',
  227. rssi: '--',
  228. alreadyConnected: true,
  229. connectionState: res.state
  230. };
  231. // 避免重复添加
  232. const index = this.deviceList.findIndex(item => item.mac === mac);
  233. if (index === -1) {
  234. this.deviceList.push(connectedDevice);
  235. } else {
  236. this.$set(this.deviceList, index, { ...this.deviceList[index], alreadyConnected: true });
  237. }
  238. }
  239. }
  240. }
  241. } else if (res.state === 'DISCONNECTED') {
  242. if (this.retryCount > 0 && this.retryCount < this.maxRetries) {
  243. // 正在重试中,忽略 DISCONNECTED 事件,让 onConnectionError 或下一次尝试处理
  244. return;
  245. }
  246. // 只有在没有重试或者重试完之后才置为关闭状态
  247. if (this.retryCount === 0 || this.retryCount >= this.maxRetries) {
  248. this.isConnecting = false;
  249. uni.showToast({ title: '已断开连接', icon: 'none' });
  250. }
  251. }
  252. },
  253. onConnectionError(res) {
  254. console.log('连接错误:', res);
  255. if (res.isRetry) {
  256. this.statusTitle = `连接重试中(${this.retryCount}/${this.maxRetries})...`;
  257. return;
  258. }
  259. if (this.retryCount < this.maxRetries) {
  260. this.retryCount++;
  261. this.statusTitle = `连接失败,正在第${this.retryCount}次重试...`;
  262. this.statusSubtitle = '请确保手表在手机附近';
  263. // 重新执行连接指令
  264. this.executeConnect(this.connectingDevice);
  265. } else {
  266. this.isConnecting = false;
  267. this.connectionState = 'DISCONNECTED';
  268. uni.showModal({
  269. title: '连接失败',
  270. content: '多次连接尝试失败,请检查手表是否已开启并靠近手机',
  271. showCancel: false,
  272. confirmText: '确定'
  273. });
  274. }
  275. },
  276. async startScan() {
  277. if (!fitCloudWatch) return;
  278. if (plus.os.name === 'Android') {
  279. const permissions = ['android.permission.ACCESS_FINE_LOCATION', 'android.permission.ACCESS_COARSE_LOCATION'];
  280. if (parseInt(plus.os.version) >= 12) {
  281. permissions.push('android.permission.BLUETOOTH_SCAN', 'android.permission.BLUETOOTH_CONNECT');
  282. }
  283. for (let p of permissions) {
  284. const granted = await new Promise(resolve => {
  285. plus.android.requestPermissions([p], res => resolve(res.granted.length > 0), () => resolve(false));
  286. });
  287. if (!granted) {
  288. uni.showToast({ title: '未获取蓝牙或定位权限', icon: 'none' });
  289. return;
  290. }
  291. }
  292. }
  293. this.isScanning = true;
  294. fitCloudWatch.startScan({}, (res) => {
  295. console.log('启动扫描==:', res);
  296. if (res.code !== 0) {
  297. this.isScanning = false;
  298. uni.showToast({ title: '启动扫描失败', icon: 'none' });
  299. }
  300. });
  301. },
  302. stopScan() {
  303. console.log('关闭扫描==:');
  304. if (!fitCloudWatch) return;
  305. fitCloudWatch.stopScan({}, () => {
  306. this.isScanning = false;
  307. });
  308. },
  309. startSubtitleRotation() {
  310. const subtitles = ['请确认设备在旁边', '请打开蓝牙和定位'];
  311. let index = 0;
  312. this.subtitleTimer = setInterval(() => {
  313. index = (index + 1) % subtitles.length;
  314. this.currentSubtitle = subtitles[index];
  315. }, 4000);
  316. },
  317. startConnect(device) {
  318. if (this.connectionState === 'CONNECTED') {
  319. // 如果点击的是已经连接的设备,则直接去绑定
  320. if (device.alreadyConnected || (this.connectingDevice && this.connectingDevice.mac === device.mac)) {
  321. this.bindDevice(device.mac);
  322. return;
  323. }
  324. uni.showToast({ title: '已有设备连接', icon: 'none' });
  325. return;
  326. }
  327. this.stopScan();
  328. this.connectingDevice = device;
  329. this.isConnecting = true;
  330. this.retryCount = 0;
  331. this.statusTitle = '设备正在连接中...';
  332. this.statusSubtitle = '请勿离开本应用及本页面';
  333. this.executeConnect(device);
  334. },
  335. executeConnect(device) {
  336. if (!device || !device.mac) return;
  337. this.connectionState = 'CONNECTING';
  338. const userId = (this.fitCloudWatchUser.userId || 'test') + '_' + device.mac;
  339. fitCloudWatch.connect({
  340. mac: device.mac,
  341. userId: userId,
  342. isBind: true,
  343. sex: this.fitCloudWatchUser.sex || true,
  344. age: this.fitCloudWatchUser.age || 25,
  345. height: this.fitCloudWatchUser.height || 175,
  346. weight: this.fitCloudWatchUser.weight || 70
  347. }, (res) => {
  348. if (res.code !== 0) {
  349. // 指令发送失败也尝试重试
  350. if (this.retryCount < this.maxRetries) {
  351. this.retryCount++;
  352. this.statusTitle = `指令发送失败,正在进行第${this.retryCount}次尝试...`;
  353. setTimeout(() => this.executeConnect(device), 2000);
  354. } else {
  355. this.isConnecting = false;
  356. this.connectionState = 'DISCONNECTED';
  357. uni.showToast({ title: '发送连接指令失败,请检查蓝牙状态', icon: 'none' });
  358. }
  359. }
  360. });
  361. },
  362. bindDevice(mac) {
  363. this.statusTitle = '正在绑定设备...';
  364. this.statusSubtitle = '正在同步云端数据';
  365. if (this.xhsDeviceList.some(item => item.newXhsDeviceId === mac)) {
  366. this.statusTitle = '设备已绑定';
  367. this.statusSubtitle = '即将返回主页';
  368. setTimeout(() => {
  369. uni.$emit('scanFitWatch')
  370. uni.navigateBack();
  371. }, 1500);
  372. return;
  373. }
  374. const newXhsDeviceId = this.xhsDeviceList.map(item => item.newXhsDeviceId);
  375. newXhsDeviceId.push(mac);
  376. if(!this.isConnecting) {
  377. uni.showLoading({
  378. title: '绑定中'
  379. });
  380. }
  381. const handleBindResult = (res) => {
  382. uni.hideLoading()
  383. if (res.code == 200) {
  384. this.statusTitle = '绑定成功';
  385. this.statusSubtitle = '正在跳转...';
  386. uni.showToast({ title: '绑定成功', icon: 'success' });
  387. setTimeout(() => {
  388. uni.$emit('scanFitWatch')
  389. uni.navigateBack()
  390. }, 1500);
  391. } else {
  392. this.statusTitle = '绑定失败';
  393. this.statusSubtitle = res.msg || '服务器异常';
  394. uni.showModal({
  395. title: '绑定失败',
  396. content: '设备已连接但绑定失败:' + (res.msg || '未知错误'),
  397. confirmText: '重试',
  398. cancelText: '取消',
  399. success: (modalRes) => {
  400. if (modalRes.confirm) {
  401. this.bindDevice(mac);
  402. } else {
  403. this.isConnecting = false;
  404. }
  405. }
  406. });
  407. }
  408. };
  409. if (this.isFamily) {
  410. console.log("qxj 222");
  411. const otherDevice = JSON.parse(this.fitCloudWatchUser.otherDevice || '[]');
  412. const index = this.selectUser - 1;
  413. // 安全判断:如果成员不存在,初始化一个空对象防止报错
  414. if (!otherDevice[index]) {
  415. otherDevice[index] = {};
  416. }
  417. // 赋值
  418. otherDevice[index] = {
  419. ...otherDevice[index],
  420. newXhsDeviceId: newXhsDeviceId.join(',')
  421. }
  422. editMyfamily({ otherDevice: JSON.stringify(otherDevice) })
  423. .then(handleBindResult)
  424. .catch(() => handleBindResult({ code: 500, msg: '网络连接失败' }));
  425. } else {
  426. // this.bindDevice(mac);
  427. // return;
  428. console.log("qxj 111")
  429. editXHSDevice({
  430. newXhsDeviceId: newXhsDeviceId.join(','),
  431. deviceType: this.deviceType
  432. }).then(handleBindResult)
  433. .catch(() => handleBindResult({ code: 500, msg: '网络连接失败' }));
  434. }
  435. },
  436. closePopup() {
  437. // 如果正在连接,允许关闭弹窗但不断开蓝牙?或者关闭时断开?
  438. // 参考 fitWatch2,通常连接中不建议关闭,或者关闭即放弃连接
  439. this.isConnecting = false;
  440. if (this.connectionState === 'CONNECTING') {
  441. fitCloudWatch.disconnect({}, () => {});
  442. this.connectionState = 'DISCONNECTED';
  443. }
  444. }
  445. }
  446. }
  447. </script>
  448. <style lang="scss" scoped>
  449. .container {
  450. min-height: 100vh;
  451. position: relative;
  452. background-color: #F5F7FA;
  453. overflow: hidden;
  454. }
  455. .bg-gradient {
  456. position: absolute;
  457. top: 0;
  458. left: 0;
  459. width: 100%;
  460. height: 600rpx;
  461. background: linear-gradient(180deg, #FFEBD6 0%, rgba(245, 247, 250, 0) 100%);
  462. z-index: 0;
  463. }
  464. .scan-section {
  465. position: relative;
  466. z-index: 1;
  467. padding: 40rpx;
  468. }
  469. .searching-box {
  470. display: flex;
  471. align-items: center;
  472. padding: 40rpx 0;
  473. margin-top: 10rpx;
  474. .search-icon {
  475. width: 120rpx;
  476. height: 120rpx;
  477. margin-right: 30rpx;
  478. }
  479. .search-text-content {
  480. flex: 1;
  481. .search-title {
  482. font-size: 34rpx;
  483. font-weight: bold;
  484. color: #3B4144;
  485. margin-bottom: 12rpx;
  486. }
  487. .search-subtitle {
  488. font-size: 26rpx;
  489. color: #FF7700;
  490. }
  491. }
  492. }
  493. .connecting-popup-content {
  494. padding: 40rpx;
  495. background: linear-gradient(180deg, #FFEBD6 0%, #F5F7FA 30%, #F5F7FA 100%);
  496. border-radius: 24rpx 24rpx 0 0;
  497. min-height: 85vh;
  498. .popup-handle {
  499. width: 80rpx;
  500. height: 8rpx;
  501. background-color: rgba(0,0,0,0.1);
  502. border-radius: 4rpx;
  503. margin: 0 auto 40rpx;
  504. }
  505. }
  506. .header {
  507. text-align: center;
  508. margin-top: 60rpx;
  509. margin-bottom: 60rpx;
  510. .title {
  511. font-size: 44rpx;
  512. font-weight: bold;
  513. color: #333;
  514. margin-bottom: 16rpx;
  515. }
  516. .subtitle {
  517. font-size: 28rpx;
  518. color: #999;
  519. }
  520. }
  521. .tips {
  522. font-size: 24rpx;
  523. color: #999;
  524. margin-bottom: 40rpx;
  525. line-height: 1.5;
  526. }
  527. .device-list {
  528. height: calc(100vh - 400rpx);
  529. }
  530. .device-card {
  531. background: #FFFFFF;
  532. border-radius: 24rpx;
  533. padding: 30rpx;
  534. margin-bottom: 24rpx;
  535. display: flex;
  536. align-items: center;
  537. box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
  538. .device-icon {
  539. width: 80rpx;
  540. height: 80rpx;
  541. margin-right: 24rpx;
  542. }
  543. .device-info {
  544. flex: 1;
  545. .device-name {
  546. font-size: 32rpx;
  547. font-weight: bold;
  548. color: #333;
  549. margin-bottom: 8rpx;
  550. }
  551. .device-signal {
  552. font-size: 24rpx;
  553. color: #999;
  554. }
  555. }
  556. .connect-btn {
  557. background: linear-gradient(90deg, #FF9933 0%, #FF7700 100%);
  558. color: #FFFFFF;
  559. font-size: 28rpx;
  560. padding: 12rpx 40rpx;
  561. border-radius: 40rpx;
  562. box-shadow: 0 4rpx 8rpx rgba(255, 119, 0, 0.3);
  563. }
  564. }
  565. // 连接中页面样式
  566. .connecting-card {
  567. background: #FFFFFF;
  568. border-radius: 24rpx;
  569. padding: 20rpx 40rpx;
  570. margin-top: 20rpx;
  571. display: flex;
  572. align-items: center;
  573. box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
  574. .device-icon-small {
  575. width: 60rpx;
  576. height: 60rpx;
  577. margin-right: 20rpx;
  578. }
  579. .device-name-small {
  580. font-size: 30rpx;
  581. color: #333;
  582. font-weight: 500;
  583. }
  584. }
  585. .status-header {
  586. text-align: center;
  587. margin-top: 80rpx;
  588. .status-title {
  589. font-size: 44rpx;
  590. font-weight: bold;
  591. color: #333;
  592. margin-bottom: 20rpx;
  593. }
  594. .status-subtitle {
  595. font-size: 28rpx;
  596. color: #FF7700;
  597. font-weight: 500;
  598. }
  599. }
  600. .watch-display {
  601. display: flex;
  602. justify-content: center;
  603. margin-top: 60rpx;
  604. margin-bottom: 80rpx;
  605. .watch-large {
  606. width: 360rpx;
  607. height: 360rpx;
  608. }
  609. }
  610. .connect-tips {
  611. padding: 0 40rpx;
  612. .tip-title {
  613. font-size: 28rpx;
  614. color: #999;
  615. margin-bottom: 20rpx;
  616. }
  617. .tip-item {
  618. font-size: 28rpx;
  619. color: #999;
  620. margin-bottom: 12rpx;
  621. line-height: 1.4;
  622. }
  623. }
  624. </style>