RanNumberView.ets 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. import { it } from '@ohos/hypium';
  2. import { IBestToast, YTAvoid, YTButton, YTHeader } from 'basic'
  3. import { LengthMetrics, promptAction } from '@kit.ArkUI';
  4. @Builder
  5. function RanNumberViewBuilder(){
  6. NavDestination(){
  7. RanNumberView()
  8. }.title("随机数")
  9. .hideTitleBar(true)
  10. }
  11. @Component
  12. struct RanNumberView{
  13. @StorageProp(YTAvoid.SAFE_TOP_KEY) safeBottom: number = 0
  14. // 存储生成的随机数字符串
  15. @State private generatedNumbers: string = '';
  16. // 应用的主题色
  17. @State private primaryColor: string = '#fea024';
  18. // 文本的颜色
  19. @State private fontColor: string = "#2e2e2e";
  20. // 输入框是否获取焦点的状态变量
  21. @State private isFocusStart: boolean = false;
  22. @State private isFocusEnd: boolean = false;
  23. @State private isFocusCount: boolean = false;
  24. // 是否允许生成的随机数重复
  25. @State private isUnique: boolean = true;
  26. // 随机数生成的起始值
  27. @State private startValue: number = 0;
  28. // 随机数生成的结束值
  29. @State private endValue: number = 0;
  30. // 要生成的随机数个数
  31. @State private countValue: number = 0;
  32. @State private randomNumberArr:number[]=[]
  33. /**
  34. * todo:bug:
  35. * 改变值,会引起UI刷新
  36. */
  37. // 生成随机数的方法
  38. private generateRandomNumbers(): void {
  39. const startValue = this.startValue; // 获取当前设定的起始值
  40. const endValue = this.endValue; // 获取当前设定的结束值
  41. const countValue = this.countValue; // 获取当前设定的生成个数
  42. const range: number = endValue - startValue + 1; // 计算生成范围
  43. // 用于存储生成的随机数
  44. const generatedNumbers = new Set<number>(); // 使用Set来自动去重
  45. const tempArray: number[] = []; // 临时数组,用于辅助生成不重复的随机数
  46. // 如果不允许重复,则使用去重算法生成随机数
  47. if (!this.isUnique) {
  48. // 如果请求的随机数数量超过了范围内的总数,则显示错误提示
  49. if (countValue > range) {
  50. this.getUIContext().showAlertDialog({
  51. title: '错误提示',
  52. message: `请求的随机数数量超过了范围内的总数`,
  53. confirm: {
  54. defaultFocus: true,
  55. value: '我知道了',
  56. fontColor: Color.White,
  57. backgroundColor: this.primaryColor,
  58. action: () => {} // 点击确认后的回调
  59. },
  60. onWillDismiss: () => {}, // 对话框即将关闭时的回调
  61. alignment: DialogAlignment.Center, // 对话框的对齐方式
  62. });
  63. return;
  64. }
  65. for (let i = 0; i < countValue; i++) {
  66. let randomIndex = Math.floor(Math.random() * (range - i)); // 在剩余范围内选择一个随机索引
  67. let randomNum = 0;
  68. if (tempArray[randomIndex] !== undefined) { // 如果索引位置已有值,则使用该值
  69. randomNum = tempArray[randomIndex];
  70. } else {
  71. randomNum = startValue + randomIndex; // 否则计算新的随机数
  72. }
  73. generatedNumbers.add(randomNum); // 添加到Set中,自动去重
  74. if (tempArray[range - 1 - i] === undefined) { // 更新末尾元素的位置
  75. tempArray[range - 1 - i] = startValue + range - 1 - i;
  76. }
  77. tempArray[randomIndex] = tempArray[range - 1 - i]; // 将末尾元素移到随机位置
  78. }
  79. // 将生成的随机数转换成JSON格式的字符串
  80. this.generatedNumbers = JSON.stringify(Array.from(generatedNumbers));
  81. } else {
  82. // 如果允许重复,则直接生成随机数
  83. for (let i = 0; i < this.countValue; i++) {
  84. let randomNumber = this.startValue + Math.floor(Math.random() * (this.endValue - this.startValue));
  85. tempArray.push(randomNumber);
  86. }
  87. // 将生成的随机数转换成JSON格式的字符串
  88. this.generatedNumbers = JSON.stringify(tempArray);
  89. }
  90. //最终将生成的字符串转化为数组
  91. this.randomNumberArr=JSON.parse(this.generatedNumbers)
  92. // this.flexChangeValue=this.countValue
  93. }
  94. // // 将生成的随机数复制到剪贴板的方法
  95. // private copyToClipboard(text: string): void {
  96. // const pasteboardData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_PLAIN, text); // 创建剪贴板数据
  97. // const systemPasteboard = pasteboard.getSystemPasteboard(); // 获取系统剪贴板
  98. // systemPasteboard.setData(pasteboardData); // 设置剪贴板数据
  99. // // 显示复制成功的提示信息
  100. // promptAction.showToast({ message: '已复制' });
  101. // }
  102. build() {
  103. Column() {
  104. YTHeader({ title: '随机数' })
  105. //声音
  106. Row(){
  107. Image($r('app.media.app_icon')).width(24)
  108. }.width('100%')
  109. .justifyContent(FlexAlign.Start)
  110. .padding({left:30})
  111. Column() {
  112. Flex({ wrap: FlexWrap.Wrap, justifyContent: FlexAlign.SpaceBetween }) {
  113. ForEach(this.randomNumberArr, (item: number, index: number) => {
  114. Column() {
  115. Text(item.toString()).width(30)
  116. }
  117. .width(this.countValue > 3 ? 70 : 95)
  118. .height(this.countValue > 3 ? 60 : 85)
  119. .justifyContent(FlexAlign.Center)
  120. .alignItems(HorizontalAlign.Center)
  121. .margin({ bottom: 20 })
  122. .backgroundImage($r('[basic].media.number'))
  123. .backgroundImageSize({ width: "100%", height: '100%' })
  124. })
  125. }.padding({ left: 30, right: 30 })
  126. }.width('100%')
  127. .height(300)
  128. // 输入随机数范围的两个值
  129. Column({space:20}) {
  130. Row() {
  131. Text('取值范围:').margin({right:30})
  132. TextInput() // 输入框,显示占位符
  133. .width(60)
  134. .height(60)
  135. .type(InputType.Number) // 设置输入类型为数字
  136. .placeholderColor(this.isFocusStart ? this.primaryColor : Color.Gray) // 设置占位符颜色
  137. .fontColor(this.isFocusStart ? this.primaryColor : this.fontColor) // 设置文本颜色
  138. .borderColor(this.isFocusStart ? this.primaryColor : Color.Gray) // 设置边框颜色
  139. .borderWidth(1) // 设置边框宽度
  140. .borderRadius(10) // 设置圆角半径
  141. .backgroundColor(Color.White) // 设置背景颜色
  142. .showUnderline(false) // 不显示下划线
  143. .onBlur(() => this.isFocusStart = false) // 输入框失去焦点时的处理
  144. .onFocus(() => this.isFocusStart = true) // 输入框获得焦点时的处理
  145. .onChange((value: string) => {
  146. if(Number(value)>100){
  147. IBestToast.show({
  148. message:'生成范围只能是100以内'
  149. })
  150. return
  151. }
  152. if(Number(value)<=0){
  153. IBestToast.show({
  154. message:'生成范围只能是100以内'
  155. })
  156. return
  157. }
  158. this.startValue = Number(value)
  159. }); // 输入值变化时的处理
  160. // 分隔符
  161. // Line().width(10) // 设置分隔符宽度
  162. Text().width(30).height(1).fontColor(Color.Gray)
  163. TextInput() // 输入框,显示占位符
  164. .width(60)
  165. .height(60)
  166. .type(InputType.Number) // 设置输入类型为数字
  167. .placeholderColor(this.isFocusEnd ? this.primaryColor : Color.Gray) // 设置占位符颜色
  168. .fontColor(this.isFocusEnd ? this.primaryColor : this.fontColor) // 设置文本颜色
  169. .borderColor(this.isFocusEnd ? this.primaryColor : Color.Gray) // 设置边框颜色
  170. .borderWidth(1) // 设置边框宽度
  171. .borderRadius(10) // 设置圆角半径
  172. .backgroundColor(Color.White) // 设置背景颜色
  173. .showUnderline(false) // 不显示下划线
  174. .onBlur(() => this.isFocusEnd = false) // 输入框失去焦点时的处理
  175. .onFocus(() => this.isFocusEnd = true) // 输入框获得焦点时的处理
  176. .onChange((value: string) =>{
  177. if(Number(value)>100){
  178. IBestToast.show({
  179. message:'生成范围只能是100以内'
  180. })
  181. return
  182. }
  183. if(Number(value)<=0){
  184. IBestToast.show({
  185. message:'生成范围只能是100以内'
  186. })
  187. return
  188. }
  189. this.endValue = Number(value)
  190. }); // 输入值变化时的处理
  191. }.width('100%').margin({top:10})
  192. Row() {
  193. Text('生成个数:').margin({right:30})
  194. TextInput({ placeholder: ''}) // 输入框,显示占位符
  195. .width(60)
  196. .height(60)
  197. .type(InputType.Number) // 设置输入类型为数字
  198. .placeholderColor(this.isFocusCount ? this.primaryColor : Color.Gray) // 设置占位符颜色
  199. .fontColor(this.isFocusCount ? this.primaryColor : this.fontColor) // 设置文本颜色
  200. .borderColor(Color.Orange) // 设置边框颜色
  201. .borderWidth(1) // 设置边框宽度
  202. .borderRadius(10) // 设置圆角半径
  203. .backgroundColor(Color.White) // 设置背景颜色
  204. .showUnderline(false) // 不显示下划线
  205. .onBlur(() => this.isFocusCount = false) // 输入框失去焦点时的处理
  206. .onFocus(() => this.isFocusCount = true) // 输入框获得焦点时的处理
  207. .onChange((value: string) =>{
  208. if(Number(value)>10){
  209. IBestToast.show({
  210. message:'只能生成10个数'
  211. })
  212. return
  213. }
  214. if(Number(value)<0){
  215. IBestToast.show({
  216. message:'不能是负数'
  217. })
  218. return
  219. }
  220. this.countValue = Number(value)
  221. }); // 输入值变化时的处理
  222. }.width('100%')
  223. }.width(330)
  224. .height(170)
  225. .padding({left:30,top:10})
  226. .borderRadius(20)
  227. .backgroundColor('#e0f8ff')
  228. .justifyContent(FlexAlign.Start)
  229. Text('生成范围为100以内,最多生成10个数')
  230. Button('数字是否可以重复').onClick(()=>{
  231. this.isUnique=!this.isUnique
  232. })
  233. Text(JSON.stringify(this.isUnique))
  234. YTButton({
  235. bgc:'#fd54e3',
  236. btHeight:54,
  237. btBorderRadius:20,
  238. btWidth:300,
  239. btFontColor:Color.White,
  240. btFontSize:20,
  241. click:()=>{
  242. this.generateRandomNumbers()
  243. },
  244. btContent:'随机数生成'
  245. })
  246. }.padding({ bottom: this.safeBottom })
  247. .height('100%')
  248. .backgroundColor(Color.White)
  249. .backgroundImage($r('[basic].media.backimgNumber'))
  250. .backgroundImageSize({width:'100%',height:"100%"})
  251. }
  252. }
  253. /**
  254. * Row() {
  255. Text('数字是否可重复')
  256. .fontWeight(400) // 设置字体粗细为400
  257. .fontSize(16) // 设置字体大小为16
  258. .fontColor(this.fontColor) // 设置文本颜色
  259. .layoutWeight(1); // 设置布局权重为1
  260. Toggle({ type: ToggleType.Checkbox, isOn: this.isUnique }) // 切换按钮
  261. .width('100lpx') // 设置宽度
  262. .height('50lpx') // 设置高度
  263. .borderColor(Color.Gray) // 设置边框颜色
  264. .selectedColor(this.primaryColor) // 设置选中时的颜色
  265. .onChange((isOn: boolean) => this.isUnique = isOn) // 切换状态变化时的处理
  266. .align(Alignment.End); // 设置对齐方式为右对齐
  267. }
  268. .margin({
  269. top: `${this.baseSpacing}lpx`, // 上边距
  270. })
  271. .width('100%') // 设置宽度为100%
  272. .padding({
  273. left: `${this.baseSpacing}lpx`, // 左内边距
  274. right: `${this.baseSpacing}lpx`, // 右内边距
  275. top: `${this.baseSpacing / 3}lpx`, // 上内边距
  276. })
  277. .hitTestBehavior(HitTestMode.Block) // 设置点击测试行为
  278. .onClick(() => this.isUnique = !this.isUnique); // 点击时切换状态
  279. */