鸿蒙NEXT开发案例:二维码的生成与辨认

打印 上一主题 下一主题

主题 963|帖子 963|积分 2889


【弁言】
在本篇文章中,我们将探讨如何在鸿蒙NEXT平台上实现二维码的生成与辨认功能。通过使用ArkUI组件库和相关的媒体库,我们将创建一个简单的应用步伐,用户可以生成二维码并扫描辨认。
【环境准备】
• 操纵体系:Windows 10
• 开发工具:DevEco Studio NEXT Beta1 Build Version: 5.0.3.806
• 目标设备:华为Mate60 Pro
• 开发语言:ArkTS
• 框架:ArkUI
• API版本:API 12
• 权限:ohos.permission.WRITE_IMAGEVIDEO(为实现将图片保存至相册功能)
【项目介绍】
1. 项目结构

我们首先界说一个名为QrCodeGeneratorAndScanner的组件,使用@Component装饰器进行标记。该组件包含多个状态变量和方法,用于处置惩罚二维码的生成、辨认和剪贴板操纵。
2. 组件状态

组件的状态包括:


  • buttonOptions: 界说分段按钮的选项,用于切换生成和辨认二维码的功能。
  • inputText: 用户输入的文本,用于生成二维码。
  • scanResult: 扫描结果文本。
  • scanResultObject: 存储扫描结果的对象。
3. 用户界面构建

在build方法中,我们使用Column和Row布局来构建用户界面。重要包含以下部分:


  • 分段按钮:用户可以选择生成二维码或辨认二维码。
  • 输入地区:用户可以输入文本并生成二维码。
  • 二维码显示:根据输入文本生成二维码。
  • 扫描地区:用户可以通过相机扫描二维码或从图库选择图片进行辨认。
4. 二维码生成

二维码生成使用QRCode组件,输入文本通过this.inputText传递。用户输入后,二维码会实时更新。
5. 二维码辨认

二维码辨认功能通过scanBarcode模块实现。用户可以点击“扫一扫”按钮,启动相机进行扫描,或选择图库中的图片进行辨认。辨认结果将显示在界面上,并提供复制功能。
6. 剪贴板操纵

用户可以将扫描结果复制到剪贴板,使用pasteboard模块实现。点击“复制”按钮后,扫描结果将被复制,用户会收到提示。
【完整代码】
填写权限使用声明字符串:src/main/resources/base/element/string.json
  1. {
  2.   "string": [
  3.     {
  4.       "name": "module_desc",
  5.       "value": "module description"
  6.     },
  7.     {
  8.       "name": "EntryAbility_desc",
  9.       "value": "description"
  10.     },
  11.     {
  12.       "name": "EntryAbility_label",
  13.       "value": "label"
  14.     },
  15.     {
  16.       "name": "WRITE_IMAGEVIDEO_info",
  17.       "value": "保存功能需要该权限"
  18.     }
  19.   ]
  20. }
复制代码
设置权限:src/main/module.json5
  1. {
  2.   "module": {
  3.     "requestPermissions": [
  4.       {
  5.         "name": 'ohos.permission.WRITE_IMAGEVIDEO',
  6.         "reason": "$string:WRITE_IMAGEVIDEO_info",
  7.         "usedScene": {
  8.         }
  9.       }
  10.     ],
  11. //... ...
复制代码
示例代码:src/main/ets/pages/Index.ets
  1. import {
  2.   componentSnapshot, // 组件快照
  3.   promptAction, // 提示操作
  4.   SegmentButton, // 分段按钮
  5.   SegmentButtonItemTuple, // 分段按钮项元组
  6.   SegmentButtonOptions // 分段按钮选项
  7. } from '@kit.ArkUI'; // 引入 ArkUI 组件库
  8. import { photoAccessHelper } from '@kit.MediaLibraryKit'; // 引入 MediaLibraryKit 中的照片访问助手
  9. import { common } from '@kit.AbilityKit'; // 引入 AbilityKit 中的通用功能
  10. import { fileIo as fs } from '@kit.CoreFileKit'; // 引入 CoreFileKit 中的文件 I/O 模块
  11. import { image } from '@kit.ImageKit'; // 引入 ImageKit 中的图像处理模块
  12. import { BusinessError, pasteboard } from '@kit.BasicServicesKit'; // 引入 BasicServicesKit 中的业务错误和剪贴板操作
  13. import { hilog } from '@kit.PerformanceAnalysisKit'; // 引入 PerformanceAnalysisKit 中的性能分析模块
  14. import { detectBarcode, scanBarcode } from '@kit.ScanKit'; // 引入 ScanKit 中的条形码识别模块
  15. @Entry
  16.   // 入口标记
  17. @Component
  18.   // 组件标记
  19. struct QrCodeGeneratorAndScanner { // 定义二维码生成与识别组件
  20.   @State private buttonOptions: SegmentButtonOptions = SegmentButtonOptions.capsule({
  21.     // 定义分段按钮选项
  22.     buttons: [{ text: '生成二维码' }, { text: '识别二维码' }] as SegmentButtonItemTuple, // 按钮文本
  23.     multiply: false, // 不允许多选
  24.     fontColor: Color.White, // 字体颜色为白色
  25.     selectedFontColor: Color.White, // 选中字体颜色为白色
  26.     selectedBackgroundColor: Color.Orange, // 选中背景颜色为橙色
  27.     backgroundColor: "#d5d5d5", // 背景颜色
  28.     backgroundBlurStyle: BlurStyle.BACKGROUND_THICK // 背景模糊样式
  29.   })
  30.   @State private sampleText: string = 'hello world'; // 示例文本
  31.   @State private inputText: string = ""; // 输入文本
  32.   @State private scanResult: string = ""; // 扫描结果
  33.   @State @Watch('selectIndexChanged') selectIndex: number = 0 // 选择索引
  34.   @State @Watch('selectedIndexesChanged') selectedIndexes: number[] = [0]; // 选中索引数组
  35.   private qrCodeId: string = "qrCodeId" // 二维码 ID
  36.   @State private scanResultObject: scanBarcode.ScanResult = ({} as scanBarcode.ScanResult) // 扫描结果对象
  37.   @State private textColor: string = "#2e2e2e"; // 文本颜色
  38.   @State private shadowColor: string = "#d5d5d5"; // 阴影颜色
  39.   @State private basePadding: number = 30; // 基础内边距
  40.   selectedIndexesChanged() { // 选中索引改变事件
  41.     console.info(`this.selectedIndexes[0]:${this.selectedIndexes[0]}`)
  42.     this.selectIndex = this.selectedIndexes[0]
  43.   }
  44.   selectIndexChanged() { // 选择索引改变事件
  45.     console.info(`selectIndex:${this.selectIndex}`)
  46.     this.selectedIndexes[0] = this.selectIndex
  47.   }
  48.   private copyToClipboard(text: string): void { // 复制文本到剪贴板
  49.     const pasteboardData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_PLAIN, text); // 创建剪贴板数据
  50.     const systemPasteboard = pasteboard.getSystemPasteboard(); // 获取系统剪贴板
  51.     systemPasteboard.setData(pasteboardData); // 设置数据
  52.     promptAction.showToast({ message: '已复制' }); // 弹出提示消息
  53.   }
  54.   build() { // 构建界面
  55.     Column() { // 列布局
  56.       SegmentButton({ // 分段按钮
  57.         options: this.buttonOptions, // 选项
  58.         selectedIndexes: this.selectedIndexes // 选中索引
  59.       }).width('400lpx').margin({ top: 20 }) // 设置宽度和外边距
  60.       Tabs({ index: this.selectIndex }) { // 选项卡
  61.         TabContent() { // 选项卡内容
  62.           Scroll() { // 滚动视图
  63.             Column() { // 列布局
  64.               Column() { // 列布局
  65.                 Row() { // 行布局
  66.                   Text('示例') // 文本
  67.                     .fontColor("#5871ce") // 字体颜色
  68.                     .fontSize(16) // 字体大小
  69.                     .padding(`${this.basePadding / 2}lpx`) // 内边距
  70.                     .backgroundColor("#f2f1fd") // 背景颜色
  71.                     .borderRadius(5) // 边框圆角
  72.                     .clickEffect({ level: ClickEffectLevel.LIGHT, scale: 0.8 }) // 点击效果
  73.                     .onClick(() => { // 点击事件
  74.                       this.inputText = this.sampleText; // 设置输入文本为示例文本
  75.                     });
  76.                   Blank(); // 空白占位
  77.                   Text('清空') // 清空按钮
  78.                     .fontColor("#e48742") // 字体颜色
  79.                     .fontSize(16) // 字体大小
  80.                     .padding(`${this.basePadding / 2}lpx`) // 内边距
  81.                     .clickEffect({ level: ClickEffectLevel.LIGHT, scale: 0.8 }) // 点击效果
  82.                     .backgroundColor("#ffefe6") // 背景颜色
  83.                     .borderRadius(5) // 边框圆角
  84.                     .onClick(() => { // 点击事件
  85.                       this.inputText = ""; // 清空输入文本
  86.                     });
  87.                 }
  88.                 .height(45) // 设置高度
  89.                 .justifyContent(FlexAlign.SpaceBetween) // 主轴对齐方式
  90.                 .width('100%'); // 设置宽度
  91.                 Divider(); // 分隔线
  92.                 TextArea({ text: $$this.inputText, placeholder: `请输入内容` }) // 文本输入框
  93.                   .width(`${650 - this.basePadding * 2}lpx`) // 设置宽度
  94.                   .height(100) // 设置高度
  95.                   .fontSize(16) // 字体大小
  96.                   .caretColor(this.textColor) // 光标颜色
  97.                   .fontColor(this.textColor) // 字体颜色
  98.                   .margin({ top: `${this.basePadding}lpx` }) // 外边距
  99.                   .padding(0) // 内边距
  100.                   .backgroundColor(Color.Transparent) // 背景颜色
  101.                   .borderRadius(0) // 边框圆角
  102.                   .textAlign(TextAlign.JUSTIFY); // 文本对齐方式
  103.               }
  104.               .alignItems(HorizontalAlign.Start) // 交叉轴对齐方式
  105.               .width('650lpx') // 设置宽度
  106.               .padding(`${this.basePadding}lpx`) // 内边距
  107.               .borderRadius(10) // 边框圆角
  108.               .backgroundColor(Color.White) // 背景颜色
  109.               .shadow({ // 阴影
  110.                 radius: 10, // 阴影半径
  111.                 color: this.shadowColor, // 阴影颜色
  112.                 offsetX: 0, // X 轴偏移
  113.                 offsetY: 0 // Y 轴偏移
  114.               });
  115.               Row() { // 行布局
  116.                 QRCode(this.inputText) // 二维码组件
  117.                   .width('300lpx') // 设置宽度
  118.                   .aspectRatio(1) // 设置宽高比
  119.                   .id(this.qrCodeId) // 设置 ID
  120.                 SaveButton() // 保存按钮
  121.                   .onClick(async (_event: ClickEvent, result: SaveButtonOnClickResult) => { // 点击事件
  122.                     if (result === SaveButtonOnClickResult.SUCCESS) { // 如果保存成功
  123.                       const context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; // 获取上下文
  124.                       let helper = photoAccessHelper.getPhotoAccessHelper(context); // 获取照片访问助手
  125.                       try { // 尝试
  126.                         let uri = await helper.createAsset(photoAccessHelper.PhotoType.IMAGE, 'jpg'); // 创建图片资源
  127.                         let file = await fs.open(uri, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE); // 打开文件
  128.                         componentSnapshot.get(this.qrCodeId).then((pixelMap) => { // 获取二维码快照
  129.                           let packOpts: image.PackingOption = { format: 'image/png', quality: 100 } // 打包选项
  130.                           const imagePacker: image.ImagePacker = image.createImagePacker(); // 创建图像打包器
  131.                           return imagePacker.packToFile(pixelMap, file.fd, packOpts).finally(() => { // 打包并保存文件
  132.                             imagePacker.release(); // 释放打包器
  133.                             fs.close(file.fd); // 关闭文件
  134.                             promptAction.showToast({ // 弹出提示消息
  135.                               message: '图片已保存至相册', // 提示内容
  136.                               duration: 2000 // 持续时间
  137.                             });
  138.                           });
  139.                         })
  140.                       } catch (error) { // 捕获错误
  141.                         const err: BusinessError = error as BusinessError; // 转换为业务错误
  142.                         console.error(`Failed to save photo. Code is ${err.code}, message is ${err.message}`); // 打印错误信息
  143.                       }
  144.                     } else { // 如果保存失败
  145.                       promptAction.showToast({ // 弹出提示消息
  146.                         message: '设置权限失败!', // 提示内容
  147.                         duration: 2000 // 持续时间
  148.                       });
  149.                     }
  150.                   })
  151.               }
  152.               .visibility(this.inputText ? Visibility.Visible : Visibility.Hidden) // 根据输入文本设置可见性
  153.               .justifyContent(FlexAlign.SpaceBetween) // 主轴对齐方式
  154.               .width('650lpx') // 设置宽度
  155.               .padding(`${this.basePadding}lpx`) // 内边距
  156.               .margin({ top: `${this.basePadding}lpx` }) // 外边距
  157.               .borderRadius(10) // 边框圆角
  158.               .backgroundColor(Color.White) // 背景颜色
  159.               .shadow({ // 阴影
  160.                 radius: 10, // 阴影半径
  161.                 color: this.shadowColor, // 阴影颜色
  162.                 offsetX: 0, // X 轴偏移
  163.                 offsetY: 0 // Y 轴偏移
  164.               });
  165.             }.padding({ top: 20, bottom: 20 }) // 设置内边距
  166.             .width('100%') // 设置宽度
  167.           }.scrollBar(BarState.Off) // 禁用滚动条
  168.           .align(Alignment.Top) // 顶部对齐
  169.           .height('100%') // 设置高度
  170.         }
  171.         TabContent() { // 第二个选项卡内容
  172.           Scroll() { // 滚动视图
  173.             Column() { // 列布局
  174.               Row() { // 行布局
  175.                 Text('扫一扫') // 扫一扫文本
  176.                   .fontSize(20) // 字体大小
  177.                   .textAlign(TextAlign.Center) // 文本居中对齐
  178.                   .fontColor("#5871ce") // 字体颜色
  179.                   .backgroundColor("#f2f1fd") // 背景颜色
  180.                   .clickEffect({ scale: 0.8, level: ClickEffectLevel.LIGHT }) // 点击效果
  181.                   .borderRadius(10) // 边框圆角
  182.                   .height('250lpx') // 设置高度
  183.                   .layoutWeight(1) // 布局权重
  184.                   .onClick(() => { // 点击事件
  185.                     if (canIUse('SystemCapability.Multimedia.Scan.ScanBarcode')) { // 检查是否支持扫描
  186.                       try { // 尝试
  187.                         scanBarcode.startScanForResult(getContext(this), { // 开始扫描
  188.                           enableMultiMode: true, // 启用多模式
  189.                           enableAlbum: true // 启用相册选择
  190.                         },
  191.                           (error: BusinessError, result: scanBarcode.ScanResult) => { // 扫描结果回调
  192.                             if (error) { // 如果发生错误
  193.                               hilog.error(0x0001, '[Scan CPSample]', // 记录错误日志
  194.                                 `Failed to get ScanResult by callback with options. Code: ${error.code}, message: ${error.message}`);
  195.                               return; // 退出
  196.                             }
  197.                             hilog.info(0x0001, '[Scan CPSample]', // 记录成功日志
  198.                               `Succeeded in getting ScanResult by callback with options, result is ${JSON.stringify(result)}`);
  199.                             this.scanResultObject = result; // 设置扫描结果对象
  200.                             this.scanResult = result.originalValue ? result.originalValue : '无法识别'; // 设置扫描结果文本
  201.                           });
  202.                       } catch (error) { // 捕获错误
  203.                         hilog.error(0x0001, '[Scan CPSample]', // 记录错误日志
  204.                           `Failed to start the scanning service. Code:${error.code}, message: ${error.message}`);
  205.                       }
  206.                     } else { // 如果不支持扫描
  207.                       promptAction.showToast({ message: '当前设备不支持二维码扫描' }); // 弹出提示消息
  208.                     }
  209.                   });
  210.                 Line().width(`${this.basePadding}lpx`).aspectRatio(1); // 分隔线
  211.                 Text('图库选') // 图库选择文本
  212.                   .fontSize(20) // 字体大小
  213.                   .textAlign(TextAlign.Center) // 文本居中对齐
  214.                   .fontColor("#e48742") // 字体颜色
  215.                   .backgroundColor("#ffefe6") // 背景颜色
  216.                   .borderRadius(10) // 边框圆角
  217.                   .clickEffect({ scale: 0.8, level: ClickEffectLevel.LIGHT }) // 点击效果
  218.                   .height('250lpx') // 设置高度
  219.                   .layoutWeight(1) // 布局权重
  220.                   .onClick(() => { // 点击事件
  221.                     if (canIUse('SystemCapability.Multimedia.Scan.ScanBarcode')) { // 检查是否支持扫描
  222.                       let photoOption = new photoAccessHelper.PhotoSelectOptions(); // 创建照片选择选项
  223.                       photoOption.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE; // 设置 MIME 类型
  224.                       photoOption.maxSelectNumber = 1; // 设置最大选择数量
  225.                       let photoPicker = new photoAccessHelper.PhotoViewPicker(); // 创建照片选择器
  226.                       photoPicker.select(photoOption).then((result) => { // 选择照片
  227.                         let inputImage: detectBarcode.InputImage = { uri: result.photoUris[0] }; // 获取选中的图片 URI
  228.                         try { // 尝试
  229.                           detectBarcode.decode(inputImage, // 解码条形码
  230.                             (error: BusinessError, result: Array<scanBarcode.ScanResult>) => { // 解码结果回调
  231.                               if (error && error.code) { // 如果发生错误
  232.                                 hilog.error(0x0001, '[Scan Sample]', // 记录错误日志
  233.                                   `Failed to get ScanResult by callback. Code: ${error.code}, message: ${error.message}`);
  234.                                 return; // 退出
  235.                               }
  236.                               hilog.info(0x0001, '[Scan Sample]', // 记录成功日志
  237.                                 `Succeeded in getting ScanResult by callback, result is ${JSON.stringify(result, null, '\u00A0\u00A0')}`);
  238.                               if (result.length > 0) { // 如果有结果
  239.                                 this.scanResultObject = result[0]; // 设置扫描结果对象
  240.                                 this.scanResult = result[0].originalValue ? result[0].originalValue : '无法识别'; // 设置扫描结果文本
  241.                               } else { // 如果没有结果
  242.                                 this.scanResult = '不存在二维码'; // 设置结果文本
  243.                               }
  244.                             });
  245.                         } catch (error) { // 捕获错误
  246.                           hilog.error(0x0001, '[Scan Sample]', // 记录错误日志
  247.                             `Failed to detect Barcode. Code: ${error.code}, message: ${error.message}`);
  248.                         }
  249.                       });
  250.                     } else { // 如果不支持扫描
  251.                       promptAction.showToast({ message: '当前设备不支持二维码扫描' }); // 弹出提示消息
  252.                     }
  253.                   });
  254.               }
  255.               .justifyContent(FlexAlign.SpaceEvenly) // 主轴对齐方式
  256.               .width('650lpx') // 设置宽度
  257.               .padding(`${this.basePadding}lpx`) // 内边距
  258.               .borderRadius(10) // 边框圆角
  259.               .backgroundColor(Color.White) // 背景颜色
  260.               .shadow({ // 阴影
  261.                 radius: 10, // 阴影半径
  262.                 color: this.shadowColor, // 阴影颜色
  263.                 offsetX: 0, // X 轴偏移
  264.                 offsetY: 0 // Y 轴偏移
  265.               });
  266.               Column() { // 列布局
  267.                 Row() { // 行布局
  268.                   Text(`解析结果:\n${this.scanResult}`) // 显示解析结果文本
  269.                     .fontColor(this.textColor) // 设置字体颜色
  270.                     .fontSize(18) // 设置字体大小
  271.                     .layoutWeight(1) // 设置布局权重
  272.                   Text('复制') // 复制按钮文本
  273.                     .fontColor(Color.White) // 设置字体颜色为白色
  274.                     .fontSize(16) // 设置字体大小
  275.                     .padding(`${this.basePadding / 2}lpx`) // 设置内边距
  276.                     .backgroundColor("#0052d9") // 设置背景颜色
  277.                     .borderRadius(5) // 设置边框圆角
  278.                     .clickEffect({ level: ClickEffectLevel.LIGHT, scale: 0.8 }) // 设置点击效果
  279.                     .onClick(() => { // 点击事件
  280.                       this.copyToClipboard(this.scanResult); // 复制扫描结果到剪贴板
  281.                     });
  282.                 }.constraintSize({ minHeight: 45 }) // 设置最小高度约束
  283.                 .justifyContent(FlexAlign.SpaceBetween) // 设置主轴对齐方式
  284.                 .width('100%'); // 设置宽度为100%
  285.               }
  286.               .visibility(this.scanResult ? Visibility.Visible : Visibility.Hidden) // 根据扫描结果设置可见性
  287.               .alignItems(HorizontalAlign.Start) // 设置交叉轴对齐方式
  288.               .width('650lpx') // 设置宽度
  289.               .padding(`${this.basePadding}lpx`) // 设置内边距
  290.               .margin({ top: `${this.basePadding}lpx` }) // 设置外边距
  291.               .borderRadius(10) // 设置边框圆角
  292.               .backgroundColor(Color.White) // 设置背景颜色为白色
  293.               .shadow({ // 设置阴影
  294.                 radius: 10, // 设置阴影半径
  295.                 color: this.shadowColor, // 设置阴影颜色
  296.                 offsetX: 0, // 设置X轴偏移
  297.                 offsetY: 0 // 设置Y轴偏移
  298.               });
  299.               Column() { // 列布局
  300.                 Row() { // 行布局
  301.                   Text(`完整结果:`).fontColor(this.textColor).fontSize(18).layoutWeight(1) // 显示完整结果文本
  302.                 }.constraintSize({ minHeight: 45 }) // 设置最小高度约束
  303.                 .justifyContent(FlexAlign.SpaceBetween) // 设置主轴对齐方式
  304.                 .width('100%'); // 设置宽度为100%
  305.                 Divider().margin({ top: 2, bottom: 15 }); // 添加分隔线并设置外边距
  306.                 Row() { // 行布局
  307.                   Text(`${JSON.stringify(this.scanResultObject, null, '\u00A0\u00A0')}`) // 显示完整扫描结果
  308.                     .fontColor(this.textColor) // 设置字体颜色
  309.                     .fontSize(18) // 设置字体大小
  310.                     .layoutWeight(1) // 设置布局权重
  311.                     .copyOption(CopyOptions.LocalDevice); // 设置复制选项
  312.                 }.constraintSize({ minHeight: 45 }) // 设置最小高度约束
  313.                 .justifyContent(FlexAlign.SpaceBetween) // 设置主轴对齐方式
  314.                 .width('100%'); // 设置宽度为100%
  315.               }
  316.               .visibility(this.scanResult ? Visibility.Visible : Visibility.Hidden) // 根据扫描结果设置可见性
  317.               .alignItems(HorizontalAlign.Start) // 设置交叉轴对齐方式
  318.               .width('650lpx') // 设置宽度
  319.               .padding(`${this.basePadding}lpx`) // 设置内边距
  320.               .margin({ top: `${this.basePadding}lpx` }) // 设置外边距
  321.               .borderRadius(10) // 设置边框圆角
  322.               .backgroundColor(Color.White) // 设置背景颜色为白色
  323.               .shadow({ // 设置阴影
  324.                 radius: 10, // 设置阴影半径
  325.                 color: this.shadowColor, // 设置阴影颜色
  326.                 offsetX: 0, // 设置X轴偏移
  327.                 offsetY: 0 // 设置Y轴偏移
  328.               });
  329.             }
  330.             .padding({ top: 20, bottom: 20 }) // 设置内边距
  331.             .width('100%') // 设置宽度为100%
  332.           }.scrollBar(BarState.Off) // 禁用滚动条
  333.           .align(Alignment.Top) // 顶部对齐
  334.           .height('100%') // 设置高度为100%
  335.         }
  336.       }
  337.       .barHeight(0) // 设置选项卡条高度为0
  338.       .tabIndex(this.selectIndex) // 设置当前选中的索引
  339.       .width('100%') // 设置宽度为100%
  340.       .layoutWeight(1) // 设置布局权重
  341.       .onChange((index: number) => { // 选项卡变化事件
  342.         this.selectIndex = index; // 更新选择的索引
  343.       });
  344.     }
  345.     .height('100%') // 设置高度为100%
  346.     .width('100%') // 设置宽度为100%
  347.     .backgroundColor("#f4f8fb"); // 设置背景颜色
  348.   }
  349. }
复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

罪恶克星

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表