• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16import bundle from '@ohos.bundle';
17import router from '@ohos.router';
18import abilityAccessCtrl from '@ohos.abilityAccessCtrl';
19import privacyManager from '@ohos.privacyManager'
20import { backBar } from "../common/components/backBar";
21import Constants from '../common/utils/constant';
22import { noNeedDisplayApp, userGrantPermissions, permissionGroupIds } from "../common/model/permissionGroup";
23import { getPermissionGroup } from '../common/utils/utils'
24
25var TAG = 'PermissionManager_MainAbility:'
26
27@Extend(Image) function customizeImage(width: number, height: number) {
28  .objectFit(ImageFit.Contain)
29  .width(width)
30  .height(height)
31};
32
33class StringObj {
34  visits: string
35  recent_visit: string
36  morning: string
37  afternoon: string
38  constructor(visits: string, recent_visit: string, morning: string, afternoon: string) {
39    this.visits = visits
40    this.recent_visit = recent_visit
41    this.morning = morning
42    this.afternoon = afternoon
43  }
44}
45
46@Entry
47@Component
48struct permissionRecordPage {
49  @State groups: any[] = []
50  @State applicationInfos: any[] = []
51  @State permissionApplications: any[] = []
52  @State permissionIndex: number = -1
53  @State applicationIndex: number = -1
54  @State strings: StringObj = new StringObj('', '', '', '')
55  @State currentIndex: number = 0
56  @Builder TabBuilder(index: number) {
57    Flex({ alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
58      Text(index ? $r('app.string.application') : $r('app.string.authority'))
59        .fontColor(this.currentIndex == index ? $r('app.color.button_color') : $r('app.color.label_color'))
60        .fontWeight(this.currentIndex == index ? FontWeight.Bold : FontWeight.Regular)
61        .lineHeight(Constants.TEXT_LINE_HEIGHT)
62      if(this.currentIndex == index) {
63        Row().width(Constants.FULL_WIDTH).height(Constants.TAB_DECORATION_HEIGHT)
64          .backgroundColor($r('app.color.button_color'))
65          .position({ y: Constants.TAB_DECORATION_POSITION_Y })
66      }
67    }.height(Constants.TAB_HEIGHT)
68  }
69
70  @Builder ListItemLayout(item, index, dimension) {
71    ListItem() {
72      Column() {
73        Column() {
74          Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {
75            Row() {
76              if(dimension) {
77                Image(item.icon)
78                  .customizeImage(Constants.MANAGEMENT_IMAGE_WIDTH, Constants.MANAGEMENT_IMAGE_HEIGHT)
79                  .margin({ right: Constants.MANAGEMENT_IMAGE_MARGIN_RIGHT_RECORD, left: Constants.MANAGEMENT_IMAGE_MARGIN_LEFT })
80              }else {
81                Image(item.icon)
82                  .customizeImage(Constants.APPLICATION_IMAGE_WIDTH, Constants.APPLICATION_IMAGE_HEIGHT)
83                  .margin({ right: Constants.MANAGEMENT_IMAGE_MARGIN_RIGHT })
84              }
85              Column() {
86                Text(item.groupName)
87                  .fontSize(Constants.TEXT_MIDDLE_FONT_SIZE)
88                  .fontWeight(FontWeight.Medium)
89                  .fontColor($r('app.color.label_color'))
90                  .lineHeight(Constants.TEXT_LINE_HEIGHT)
91                  .margin({ bottom: Constants.TERTIARY_LABEL_MARGIN_BOTTOM })
92                if(dimension) {
93                  Text(this.strings.visits + item.sum)
94                    .fontSize(Constants.TEXT_SMAL_FONT_SIZE)
95                    .fontColor($r('app.color.label_color_light'))
96                    .lineHeight(Constants.TEXT_SMALL_LINE_HEIGHT)
97                }else {
98                  Row() {
99                    if (item.permissions) {
100                      ForEach(item.permissions, permission => {
101                        Image(permission.icon)
102                          .customizeImage(Constants.IMAGE_WIDTH_RECORD_APPLICATION, Constants.IMAGE_HEIGHT_RECORD_APPLICATION)
103                          .margin({ right: Constants.APPLICATION_TEXT_MARGIN_RIGHT })
104                      })
105                    }
106                  }
107                }
108              }.flexGrow(Constants.FLEX_GROW)
109              .alignItems(HorizontalAlign.Start)
110              if(dimension) {
111                if(index == this.permissionIndex) {
112                  Image($r('app.media.xiangshangjiantou'))
113                    .customizeImage(Constants.IMAGE_WIDTH_RECORD, Constants.IMAGE_HEIGHT_RECORD)
114                }else {
115                  Image($r('app.media.xiangxiajiantou'))
116                    .customizeImage(Constants.IMAGE_WIDTH_RECORD, Constants.IMAGE_HEIGHT_RECORD)
117                }
118              }else {
119                if(index == this.applicationIndex) {
120                  Image($r('app.media.xiangshangjiantou'))
121                    .customizeImage(Constants.IMAGE_WIDTH_RECORD, Constants.IMAGE_HEIGHT_RECORD)
122                }else {
123                  Image($r('app.media.xiangxiajiantou'))
124                    .customizeImage(Constants.IMAGE_WIDTH_RECORD, Constants.IMAGE_HEIGHT_RECORD)
125                }
126              }
127            }
128            .width(Constants.FULL_WIDTH)
129            .height(dimension ? Constants.LISTITEM_HEIGHT_PERMISSION : Constants.LISTITEM_HEIGHT_APPLICATION)
130          }
131        }.onClick(() => {
132          dimension ?
133            (this.permissionIndex = this.permissionIndex == index ? -1 : index) :
134            (this.applicationIndex = this.applicationIndex == index ? -1 : index)
135          if(dimension) {
136            this.permissionApplications = this.applicationInfos.filter(appInfo => {
137              return appInfo.groupNames.includes(item.groupName)
138            })
139          }
140        })
141        if(dimension && (index == this.permissionIndex)) {
142          List() {
143            ForEach(this.permissionApplications, (permissionApplication) => {
144              ListItem() {
145                Row() {
146                  Image(permissionApplication.icon)
147                    .customizeImage(Constants.APPLICATION_IMAGE_WIDTH, Constants.APPLICATION_IMAGE_HEIGHT)
148                    .margin({ right: Constants.MANAGEMENT_IMAGE_MARGIN_RIGHT })
149                  Column() {
150                    Row().width(Constants.FULL_WIDTH).height(Constants.TEXT_DECORATION_HEIGHT)
151                      .backgroundColor($r("app.color.label_color_lightest"))
152                      .margin({ bottom: Constants.LISTITEM_MARGIN_BOTTOM_PERMISSION })
153                    Text(permissionApplication.groupName)
154                      .fontSize(Constants.TEXT_MIDDLE_FONT_SIZE)
155                      .fontWeight(FontWeight.Medium)
156                      .fontColor($r('app.color.label_color'))
157                      .lineHeight(Constants.TEXT_LINE_HEIGHT)
158                      .margin({ bottom: Constants.TERTIARY_LABEL_MARGIN_BOTTOM })
159                    Text(this.strings.visits + this.getAppRecords(permissionApplication, item.groupName, true) +
160                        this.strings.recent_visit + this.getTime(this.getAppRecords(permissionApplication, item.groupName, false)))
161                      .fontSize(Constants.TEXT_SMAL_FONT_SIZE)
162                      .fontColor($r('app.color.label_color_light'))
163                      .lineHeight(Constants.TEXT_SMALL_LINE_HEIGHT)
164                  }.alignItems(HorizontalAlign.Start)
165                  .height(Constants.FULL_HEIGHT)
166                }
167              }.height(Constants.LISTITEM_HEIGHT_APPLICATION)
168              .onClick(() => {
169                globalThis.applicationInfo = {
170                  'bundleName': permissionApplication.name,
171                  'api': permissionApplication.api,
172                  'tokenId': permissionApplication.accessTokenId,
173                  'iconId': permissionApplication.icon,
174                  'labelId': permissionApplication.groupName,
175                  'permissions': permissionApplication.reqUserPermissions,
176                  'groupId': permissionApplication.groupIds
177                }
178                router.pushUrl({ url: 'pages/application-secondary' });
179              })
180            })
181          }
182        }
183        if(!dimension && (index == this.applicationIndex)) {
184          List() {
185            ForEach(item.permissions, (permission) => {
186              ListItem() {
187                Row() {
188                  Image(permission.icon)
189                    .customizeImage(Constants.MANAGEMENT_IMAGE_WIDTH, Constants.MANAGEMENT_IMAGE_HEIGHT)
190                    .margin({ right: Constants.MANAGEMENT_IMAGE_MARGIN_RIGHT_RECORD, left: Constants.MANAGEMENT_IMAGE_MARGIN_LEFT })
191                  Column() {
192                    Row().width(Constants.FULL_WIDTH).height(Constants.TEXT_DECORATION_HEIGHT)
193                      .backgroundColor($r("app.color.label_color_lightest"))
194                      .margin({ bottom: Constants.LISTITEM_MARGIN_BOTTOM_APPLICATION })
195                    Text(permission.groupName)
196                      .fontSize(Constants.TEXT_MIDDLE_FONT_SIZE)
197                      .fontWeight(FontWeight.Medium)
198                      .fontColor($r('app.color.label_color'))
199                      .lineHeight(Constants.TEXT_LINE_HEIGHT)
200                      .margin({ bottom: Constants.TERTIARY_LABEL_MARGIN_BOTTOM })
201                    Text(this.strings.visits + permission['count' + item.accessTokenId]
202                        + this.strings.recent_visit + this.getTime(permission['lastTime' + item.accessTokenId]))
203                      .fontSize(Constants.TEXT_SMAL_FONT_SIZE)
204                      .fontColor($r('app.color.label_color_light'))
205                      .lineHeight(Constants.TEXT_SMALL_LINE_HEIGHT)
206                  }.alignItems(HorizontalAlign.Start)
207                  .height(Constants.FULL_HEIGHT)
208                }
209              }.height(Constants.LISTITEM_HEIGHT_PERMISSION)
210              .onClick(() => {
211                globalThis.applicationInfo = {
212                  'bundleName': item.name,
213                  'api': item.api,
214                  'tokenId': item.accessTokenId,
215                  'iconId': item.icon,
216                  'labelId': item.groupName,
217                  'permissions': item.reqUserPermissions,
218                  'groupId': item.groupIds
219                }
220                router.pushUrl({ url: 'pages/application-secondary' });
221              })
222            })
223          }
224        }
225      }
226    }.padding({ left: Constants.DEFAULT_PADDING_START, right: Constants.DEFAULT_PADDING_END,
227      top: Constants.LIST_PADDING_TOP, bottom: Constants.LIST_PADDING_BOTTOM })
228    .margin({ bottom: Constants.LISTITEM_MARGIN_BOTTOM })
229    .backgroundColor($r('app.color.default_background_color'))
230    .borderRadius(Constants.BORDER_RADIUS)
231  }
232
233  build() {
234    GridContainer({ gutter: Constants.GUTTER, margin: Constants.GRID_MARGIN }) {
235      Row() {
236        Row()
237          .useSizeType({
238            xs: { span: Constants.LEFT_XS_SPAN, offset: Constants.LEFT_XS_OFFSET },
239            sm: { span: Constants.LEFT_SM_SPAN, offset: Constants.LEFT_SM_OFFSET },
240            md: { span: Constants.LEFT_MD_SPAN, offset: Constants.LEFT_MD_OFFSET },
241            lg: { span: Constants.LEFT_LG_SPAN, offset: Constants.LEFT_LG_OFFSET }
242          })
243          .height(Constants.FULL_HEIGHT)
244        Row() {
245          Column() {
246            Row() {
247              backBar( { title: JSON.stringify($r('app.string.permission_access_record')), recordable: false })
248            }
249            Row() {
250              Column() {
251                Column() {
252                  Flex({ justifyContent: FlexAlign.Start }) {
253                    Text($r('app.string.record_time_limit'))
254                      .margin({ left: Constants.BACKBAR_IMAGE_MARGIN_LEFT })
255                      .fontSize(Constants.TEXT_SMAL_FONT_SIZE)
256                      .fontColor($r('app.color.label_color_light'))
257                      .lineHeight(Constants.SUBTITLE_LINE_HEIGHT)
258                  }.constraintSize({ minHeight: Constants.SUBTITLE_MIN_HEIGHT })
259                  .padding({ top: Constants.SUBTITLE_PADDING_TOP, bottom: Constants.SUBTITLE_PADDING_BOTTOM })
260                  if(this.groups.length) {
261                    Stack() {
262                      Tabs() {
263                        TabContent() {
264                          Row() {
265                            Column() {
266                              Scroll() {
267                                Row() {
268                                  List() {
269                                    ForEach(this.groups, (item, index) => {
270                                      this.ListItemLayout(item, index, Constants.PERMISSION)
271                                    }, item => item.toString())
272                                  }.padding({ top: Constants.LIST_PADDING_TOP, bottom: Constants.LIST_PADDING_BOTTOM })
273                                }.padding({
274                                  left: Constants.MANAGEMENT_ROW_PADDING_LEFT,
275                                  right: Constants.MANAGEMENT_ROW_PADDING_RIGHT,
276                                  top: Constants.MANAGEMENT_ROW_PADDING_TOP
277                                })
278                              }.scrollBar(BarState.Off)
279                            }.width(Constants.FULL_WIDTH)
280                          }
281                        }.tabBar(this.TabBuilder(0))
282                        TabContent() {
283                          Row() {
284                            Column() {
285                              Scroll() {
286                                Row() {
287                                  List() {
288                                    ForEach(this.applicationInfos, (item, index) => {
289                                      this.ListItemLayout(item, index, Constants.APPLICATION)
290                                    }, item => item.toString())
291                                  }.padding({ top: Constants.LIST_PADDING_TOP, bottom: Constants.LIST_PADDING_BOTTOM })
292                                }.padding({
293                                  left: Constants.MANAGEMENT_ROW_PADDING_LEFT,
294                                  right: Constants.MANAGEMENT_ROW_PADDING_RIGHT,
295                                  top: Constants.MANAGEMENT_ROW_PADDING_TOP
296                                })
297                              }.scrollBar(BarState.Off)
298                            }.width(Constants.FULL_WIDTH)
299                          }
300                        }.tabBar(this.TabBuilder(1))
301                      }
302                      .barWidth(Constants.BAR_WIDTH)
303                      .barMode(BarMode.Fixed)
304                      .onChange((index) => {
305                        this.currentIndex = index
306                      })
307                    }.height(Constants.FULL_HEIGHT)
308                  }else {
309                    Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center, direction: FlexDirection.Column }) {
310                      Image($r('app.media.noRecord'))
311                        .customizeImage(Constants.NORECORD_IMAGE_WIDTH, Constants.NORECORD_IMAGE_HEIGHT)
312                        .margin({ left: Constants.NORECORD_IMAGE_MARGIN_LEFT })
313                      Text($r('app.string.no_record')).margin({ top: Constants.DIALOG_REQ_MARGIN_TOP })
314                        .fontSize(Constants.TEXT_SMAL_FONT_SIZE)
315                        .fontColor($r('app.color.label_color_light'))
316                    }.width(Constants.FULL_WIDTH).height(Constants.FULL_HEIGHT)
317                    .padding({ bottom: Constants.RECORD_PADDING_BOTTOM })
318                  }
319                }
320              }
321            }
322            .layoutWeight(Constants.LAYOUT_WEIGHT)
323          }
324        }
325        .useSizeType({
326          xs: { span: Constants.MIDDLE_XS_SPAN, offset: Constants.MIDDLE_XS_OFFSET },
327          sm: { span: Constants.MIDDLE_SM_SPAN, offset: Constants.MIDDLE_SM_OFFSET },
328          md: { span: Constants.MIDDLE_MD_SPAN, offset: Constants.MIDDLE_MD_OFFSET },
329          lg: { span: Constants.MIDDLE_LG_SPAN, offset: Constants.MIDDLE_LG_OFFSET }
330        })
331        .height(Constants.FULL_HEIGHT)
332        Row()
333          .useSizeType({
334            xs: { span: Constants.RIGHT_XS_SPAN, offset: Constants.RIGHT_XS_OFFSET },
335            sm: { span: Constants.RIGHT_SM_SPAN, offset: Constants.RIGHT_SM_OFFSET },
336            md: { span: Constants.RIGHT_MD_SPAN, offset: Constants.RIGHT_MD_OFFSET },
337            lg: { span: Constants.RIGHT_LG_SPAN, offset: Constants.RIGHT_LG_OFFSET }
338          })
339          .height(Constants.FULL_HEIGHT)
340      }
341      .height(Constants.FULL_HEIGHT)
342      .width(Constants.FULL_WIDTH)
343      .backgroundColor($r("sys.color.ohos_id_color_sub_background"))
344    }
345  }
346
347  /**
348   * Get time
349   * @param {Number} The time stamp
350   */
351  getTime(time, format='MM月DD日 NNHH:mm') {
352    if(this.strings.morning == 'am') { format = 'HH:mm NN MM/DD' }
353    let date = new Date(time)
354    let config = {
355      MM: date.getMonth() + 1,
356      DD: date.getDate(),
357      NN: date.getHours() >= 12 ? this.strings.afternoon : this.strings.morning,
358      HH: date.getHours() >= 12 ? date.getHours() - 12 : date.getHours(),
359      mm: date.getMinutes() > 10 ? date.getMinutes() : '0' + date.getMinutes(),
360    }
361
362    for(const key in config){
363      format = format.replace(key,config[key])
364    }
365    return format
366  }
367
368  /**
369   * Get application record info
370   * @param {Object} application info
371   * @param {String} groupName
372   * @param {Boolean} true: count, false: lastTime
373   */
374  getAppRecords(appInfo, groupName, option) {
375    var record = appInfo.permissions.filter(permission => {
376      return permission.groupName == groupName
377    })
378    return option ? record[0]['count' + appInfo.accessTokenId] : record[0]['lastTime' + appInfo.accessTokenId]
379  }
380
381  getStrings() {
382    globalThis.context.resourceManager.getString($r("app.string.visits").id, (err, val) => {
383      this.strings.visits = val
384    })
385    globalThis.context.resourceManager.getString($r("app.string.recent_visit").id, (err, val) => {
386      this.strings.recent_visit = val
387    })
388    globalThis.context.resourceManager.getString($r("app.string.morning").id, (err, val) => {
389      this.strings.morning = val
390    })
391    globalThis.context.resourceManager.getString($r("app.string.afternoon").id, (err, val) => {
392      this.strings.afternoon = val
393    })
394  }
395
396  getInfo(record, sortFlag) {
397    bundle.getBundleInfo(record.bundleName, Constants.PARMETER_BUNDLE_FLAG).then(async info => {
398      var reqUserPermissions: string[] = [];
399      var reqUserRecords: any[] = [];
400      var permissionGroups: any[] = [];
401      var acManager = abilityAccessCtrl.createAtManager()
402      var appInfo: any = {}
403      for (let j = 0; j < record.permissionRecords.length; j++) {
404        var permission = record.permissionRecords[j].permissionName;
405        try {
406          var flag = await acManager.getPermissionFlags(info.appInfo.accessTokenId, permission)
407          if(flag == Constants.PRE_AUTHORIZATION_NOT_MODIFIED) {
408            continue
409          }
410        }
411        catch(err) {
412          console.log(TAG + 'getPermissionFlags error: ' + JSON.stringify(err))
413        }
414        if (userGrantPermissions.indexOf(permission) != -1) {
415          reqUserRecords.push(record.permissionRecords[j])
416        }
417      }
418      for (let k = 0; k < info.reqPermissions.length; k++) {
419        var reqPermission: any = info.reqPermissions[k];
420        try {
421          var reqFlag = await acManager.getPermissionFlags(info.appInfo.accessTokenId, reqPermission)
422          if(reqFlag == Constants.PRE_AUTHORIZATION_NOT_MODIFIED) {
423            continue
424          }
425        }
426        catch(err) {
427          console.log(TAG + 'getPermissionFlags error: ' + JSON.stringify(err))
428        }
429        if (userGrantPermissions.indexOf(reqPermission) != -1) {
430          reqUserPermissions.push(reqPermission);
431        }
432      }
433
434      let groupNames = [];
435      let appLastTime = 0;
436      reqUserRecords.forEach(reqUserRecord => {
437        var group = getPermissionGroup(reqUserRecord.permissionName)
438        if(!group) {
439          console.info(TAG + "permission not find:" + reqUserRecord.permissionName)
440        }else {
441          var existing = permissionGroups.find(permissionGroup => permissionGroup.name == group.name)
442          var lastTime = reqUserRecord.lastAccessTime
443          lastTime > appLastTime ? appLastTime = lastTime : ''
444          if(!existing) {
445            group['count' + record.tokenId] = reqUserRecord.accessCount
446            group['lastTime' + record.tokenId] = lastTime
447            permissionGroups.push(group)
448            groupNames.push(group.groupName)
449          }else {
450            existing['count' + record.tokenId] += reqUserRecord.accessCount
451            lastTime > existing['lastTime' + record.tokenId] ? existing['lastTime' + record.tokenId] = lastTime : ''
452          }
453        }
454      })
455
456      let groupIds = [];
457      for (let i = 0; i < reqUserPermissions.length; i++) {
458        if(groupIds.indexOf(permissionGroupIds[reqUserPermissions[i]]) == -1){
459          groupIds.push(permissionGroupIds[reqUserPermissions[i]]);
460        }
461      }
462
463      let  context = globalThis.context.createBundleContext(info.name)
464      await context.resourceManager.getString(info.appInfo.labelId, (error, value) => {
465        if (value == undefined) {
466          appInfo.groupName = info.appInfo.label;
467        } else {
468          appInfo.groupName = value;
469        }
470      })
471
472      await context.resourceManager.getMediaBase64(info.appInfo.iconId, (error, value) => {
473        appInfo.icon = value;
474      })
475
476      appInfo.name = info.appInfo.name
477      appInfo.api = info.targetVersion
478      appInfo.accessTokenId = info.appInfo.accessTokenId
479      appInfo.reqUserPermissions = reqUserPermissions
480      appInfo.permissions = permissionGroups
481      appInfo.groupNames = groupNames
482      appInfo.groupIds = groupIds
483      appInfo.appLastTime = appLastTime
484      this.applicationInfos.push(appInfo)
485      if(sortFlag) {
486        var appInfos: any[] = []
487        this.applicationInfos.forEach(item => { appInfos.push(item) })
488        appInfos.sort((a, b) => { return b.appLastTime - a.appLastTime })
489        this.applicationInfos = appInfos
490      }
491    })
492  }
493
494  getAllRecords() {
495    let request = {
496      "tokenId": 0,
497      "isRemote": false,
498      "deviceId": '',
499      "bundleName": '',
500      "permissionNames": [],
501      "beginTime": 0,
502      "endTime": 0,
503      "flag": 1
504    }
505    privacyManager.getPermissionUsedRecord(request).then(async records => {
506      console.info(TAG + "records: " + JSON.stringify(records.bundleRecords))
507      var groupArray: any[] = []
508      for (let i = 0; i < records.bundleRecords.length; i++) {
509        var record = records.bundleRecords[i]
510        try {
511          const ret = await bundle.queryAbilityByWant({
512            bundleName: record.bundleName,
513            action: "action.system.home",
514            entities: ["entity.system.home"]
515          }, bundle.BundleFlag.GET_ABILITY_INFO_WITH_APPLICATION, Constants.USERID);
516        } catch(e) {
517          continue;
518        }
519        if (noNeedDisplayApp.indexOf(record.bundleName) != -1) {
520          continue;
521        }
522        console.info(TAG + "record: " + JSON.stringify(record))
523        this.getInfo(record, (i + 1) == records.bundleRecords.length)
524
525        record.permissionRecords.forEach(permissionRecord => {
526          var group = getPermissionGroup(permissionRecord.permissionName)
527          if(group) {
528            var exist = groupArray.find(permissionGroup => permissionGroup.name == group.name)
529            var lastTime = permissionRecord.lastAccessTime
530            if(!exist) {
531              group.sum = permissionRecord.accessCount
532              group.recentVisit = lastTime
533              groupArray.push(group)
534            }else {
535              exist.sum += permissionRecord.accessCount
536              lastTime > exist.recentVisit ? exist.recentVisit = lastTime : ''
537            }
538          }
539        })
540      }
541      groupArray.sort((a, b) => { return b.recentVisit - a.recentVisit })
542      this.groups = groupArray
543    })
544  }
545
546  aboutToAppear() {
547    this.getStrings()
548    this.getAllRecords()
549  }
550}
551